正在显示
11 个修改的文件
包含
199 行增加
和
159 行删除
... | ... | @@ -24,19 +24,6 @@ eskimo --help |
24 | 24 | ``` |
25 | 25 | |
26 | 26 | |
27 | -## Components | |
28 | - | |
29 | -Using `electrolyte`, you an inject the following dependencies into your app with `eskimo`: | |
30 | - | |
31 | -* `app` - returns an instance of `express()` | |
32 | -* `error-handler` - returns an error handler that can be used via `app.use` | |
33 | -* `db` - returns connection to MongoDB | |
34 | -* `logger` - returns a Winston logger instance | |
35 | -* `model-common-plugin` - returns a Mongoose plugin for common schema paths | |
36 | -* `sessions` - returns connection to Redis | |
37 | -* `settings` - returns config | |
38 | - | |
39 | - | |
40 | 27 | ## Contributors |
41 | 28 | |
42 | 29 | * Nick Baugh <niftylettuce@gmail.com> | ... | ... |
1 | 1 | |
2 | -// # db | |
2 | +// # boot - db | |
3 | 3 | |
4 | 4 | var mongoose = require('mongoose') |
5 | 5 | var _ = require('underscore') |
... | ... | @@ -30,4 +30,4 @@ exports = module.exports = function(logger, settings) { |
30 | 30 | } |
31 | 31 | |
32 | 32 | exports['@singleton'] = true |
33 | -exports['@require'] = [ 'logger', 'settings' ] | |
33 | +exports['@require'] = [ 'igloo/logger', 'igloo/settings' ] | ... | ... |
1 | 1 | |
2 | -// # error handler | |
2 | +// # boot - error handler | |
3 | 3 | |
4 | 4 | var _ = require('underscore') |
5 | 5 | var util = require('util') |
6 | 6 | |
7 | 7 | exports = module.exports = function(logger, settings) { |
8 | 8 | |
9 | - return function(err, req, res, next) { | |
10 | - | |
11 | - // set default error status code | |
12 | - res.statusCode = (_.isNumber(err.status)) ? err.status : 500 | |
13 | - | |
14 | - if (!_.isString(err.message)) | |
15 | - err.message = 'An unknown error has occured, please try again' | |
16 | - | |
17 | - if (_.isObject(err) && _.isNumber(err.code) && err.code === 11000) { | |
18 | - // <https://github.com/LearnBoost/mongoose/issues/2129> | |
19 | - var field = err.message.split('index: test.')[1].split('.$')[1] | |
20 | - // now we have `email_1 dup key` | |
21 | - field = field.split(' dup key')[0] | |
22 | - field = field.substring(0, field.lastIndexOf('_')) | |
23 | - err.message = util.format('Duplicate %s already exists in database, try making a more unique value', field) | |
24 | - err.param = field | |
25 | - } | |
26 | - | |
27 | - // if we pass an error object, then we want to simply return the message... | |
28 | - // if we pass an object, then we want to do a stack trace, and then return the object + stack | |
29 | - var error = {} | |
30 | - | |
31 | - // set error type | |
32 | - error.type = _.isString(err.param) ? 'invalid_request_error' : 'api_error' | |
33 | - | |
34 | - if (error.type === 'invalid_request_error' && res.statusCode === 500) | |
35 | - res.statusCode = 400 | |
36 | - | |
37 | - // set error message and stack trace | |
38 | - if (util.isError(err)) { | |
39 | - error.message = err.message | |
40 | - } else { | |
41 | - _.extend(error, err) | |
42 | - } | |
43 | - | |
44 | - // set status code for BadRequestError | |
45 | - if (_.isString(error.name) && error.name === 'BadRequestError') { | |
46 | - error.type = 'invalid_request_error' | |
47 | - res.statusCode = 400 | |
48 | - delete error.name | |
49 | - } | |
50 | - | |
51 | - if (settings.showStack) | |
52 | - error.stack = _.isUndefined(err.stack) ? new Error(err.message).stack : err.stack | |
53 | - | |
54 | - // set error level | |
55 | - var level = (res.statusCode < 500) ? 'warn' : 'error' | |
56 | - logger[level](error) | |
57 | - | |
58 | - // set error back to warning if it was warn | |
59 | - // logger level type = "warn" | |
60 | - // req.flash messages type = "warning" | |
61 | - if (level === 'warn') | |
62 | - level = 'warning' | |
63 | - | |
64 | - // if we have a mongoose validation err | |
65 | - // then we know to output all the errors | |
66 | - if (_.isObject(error.errors) && !_.isEmpty(error.errors)) { | |
67 | - var messages = [] | |
68 | - _.each(error.errors, function(errMsg) { | |
69 | - if (_.isString(errMsg.message)) | |
70 | - messages.push(errMsg.message) | |
71 | - }) | |
72 | - if (!_.isEmpty(messages)) | |
73 | - error.message = messages.join(' ') | |
74 | - } | |
75 | - | |
76 | - res.format({ | |
77 | - text: function() { | |
78 | - res.send(error.message) | |
79 | - }, | |
80 | - html: function() { | |
81 | - req.flash(level, error.message) | |
82 | - res.redirect('back') | |
83 | - }, | |
84 | - json: function() { | |
85 | - res.json({ error: error }) | |
9 | + return function() { | |
10 | + | |
11 | + var app = this | |
12 | + | |
13 | + app.use(function(err, req, res, next) { | |
14 | + | |
15 | + // set default error status code | |
16 | + res.statusCode = (_.isNumber(err.status)) ? err.status : 500 | |
17 | + | |
18 | + if (!_.isString(err.message)) | |
19 | + err.message = 'An unknown error has occured, please try again' | |
20 | + | |
21 | + if (_.isObject(err) && _.isNumber(err.code) && err.code === 11000) { | |
22 | + // <https://github.com/LearnBoost/mongoose/issues/2129> | |
23 | + var field = err.message.split('index: test.')[1].split('.$')[1] | |
24 | + // now we have `email_1 dup key` | |
25 | + field = field.split(' dup key')[0] | |
26 | + field = field.substring(0, field.lastIndexOf('_')) | |
27 | + err.message = util.format('Duplicate %s already exists in database, try making a more unique value', field) | |
28 | + err.param = field | |
29 | + } | |
30 | + | |
31 | + // if we pass an error object, then we want to simply return the message... | |
32 | + // if we pass an object, then we want to do a stack trace, and then return the object + stack | |
33 | + var error = {} | |
34 | + | |
35 | + // set error type | |
36 | + error.type = _.isString(err.param) ? 'invalid_request_error' : 'api_error' | |
37 | + | |
38 | + if (error.type === 'invalid_request_error' && res.statusCode === 500) | |
39 | + res.statusCode = 400 | |
40 | + | |
41 | + // set error message and stack trace | |
42 | + if (util.isError(err)) { | |
43 | + error.message = err.message | |
44 | + } else { | |
45 | + _.extend(error, err) | |
86 | 46 | } |
47 | + | |
48 | + // set status code for BadRequestError | |
49 | + if (_.isString(error.name) && error.name === 'BadRequestError') { | |
50 | + error.type = 'invalid_request_error' | |
51 | + res.statusCode = 400 | |
52 | + delete error.name | |
53 | + } | |
54 | + | |
55 | + if (settings.showStack) | |
56 | + error.stack = _.isUndefined(err.stack) ? new Error(err.message).stack : err.stack | |
57 | + | |
58 | + // set error level | |
59 | + var level = (res.statusCode < 500) ? 'warn' : 'error' | |
60 | + logger[level](error) | |
61 | + | |
62 | + // set error back to warning if it was warn | |
63 | + // logger level type = "warn" | |
64 | + // req.flash messages type = "warning" | |
65 | + if (level === 'warn') | |
66 | + level = 'warning' | |
67 | + | |
68 | + // if we have a mongoose validation err | |
69 | + // then we know to output all the errors | |
70 | + if (_.isObject(error.errors) && !_.isEmpty(error.errors)) { | |
71 | + var messages = [] | |
72 | + _.each(error.errors, function(errMsg) { | |
73 | + if (_.isString(errMsg.message)) | |
74 | + messages.push(errMsg.message) | |
75 | + }) | |
76 | + if (!_.isEmpty(messages)) | |
77 | + error.message = messages.join(' ') | |
78 | + } | |
79 | + | |
80 | + res.format({ | |
81 | + text: function() { | |
82 | + res.send(error.message) | |
83 | + }, | |
84 | + html: function() { | |
85 | + req.flash(level, error.message) | |
86 | + res.redirect('back') | |
87 | + }, | |
88 | + json: function() { | |
89 | + res.json({ error: error }) | |
90 | + } | |
91 | + }) | |
92 | + | |
87 | 93 | }) |
88 | 94 | |
89 | 95 | } |
... | ... | @@ -91,4 +97,4 @@ exports = module.exports = function(logger, settings) { |
91 | 97 | } |
92 | 98 | |
93 | 99 | exports['@singleton'] = true |
94 | -exports['@require'] = [ 'logger', 'settings' ] | |
100 | +exports['@require'] = [ 'igloo/logger', 'igloo/settings' ] | ... | ... |
1 | 1 | |
2 | -// # logger | |
2 | +// # boot - logger | |
3 | 3 | |
4 | 4 | var mergeDefaults = require('merge-defaults') |
5 | 5 | var winston = require('winston') |
... | ... | @@ -46,4 +46,4 @@ exports = module.exports = function(settings) { |
46 | 46 | } |
47 | 47 | |
48 | 48 | exports['@singleton'] = true |
49 | -exports['@require'] = [ 'settings' ] | |
49 | +exports['@require'] = [ 'igloo/settings' ] | ... | ... |
1 | 1 | |
2 | -// # boot - model common plugin | |
2 | +// # boot - mongoose plugin | |
3 | 3 | |
4 | 4 | var _ = require('underscore') |
5 | 5 | var jsonSelect = require('mongoose-json-select') |
... | ... | @@ -58,4 +58,4 @@ exports = module.exports = function(settings) { |
58 | 58 | } |
59 | 59 | |
60 | 60 | exports['@singleton'] = true |
61 | -exports['@require'] = [ 'settings' ] | |
61 | +exports['@require'] = [ 'igloo/settings' ] | ... | ... |
lib/boot/server.js
0 → 100644
1 | + | |
2 | +// # boot - server | |
3 | + | |
4 | +// Inspired by `bixby-server` by Jared Hanson | |
5 | + | |
6 | +var https = require('https') | |
7 | +var http = require('http') | |
8 | +var cluster = require('cluster') | |
9 | +var os = require('os') | |
10 | +var path = require('path') | |
11 | + | |
12 | +exports = module.exports = function(logger, settings) { | |
13 | + | |
14 | + return function(done) { | |
15 | + | |
16 | + if (cluster.isMaster && settings.server.cluster) { | |
17 | + | |
18 | + var size = settings.server.cluster.size || os.cpus().length | |
19 | + | |
20 | + logger.info('creating cluster with %d workers', size) | |
21 | + | |
22 | + for (var i=0; i<size; i++) { | |
23 | + logger.info('spawning worker #%d', i + 1) | |
24 | + cluster.fork() | |
25 | + } | |
26 | + | |
27 | + cluster.on('fork', function(worker) { | |
28 | + logger.info('worker #%s with pid %d spawned', worker.id, worker.process.pid) | |
29 | + }) | |
30 | + | |
31 | + cluster.on('online', function(worker) { | |
32 | + logger.info('worker #%s with pid %d online', worker.id, worker.process.pid) | |
33 | + }) | |
34 | + | |
35 | + cluster.on('listening', function(worker, addr) { | |
36 | + logger.info('worker #%s with pid %d listening on %s:%d', worker.id, worker.process.pid, addr.address, addr.port) | |
37 | + }) | |
38 | + | |
39 | + cluster.on('disconnect', function(worker) { | |
40 | + logger.info('worker #%s with pid %d disconnected', worker.id, worker.process.pid) | |
41 | + }) | |
42 | + | |
43 | + cluster.on('exit', function(worker, code, signal) { | |
44 | + logger.error('worker #%s with pid %d exited with code/signal', worker.id, worker.process.pid, signal, code) | |
45 | + if (worker.suicide) return | |
46 | + logger.info('worker #%s restarting', worker.id) | |
47 | + cluster.fork() | |
48 | + }) | |
49 | + | |
50 | + } else { | |
51 | + | |
52 | + if (settings.server.ssl.enabled) | |
53 | + this.server = https.createServer(settings.server.ssl.options, this) | |
54 | + else | |
55 | + this.server = http.createServer(this) | |
56 | + | |
57 | + this.server.listen(settings.server.port, settings.server.host, function() { | |
58 | + var addr = this.address() | |
59 | + logger.info('app listening on %s:%d', addr.address, addr.port) | |
60 | + done() | |
61 | + }) | |
62 | + | |
63 | + } | |
64 | + | |
65 | + } | |
66 | + | |
67 | +} | |
68 | + | |
69 | +exports['@singleton'] = true | |
70 | +exports['@require'] = [ 'igloo/logger', 'igloo/settings' ] | ... | ... |
1 | 1 | |
2 | -// # sessions | |
2 | +// # boot - sessions | |
3 | 3 | |
4 | 4 | var session = require('express-session') |
5 | 5 | var RedisStore = require('connect-redis')(session) |
... | ... | @@ -19,4 +19,4 @@ exports = module.exports = function(logger, settings) { |
19 | 19 | } |
20 | 20 | |
21 | 21 | exports['@singleton'] = true |
22 | -exports['@require'] = [ 'logger', 'settings' ] | |
22 | +exports['@require'] = [ 'igloo/logger', 'igloo/settings' ] | ... | ... |
1 | 1 | |
2 | -// # settings | |
2 | +// # boot - settings | |
3 | 3 | |
4 | +var _ = require('underscore') | |
5 | +var util = require('util') | |
4 | 6 | var mergeDefaults = require('merge-defaults') |
5 | 7 | |
6 | 8 | exports = module.exports = function(config) { |
... | ... | @@ -9,6 +11,9 @@ exports = module.exports = function(config) { |
9 | 11 | |
10 | 12 | var env = process.env.NODE_ENV || 'development' |
11 | 13 | |
14 | + if (!_.isObject(config[env])) | |
15 | + throw new Error(util.format('Unknown environment %s', env)) | |
16 | + | |
12 | 17 | mergeDefaults(settings, config[env], config.defaults) |
13 | 18 | |
14 | 19 | return settings | ... | ... |
1 | 1 | |
2 | -// # app | |
2 | +// # boot - update notifier | |
3 | 3 | |
4 | -var express = require('express') | |
5 | -var winstonRequestLogger = require('winston-request-logger') | |
6 | -var bootable = require('bootable') | |
7 | 4 | var _ = require('underscore') |
8 | 5 | var updateNotifier = require('update-notifier') |
9 | -var path = require('path') | |
10 | -var expressResource = require('express-resource') | |
11 | 6 | |
12 | 7 | exports = module.exports = function(logger, settings) { |
13 | 8 | |
14 | - // check for updates to all packages when not in production | |
15 | - if (settings.updateNotifier.enabled) | |
16 | - _.each(settings.pkg.dependencies, function(version, name) { | |
17 | - var notifier = updateNotifier({ | |
18 | - packageName: name, | |
19 | - packageVersion: version, | |
20 | - optOut: settings.updateNotifier.dependencies[name] || false, | |
21 | - updateCheckInterval: settings.updateNotifier.updateCheckInterval | 1000 * 60 * 60, // hourly | |
22 | - updateCheckTimeout: settings.updateNotifier.updateCheckTimeout | 1000 * 20 // 20 seconds | |
9 | + return function() { | |
10 | + | |
11 | + // check for updates to all packages when not in production | |
12 | + if (settings.updateNotifier.enabled) | |
13 | + _.each(settings.pkg.dependencies, function(version, name) { | |
14 | + var notifier = updateNotifier({ | |
15 | + packageName: name, | |
16 | + packageVersion: version, | |
17 | + optOut: settings.updateNotifier.dependencies[name] || false, | |
18 | + updateCheckInterval: settings.updateNotifier.updateCheckInterval | 1000 * 60 * 60, // hourly | |
19 | + updateCheckTimeout: settings.updateNotifier.updateCheckTimeout | 1000 * 20 // 20 seconds | |
20 | + }) | |
21 | + if (_.isUndefined(notifier.update) || !_.isString(notifier.update.latest)) return | |
22 | + logger.warn( | |
23 | + '%s of %s released (current: %s), run `npm install -S %s@%s` to upgrade', | |
24 | + notifier.update.latest, | |
25 | + name, | |
26 | + version, | |
27 | + name, | |
28 | + notifier.update.latest | |
29 | + ) | |
23 | 30 | }) |
24 | - if (_.isUndefined(notifier.update) || !_.isString(notifier.update.latest)) return | |
25 | - logger.warn( | |
26 | - '%s of %s released (current: %s), run `npm install -S %s@%s` to upgrade', | |
27 | - notifier.update.latest, | |
28 | - name, | |
29 | - version, | |
30 | - name, | |
31 | - notifier.update.latest | |
32 | - ) | |
33 | - }) | |
34 | - | |
35 | - // create the app | |
36 | - var app = bootable(express()) | |
37 | - | |
38 | - // winston request logger before everything else | |
39 | - // but only if it was enabled in settings | |
40 | - if (settings.logger.requests) | |
41 | - app.use(winstonRequestLogger.create(logger)) | |
42 | - | |
43 | - // integrate express-resource | |
44 | - app = expressResource(app) | |
45 | - | |
46 | - return app | |
31 | + | |
32 | + } | |
47 | 33 | |
48 | 34 | } |
49 | 35 | |
50 | 36 | exports['@singleton'] = true |
51 | -exports['@require'] = [ 'logger', 'settings' ] | |
37 | +exports['@require'] = [ 'igloo/logger', 'igloo/settings' ] | ... | ... |
... | ... | @@ -15,18 +15,7 @@ |
15 | 15 | // # igloo |
16 | 16 | |
17 | 17 | var path = require('path') |
18 | -var os = require('os') | |
19 | -var cluster = require('cluster') | |
20 | 18 | |
21 | -var bootDir = path.join(__dirname, 'boot') | |
22 | - | |
23 | -module.exports = { | |
24 | - loader: function(id) { | |
25 | - return require(path.join(bootDir, id)) | |
26 | - }, | |
27 | - app: function(IoC) { | |
28 | - IoC.loader(IoC.node(bootDir)) | |
29 | - var app = IoC.create('app') | |
30 | - return app | |
31 | - } | |
19 | +module.exports = function(id) { | |
20 | + return require(path.join(__dirname, 'boot', id)) | |
32 | 21 | } | ... | ... |
1 | 1 | { |
2 | 2 | "name": "igloo", |
3 | - "version": "0.0.4", | |
3 | + "version": "0.0.4-patch", | |
4 | 4 | "description": "Igloo is a lightweight, fast, and minimal framework for rapid development", |
5 | - "main": "./index.js", | |
5 | + "main": "./lib", | |
6 | 6 | "repository": { |
7 | 7 | "type": "git", |
8 | 8 | "url": "git://github.com/niftylettuce/igloo.git" |
... | ... | @@ -18,8 +18,6 @@ |
18 | 18 | "chalk": "^0.4.0", |
19 | 19 | "commander": "^2.2.0", |
20 | 20 | "connect-redis": "~2.0.0", |
21 | - "express": "~4.2.0", | |
22 | - "express-resource": "git://github.com/niftylettuce/express-resource", | |
23 | 21 | "express-session": "^1.2.1", |
24 | 22 | "merge-defaults": "^0.1.0", |
25 | 23 | "mongoose": "~3.8.7", |
... | ... | @@ -28,7 +26,6 @@ |
28 | 26 | "underscore": "~1.6.0", |
29 | 27 | "update-notifier": "git://github.com/niftylettuce/update-notifier", |
30 | 28 | "winston": "git://github.com/niftylettuce/winston", |
31 | - "winston-mongodb": "~0.4.3", | |
32 | - "winston-request-logger": "^1.0.5" | |
29 | + "winston-mongodb": "~0.4.3" | |
33 | 30 | } |
34 | 31 | } | ... | ... |
请
注册
或
登录
后发表评论