├── examples └── login │ ├── views │ ├── login.ejs │ ├── index.ejs │ ├── account.ejs │ └── layout.ejs │ ├── package.json │ ├── app.js │ └── package-lock.json ├── renovate.json ├── .github └── FUNDING.yml ├── .gitignore ├── test ├── bootstrap │ └── node.js ├── package.test.js └── strategy.test.js ├── Makefile ├── lib ├── index.js └── strategy.js ├── .travis.yml ├── .npmignore ├── package.json ├── LICENSE └── README.md /examples/login/views/login.ejs: -------------------------------------------------------------------------------- 1 | Login with Weibo 2 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: xinbenlv 2 | patreon: xinbenlv 3 | ko_fi: xinbenlv 4 | issuehunt: xinbenlv 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Mac OS X 2 | .DS_Store 3 | 4 | # Node.js 5 | node_modules 6 | npm-debug.log 7 | 8 | 9 | .idea 10 | -------------------------------------------------------------------------------- /test/bootstrap/node.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | 3 | chai.use(require('chai-passport-strategy')); 4 | 5 | global.expect = chai.expect; 6 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include node_modules/make-node/main.mk 2 | 3 | MOCHAFLAGS = --require ./test/bootstrap/node 4 | 5 | # Perform self-tests. 6 | check: test 7 | -------------------------------------------------------------------------------- /examples/login/views/index.ejs: -------------------------------------------------------------------------------- 1 | <% if (!user) { %> 2 |

Welcome! Please log in.

3 | <% } else { %> 4 |

Hello, <%= user.displayName %>.

5 | <% } %> 6 | -------------------------------------------------------------------------------- /examples/login/views/account.ejs: -------------------------------------------------------------------------------- 1 |

ID: <%= user.id %>

2 |

Username: <%= user.username %>

3 |

Name: <%= user.displayName %>

4 |

Email: <%= user.emails[0].value %>

5 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | // Load modules. 2 | var Strategy = require('./strategy'); 3 | 4 | 5 | // Expose Strategy. 6 | exports = module.exports = Strategy; 7 | 8 | // Exports. 9 | exports.Strategy = Strategy; 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: "node_js" 2 | node_js: 3 | - 8 4 | - 9 5 | - 10 6 | - 11 7 | - 12 8 | - node # Current stable, i.e. 13 in October, 2019 9 | - lts/* # Most recent LTS version, i.e. 12 in October, 2019 10 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | README.md 2 | Makefile 3 | doc/ 4 | examples/ 5 | test/ 6 | 7 | # Mac OS X 8 | .DS_Store 9 | 10 | # Node.js 11 | .npmignore 12 | node_modules/ 13 | npm-debug.log 14 | 15 | # Git 16 | .git* 17 | 18 | .idea/ 19 | renovate.json 20 | .travis.yml 21 | .github/ 22 | -------------------------------------------------------------------------------- /examples/login/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "passport-weibo-examples-login", 3 | "version": "0.2.0-beta.0", 4 | "scripts": { 5 | "start": "node app.js" 6 | }, 7 | "dependencies": { 8 | "ejs": ">= 2.5.2", 9 | "express": "3.12.0", 10 | "passport": ">= 0.3.2", 11 | "passport-weibo": ">= 0.2.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/login/views/layout.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Passport-Weibo Example 5 | 6 | 7 | <% if (!user) { %> 8 |

9 | Home | 10 | Log In 11 |

12 | <% } else { %> 13 |

14 | Home | 15 | Account | 16 | Log Out 17 |

18 | <% } %> 19 | <%- body %> 20 | 21 | 22 | -------------------------------------------------------------------------------- /test/package.test.js: -------------------------------------------------------------------------------- 1 | /* global describe, it, expect */ 2 | 3 | var strategy = require('..'); 4 | 5 | describe('passport-weibo', function() { 6 | 7 | it('should export Strategy constructor', function() { 8 | expect(strategy.Strategy).to.be.a('function'); 9 | }); 10 | 11 | it('should export Strategy constructor as module', function() { 12 | expect(strategy).to.be.a('function'); 13 | expect(strategy).to.equal(strategy.Strategy); 14 | }); 15 | 16 | }); 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "passport-weibo", 3 | "version": "1.0.0-beta.0", 4 | "description": "Weibo authentication strategy for PassportJS. Supports Weibo API 2.0", 5 | "keywords": [ 6 | "passport", 7 | "weibo", 8 | "auth", 9 | "authn", 10 | "authentication", 11 | "identity" 12 | ], 13 | "main": "./lib", 14 | "repository": { 15 | "type": "git", 16 | "url": "http://github.com/xinbenlv/passport-weibo.git" 17 | }, 18 | "bugs": { 19 | "url": "http://github.com/xinbenlv/passport-weibo/issues" 20 | }, 21 | "author": { 22 | "name": "Zainan Victor Zhou", 23 | "email": "zzn@zzn.im", 24 | "url": "http://www.zzn.im/" 25 | }, 26 | "license": "MIT", 27 | "dependencies": { 28 | "passport-oauth2": "^1.5.0" 29 | }, 30 | "devDependencies": { 31 | "chai": "4.2.0", 32 | "chai-passport-strategy": "1.0.1", 33 | "make-node": "0.4.6", 34 | "mocha": "7.0.0" 35 | }, 36 | "scripts": { 37 | "test": "make test" 38 | }, 39 | "engines": { 40 | "node": ">=8" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2013 Zainan Victor Zhou 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /test/strategy.test.js: -------------------------------------------------------------------------------- 1 | /* global describe, it, expect */ 2 | /* jshint expr: true */ 3 | 4 | var WeiboStrategy = require('../lib/strategy'); 5 | 6 | 7 | describe('Strategy', function() { 8 | 9 | var strategy = new WeiboStrategy({ 10 | clientID: 'ABC123', 11 | clientSecret: 'secret' 12 | }, 13 | function() {}); 14 | 15 | it('should be named weibo', function() { 16 | expect(strategy.name).to.equal('weibo'); 17 | }); 18 | 19 | it('should have default user agent', function() { 20 | expect(strategy._oauth2._customHeaders['User-Agent']).to.equal('passport-weibo'); 21 | }); 22 | 23 | 24 | describe('constructed with user agent option', function() { 25 | 26 | var strategy = new WeiboStrategy({ 27 | clientID: 'ABC123', 28 | clientSecret: 'secret', 29 | userAgent: 'example.com' 30 | }, 31 | function() {}); 32 | 33 | it('should have default user agent', function() { 34 | expect(strategy._oauth2._customHeaders['User-Agent']).to.equal('example.com'); 35 | }); 36 | }); 37 | 38 | describe('constructed with custom headers including user agent', function() { 39 | 40 | var strategy = new WeiboStrategy({ 41 | clientID: 'ABC123', 42 | clientSecret: 'secret', 43 | customHeaders: { 'User-Agent': 'example.net' } 44 | }, 45 | function() {}); 46 | 47 | it('should have default user agent', function() { 48 | expect(strategy._oauth2._customHeaders['User-Agent']).to.equal('example.net'); 49 | }); 50 | }); 51 | 52 | describe('constructed with both custom headers including user agent and user agent option', function() { 53 | 54 | var strategy = new WeiboStrategy({ 55 | clientID: 'ABC123', 56 | clientSecret: 'secret', 57 | customHeaders: { 'User-Agent': 'example.org' }, 58 | userAgent: 'example.net' 59 | }, 60 | function() {}); 61 | 62 | it('should have default user agent', function() { 63 | expect(strategy._oauth2._customHeaders['User-Agent']).to.equal('example.org'); 64 | }); 65 | }); 66 | 67 | }); 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Passport-Weibo 2 | 3 | [![Build Status](https://travis-ci.org/xinbenlv/passport-weibo.svg?branch=master)](https://travis-ci.org/xinbenlv/passport-weibo) 4 | 5 | [PassportJS](http://passportjs.org/) strategy for authenticating with Sina [Weibo](https://weibo.com/) 6 | using the OAuth 2.0 API. 7 | 8 | This module lets you authenticate using Weibo in your Node.js applications. 9 | By plugging into Passport, Weibo authentication can be easily and 10 | unobtrusively integrated into any application or framework that supports 11 | [Connect](http://www.senchalabs.org/connect/)-style middleware, including 12 | [Express](http://expressjs.com/). 13 | 14 | ## Install 15 | 16 | $ npm install passport-weibo --save 17 | 18 | ## Usage 19 | 20 | #### Configure Strategy 21 | 22 | The Weibo authentication strategy authenticates users using a Weibo account 23 | and OAuth 2.0 tokens. The strategy requires a `verify` callback, which accepts 24 | these credentials and calls `done` providing a user, as well as `options` 25 | specifying a client ID, client secret, and callback URL. 26 | 27 | passport.use(new WeiboStrategy({ 28 | clientID: WEIBO_CLIENT_ID, 29 | clientSecret: WEIBO_CLIENT_SECRET, 30 | callbackURL: "http://127.0.0.1:3000/auth/weibo/callback" 31 | }, 32 | function(accessToken, refreshToken, profile, done) { 33 | User.findOrCreate({ weiboId: profile.id }, function (err, user) { 34 | return done(err, user); 35 | }); 36 | } 37 | )); 38 | 39 | #### Authenticate Requests 40 | 41 | Use `passport.authenticate()`, specifying the `'weibo'` strategy, to 42 | authenticate requests. 43 | 44 | For example, as route middleware in an [Express](http://expressjs.com/) 45 | application: 46 | 47 | app.get('/auth/weibo', 48 | passport.authenticate('weibo')); 49 | 50 | app.get('/auth/weibo/callback', 51 | passport.authenticate('weibo', { failureRedirect: '/login' }), 52 | function(req, res) { 53 | // Successful authentication, redirect home. 54 | res.redirect('/'); 55 | }); 56 | 57 | ## Examples 58 | 59 | For a complete, working example, refer to the [login example](https://github.com/xinbenlv/passport-weibo/tree/master/examples/login). 60 | 61 | ## Tests 62 | 63 | $ npm install --dev 64 | $ make test 65 | 66 | 67 | 68 | ## Credits 69 | 70 | - [Jared Hanson](http://github.com/jaredhanson) for `passport-github` 71 | - [Zainan Victor Zhou](http://github.com/xinbenv) 72 | 73 | 74 | ## License 75 | 76 | [The MIT License](http://opensource.org/licenses/MIT) 77 | 78 | Copyright (c) 2013 Zainan Victor Zhou <[http://zzn.im/](http://www.zzn.im/)> 79 | 80 | -------------------------------------------------------------------------------- /lib/strategy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | var util = require('util') 5 | , OAuth2Strategy = require('passport-oauth2') 6 | , InternalOAuthError = require('passport-oauth2').InternalOAuthError; 7 | 8 | 9 | /** 10 | * `Strategy` constructor. 11 | * 12 | * The Weibo authentication strategy authenticates requests by delegating to 13 | * Weibo using the OAuth 2.0 protocol. 14 | * 15 | * Applications must supply a `verify` callback which accepts an `accessToken`, 16 | * `refreshToken` and service-specific `profile`, and then calls the `done` 17 | * callback supplying a `user`, which should be set to `false` if the 18 | * credentials are not valid. If an exception occured, `err` should be set. 19 | * 20 | * Options: 21 | * - `clientID` your Weibo application's Client ID 22 | * - `clientSecret` your Weibo application's Client Secret 23 | * - `callbackURL` URL to which Weibo will redirect the user after granting authorization 24 | * - `scope` array of permission scopes to request. valid scopes include: 25 | * 'user', 'public_repo', 'repo', 'gist', or none. 26 | * (see http://open.weibo.com/wiki/Oauth/en#User_Authentication for more info) 27 | * 28 | * Examples: 29 | * 30 | * passport.use(new WeiboStrategy({ 31 | * clientID: '123-456-789', 32 | * clientSecret: 'shhh-its-a-secret' 33 | * callbackURL: 'https://www.example.net/auth/weibo/callback' 34 | * }, 35 | * function(accessToken, refreshToken, profile, done) { 36 | * User.findOrCreate(..., function (err, user) { 37 | * done(err, user); 38 | * }); 39 | * } 40 | * )); 41 | * 42 | * @param {Object} options 43 | * @param {Function} verify 44 | * @api public 45 | */ 46 | function Strategy(options, verify) { 47 | options = options || {}; 48 | options.authorizationURL = options.authorizationURL || 'https://api.weibo.com/oauth2/authorize'; 49 | options.tokenURL = options.tokenURL || 'https://api.weibo.com/oauth2/access_token'; 50 | options.scopeSeparator = options.scopeSeparator || ','; 51 | options.customHeaders = options.customHeaders || {}; 52 | if (!options.customHeaders['User-Agent']) { 53 | options.customHeaders['User-Agent'] = options.userAgent || 'passport-weibo'; 54 | } 55 | 56 | OAuth2Strategy.call(this, options, verify); 57 | this.name = 'weibo'; 58 | this._getuidAPI = options.getuidAPI || 'https://api.weibo.com/2/account/get_uid.json'; 59 | this._getProfileAPI = options.getProfileAPI || 'https://api.weibo.com/2/users/show.json'; 60 | 61 | } 62 | 63 | /** 64 | * Inherit from `OAuth2Strategy`. 65 | */ 66 | util.inherits(Strategy, OAuth2Strategy); 67 | 68 | 69 | /** 70 | * Retrieve user profile from Weibo. 71 | * 72 | * This function constructs a normalized profile, with the following properties: 73 | * 74 | * - `provider` always set to `weibo` 75 | * - `id` the user's Weibo ID 76 | * - `username` the user's Weibo username 77 | * - `displayName` the user's full name 78 | * - `profileUrl` the URL of the profile for the user on Weibo 79 | * - `emails` the user's email addresses 80 | * 81 | * @param {String} accessToken 82 | * @param {Function} done 83 | * @api protected 84 | */ 85 | Strategy.prototype.userProfile = function(accessToken, callback) { 86 | var self = this; 87 | this._oauth2.getProtectedResource(this._getuidAPI, accessToken, function(err, body, res) { 88 | if (err) return callback(new InternalOAuthError('', err)); 89 | 90 | try { 91 | var raw = JSON.parse(body); 92 | self._oauth2.getProtectedResource(self._getProfileAPI + '?uid=' + raw.uid, accessToken, function(err, body, res) { 93 | if (err) return callback(new InternalOAuthError('', err)); 94 | 95 | try { 96 | callback(null, self.formatProfile(JSON.parse(body))); // this is different with raw. 97 | } catch(e) { 98 | callback(e); 99 | } 100 | }) 101 | } catch(e) { 102 | callback(e); 103 | } 104 | }) 105 | } 106 | 107 | Strategy.prototype.formatProfile = function(raw) { 108 | var user = {}; 109 | user.provider = 'weibo'; 110 | user.id = raw.idstr; 111 | user.displayName = raw.screen_name || raw.name; 112 | user._raw = raw; 113 | user._json = raw; 114 | 115 | return user; 116 | }; 117 | 118 | /** 119 | * Expose `Strategy`. 120 | */ 121 | module.exports = Strategy; 122 | -------------------------------------------------------------------------------- /examples/login/app.js: -------------------------------------------------------------------------------- 1 | var express = require('express') 2 | , passport = require('passport') 3 | , util = require('util') 4 | , WeiboStrategy = require('../../').Strategy; 5 | 6 | var WEIBO_CLIENT_ID = "--CLIENT_ID--"; 7 | var WEIBO_CLIENT_SECRET = "--CLIENT_SECRET--"; 8 | 9 | 10 | // Passport session setup. 11 | // To support persistent login sessions, Passport needs to be able to 12 | // serialize users into and deserialize users out of the session. Typically, 13 | // this will be as simple as storing the user ID when serializing, and finding 14 | // the user by ID when deserializing. However, since this example does not 15 | // have a database of user records, the complete Weibo profile is serialized 16 | // and deserialized. 17 | passport.serializeUser(function(user, done) { 18 | done(null, user); 19 | }); 20 | 21 | passport.deserializeUser(function(obj, done) { 22 | done(null, obj); 23 | }); 24 | 25 | 26 | // Use the WeiboStrategy within Passport. 27 | // Strategies in Passport require a `verify` function, which accept 28 | // credentials (in this case, an accessToken, refreshToken, and Weibo 29 | // profile), and invoke a callback with a user object. 30 | passport.use(new WeiboStrategy({ 31 | clientID: WEIBO_CLIENT_ID, 32 | clientSecret: WEIBO_CLIENT_SECRET, 33 | callbackURL: "http://127.0.0.1:3000/auth/weibo/callback" 34 | }, 35 | function(accessToken, refreshToken, profile, done) { 36 | // asynchronous verification, for effect... 37 | process.nextTick(function () { 38 | 39 | // To keep the example simple, the user's Weibo profile is returned to 40 | // represent the logged-in user. In a typical application, you would want 41 | // to associate the Weibo account with a user record in your database, 42 | // and return that user instead. 43 | return done(null, profile); 44 | }); 45 | } 46 | )); 47 | 48 | 49 | 50 | 51 | var app = express.createServer(); 52 | 53 | // configure Express 54 | app.configure(function() { 55 | app.set('views', __dirname + '/views'); 56 | app.set('view engine', 'ejs'); 57 | app.use(express.logger()); 58 | app.use(express.cookieParser()); 59 | app.use(express.bodyParser()); 60 | app.use(express.methodOverride()); 61 | app.use(express.session({ secret: 'keyboard cat' })); 62 | // Initialize Passport! Also use passport.session() middleware, to support 63 | // persistent login sessions (recommended). 64 | app.use(passport.initialize()); 65 | app.use(passport.session()); 66 | app.use(app.router); 67 | app.use(express.static(__dirname + '/public')); 68 | }); 69 | 70 | 71 | app.get('/', function(req, res){ 72 | res.render('index', { user: req.user }); 73 | }); 74 | 75 | app.get('/account', ensureAuthenticated, function(req, res){ 76 | res.render('account', { user: req.user }); 77 | }); 78 | 79 | app.get('/login', function(req, res){ 80 | res.render('login', { user: req.user }); 81 | }); 82 | 83 | // GET /auth/weibo 84 | // Use passport.authenticate() as route middleware to authenticate the 85 | // request. The first step in Weibo authentication will involve redirecting 86 | // the user to weibo.com. After authorization, Weibo will redirect the user 87 | // back to this application at /auth/weibo/callback 88 | app.get('/auth/weibo', 89 | passport.authenticate('weibo'), 90 | function(req, res){ 91 | // The request will be redirected to Weibo for authentication, so this 92 | // function will not be called. 93 | }); 94 | 95 | // GET /auth/weibo/callback 96 | // Use passport.authenticate() as route middleware to authenticate the 97 | // request. If authentication fails, the user will be redirected back to the 98 | // login page. Otherwise, the primary route function function will be called, 99 | // which, in this example, will redirect the user to the home page. 100 | app.get('/auth/weibo/callback', 101 | passport.authenticate('weibo', { failureRedirect: '/login' }), 102 | function(req, res) { 103 | res.redirect('/'); 104 | }); 105 | 106 | app.get('/logout', function(req, res){ 107 | req.logout(); 108 | res.redirect('/'); 109 | }); 110 | 111 | app.listen(3000); 112 | 113 | 114 | // Simple route middleware to ensure user is authenticated. 115 | // Use this route middleware on any resource that needs to be protected. If 116 | // the request is authenticated (typically via a persistent login session), 117 | // the request will proceed. Otherwise, the user will be redirected to the 118 | // login page. 119 | function ensureAuthenticated(req, res, next) { 120 | if (req.isAuthenticated()) { return next(); } 121 | res.redirect('/login') 122 | } 123 | -------------------------------------------------------------------------------- /examples/login/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "passport-weibo-examples-login", 3 | "version": "0.2.0-beta.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.0.7", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.0.7.tgz", 10 | "integrity": "sha1-W1AftPBwQwmWTM2wSBclQSCNqxo=", 11 | "requires": { 12 | "mime-types": "~1.0.0", 13 | "negotiator": "0.4.7" 14 | } 15 | }, 16 | "any-promise": { 17 | "version": "1.3.0", 18 | "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", 19 | "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" 20 | }, 21 | "base64-url": { 22 | "version": "1.3.3", 23 | "resolved": "https://registry.npmjs.org/base64-url/-/base64-url-1.3.3.tgz", 24 | "integrity": "sha1-+LbFN/CaT8WMmcuG4LDpxhRhog8=" 25 | }, 26 | "basic-auth-connect": { 27 | "version": "1.0.0", 28 | "resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", 29 | "integrity": "sha1-/bC0OWLKe0BFanwrtI/hc9otISI=" 30 | }, 31 | "batch": { 32 | "version": "0.5.1", 33 | "resolved": "https://registry.npmjs.org/batch/-/batch-0.5.1.tgz", 34 | "integrity": "sha1-NqS6tZTAUP17UHvKDbMMLZKvT/I=" 35 | }, 36 | "body-parser": { 37 | "version": "1.4.3", 38 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.4.3.tgz", 39 | "integrity": "sha1-RyeVLP9K8Hc+76SyJsL0Ei9eI00=", 40 | "requires": { 41 | "bytes": "1.0.0", 42 | "depd": "0.3.0", 43 | "iconv-lite": "0.4.3", 44 | "media-typer": "0.2.0", 45 | "qs": "0.6.6", 46 | "raw-body": "1.2.2", 47 | "type-is": "1.3.1" 48 | } 49 | }, 50 | "buffer-crc32": { 51 | "version": "0.2.3", 52 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.3.tgz", 53 | "integrity": "sha1-u1RRnpXRB8vSQA520MqxRnM22SE=" 54 | }, 55 | "bytes": { 56 | "version": "1.0.0", 57 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", 58 | "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=" 59 | }, 60 | "commander": { 61 | "version": "1.3.2", 62 | "resolved": "https://registry.npmjs.org/commander/-/commander-1.3.2.tgz", 63 | "integrity": "sha1-io8w7GcKb91kr1LxkUuQfXnq1bU=", 64 | "requires": { 65 | "keypress": "0.1.x" 66 | } 67 | }, 68 | "compressible": { 69 | "version": "1.1.1", 70 | "resolved": "https://registry.npmjs.org/compressible/-/compressible-1.1.1.tgz", 71 | "integrity": "sha1-I7ceqQ6mxqZiiXAakYGCwk0HKe8=" 72 | }, 73 | "compression": { 74 | "version": "1.0.11", 75 | "resolved": "https://registry.npmjs.org/compression/-/compression-1.0.11.tgz", 76 | "integrity": "sha1-aXAM8e6JY0VDVqwZKm5ekeIyv/s=", 77 | "requires": { 78 | "accepts": "~1.0.7", 79 | "bytes": "1.0.0", 80 | "compressible": "~1.1.1", 81 | "debug": "1.0.4", 82 | "on-headers": "~1.0.0", 83 | "vary": "~1.0.0" 84 | }, 85 | "dependencies": { 86 | "debug": { 87 | "version": "1.0.4", 88 | "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.4.tgz", 89 | "integrity": "sha1-W5wla9VLbsAigxdvqKDt5tFUy/g=", 90 | "requires": { 91 | "ms": "0.6.2" 92 | } 93 | }, 94 | "on-headers": { 95 | "version": "1.0.2", 96 | "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", 97 | "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" 98 | }, 99 | "vary": { 100 | "version": "1.0.1", 101 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz", 102 | "integrity": "sha1-meSYFWaihhGN+yuBc1ffeZM3bRA=" 103 | } 104 | } 105 | }, 106 | "connect": { 107 | "version": "2.21.0", 108 | "resolved": "https://registry.npmjs.org/connect/-/connect-2.21.0.tgz", 109 | "integrity": "sha1-qdYY+WEXPgLB2PITEICilfj/I3s=", 110 | "requires": { 111 | "basic-auth-connect": "1.0.0", 112 | "body-parser": "1.4.3", 113 | "bytes": "1.0.0", 114 | "compression": "~1.0.8", 115 | "connect-timeout": "1.1.1", 116 | "cookie": "0.1.2", 117 | "cookie-parser": "1.3.1", 118 | "cookie-signature": "1.0.3", 119 | "csurf": "1.2.2", 120 | "debug": "1.0.2", 121 | "depd": "0.3.0", 122 | "errorhandler": "1.1.1", 123 | "express-session": "~1.5.0", 124 | "finalhandler": "0.0.2", 125 | "fresh": "0.2.2", 126 | "media-typer": "0.2.0", 127 | "method-override": "2.0.2", 128 | "morgan": "1.1.1", 129 | "multiparty": "3.2.9", 130 | "on-headers": "0.0.0", 131 | "parseurl": "1.0.1", 132 | "pause": "0.0.1", 133 | "qs": "0.6.6", 134 | "response-time": "2.0.0", 135 | "serve-favicon": "2.0.1", 136 | "serve-index": "~1.1.3", 137 | "serve-static": "1.2.3", 138 | "type-is": "1.3.1", 139 | "vhost": "2.0.0" 140 | } 141 | }, 142 | "connect-timeout": { 143 | "version": "1.1.1", 144 | "resolved": "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.1.1.tgz", 145 | "integrity": "sha1-bH4xyY8Kxo620TBfZ/IfWm6Q/QQ=", 146 | "requires": { 147 | "debug": "1.0.2", 148 | "on-headers": "0.0.0" 149 | } 150 | }, 151 | "cookie": { 152 | "version": "0.1.2", 153 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.2.tgz", 154 | "integrity": "sha1-cv7D0k5Io0Mgc9kMEmQgBQYQBLE=" 155 | }, 156 | "cookie-parser": { 157 | "version": "1.3.1", 158 | "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.1.tgz", 159 | "integrity": "sha1-ML/CkGoESJ1ZvLnjL5DbCOBLtR4=", 160 | "requires": { 161 | "cookie": "0.1.2", 162 | "cookie-signature": "1.0.3" 163 | } 164 | }, 165 | "cookie-signature": { 166 | "version": "1.0.3", 167 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.3.tgz", 168 | "integrity": "sha1-kc2ZfMUftkFZVzjGnNoCAyj1D/k=" 169 | }, 170 | "core-util-is": { 171 | "version": "1.0.2", 172 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 173 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 174 | }, 175 | "csrf-tokens": { 176 | "version": "2.0.0", 177 | "resolved": "https://registry.npmjs.org/csrf-tokens/-/csrf-tokens-2.0.0.tgz", 178 | "integrity": "sha1-yCEAP7i2rRe8l31v0ahL7cPtYZs=", 179 | "requires": { 180 | "base64-url": "1", 181 | "rndm": "1", 182 | "scmp": "~0.0.3", 183 | "uid-safe": "1" 184 | } 185 | }, 186 | "csurf": { 187 | "version": "1.2.2", 188 | "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.2.2.tgz", 189 | "integrity": "sha1-Lqny0/LWex4iUykOZ2tiGV3Ld1Y=", 190 | "requires": { 191 | "csrf-tokens": "~2.0.0" 192 | } 193 | }, 194 | "debug": { 195 | "version": "1.0.2", 196 | "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.2.tgz", 197 | "integrity": "sha1-OElZHBDM5khHbDx8Li40FttZY8Q=", 198 | "requires": { 199 | "ms": "0.6.2" 200 | } 201 | }, 202 | "depd": { 203 | "version": "0.3.0", 204 | "resolved": "https://registry.npmjs.org/depd/-/depd-0.3.0.tgz", 205 | "integrity": "sha1-Ecm8KOQlMl+9iziUC+/2n6UyaIM=" 206 | }, 207 | "ee-first": { 208 | "version": "1.0.3", 209 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.0.3.tgz", 210 | "integrity": "sha1-bJjECJq+y1p7hcGsRJqmA9Oz2r4=" 211 | }, 212 | "ejs": { 213 | "version": "3.0.1", 214 | "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.0.1.tgz", 215 | "integrity": "sha512-cuIMtJwxvzumSAkqaaoGY/L6Fc/t6YvoP9/VIaK0V/CyqKLEQ8sqODmYfy/cjXEdZ9+OOL8TecbJu+1RsofGDw==" 216 | }, 217 | "errorhandler": { 218 | "version": "1.1.1", 219 | "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.1.1.tgz", 220 | "integrity": "sha1-GN79Q22Mou/gotiGxcTW7m121pE=", 221 | "requires": { 222 | "accepts": "~1.0.4", 223 | "escape-html": "1.0.1" 224 | } 225 | }, 226 | "escape-html": { 227 | "version": "1.0.1", 228 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz", 229 | "integrity": "sha1-GBoobq05ejmpKFfPsdQwUuNWv/A=" 230 | }, 231 | "express": { 232 | "version": "3.12.0", 233 | "resolved": "https://registry.npmjs.org/express/-/express-3.12.0.tgz", 234 | "integrity": "sha1-jwDJvvb00Yb0pIGtgxhE3X1zM24=", 235 | "requires": { 236 | "buffer-crc32": "0.2.3", 237 | "commander": "1.3.2", 238 | "connect": "2.21.0", 239 | "cookie": "0.1.2", 240 | "cookie-signature": "1.0.3", 241 | "debug": "1.0.2", 242 | "depd": "0.3.0", 243 | "escape-html": "1.0.1", 244 | "fresh": "0.2.2", 245 | "media-typer": "0.2.0", 246 | "merge-descriptors": "0.0.2", 247 | "methods": "1.0.1", 248 | "mkdirp": "0.5.0", 249 | "parseurl": "1.0.1", 250 | "proxy-addr": "1.0.1", 251 | "range-parser": "1.0.0", 252 | "send": "0.4.3", 253 | "vary": "0.1.0" 254 | } 255 | }, 256 | "express-session": { 257 | "version": "1.5.2", 258 | "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.5.2.tgz", 259 | "integrity": "sha1-56Tr74ob/8EyMt0J/mq18DMeMw8=", 260 | "requires": { 261 | "buffer-crc32": "0.2.3", 262 | "cookie": "0.1.2", 263 | "cookie-signature": "1.0.4", 264 | "debug": "1.0.2", 265 | "depd": "0.3.0", 266 | "on-headers": "0.0.0", 267 | "uid-safe": "1.0.1", 268 | "utils-merge": "1.0.0" 269 | }, 270 | "dependencies": { 271 | "cookie-signature": { 272 | "version": "1.0.4", 273 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.4.tgz", 274 | "integrity": "sha1-Dt0iKG46ERuaKnDbNj6SXoZ/aso=" 275 | }, 276 | "uid-safe": { 277 | "version": "1.0.1", 278 | "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-1.0.1.tgz", 279 | "integrity": "sha1-W9FIRgouhPVPGT/SA1LIw9feasg=", 280 | "requires": { 281 | "base64-url": "1", 282 | "mz": "1" 283 | } 284 | } 285 | } 286 | }, 287 | "finalhandler": { 288 | "version": "0.0.2", 289 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.0.2.tgz", 290 | "integrity": "sha1-BgPYde6H1WeiZmkoFcyK1E/M7to=", 291 | "requires": { 292 | "debug": "1.0.2", 293 | "escape-html": "1.0.1" 294 | } 295 | }, 296 | "finished": { 297 | "version": "1.2.2", 298 | "resolved": "https://registry.npmjs.org/finished/-/finished-1.2.2.tgz", 299 | "integrity": "sha1-QWCOr639ZWg7RqEiC8Sx7D2u3Ng=", 300 | "requires": { 301 | "ee-first": "1.0.3" 302 | } 303 | }, 304 | "fresh": { 305 | "version": "0.2.2", 306 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.2.2.tgz", 307 | "integrity": "sha1-lzHc9WeMf660T7kDxPct9VGH+nc=" 308 | }, 309 | "iconv-lite": { 310 | "version": "0.4.3", 311 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.3.tgz", 312 | "integrity": "sha1-nniHeTt2nMaV6yLSVGpP0tebeh4=" 313 | }, 314 | "inherits": { 315 | "version": "2.0.4", 316 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 317 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 318 | }, 319 | "ipaddr.js": { 320 | "version": "0.1.2", 321 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-0.1.2.tgz", 322 | "integrity": "sha1-ah/T2FT1ACllw017vNm0qNSwRn4=" 323 | }, 324 | "isarray": { 325 | "version": "0.0.1", 326 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 327 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" 328 | }, 329 | "keypress": { 330 | "version": "0.1.0", 331 | "resolved": "https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz", 332 | "integrity": "sha1-SjGI1CkbZrT2XtuZ+AaqmuKTWSo=" 333 | }, 334 | "media-typer": { 335 | "version": "0.2.0", 336 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.2.0.tgz", 337 | "integrity": "sha1-2KBlITrf6qLnYyGitt2jb/YzWYQ=" 338 | }, 339 | "merge-descriptors": { 340 | "version": "0.0.2", 341 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-0.0.2.tgz", 342 | "integrity": "sha1-w2pSp4FDdRPFcnXzndnTF1FKyMc=" 343 | }, 344 | "method-override": { 345 | "version": "2.0.2", 346 | "resolved": "https://registry.npmjs.org/method-override/-/method-override-2.0.2.tgz", 347 | "integrity": "sha1-AFMSeMeXiWQL8n6X4mo6Wh98ynM=", 348 | "requires": { 349 | "methods": "1.0.1", 350 | "parseurl": "1.0.1", 351 | "vary": "0.1.0" 352 | } 353 | }, 354 | "methods": { 355 | "version": "1.0.1", 356 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.0.1.tgz", 357 | "integrity": "sha1-dbyRlD3/19oDfPPusO1zoAN80Us=" 358 | }, 359 | "mime": { 360 | "version": "1.2.11", 361 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", 362 | "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=" 363 | }, 364 | "mime-types": { 365 | "version": "1.0.0", 366 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.0.tgz", 367 | "integrity": "sha1-antKavLn2S+Xr+A/BHx4AejwAdI=" 368 | }, 369 | "minimist": { 370 | "version": "0.0.8", 371 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 372 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" 373 | }, 374 | "mkdirp": { 375 | "version": "0.5.0", 376 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", 377 | "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", 378 | "requires": { 379 | "minimist": "0.0.8" 380 | } 381 | }, 382 | "morgan": { 383 | "version": "1.1.1", 384 | "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.1.1.tgz", 385 | "integrity": "sha1-zeRdLoB+vMQ5dFhG6oA5LmkJgUY=", 386 | "requires": { 387 | "bytes": "1.0.0" 388 | } 389 | }, 390 | "ms": { 391 | "version": "0.6.2", 392 | "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", 393 | "integrity": "sha1-2JwhJMb9wTU9Zai3e/GqxLGTcIw=" 394 | }, 395 | "multiparty": { 396 | "version": "3.2.9", 397 | "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-3.2.9.tgz", 398 | "integrity": "sha1-xzNz6pwBLnd2zlvEDJNiZLa6LB4=", 399 | "requires": { 400 | "readable-stream": "~1.1.9", 401 | "stream-counter": "~0.2.0" 402 | } 403 | }, 404 | "mz": { 405 | "version": "1.3.0", 406 | "resolved": "https://registry.npmjs.org/mz/-/mz-1.3.0.tgz", 407 | "integrity": "sha1-BvCT/dmVagbTfhsegTROJ0eMQvA=", 408 | "requires": { 409 | "native-or-bluebird": "1", 410 | "thenify": "3", 411 | "thenify-all": "1" 412 | } 413 | }, 414 | "native-or-bluebird": { 415 | "version": "1.1.2", 416 | "resolved": "https://registry.npmjs.org/native-or-bluebird/-/native-or-bluebird-1.1.2.tgz", 417 | "integrity": "sha1-OSHhECMtHreQ89rGG7NwUxx9NW4=" 418 | }, 419 | "negotiator": { 420 | "version": "0.4.7", 421 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.7.tgz", 422 | "integrity": "sha1-pBYPcXfsgGc4Yx0NMFIyXaQqvcg=" 423 | }, 424 | "oauth": { 425 | "version": "0.9.15", 426 | "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", 427 | "integrity": "sha1-vR/vr2hslrdUda7VGWQS/2DPucE=" 428 | }, 429 | "on-headers": { 430 | "version": "0.0.0", 431 | "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-0.0.0.tgz", 432 | "integrity": "sha1-7igX+DRDJXhc2cLfKyQrvBfK9MQ=" 433 | }, 434 | "parseurl": { 435 | "version": "1.0.1", 436 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.0.1.tgz", 437 | "integrity": "sha1-Llfc5u/dN8NRhwEDCUTCK/OIt7Q=" 438 | }, 439 | "passport": { 440 | "version": "0.4.1", 441 | "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz", 442 | "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==", 443 | "requires": { 444 | "passport-strategy": "1.x.x", 445 | "pause": "0.0.1" 446 | } 447 | }, 448 | "passport-oauth": { 449 | "version": "0.1.15", 450 | "resolved": "https://registry.npmjs.org/passport-oauth/-/passport-oauth-0.1.15.tgz", 451 | "integrity": "sha1-+3Tgr+hGFL+iVsX8cWzFa7/IzsA=", 452 | "requires": { 453 | "oauth": "0.9.x", 454 | "passport": "~0.1.1", 455 | "pkginfo": "0.2.x" 456 | }, 457 | "dependencies": { 458 | "passport": { 459 | "version": "0.1.18", 460 | "resolved": "https://registry.npmjs.org/passport/-/passport-0.1.18.tgz", 461 | "integrity": "sha1-yCZEedy2QUytu2Z1LRKzfgtlJaE=", 462 | "requires": { 463 | "pause": "0.0.1", 464 | "pkginfo": "0.2.x" 465 | } 466 | } 467 | } 468 | }, 469 | "passport-strategy": { 470 | "version": "1.0.0", 471 | "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", 472 | "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" 473 | }, 474 | "passport-weibo": { 475 | "version": "0.1.2", 476 | "resolved": "https://registry.npmjs.org/passport-weibo/-/passport-weibo-0.1.2.tgz", 477 | "integrity": "sha1-5QlCEwVu6TLbV9dxyOtsC+owsi8=", 478 | "requires": { 479 | "passport-oauth": "0.1.x", 480 | "pkginfo": "0.2.x" 481 | } 482 | }, 483 | "pause": { 484 | "version": "0.0.1", 485 | "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", 486 | "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" 487 | }, 488 | "pkginfo": { 489 | "version": "0.2.3", 490 | "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.2.3.tgz", 491 | "integrity": "sha1-cjnEKl72wwuPMoQ52bn/cQQkkPg=" 492 | }, 493 | "proxy-addr": { 494 | "version": "1.0.1", 495 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.0.1.tgz", 496 | "integrity": "sha1-x8Vm1etOP61n7rnHfFVYzMObiKg=", 497 | "requires": { 498 | "ipaddr.js": "0.1.2" 499 | } 500 | }, 501 | "qs": { 502 | "version": "0.6.6", 503 | "resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz", 504 | "integrity": "sha1-bgFQmP9RlouKPIGQAdXyyJvEsQc=" 505 | }, 506 | "range-parser": { 507 | "version": "1.0.0", 508 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.0.tgz", 509 | "integrity": "sha1-pLJkz+C+XONqvjdlrJwqJIdG28A=" 510 | }, 511 | "raw-body": { 512 | "version": "1.2.2", 513 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.2.2.tgz", 514 | "integrity": "sha1-DGjh7ijP7X26SCIjSuxgeEYcvB8=", 515 | "requires": { 516 | "bytes": "1", 517 | "iconv-lite": "0.4.3" 518 | } 519 | }, 520 | "readable-stream": { 521 | "version": "1.1.14", 522 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", 523 | "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", 524 | "requires": { 525 | "core-util-is": "~1.0.0", 526 | "inherits": "~2.0.1", 527 | "isarray": "0.0.1", 528 | "string_decoder": "~0.10.x" 529 | } 530 | }, 531 | "response-time": { 532 | "version": "2.0.0", 533 | "resolved": "https://registry.npmjs.org/response-time/-/response-time-2.0.0.tgz", 534 | "integrity": "sha1-Zcs5/VDeL0/9vdKF8YVZZr1vyzY=", 535 | "requires": { 536 | "on-headers": "0.0.0" 537 | } 538 | }, 539 | "rndm": { 540 | "version": "1.2.0", 541 | "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", 542 | "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=" 543 | }, 544 | "scmp": { 545 | "version": "0.0.3", 546 | "resolved": "https://registry.npmjs.org/scmp/-/scmp-0.0.3.tgz", 547 | "integrity": "sha1-NkjfLXKUZB5/eGc//CloHZutkHM=" 548 | }, 549 | "send": { 550 | "version": "0.4.3", 551 | "resolved": "https://registry.npmjs.org/send/-/send-0.4.3.tgz", 552 | "integrity": "sha1-lieyO3cH+/Y3ODHKxXkzMLWUtkA=", 553 | "requires": { 554 | "debug": "1.0.2", 555 | "escape-html": "1.0.1", 556 | "finished": "1.2.2", 557 | "fresh": "0.2.2", 558 | "mime": "1.2.11", 559 | "range-parser": "~1.0.0" 560 | } 561 | }, 562 | "serve-favicon": { 563 | "version": "2.0.1", 564 | "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.0.1.tgz", 565 | "integrity": "sha1-SCaXXZ8XPKOkFY6WmBYfdd7Hr+w=", 566 | "requires": { 567 | "fresh": "0.2.2" 568 | } 569 | }, 570 | "serve-index": { 571 | "version": "1.1.6", 572 | "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.1.6.tgz", 573 | "integrity": "sha1-t1gxj+eBYoOD9mrIDdRHcS6neB8=", 574 | "requires": { 575 | "accepts": "~1.0.7", 576 | "batch": "0.5.1", 577 | "parseurl": "~1.3.0" 578 | }, 579 | "dependencies": { 580 | "parseurl": { 581 | "version": "1.3.3", 582 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 583 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 584 | } 585 | } 586 | }, 587 | "serve-static": { 588 | "version": "1.2.3", 589 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.2.3.tgz", 590 | "integrity": "sha1-k87Lw0Dweey4WJKB0dwxwmwM0Vg=", 591 | "requires": { 592 | "escape-html": "1.0.1", 593 | "parseurl": "1.0.1", 594 | "send": "0.4.3" 595 | } 596 | }, 597 | "stream-counter": { 598 | "version": "0.2.0", 599 | "resolved": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz", 600 | "integrity": "sha1-3tJmVWMZyLDiIoErnPOyb6fZR94=", 601 | "requires": { 602 | "readable-stream": "~1.1.8" 603 | } 604 | }, 605 | "string_decoder": { 606 | "version": "0.10.31", 607 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 608 | "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" 609 | }, 610 | "thenify": { 611 | "version": "3.3.0", 612 | "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz", 613 | "integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=", 614 | "requires": { 615 | "any-promise": "^1.0.0" 616 | } 617 | }, 618 | "thenify-all": { 619 | "version": "1.6.0", 620 | "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", 621 | "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", 622 | "requires": { 623 | "thenify": ">= 3.1.0 < 4" 624 | } 625 | }, 626 | "type-is": { 627 | "version": "1.3.1", 628 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.3.1.tgz", 629 | "integrity": "sha1-pnibWlITgomt4e+PbZ8odP/XC2s=", 630 | "requires": { 631 | "media-typer": "0.2.0", 632 | "mime-types": "1.0.0" 633 | } 634 | }, 635 | "uid-safe": { 636 | "version": "1.1.0", 637 | "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-1.1.0.tgz", 638 | "integrity": "sha1-WNbF2r+N+9jVKDSDmAbAP9YUMjI=", 639 | "requires": { 640 | "base64-url": "1.2.1", 641 | "native-or-bluebird": "~1.1.2" 642 | }, 643 | "dependencies": { 644 | "base64-url": { 645 | "version": "1.2.1", 646 | "resolved": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz", 647 | "integrity": "sha1-GZ/WYXAqDnt9yubgaYuwicUvbXg=" 648 | } 649 | } 650 | }, 651 | "utils-merge": { 652 | "version": "1.0.0", 653 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", 654 | "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=" 655 | }, 656 | "vary": { 657 | "version": "0.1.0", 658 | "resolved": "https://registry.npmjs.org/vary/-/vary-0.1.0.tgz", 659 | "integrity": "sha1-3wlFiZ6TwMxb0YzIMh2dIedPYXY=" 660 | }, 661 | "vhost": { 662 | "version": "2.0.0", 663 | "resolved": "https://registry.npmjs.org/vhost/-/vhost-2.0.0.tgz", 664 | "integrity": "sha1-HiZ3C9D86GxAlFWR5vKExokXkeI=" 665 | } 666 | } 667 | } 668 | --------------------------------------------------------------------------------