正在显示
6 个修改的文件
包含
165 行增加
和
19 行删除
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 | |||
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 |
lib/boot/email.js
0 → 100644
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", |
请
注册
或
登录
后发表评论