提交 987c3c6bf0594eceb012afd9f2538a73b81ed2e1

作者 Nick Baugh
1 个父辈 817a1ec9

cleanup

1   -
2   -// # grunt
3   -
4   -// TODO
... ... @@ -3,7 +3,7 @@
3 3
4 4 ![Igloo](https://filenode.s3.amazonaws.com/igloo.png)
5 5
6   -Igloo is a minimal app boilerplate built with Express.
  6 +Igloo is a lightweight, fast, and minimal framework for rapid development
7 7
8 8 View documentation for Igloo at <http://documentup.com/niftylettuce/igloo>.
9 9
... ... @@ -18,7 +18,7 @@ View documentation for Igloo at <http://documentup.com/niftylettuce/igloo>.
18 18
19 19 ### Installation
20 20
21   -* Install the `igloo` package from the NPM repository:
  21 +* Install the `igloo` package globally from the NPM repository:
22 22
23 23 ```bash
24 24 npm install -g igloo
... ... @@ -57,6 +57,7 @@ info: Igloo started at http://localhost:3000
57 57 ## Contributors
58 58
59 59 * Nick Baugh <niftylettuce@gmail.com>
  60 +* Sandaruwan Silva <c-h@users.sf.net>
60 61
61 62
62 63 ## Credits
... ...
... ... @@ -18,4 +18,4 @@ function home(lib, settings) {
18 18 }
19 19 }
20 20
21   -exports['@require'] = [ 'lib', 'settings' ];
\ No newline at end of file
  21 +exports['@require'] = [ 'lib', 'settings' ];
... ...
1 1
2   -// # common
  2 +// # models - common
  3 +
  4 +var jsonSelect = require('mongoose-json-select')
3 5
4 6 module.exports = common
5 7
6 8 function common(Schema) {
7 9
8   - Schema.virtual('id').get(function() {
9   - return this._id.valueOf()
  10 + // NOTE: To allow `.sort('-created_at')` to work
  11 + // we need to have these as actual paths
  12 + Schema.add({
  13 + updated_at: Date,
  14 + created_at: Date
10 15 })
11 16
12   - Schema.add({
13   - updated: {
14   - default: Date.now,
15   - type: Date
16   - }
  17 + Schema.pre('save', function(next) {
  18 + this.updated_at = (!this.created_at) ? Date.now() : this._id.getTimestamp()
  19 + if (!this.created_at)
  20 + this.created_at = this._id.getTimestamp()
  21 + next()
17 22 })
18 23
19   - Schema.virtual('created').get(function() {
20   - return this._id.getTimestamp()
  24 + Schema.set('toObject', {
  25 + virtuals: true,
  26 + getters: true
21 27 })
22 28
23   - Schema.pre('save', function(next) {
24   - this.updated = Date.now()
25   - next()
  29 + Schema.set('toJSON', {
  30 + virtuals: true,
  31 + getters: true
26 32 })
27 33
  34 + Schema.plugin(jsonSelect, '-_id -__v')
  35 +
28 36 }
... ...
1 1
2   -// # user
  2 +// # models - user
3 3
4   -var mongoose = require('mongoose'),
5   - common = require('./common'),
6   - Schema = mongoose.Schema,
7   - mongooseTypes = require('mongoose-types')
  4 +var mongoose = require('mongoose')
  5 +var common = require('./common')
  6 +var Schema = mongoose.Schema
  7 +var mongooseTypes = require('nifty-mongoose-types')
  8 +var jsonSelect = require('mongoose-json-select')
  9 +var passportLocalMongoose = require('passport-local-mongoose')
8 10
9 11 mongooseTypes.loadTypes(mongoose)
10 12
... ... @@ -20,4 +22,18 @@ var User = new Schema({
20 22
21 23 User.plugin(common)
22 24
23   -module.exports = User;
\ No newline at end of file
  25 +User.virtual('type').get(function() {
  26 + return 'User'
  27 +})
  28 +
  29 +User.plugin(common)
  30 +
  31 +User.plugin(passportLocalMongoose, {
  32 + usernameField: 'email',
  33 + usernameLowerCase: true,
  34 + userExistsError: 'User already exists with email %s'
  35 +})
  36 +
  37 +User.plugin(jsonSelect, '-_group -salt -hash')
  38 +
  39 +module.exports = User
... ...
1   -doctype html
2   -<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
3   -<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
4   -<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
5   -<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
6   -head
7 1
8   - meta(charset="utf-8")
9   - meta(http-equiv="X-UA-Compatible", content="IE=edge,chrome=1")
  2 +//- # views - home
10 3
11   - title Igloo
  4 +extends layout
12 5
13   - meta(name="description", content="")
14   - meta(name="viewport", content="width=device-width, initial-scale=1")
15   -
16   - link(rel="stylesheet", href="/css/bootstrap.min.css")
17   - link(rel="stylesheet", href="/css/bootstrap-theme.min.css")
18   -
19   - script(src="/js/vendor/modernizr-2.6.2-respond-1.1.0.min.js")
20   -
21   - // todo: add your stylesheets here
22   -
23   -body
24   - <!--[if lt IE 7]>
25   - p.browsehappy
26   - | You are using an
27   - strong outdated
28   - | browser. Please
29   - a(href="http://browsehappy.com/") upgrade your browser
30   - | to improve your experience.
31   - <!--[endif]-->
32   -
33   - // real thing
34   -
35   - div.container
36   - div.col-md-12
37   - div.igloo-intro(style='padding: 60px 15px; text-align: center;')
38   - h1 Welcome to Igloo!
39   - img(src='/img/igloo.png', alt='Igloo', style='padding: 40px;', onclick='bootbox.alert("Hey! This is BootBox!")')
40   -
41   - p Igloo is a minimal app boilerplate built with Express.
42   -
43   - - var igloo = 'https://github.com/niftylettuce/igloo'
44   - p: a(href=igloo)= igloo
45   -
46   -
47   -
48   - // scripts
49   -
50   - script(src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js")
51   - script.
52   - window.jQuery || document.write('<script src="js/vendor/jquery-1.11.0.min.js"><\\/script>')
53   - script(src="/js/vendor/bootstrap.min.js")
54   - script(src="/js/vendor/bootbox.min.js")
55   -
56   - script(src="/js/plugins.js")
57   - script(src="/js/main.js")
58   -
59   - // todo: add your scripts here
60   -
61   -
62   -
63   - // Google Analytics: change UA-XXXXX-X to be your site's ID.
64   - script.
65   - (function(b,o,i,l,e,r){b.GoogleAnalyticsObject=l;b[l]||(b[l]=
66   - function(){(b[l].q=b[l].q||[]).push(arguments)});b[l].l=+new Date;
67   - e=o.createElement(i);r=o.getElementsByTagName(i)[0];
68   - e.src='//www.google-analytics.com/analytics.js';
69   - r.parentNode.insertBefore(e,r)}(window,document,'script','ga'));
70   - ga('create','UA-XXXXX-X');ga('send','pageview');
71   -
72   - // the line below closes html element opened in IE conditional comments
73   -</html>
  6 +block content
  7 + .container
  8 + .row
  9 + .col-md-12
  10 + .igloo-intro(style='padding: 60px 15px; text-align: center;')
  11 + h1 Welcome to Igloo!
  12 + img(src='/img/igloo.png', alt='Igloo', style='padding: 40px;', onclick='bootbox.alert("Hey! This is BootBox!")')
  13 + p Igloo is a lightweight, fast, and minimal framework for rapid development
  14 + - var igloo = 'http://igloojs.com'
  15 + p: a(href=igloo)= igloo
... ...
  1 +
  2 +//- # views - layout
  3 +
  4 +doctype
  5 +html.no-js
  6 + head
  7 + title Igloo
  8 + block meta
  9 + meta(charset='utf-8')
  10 + meta(http-equiv='X-UA-Compatible', content='IE=edge,chrome=1')
  11 + meta(name='description', content='')
  12 + meta(name='viewport', content='width=device-width, initial-scale=1')
  13 + block stylesheets
  14 + link(rel='stylesheet', href='/css/bootstrap.min.css')
  15 + link(rel='stylesheet', href='/css/bootstrap-theme.min.css')
  16 + link(rel='stylesheet', href='/css/style.css')
  17 + script(src='/js/vendor/modernizr-2.6.2-respond-1.1.0.min.js')
  18 + body
  19 +
  20 + //- Browse Happy
  21 + //- <http://browsehappy.com/>
  22 + != "<!--[if lt IE 8]>"
  23 + p.browsehappy
  24 + = 'You are using an '
  25 + strong outdated
  26 + = ' browser. Please '
  27 + a(href="http://browsehappy.com/") upgrade your browser
  28 + = ' to improve your experience.'
  29 + != "<!--<![endif]-->"
  30 +
  31 + block content
  32 + block scripts
  33 + script(src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js")
  34 + script.
  35 + window.jQuery || document.write('<script src="js/vendor/jquery-1.11.0.min.js"><\\/script>')
  36 + script(src="/js/vendor/bootstrap.min.js")
  37 + script(src="/js/vendor/bootbox.min.js")
  38 + script(src="/js/plugins.js")
  39 + script(src="/js/main.js")
  40 + script(src='/js/ga.js')
... ...
  1 +
  2 +/* Browse Happy prompt */
  3 +
  4 +.browsehappy {
  5 + margin: 0.2em 0;
  6 + background: #ccc;
  7 + color: #000;
  8 + padding: 0.2em 0;
  9 +}
... ...
  1 +// Google Analytics: change UA-XXXXX-X to be your site's ID.
  2 +(function(b,o,i,l,e,r){b.GoogleAnalyticsObject=l;b[l]||(b[l]=
  3 +function(){(b[l].q=b[l].q||[]).push(arguments)});b[l].l=+new Date;
  4 +e=o.createElement(i);r=o.getElementsByTagName(i)[0];
  5 +e.src='//www.google-analytics.com/analytics.js';
  6 +r.parentNode.insertBefore(e,r)}(window,document,'script','ga'));
  7 +ga('create','UA-XXXXX-X');ga('send','pageview');
... ...
1   -
2   -// # cluster
3   -
4   -// TODO: <http://nodejs.org/api/cluster.html>
1 1
2   -// # app
  2 +// # config - app
3 3
4 4 var express = require('express')
5 5 var flash = require('connect-flash')
6 6 var dynamicHelpers = require('./dynamic-helpers')
7 7 var development = require('./development')
8 8 var production = require('./production')
9   -var auth = require('./auth')
  9 +var passport = require('passport')
10 10 var settings = require('./settings')
11 11 var routes = require('./routes')
12 12 var ioc = require('electrolyte')
... ... @@ -16,8 +16,8 @@ var errorHandler = require('errorhandler')
16 16 var serveFavicon = require('serve-favicon')
17 17 var cookieParser = require('cookie-parser')
18 18 var bodyParser = require('body-parser')
19   -var dataNode = require('../lib/dataNode')
20   -
  19 +var dataNode = require('../lib/data-node')
  20 +var helmet = require('helmet')
21 21
22 22 module.exports = function(lib, callback) {
23 23
... ... @@ -50,18 +50,20 @@ module.exports = function(lib, callback) {
50 50 // make jade pretty
51 51 app.locals.pretty = true
52 52
  53 + // use helmet for security
  54 + app.use(helmet.defaults())
  55 +
53 56 // ignore GET /favicon.ico
54 57 app.use(serveFavicon(lib.config.favicon))
55 58
56   - // development only config
  59 + // environment configs
57 60 switch(lib.config.env){
58 61 case 'development':
59   - development(lib, app);
60   - break;
61   -
  62 + development(lib, app)
  63 + break
62 64 case 'production':
63 65 production(lib, app)
64   - break;
  66 + break
65 67 }
66 68
67 69 // pass a secret to cookieParser() for signed cookies
... ... @@ -75,15 +77,28 @@ module.exports = function(lib, callback) {
75 77
76 78 // add req.session cookie support
77 79 app.use(session(lib.config.session))
78   -
  80 +
79 81 // add flash message support
80 82 app.use(flash())
81 83
82 84 // add dynamic helpers for views
83   - app.use(dynamicHelpers)
  85 + app.use(function(req, res, next) {
  86 + res.locals.req = req
  87 + res.locals.messages = {
  88 + success: req.flash('success'),
  89 + error: req.flash('error'),
  90 + info: req.flash('info'),
  91 + warning: req.flash('warning')
  92 + }
  93 + next()
  94 + })
84 95
85 96 // add support for authentication
86   - auth(lib, app)()
  97 + app.use(passport.initialize())
  98 + app.use(passport.session())
  99 + passport.use(lib.db.model('User').createStrategy())
  100 + passport.serializeUser(lib.db.model('User').serializeUser())
  101 + passport.deserializeUser(lib.db.model('User').deserializeUser())
87 102
88 103 // load the routes
89 104 routes(lib, app)()
... ... @@ -94,9 +109,12 @@ module.exports = function(lib, callback) {
94 109 // error handling
95 110 app.use(errorHandler())
96 111
97   -
98 112 callback(null, app)
99 113
100   - return {app: app, lib: lib}
  114 + return {
  115 + app: app,
  116 + lib: lib
  117 + }
  118 +
101 119 }
102 120
... ...
1   -
2   -// # auth
3   -
4   -var passport = require('passport')
5   -var lib, app
6   -
7   -module.exports = function(_lib, _app) {
8   - lib = _lib
9   - app = _app
10   - return auth
11   -}
12   -
13   -function auth() {
14   -
15   - app.use(passport.initialize())
16   - app.use(passport.session())
17   -
18   - passport.serializeUser(serializeUser)
19   - passport.deserializeUser(deserializeUser)
20   -
21   - // TODO: add your passport auth here
22   -
23   -}
24   -
25   -function serializeUser(user, done) {
26   - done(null, user.id)
27   -}
28   -
29   -function deserializeUser(id, done) {
30   - lib.db.model('User').findById(id, function(err, user) {
31   - done(err, user)
32   - })
33   -}
34   -
35   -
36   -
37   -
1   -
2   -// # dynamic helpers
3   -
4   -module.exports = function(req, res, next) {
5   - res.locals.req = req
6   - res.locals.messages = {
7   - success: req.flash('success'),
8   - error: req.flash('error'),
9   - info: req.flash('info'),
10   - warning: req.flash('warning')
11   - }
12   - next()
13   -}
1   -/**
2   - * Add following code to auth() function in
3   - * ./config/auth.js
4   - *
5   - * It's better to keep 'returnURL' and 'realm'
6   - * in settings.
7   - */
8   -
9   -
10   -var GoogleStrategy = require('passport-google').Strategy
11   -
12   -passport.use( new GoogleStrategy({
13   - returnURL: 'http://localhost:3000/auth/google/callback',
14   - realm: 'http://localhost:3000',
15   - passReqToCallback: true
16   - },
17   - function(req, identifier, profile, done) {
18   -
19   - var email = profile.emails[ 0 ].value
20   - var User = lib.db.model('User')
21   -
22   - // save user
23   - User.findOne({
24   - email: email
25   - }, function( err, user ) {
26   -
27   - if (!user) {
28   - User.create({
29   - email: email,
30   - name: profile.displayName,
31   - }, function(err, user) {
32   -
33   - // Update lastToken
34   - user.lastToken = identifier
35   - user.save()
36   - return done( err, user )
37   - });
38   -
39   - } else {
40   - // Update lastToken
41   - user.lastToken = identifier
42   - user.save()
43   - return done( err, user )
44   - }
45   -
46   - });
  1 +
  2 +// # examples - auth - google
  3 +
  4 +/*globals lib*/
  5 +
  6 +// Add to `config/app.js`:
  7 +
  8 +var randomstring = require('randomstring-extended')
  9 +var passport = require('passport')
  10 +var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy
  11 +
  12 +passport.use(new GoogleStrategy({
  13 + callbackURL: lib.config.url + '/auth/google/callback',
  14 + clientID: lib.config.google.clientID,
  15 + clientSecret: lib.config.google.clientSecret
  16 +}, authCallback))
  17 +
  18 +function authCallback(token, tokenSecret, profile, done) {
  19 +
  20 + lib.db.model('User').findOne({
  21 + email: profile._json.email
  22 + }, findUserByEmail)
  23 +
  24 + function findUserByEmail(err, user) {
  25 + if (err) return done(err)
  26 + if (user) return done(null, user)
  27 + user = {
  28 + email: profile._json.email,
  29 + name: profile.name.givenName,
  30 + surname: profile.name.familyName
  31 + }
  32 + if (profile.provider === 'google') {
  33 + user.google_access_token = token
  34 + user.avatar_url = profile._json.picture
  35 + }
  36 + lib.db.model('User').register(user, randomstring.token(), findUserByEmail)
47 37 }
48   -));
\ No newline at end of file
  38 +
  39 +}
... ...
1   -/**
2   - * Add following code to routes() function in
3   - * your ./config/routes.js file.
4   - */
5 1
6   -var passport = require('passport')
7   -
8   -// auth route
9   -
10   -app.get('/auth/google', function(req,res,next) {
11   - // add remember me details etc. here
12   - next()
13   - },
14   - passport.authenticate('google', { failureRedirect: '/', failureFlash: true }),
15   - function(req, res) {
16   - res.redirect('/')
17   - });
18   -
19   -// auth callback
  2 +// # examples - auth - google
20 3
21   -app.get('/auth/google/callback',
22   - passport.authenticate( 'google', {
23   - failureRedirect: '/'
24   - }),
25   - function(req, res, next) {
26   - var redirectTo = req.session.redirectTo;
  4 +/*globals app,lib*/
27 5
28   - // Successful authentication, redirect to dashboard page.
29   - if ( redirectTo ) {
30   - req.session.redirectTo = null
31   - res.redirect(redirectTo)
32   - } else {
33   - res.redirect('/logged-in')
34   - }
35   - }
36   -);
  6 +// Add to `config/routes.js`:
37 7
38   -// log out
39   -
40   -app.get('/logout', function(req, res){
41   - req.logout()
42   - res.redirect('/')
43   -});
44   -
45   -// sample log-in message
46   -
47   -app.get('/logged-in', function(req, res){
48   - req.send(200, 'Hey!')
49   -});
\ No newline at end of file
  8 +var passport = require('passport')
  9 +var ensureLoggedIn = require('connect-ensure-login').ensureLoggedIn
  10 +var ensureLoggedOut = require('connect-ensure-login').ensureLoggedOut
  11 +
  12 +// google oauth
  13 +app.get('/auth/google', ensureLoggedOut(), passport.authenticate('google', {
  14 + scope: lib.config.google.scope
  15 +}))
  16 +app.get('/auth/google/callback', ensureLoggedOut(), passport.authenticate('google', {
  17 + successFlash: true,
  18 + successReturnToOrRedirect: '/',
  19 + failureFlash: true,
  20 + failureRedirect: '/login'
  21 +}))
... ...
... ... @@ -34,6 +34,6 @@ if (!module.parent)
34 34 igloo(function(err, app) {
35 35 if (err) return lib.logger.error(err)
36 36 app.listen(config.port, function() {
37   - lib.logger.info('Igloo started at %s://%s:%d', config.protocol, config.host, config.port)
  37 + lib.logger.info('igloo started at %s://%s:%d', config.protocol, config.host, config.port)
38 38 })
39 39 })
... ...
  1 +
  2 +//
  3 +// # data node
  4 +//
  5 +// This is the missing data injection functionality in
  6 +// electrolyte. Based on electrolyte/loaders/node.js, the
  7 +// default script loader.
  8 +//
  9 +
  10 +var _ = require('underscore')
  11 +
  12 +module.exports = function(data, options) {
  13 +
  14 + if (_.isString(options))
  15 + options = {
  16 + dirname: options
  17 + }
  18 +
  19 + return function(id) {
  20 +
  21 + var newId = null
  22 +
  23 + if (id) {
  24 + var dir = options.dirname + '/'
  25 + if (id.indexOf(dir) === 0)
  26 + newId = id.substr(dir.length)
  27 + }
  28 +
  29 + if (newId)
  30 + return data[newId]
  31 +
  32 + return data
  33 +
  34 + }
  35 +
  36 +}
... ...
1   -
2   -/**
3   - * This is the missing data injection functionality in
4   - * electrolyte. Based on electrolyte/loaders/node.js, the
5   - * default script loader.
6   - *
7   - */
8   -
9   -module.exports = function(data, options) {
10   - if ('string' == typeof options) {
11   - options = { dirname: options }
12   - }
13   -
14   - return function(id) {
15   -
16   - var newId = null;
17   -
18   - if(id){
19   - var dir = options.dirname + '/'
20   -
21   - if(id.indexOf(dir) === 0)
22   - newId = id.substr(dir.length)
23   - }
24   -
25   - if(newId)
26   - return data[newId]
27   - else
28   - return data
29   - }
30   -}
... ... @@ -3,10 +3,10 @@
3 3
4 4 module.exports = function(config) {
5 5 var lib = {
6   - mongo: require('./mongo')(config),
7   - redis: require('./redis')(config),
  6 + config: config,
8 7 logger: require('./logger')
9 8 }
10   - lib.config = config
  9 + lib.mongo = require('./mongo')(lib)
  10 + lib.redis = require('./redis')(lib)
11 11 return lib
12 12 }
... ...
... ... @@ -3,22 +3,23 @@
3 3
4 4 var mongoose = require('mongoose')
5 5
6   -var config
  6 +var lib
7 7
8   -module.exports = function(_config) {
9   - config = _config
  8 +module.exports = function(_lib) {
  9 + lib = _lib
10 10 return mongo
11 11 }
12 12
13 13 function mongo(callback) {
14 14 var connection = mongoose.createConnection(
15   - config.db.host,
16   - config.db.dbname,
17   - config.db.port,
18   - config.db.opts
  15 + lib.config.db.host,
  16 + lib.config.db.dbname,
  17 + lib.config.db.port,
  18 + lib.config.db.opts
19 19 )
20   - connection.on('error', callback)
  20 + connection.on('error', lib.logger.error)
21 21 connection.on('open', function() {
22   - callback(null, connection)
  22 + lib.logger.info('mongo connection opened')
23 23 })
  24 + callback(null, connection)
24 25 }
... ...
... ... @@ -5,17 +5,18 @@ var express = require('express')
5 5 var session = require('express-session')
6 6 var RedisStore = require('connect-redis')(session)
7 7
8   -var config
  8 +var lib
9 9
10   -module.exports = function(_config) {
11   - config = _config
  10 +module.exports = function(_lib) {
  11 + lib = _lib
12 12 return redis
13 13 }
14 14
15 15 function redis(callback) {
16   - var connection = new RedisStore(config.redis)
17   - connection.on('error', callback)
  16 + var connection = new RedisStore(lib.config.redis)
  17 + connection.on('error', lib.logger.error)
18 18 connection.on('connect', function() {
19   - callback(null, connection)
  19 + lib.logger.info('redis connected')
20 20 })
  21 + callback(null, connection)
21 22 }
... ...
1 1 {
2 2 "name": "igloo",
3 3 "version": "0.0.1",
4   - "description": "Igloo is a minimal app boilerplate built with Express.",
  4 + "description": "Igloo is a lightweight, fast, and minimal framework for rapid development",
5 5 "main": "igloo.js",
6 6 "repository": {
7 7 "type": "git",
... ... @@ -17,26 +17,28 @@
17 17 "license": "MIT",
18 18 "homepage": "https://github.com/niftylettuce/igloo",
19 19 "dependencies": {
20   - "passport": "~0.2.0",
  20 + "async": "~0.2.10",
  21 + "body-parser": "~1.2.0",
  22 + "connect-flash": "~0.1.1",
  23 + "connect-redis": "~2.0.0",
  24 + "cookie-parser": "~1.1.0",
  25 + "electrolyte": "*",
  26 + "errorhandler": "~1.0.1",
  27 + "express": "~4.2.0",
21 28 "express-rate": "0.0.1",
  29 + "express-session": "~1.1.0",
22 30 "jade": "~1.1.5",
23   - "express": "~4.2.0",
  31 + "less-middleware": "~0.1.15",
  32 + "method-override": "~1.0.1",
24 33 "mongoose": "~3.8.7",
25   - "connect-redis": "~2.0.0",
  34 + "mongoose-json-select": "^0.2.1",
  35 + "nifty-mongoose-types": "0.0.1",
  36 + "passport": "~0.2.0",
  37 + "passport-local-mongoose": "^0.3.0",
  38 + "serve-favicon": "~2.0.0",
26 39 "underscore": "~1.6.0",
27   - "async": "~0.2.10",
28 40 "winston": "~0.7.2",
29   - "mongoose-types": "~1.0.3",
30   - "less-middleware": "~0.1.15",
31   - "connect-flash": "~0.1.1",
32 41 "winston-mongodb": "~0.4.3",
33   - "winston-request-logger": "~1.0.4",
34   - "electrolyte": "*",
35   - "express-session": "~1.1.0",
36   - "method-override": "~1.0.1",
37   - "cookie-parser": "~1.1.0",
38   - "errorhandler": "~1.0.1",
39   - "body-parser": "~1.2.0",
40   - "serve-favicon": "~2.0.0"
  42 + "winston-request-logger": "~1.0.4"
41 43 }
42 44 }
... ...
注册登录 后发表评论