提交 b9fe49ef4285f273dbfe4cb9a2a06a62fb1064f7

作者 Nick Baugh
1 个父辈 3cdee8dc

Release 0.0.4-patch

@@ -24,19 +24,6 @@ eskimo --help @@ -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 ## Contributors 27 ## Contributors
41 28
42 * Nick Baugh <niftylettuce@gmail.com> 29 * Nick Baugh <niftylettuce@gmail.com>
1 1
2 -// # db 2 +// # boot - db
3 3
4 var mongoose = require('mongoose') 4 var mongoose = require('mongoose')
5 var _ = require('underscore') 5 var _ = require('underscore')
@@ -30,4 +30,4 @@ exports = module.exports = function(logger, settings) { @@ -30,4 +30,4 @@ exports = module.exports = function(logger, settings) {
30 } 30 }
31 31
32 exports['@singleton'] = true 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 var _ = require('underscore') 4 var _ = require('underscore')
5 var util = require('util') 5 var util = require('util')
6 6
7 exports = module.exports = function(logger, settings) { 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,4 +97,4 @@ exports = module.exports = function(logger, settings) {
91 } 97 }
92 98
93 exports['@singleton'] = true 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 var mergeDefaults = require('merge-defaults') 4 var mergeDefaults = require('merge-defaults')
5 var winston = require('winston') 5 var winston = require('winston')
@@ -46,4 +46,4 @@ exports = module.exports = function(settings) { @@ -46,4 +46,4 @@ exports = module.exports = function(settings) {
46 } 46 }
47 47
48 exports['@singleton'] = true 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 var _ = require('underscore') 4 var _ = require('underscore')
5 var jsonSelect = require('mongoose-json-select') 5 var jsonSelect = require('mongoose-json-select')
@@ -58,4 +58,4 @@ exports = module.exports = function(settings) { @@ -58,4 +58,4 @@ exports = module.exports = function(settings) {
58 } 58 }
59 59
60 exports['@singleton'] = true 60 exports['@singleton'] = true
61 -exports['@require'] = [ 'settings' ] 61 +exports['@require'] = [ 'igloo/settings' ]
  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 var session = require('express-session') 4 var session = require('express-session')
5 var RedisStore = require('connect-redis')(session) 5 var RedisStore = require('connect-redis')(session)
@@ -19,4 +19,4 @@ exports = module.exports = function(logger, settings) { @@ -19,4 +19,4 @@ exports = module.exports = function(logger, settings) {
19 } 19 }
20 20
21 exports['@singleton'] = true 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 var mergeDefaults = require('merge-defaults') 6 var mergeDefaults = require('merge-defaults')
5 7
6 exports = module.exports = function(config) { 8 exports = module.exports = function(config) {
@@ -9,6 +11,9 @@ exports = module.exports = function(config) { @@ -9,6 +11,9 @@ exports = module.exports = function(config) {
9 11
10 var env = process.env.NODE_ENV || 'development' 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 mergeDefaults(settings, config[env], config.defaults) 17 mergeDefaults(settings, config[env], config.defaults)
13 18
14 return settings 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 var _ = require('underscore') 4 var _ = require('underscore')
8 var updateNotifier = require('update-notifier') 5 var updateNotifier = require('update-notifier')
9 -var path = require('path')  
10 -var expressResource = require('express-resource')  
11 6
12 exports = module.exports = function(logger, settings) { 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 exports['@singleton'] = true 36 exports['@singleton'] = true
51 -exports['@require'] = [ 'logger', 'settings' ] 37 +exports['@require'] = [ 'igloo/logger', 'igloo/settings' ]
@@ -15,18 +15,7 @@ @@ -15,18 +15,7 @@
15 // # igloo 15 // # igloo
16 16
17 var path = require('path') 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 "name": "igloo", 2 "name": "igloo",
3 - "version": "0.0.4", 3 + "version": "0.0.4-patch",
4 "description": "Igloo is a lightweight, fast, and minimal framework for rapid development", 4 "description": "Igloo is a lightweight, fast, and minimal framework for rapid development",
5 - "main": "./index.js", 5 + "main": "./lib",
6 "repository": { 6 "repository": {
7 "type": "git", 7 "type": "git",
8 "url": "git://github.com/niftylettuce/igloo.git" 8 "url": "git://github.com/niftylettuce/igloo.git"
@@ -18,8 +18,6 @@ @@ -18,8 +18,6 @@
18 "chalk": "^0.4.0", 18 "chalk": "^0.4.0",
19 "commander": "^2.2.0", 19 "commander": "^2.2.0",
20 "connect-redis": "~2.0.0", 20 "connect-redis": "~2.0.0",
21 - "express": "~4.2.0",  
22 - "express-resource": "git://github.com/niftylettuce/express-resource",  
23 "express-session": "^1.2.1", 21 "express-session": "^1.2.1",
24 "merge-defaults": "^0.1.0", 22 "merge-defaults": "^0.1.0",
25 "mongoose": "~3.8.7", 23 "mongoose": "~3.8.7",
@@ -28,7 +26,6 @@ @@ -28,7 +26,6 @@
28 "underscore": "~1.6.0", 26 "underscore": "~1.6.0",
29 "update-notifier": "git://github.com/niftylettuce/update-notifier", 27 "update-notifier": "git://github.com/niftylettuce/update-notifier",
30 "winston": "git://github.com/niftylettuce/winston", 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 }
注册登录 后发表评论