提交 0126041f45af4457fb17f8a23934b438f94fc830

作者 Bruno Bernardino
2 个父辈 d8a089a2 aff6aefe

Merge remote-tracking branch 'upstream/master'

1 language: node_js 1 language: node_js
2 node_js: 2 node_js:
3 - '0.10' 3 - '0.10'
4 -- '0.11'  
5 script: npm run-script test-travis 4 script: npm run-script test-travis
6 -after_script: npm install coveralls@2 && cat ./coverage/lcov.info | coveralls 5 +after_script:
  6 +- npm install -g coveralls@2
  7 +- cat ./coverage/lcov.info | coveralls
  8 +- npm install -g codeclimate-test-reporter
  9 +- cat ./coverage/lcov.info | codeclimate
7 notifications: 10 notifications:
8 webhooks: 11 webhooks:
9 urls: 12 urls:
@@ -14,3 +17,9 @@ notifications: @@ -14,3 +17,9 @@ notifications:
14 hipchat: 17 hipchat:
15 rooms: 18 rooms:
16 secure: SZAghgIWk6b8rpItdkjSY8UJtTW8E8AIYE5KkTGa9FiV0/q9kTHIAiqxBAQyIgF9IVsrO2NZdO9FrsiKjkSUPXbkonxtuqptl2c7bJLm2gUNmku2DfG0hn8TY50MXxGpiyEySoxcX4igQTzSZlJM81T0EI+L0PQJJXUKEJGuadY= 19 secure: SZAghgIWk6b8rpItdkjSY8UJtTW8E8AIYE5KkTGa9FiV0/q9kTHIAiqxBAQyIgF9IVsrO2NZdO9FrsiKjkSUPXbkonxtuqptl2c7bJLm2gUNmku2DfG0hn8TY50MXxGpiyEySoxcX4igQTzSZlJM81T0EI+L0PQJJXUKEJGuadY=
  20 + slack:
  21 + secure: 3uMd7XP25L2pPQ+4yzWmlSwsTBaiTERvTrA/e+Nz69g+nMpNviMVMRtLF/wlp01eehgNJ9InVdQ7Bq+MqS4eJPtqjVass7a3IplMIvjugMPlzw9eCEDxrxdbW649jw2esVKOj0eB40zhLrsV1AtxPyENIWeOn8uvVNjMLhiNiUs=
  22 +addons:
  23 + code_climate:
  24 + repo_token:
  25 + secure: BZej5nHBS+etVd/Xlq0uFRxgsbhh1njqvQZkBIec1kW6u+g9k16y1GVKGzlZsThlSUkIcmZ36N7MGstRNCJ5cuY5dLq914xqm8gZGvK15EzcdqroLPLOctkeJ6/KADqCQwI9L9bhP87kNTAcuNAljAJthiO3swM4fM7nLEQMbkQ=
@@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
5 [![Build Status][travis-image]][travis-url] 5 [![Build Status][travis-image]][travis-url]
6 [![NPM downloads][npm-downloads]][npm-url] 6 [![NPM downloads][npm-downloads]][npm-url]
7 [![Test Coverage][coveralls-image]][coveralls-url] 7 [![Test Coverage][coveralls-image]][coveralls-url]
  8 +[![Static Analysis][codeclimate-image]][codeclimate-url]
8 [![MIT License][license-image]][license-url] 9 [![MIT License][license-image]][license-url]
9 [![Gitter][gitter-image]][gitter-url] 10 [![Gitter][gitter-image]][gitter-url]
10 11
@@ -164,6 +165,7 @@ app.listen(settings.port, function() { @@ -164,6 +165,7 @@ app.listen(settings.port, function() {
164 165
165 ## Components 166 ## Components
166 167
  168 +* [email](#email)
167 * [error-handler](#error-handler) 169 * [error-handler](#error-handler)
168 * [knex](#knex) 170 * [knex](#knex)
169 * [logger](#logger) 171 * [logger](#logger)
@@ -174,6 +176,31 @@ app.listen(settings.port, function() { @@ -174,6 +176,31 @@ app.listen(settings.port, function() {
174 * [settings](#settings) 176 * [settings](#settings)
175 * [update-notifier](#update-notifier) 177 * [update-notifier](#update-notifier)
176 178
  179 +### email
  180 +
  181 +> Returns a function which accepts templateName, locals, headers, transport, and callback arguments. This component uses
  182 +
  183 +[View source](lib/boot/email.js)
  184 +
  185 +```js
  186 +// example - email
  187 +
  188 +// TODO: finish this!
  189 +
  190 +// mention that transport defaults to settings.email.transport
  191 +
  192 +// mention that headers inherits settings.email.headers
  193 +
  194 +// but only if you don't set `headers.useDefaults: false`
  195 +
  196 +// note that is also uses `settings.email.templates` object
  197 +// which can have `dir` string and `options` object for node email-templates pkg
  198 +
  199 +// also document about having `transport` of `settings.email.transport` be an
  200 +// actual transporter already pre-created (possibly with plugins like html-to-text)
  201 +
  202 +```
  203 +
177 ### error-handler 204 ### error-handler
178 205
179 > Returns [Express][express] route middleware for error handling. 206 > Returns [Express][express] route middleware for error handling.
@@ -410,6 +437,8 @@ See [nifty-conventions][nifty-conventions] for code guidelines, general project @@ -410,6 +437,8 @@ See [nifty-conventions][nifty-conventions] for code guidelines, general project
410 [MIT][license-url] 437 [MIT][license-url]
411 438
412 439
  440 +[codeclimate-image]: http://img.shields.io/codeclimate/github/niftylettuce/igloo.svg?style=flat
  441 +[codeclimate-url]: https://codeclimate.com/github/niftylettuce/igloo
413 [license-image]: http://img.shields.io/badge/license-MIT-blue.svg?style=flat 442 [license-image]: http://img.shields.io/badge/license-MIT-blue.svg?style=flat
414 [license-url]: LICENSE 443 [license-url]: LICENSE
415 [nifty-conventions]: https://github.com/niftylettuce/nifty-conventions 444 [nifty-conventions]: https://github.com/niftylettuce/nifty-conventions
  1 +
  2 +// # boot - email
  3 +
  4 +var nodemailer = require('nodemailer')
  5 +var emailTemplates = require('email-templates')
  6 +var _ = require('underscore')
  7 +
  8 +exports = module.exports = function(settings) {
  9 +
  10 + // check to make sure we defined a default email object
  11 + if (!_.isObject(settings.email))
  12 + throw new Error('Settings did not have an `email` object')
  13 +
  14 + // check to make sure settings.email.templates is defined
  15 + if (!_.isObject(settings.email.templates))
  16 + throw new Error('Settings did not have a `settings.email.templates` object')
  17 +
  18 + // check to make sure settings.email.templates.dir is defined
  19 + if (!_.isString(settings.email.templates.dir))
  20 + throw new Error('Settings did not have a `settings.email.templates.dir` string')
  21 +
  22 + var templateName, locals, headers, callback, transporter
  23 +
  24 + function renderTemplate(_templateName, _locals, _headers, transport, _callback) {
  25 +
  26 + templateName = _templateName
  27 + locals = _locals
  28 + headers = _headers
  29 + callback = _callback
  30 +
  31 + // add ability to override default transport defined in settings
  32 + if (_.isFunction(transport)) {
  33 +
  34 + // check to make sure we defined a default transport object
  35 + if (!_.isObject(settings.email.transport))
  36 + throw new Error('Settings did not have an `email.transport` object')
  37 +
  38 + callback = transport
  39 +
  40 + //
  41 + // if the transport defined in settings is an actual transport
  42 + // (as opposed to just a config object) then we need to use that
  43 + // instead of creating a transport - to do so we'll look for the
  44 + // `.transporter` property that gets added to all transport objects
  45 + // <https://github.com/andris9/Nodemailer/blob/master/src/nodemailer.js#L39>
  46 + //
  47 + // the reason we have this support added is in case users add plugins to
  48 + // their transporter, for example the `nodemailer-html-to-text` plugin
  49 + // <https://github.com/andris9/nodemailer-html-to-text>
  50 + //
  51 + if (_.has(settings.email.transport, 'transporter'))
  52 + transporter = settings.email.transport
  53 + else
  54 + transporter = nodemailer.createTransport(settings.email.transport)
  55 +
  56 + } else {
  57 + transporter = nodemailer.createTransport(transport)
  58 + }
  59 +
  60 + if (_.isObject(settings.email.templates.options))
  61 + return emailTemplates(settings.email.templates.dir, settings.email.templates.options, createTemplate)
  62 +
  63 + emailTemplates(settings.email.templates.dir, createTemplate)
  64 +
  65 + }
  66 +
  67 + function createTemplate(err, template) {
  68 + if (err) throw err
  69 + template(templateName, locals, createEmail(headers))
  70 + }
  71 +
  72 + function createEmail(headers) {
  73 + return function(err, html, text) {
  74 + if (err) return callback(err)
  75 + // if we defined a default headers object, then inherit it here
  76 + // but only if we didn't set `useDefaults` to false in the headers
  77 + if (_.isObject(settings.email.headers) && !headers.useDefaults)
  78 + headers = _.defaults(headers, settings.email.headers)
  79 + if (_.isString(html))
  80 + headers.html = html
  81 + if (_.isString(text))
  82 + headers.text = text
  83 + transporter.sendMail(headers, callback)
  84 + }
  85 + }
  86 +
  87 + return renderTemplate
  88 +
  89 +}
  90 +
  91 +exports['@singleton'] = true
  92 +exports['@require'] = [ 'igloo/settings' ]
@@ -53,9 +53,28 @@ exports = module.exports = function(settings) { @@ -53,9 +53,28 @@ exports = module.exports = function(settings) {
53 transports: transports 53 transports: transports
54 }) 54 })
55 55
  56 + if (settings.server.env === 'development')
  57 + logger = expandErrors(logger)
56 58
57 return logger 59 return logger
58 60
  61 + // Extend a winston by making it expand errors when passed in as the
  62 + // second argument (the first argument is the log level).
  63 + // <https://gist.github.com/johndgiese/59bd96360ce411042294>
  64 + // <https://gist.github.com/getvega/6211610>
  65 + function expandErrors(logger) {
  66 + var oldLogFunc = logger.log
  67 + logger.log = function() {
  68 + var args = Array.prototype.slice.call(arguments, 0)
  69 + if (args.length >= 2 && args[1] instanceof Error) {
  70 + args[1] = args[1].stack
  71 + }
  72 + return oldLogFunc.apply(this, args)
  73 + };
  74 + return logger
  75 + }
  76 +
  77 +
59 } 78 }
60 79
61 exports['@singleton'] = true 80 exports['@singleton'] = true
@@ -5,20 +5,24 @@ var _ = require('underscore') @@ -5,20 +5,24 @@ var _ = require('underscore')
5 var util = require('util') 5 var util = require('util')
6 var mergeDefaults = require('merge-defaults') 6 var mergeDefaults = require('merge-defaults')
7 7
8 -exports = module.exports = function(config, local) { 8 +exports = module.exports = function(IoC, config) {
9 9
10 var settings = {} 10 var settings = {}
11 11
12 var env = process.env.NODE_ENV || 'development' 12 var env = process.env.NODE_ENV || 'development'
13 13
14 - if (!_.isObject(local))  
15 - local = {}  
16 -  
17 - mergeDefaults(config, local)  
18 -  
19 if (!_.isObject(config[env])) 14 if (!_.isObject(config[env]))
20 throw new Error(util.format('Unknown environment %s', env)) 15 throw new Error(util.format('Unknown environment %s', env))
21 16
  17 + if (env === 'development') {
  18 + try {
  19 + var local = IoC.create('local')
  20 + if (_.isObject(local))
  21 + mergeDefaults(settings, local)
  22 + } catch(e) {
  23 + }
  24 + }
  25 +
22 mergeDefaults(settings, config[env], config.defaults) 26 mergeDefaults(settings, config[env], config.defaults)
23 27
24 return settings 28 return settings
@@ -26,13 +30,4 @@ exports = module.exports = function(config, local) { @@ -26,13 +30,4 @@ exports = module.exports = function(config, local) {
26 } 30 }
27 31
28 exports['@singleton'] = true 32 exports['@singleton'] = true
29 -exports['@require'] = ['config']  
30 -  
31 -var fs = require('fs')  
32 -var path = require('path')  
33 -var localPath = path.join(__dirname, '..', '..', '..', '..' ,'boot', 'local.js')  
34 -  
35 -// Include local.js if it exists at boot/local.js  
36 -if (fs.existsSync(localPath)) {  
37 - exports['@require'].push('local')  
38 -} 33 +exports['@require'] = [ '$container', 'config' ]
1 { 1 {
2 "name": "igloo", 2 "name": "igloo",
3 - "version": "0.0.4-rc.13", 3 + "version": "0.0.4-rc.14",
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": "./lib", 5 "main": "./lib",
6 "repository": { 6 "repository": {
@@ -32,8 +32,10 @@ @@ -32,8 +32,10 @@
32 "chalk": "^0.4.0", 32 "chalk": "^0.4.0",
33 "commander": "^2.2.0", 33 "commander": "^2.2.0",
34 "connect-redis": "~2.0.0", 34 "connect-redis": "~2.0.0",
  35 + "email-templates": "^1.1.2",
35 "express-session": "^1.2.1", 36 "express-session": "^1.2.1",
36 "merge-defaults": "^0.1.0", 37 "merge-defaults": "^0.1.0",
  38 + "nodemailer": "^1.3.0",
37 "to-camel-case": "^0.2.1", 39 "to-camel-case": "^0.2.1",
38 "underscore": "^1.6.0", 40 "underscore": "^1.6.0",
39 "update-notifier": "^0.2.0", 41 "update-notifier": "^0.2.0",
注册登录 后发表评论