提交 b9fe49ef4285f273dbfe4cb9a2a06a62fb1064f7

作者 Nick Baugh
1 个父辈 3cdee8dc

Release 0.0.4-patch

... ... @@ -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' ]
... ...
  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 }
... ...
注册登录 后发表评论