├── tests ├── index.js └── test.js ├── .editorconfig ├── .gitignore ├── LICENSE ├── package.json ├── README.md ├── src └── store.js └── dist └── store.js /tests/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('babel/register'); 4 | require('co-mocha'); 5 | global.expect = require('chai').expect; 6 | global.assert = require('chai').assert; 7 | require('./test'); 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | 9 | # Change these settings to your own preference 10 | indent_style = space 11 | indent_size = 2 12 | 13 | # We recommend you to keep these unchanged 14 | end_of_line = lf 15 | charset = utf-8 16 | trim_trailing_whitespace = true 17 | insert_final_newline = true 18 | 19 | [*.md] 20 | trim_trailing_whitespace = false 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | # Logs 3 | logs 4 | *.log 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # Compiled binary addons (http://nodejs.org/api/addons.html) 21 | build/Release 22 | 23 | # Dependency directory 24 | # Deployed apps should consider commenting this line out: 25 | # see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git 26 | node_modules 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Pavel Vlasov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "koa-generic-session-mongo", 3 | "version": "0.4.0", 4 | "description": "MongoDB store for koa-generic-session middleware backed by node-mongodb-native.", 5 | "main": "dist/store.js", 6 | "scripts": { 7 | "test": "node_modules/.bin/mocha ./tests/index.js", 8 | "build": "node_modules/.bin/babel --optional runtime -d dist/ src/" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git://github.com/pavelvlasov/koa-generic-session-mongo.git" 13 | }, 14 | "keywords": [ 15 | "koa", 16 | "sess", 17 | "session", 18 | "mongo", 19 | "store", 20 | "co" 21 | ], 22 | "author": "Pavel Vlasov ", 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/pavelvlasov/koa-generic-session-mongo/issues" 26 | }, 27 | "homepage": "https://github.com/pavelvlasov/koa-generic-session-mongo", 28 | "dependencies": { 29 | "babel-runtime": "^5.4.7", 30 | "debug": "^2.2.0", 31 | "mongodb": "^2.0.42", 32 | "thunkify": "^2.1.2" 33 | }, 34 | "devDependencies": { 35 | "babel": "^5.4.7", 36 | "chai": "^2.3.0", 37 | "co-mocha": "^1.1.0", 38 | "ghooks": "^0.3.2", 39 | "mocha": "^2.2.5" 40 | }, 41 | "config": { 42 | "ghooks": { 43 | "pre-commit": "npm run build && npm run test" 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # koa-generic-session-mongo 2 | 3 | MongoDB store for [koa-generic-session](https://github.com/koajs/generic-session) middleware backed by [node-mongodb-native](https://github.com/mongodb/node-mongodb-native). 4 | Fork of [connect-to-mongo](https://github.com/2do2go/connect-to-mongo) store. 5 | 6 | ## Installation 7 | 8 | ```sh 9 | npm install koa-generic-session koa-generic-session-mongo --save 10 | ``` 11 | 12 | ## Usage 13 | 14 | ### Example 15 | ```js 16 | var koa = require('koa'); 17 | var session = require('koa-generic-session'); 18 | var MongoStore = require('koa-generic-session-mongo'); 19 | 20 | var app = koa(); 21 | app.keys = ['keys', 'keykeys']; 22 | app.use(session({ 23 | store: new MongoStore({ 24 | host: '127.0.0.1' 25 | }) // options 26 | })); 27 | 28 | app.use(function *() { 29 | switch (this.path) { 30 | case '/get': 31 | get.call(this); 32 | break; 33 | case '/remove': 34 | remove.call(this); 35 | break; 36 | } 37 | }); 38 | 39 | function get() { 40 | var session = this.session; 41 | session.count = session.count || 0; 42 | session.count++; 43 | this.body = session.count; 44 | } 45 | 46 | function remove() { 47 | this.session = null; 48 | this.body = 0; 49 | } 50 | 51 | app.listen(8080); 52 | ``` 53 | 54 | ## Options 55 | 56 | - `url` mongodb connection url (full connection string. host, port, db, ssl options will be ignored) 57 | - `db` mongodb-native database object or database name (`test` by default) 58 | - `collection` collection name (`sessions` by default) 59 | - `host` db hostname (`127.0.0.1` by default) 60 | - `port` db port (`27017` by default) 61 | - `ttl` ttl in milliseconds (if set it overrides cookie `maxAge`) 62 | - `user` user for MongoDB 63 | - `password` password for MongoDB authentication 64 | - `ssl` use SSL to connect to MongoDB (`false` by default) 65 | 66 | ## License 67 | MIT 68 | -------------------------------------------------------------------------------- /tests/test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import {MongoClient} from 'mongodb'; 4 | import MongoStore from '../src/store'; 5 | import thunkify from 'thunkify'; 6 | 7 | const clone = (obj) => { 8 | return JSON.parse(JSON.stringify(obj)); 9 | }; 10 | 11 | const describeStore = (msg, storeOptions, options={}) => { 12 | const {cleanDb=false} = options; 13 | let store; 14 | 15 | describe(msg, function() { 16 | const sess = {cookie: {maxAge: 2000}, name: 'name'}; 17 | 18 | before(function (done) { 19 | store = new MongoStore(typeof storeOptions === 'function' ? storeOptions() : storeOptions) 20 | .on('connect', function (conn) { 21 | cleanDb && conn.drop(); 22 | done(); 23 | }) 24 | .on('error', done); 25 | }); 26 | 27 | it('collection name should be sessions (by default) or equal to collection (when option presented)', function *() { 28 | const name = storeOptions.collection || 'sessions' 29 | const result = (yield store.col).s.name; 30 | expect(result).to.deep.equal(name); 31 | }); 32 | 33 | it('should save session to db', function *() { 34 | const result = yield store.set('123', clone(sess)); 35 | //noinspection BadExpressionStatementJS 36 | expect(result).to.be.ok; 37 | }); 38 | 39 | it('should return saved session', function *() { 40 | const result = yield store.get('123'); 41 | expect(result).to.deep.equal(sess); 42 | }); 43 | 44 | it('should destroy session', function *() { 45 | yield store.destroy('123'); 46 | const result = yield store.get('123'); 47 | //noinspection BadExpressionStatementJS 48 | expect(result).to.not.ok; 49 | }); 50 | 51 | it('should set ttl', function *() { 52 | const sess = { 53 | name: 'name' 54 | }; 55 | yield store.set('123', sess, 12345); 56 | const col = yield store.col; 57 | const result = yield thunkify(col.findOne.bind(col))({sid: '123'}, {_id: 0}); 58 | //noinspection BadExpressionStatementJS 59 | expect(result.ttl.valueOf()).to.be.ok; 60 | }); 61 | }); 62 | }; 63 | 64 | describeStore('store from url with custom session name', {url: 'mongodb://127.0.0.1:27017/test', collection: 'custom_sessions'}, {cleanDb: true}); 65 | describeStore('store from url with default session name', {url: 'mongodb://127.0.0.1:27017/test'}, {cleanDb: true}); 66 | 67 | describe('test auth', function() { 68 | let db; 69 | 70 | before(function *() { 71 | db = yield thunkify(MongoClient.connect)('mongodb://127.0.0.1:27017/testauth'); 72 | }); 73 | 74 | it('should add user', function *() { 75 | try { 76 | yield thunkify(db.removeUser.bind(db))('han'); 77 | } catch (err) { 78 | //skip error 79 | } 80 | let user = yield thunkify(db.addUser.bind(db))('han', 'solo'); 81 | }); 82 | 83 | describeStore('store from db object', () => {return {db}}, {cleanDb: true}); 84 | 85 | describeStore('auth store', {user: 'han', password: 'solo', db: 'testauth'}); 86 | }); 87 | 88 | describe('closed db', function() { 89 | let db, store; 90 | 91 | before(function *() { 92 | db = yield thunkify(MongoClient.connect)('mongodb://127.0.0.1:27017/test'); 93 | yield thunkify(db.close.bind(db))(); 94 | store = new MongoStore({db}); 95 | }); 96 | 97 | it('should crush', function *() { 98 | let throwsError; 99 | try { 100 | yield store.get('123'); 101 | } catch (err) { 102 | throwsError = true; 103 | } 104 | assert(throwsError, 'should throw error'); 105 | }); 106 | }); 107 | 108 | describe('url info exclusive', function () { 109 | it('should fail if host and url provided', function *() { 110 | assert.throw(() => {new MongoStore({url: 'mongodb://127.0.0.1:27017', host: 'localhost'})}); 111 | }); 112 | it('should fail if port and url provided', function *() { 113 | assert.throw(() => {new MongoStore({url: 'mongodb://127.0.0.1:27017', port: '27017'})}); 114 | }); 115 | it('should fail if db and url provided', function *() { 116 | assert.throw(() => {new MongoStore({url: 'mongodb://127.0.0.1:27017', db: 'admin'})}); 117 | }); 118 | it('should fail if ssl and url provided', function *() { 119 | assert.throw(() => {new MongoStore({url: 'mongodb://127.0.0.1:27017', ssl: true})}); 120 | }); 121 | }); 122 | -------------------------------------------------------------------------------- /src/store.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /*! 4 | * koa-generic-session-mongo 5 | * Copyright(c) 2013 Pavel Vlasov 6 | * MIT Licensed 7 | */ 8 | 9 | import {EventEmitter} from 'events'; 10 | import {MongoClient} from 'mongodb'; 11 | import thunkify from 'thunkify'; 12 | import debug from 'debug'; 13 | 14 | const log = debug('koa-generic-session-mongo:store'); 15 | const ONE_DAY = 86400 * 1000; 16 | const DEFAULT_COLLECTION = 'sessions'; 17 | 18 | export default class MongoStore extends EventEmitter { 19 | /** 20 | * Initialize MongoStore with the given `options`. 21 | * 22 | * @param {Object} options 23 | * @api public 24 | */ 25 | constructor(options = {}) { 26 | super(); 27 | const { 28 | db, 29 | collection, 30 | url, 31 | user, 32 | password 33 | } = options; 34 | 35 | if (url && ('host' in options || 'port' in options || 'db' in options || 'ssl' in options)) { 36 | throw new Error('url option is exclusive from host, port, db and ssl options, please include as a full url connection string'); 37 | } 38 | 39 | this.col = db && typeof db !== 'string' && typeof db.dropDatabase === 'function' ? 40 | this._initWithDb({db, collection}) : 41 | this._initWithUrl({ 42 | url: url || MongoStore._makeConnectionString(options), 43 | user, 44 | password, 45 | collection 46 | }); 47 | 48 | this.col 49 | .then(MongoStore._ensureIndexes) 50 | .then((collection) => { 51 | this.emit('connect', collection); 52 | }).catch((err) => { 53 | this.emit('error', err); 54 | }); 55 | } 56 | 57 | /** 58 | * Init session collection with given database object 59 | * @param db Database object 60 | * @param collection Collection name which will store our sessions 61 | * @returns {Promise.<*>} 62 | * @private 63 | */ 64 | _initWithDb({db, collection=DEFAULT_COLLECTION}) { 65 | return Promise.resolve(db.collection(collection)); 66 | } 67 | 68 | /** 69 | * 70 | * @param url Connection string to db 71 | * @param user 72 | * @param password 73 | * @param collection Collection name which will store our sessions 74 | * @returns {Promise} 75 | * @private 76 | */ 77 | _initWithUrl({url, user, password, collection=DEFAULT_COLLECTION}) { 78 | return new Promise((resolve, reject) => { 79 | new MongoClient().connect(url, function (err, db) { 80 | if (err) { 81 | reject(err); 82 | return; 83 | } 84 | const col = db.collection(collection); 85 | if (user && password) { 86 | db.authenticate(user, password, function (err, res) { 87 | if (err) { 88 | reject(err); 89 | } else if (!res) { 90 | reject(new Error('mongodb authentication failed')); 91 | } else { 92 | resolve(col); 93 | } 94 | }); 95 | } else { 96 | resolve(col); 97 | } 98 | }); 99 | }) 100 | } 101 | 102 | static _makeConnectionString({host='127.0.0.1', port=27017, db='test', ssl=false}) { 103 | return `mongodb://${host}:${port}/${db}?ssl=${ssl}`; 104 | } 105 | 106 | /** 107 | * Create ttl and sid indexes 108 | * @param col 109 | * @returns {Promise} 110 | */ 111 | static _ensureIndexes(col) { 112 | return new Promise(function (resolve, reject) { 113 | let times = 2; 114 | 115 | function done(err) { 116 | if (err) { 117 | reject(err); 118 | } else if (--times < 1) { 119 | resolve(col); 120 | } 121 | } 122 | 123 | col.ensureIndex({ttl: 1}, {expireAfterSeconds: 0}, done); 124 | col.ensureIndex({sid: 1}, {unique: true}, done); 125 | }); 126 | } 127 | 128 | /** 129 | * Attempt to fetch session by the given `sid`. 130 | * 131 | * @param {String} sid 132 | * @param {Function} fn 133 | * @api public 134 | */ 135 | *get(sid) { 136 | const col = yield this.col; 137 | const findOne = thunkify(col.findOne.bind(col)); 138 | 139 | return yield findOne({sid: sid}, {_id: 0, ttl: 0, sid: 0}); 140 | } 141 | 142 | /** 143 | * Commit the given `sess` object associated with the given `sid`. 144 | * 145 | * @param {String} sid 146 | * @param {Session} sess 147 | * @api public 148 | */ 149 | *set(sid, sess, ttl) { 150 | // clone original sess 151 | sess = {...sess}; 152 | const maxAge = sess.cookie && (sess.cookie.maxAge || sess.cookie.maxage); 153 | const col = yield this.col; 154 | const update = thunkify(col.update.bind(col)); 155 | 156 | sess.sid = sid; 157 | sess.ttl = new Date((ttl || ('number' == typeof maxAge 158 | ? maxAge : ONE_DAY)) + Date.now()); 159 | 160 | return yield update({sid: sid}, sess, {upsert: true}); 161 | } 162 | 163 | /** 164 | * Destroy the session associated with the given `sid`. 165 | * 166 | * @param {String} sid 167 | * @api public 168 | */ 169 | *destroy(sid) { 170 | const col = yield this.col; 171 | const remove = thunkify(col.remove.bind(col)); 172 | 173 | yield remove({sid: sid}); 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /dist/store.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /*! 4 | * koa-generic-session-mongo 5 | * Copyright(c) 2013 Pavel Vlasov 6 | * MIT Licensed 7 | */ 8 | 9 | var _get = require('babel-runtime/helpers/get')['default']; 10 | 11 | var _inherits = require('babel-runtime/helpers/inherits')['default']; 12 | 13 | var _createClass = require('babel-runtime/helpers/create-class')['default']; 14 | 15 | var _classCallCheck = require('babel-runtime/helpers/class-call-check')['default']; 16 | 17 | var _extends = require('babel-runtime/helpers/extends')['default']; 18 | 19 | var _Promise = require('babel-runtime/core-js/promise')['default']; 20 | 21 | var _regeneratorRuntime = require('babel-runtime/regenerator')['default']; 22 | 23 | var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default']; 24 | 25 | Object.defineProperty(exports, '__esModule', { 26 | value: true 27 | }); 28 | 29 | var _events = require('events'); 30 | 31 | var _mongodb = require('mongodb'); 32 | 33 | var _thunkify = require('thunkify'); 34 | 35 | var _thunkify2 = _interopRequireDefault(_thunkify); 36 | 37 | var _debug = require('debug'); 38 | 39 | var _debug2 = _interopRequireDefault(_debug); 40 | 41 | var log = (0, _debug2['default'])('koa-generic-session-mongo:store'); 42 | var ONE_DAY = 86400 * 1000; 43 | var DEFAULT_COLLECTION = 'sessions'; 44 | 45 | var MongoStore = (function (_EventEmitter) { 46 | _inherits(MongoStore, _EventEmitter); 47 | 48 | /** 49 | * Initialize MongoStore with the given `options`. 50 | * 51 | * @param {Object} options 52 | * @api public 53 | */ 54 | 55 | function MongoStore() { 56 | var _this = this; 57 | 58 | var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; 59 | 60 | _classCallCheck(this, MongoStore); 61 | 62 | _get(Object.getPrototypeOf(MongoStore.prototype), 'constructor', this).call(this); 63 | var db = options.db; 64 | var collection = options.collection; 65 | var url = options.url; 66 | var user = options.user; 67 | var password = options.password; 68 | 69 | if (url && ('host' in options || 'port' in options || 'db' in options || 'ssl' in options)) { 70 | throw new Error('url option is exclusive from host, port, db and ssl options, please include as a full url connection string'); 71 | } 72 | 73 | this.col = db && typeof db !== 'string' && typeof db.dropDatabase === 'function' ? this._initWithDb({ db: db, collection: collection }) : this._initWithUrl({ 74 | url: url || MongoStore._makeConnectionString(options), 75 | user: user, 76 | password: password, 77 | collection: collection 78 | }); 79 | 80 | this.col.then(MongoStore._ensureIndexes).then(function (collection) { 81 | _this.emit('connect', collection); 82 | })['catch'](function (err) { 83 | _this.emit('error', err); 84 | }); 85 | } 86 | 87 | /** 88 | * Init session collection with given database object 89 | * @param db Database object 90 | * @param collection Collection name which will store our sessions 91 | * @returns {Promise.<*>} 92 | * @private 93 | */ 94 | 95 | _createClass(MongoStore, [{ 96 | key: '_initWithDb', 97 | value: function _initWithDb(_ref) { 98 | var db = _ref.db; 99 | var _ref$collection = _ref.collection; 100 | var collection = _ref$collection === undefined ? DEFAULT_COLLECTION : _ref$collection; 101 | 102 | return _Promise.resolve(db.collection(collection)); 103 | } 104 | 105 | /** 106 | * 107 | * @param url Connection string to db 108 | * @param user 109 | * @param password 110 | * @param collection Collection name which will store our sessions 111 | * @returns {Promise} 112 | * @private 113 | */ 114 | }, { 115 | key: '_initWithUrl', 116 | value: function _initWithUrl(_ref2) { 117 | var url = _ref2.url; 118 | var user = _ref2.user; 119 | var password = _ref2.password; 120 | var _ref2$collection = _ref2.collection; 121 | var collection = _ref2$collection === undefined ? DEFAULT_COLLECTION : _ref2$collection; 122 | 123 | return new _Promise(function (resolve, reject) { 124 | new _mongodb.MongoClient().connect(url, function (err, db) { 125 | if (err) { 126 | reject(err); 127 | return; 128 | } 129 | var col = db.collection(collection); 130 | if (user && password) { 131 | db.authenticate(user, password, function (err, res) { 132 | if (err) { 133 | reject(err); 134 | } else if (!res) { 135 | reject(new Error('mongodb authentication failed')); 136 | } else { 137 | resolve(col); 138 | } 139 | }); 140 | } else { 141 | resolve(col); 142 | } 143 | }); 144 | }); 145 | } 146 | }, { 147 | key: 'get', 148 | 149 | /** 150 | * Attempt to fetch session by the given `sid`. 151 | * 152 | * @param {String} sid 153 | * @param {Function} fn 154 | * @api public 155 | */ 156 | value: _regeneratorRuntime.mark(function get(sid) { 157 | var col, findOne; 158 | return _regeneratorRuntime.wrap(function get$(context$2$0) { 159 | while (1) switch (context$2$0.prev = context$2$0.next) { 160 | case 0: 161 | context$2$0.next = 2; 162 | return this.col; 163 | 164 | case 2: 165 | col = context$2$0.sent; 166 | findOne = (0, _thunkify2['default'])(col.findOne.bind(col)); 167 | context$2$0.next = 6; 168 | return findOne({ sid: sid }, { _id: 0, ttl: 0, sid: 0 }); 169 | 170 | case 6: 171 | return context$2$0.abrupt('return', context$2$0.sent); 172 | 173 | case 7: 174 | case 'end': 175 | return context$2$0.stop(); 176 | } 177 | }, get, this); 178 | }) 179 | 180 | /** 181 | * Commit the given `sess` object associated with the given `sid`. 182 | * 183 | * @param {String} sid 184 | * @param {Session} sess 185 | * @api public 186 | */ 187 | }, { 188 | key: 'set', 189 | value: _regeneratorRuntime.mark(function set(sid, sess, ttl) { 190 | var maxAge, col, update; 191 | return _regeneratorRuntime.wrap(function set$(context$2$0) { 192 | while (1) switch (context$2$0.prev = context$2$0.next) { 193 | case 0: 194 | // clone original sess 195 | sess = _extends({}, sess); 196 | maxAge = sess.cookie && (sess.cookie.maxAge || sess.cookie.maxage); 197 | context$2$0.next = 4; 198 | return this.col; 199 | 200 | case 4: 201 | col = context$2$0.sent; 202 | update = (0, _thunkify2['default'])(col.update.bind(col)); 203 | 204 | sess.sid = sid; 205 | sess.ttl = new Date((ttl || ('number' == typeof maxAge ? maxAge : ONE_DAY)) + Date.now()); 206 | 207 | context$2$0.next = 10; 208 | return update({ sid: sid }, sess, { upsert: true }); 209 | 210 | case 10: 211 | return context$2$0.abrupt('return', context$2$0.sent); 212 | 213 | case 11: 214 | case 'end': 215 | return context$2$0.stop(); 216 | } 217 | }, set, this); 218 | }) 219 | 220 | /** 221 | * Destroy the session associated with the given `sid`. 222 | * 223 | * @param {String} sid 224 | * @api public 225 | */ 226 | }, { 227 | key: 'destroy', 228 | value: _regeneratorRuntime.mark(function destroy(sid) { 229 | var col, remove; 230 | return _regeneratorRuntime.wrap(function destroy$(context$2$0) { 231 | while (1) switch (context$2$0.prev = context$2$0.next) { 232 | case 0: 233 | context$2$0.next = 2; 234 | return this.col; 235 | 236 | case 2: 237 | col = context$2$0.sent; 238 | remove = (0, _thunkify2['default'])(col.remove.bind(col)); 239 | context$2$0.next = 6; 240 | return remove({ sid: sid }); 241 | 242 | case 6: 243 | case 'end': 244 | return context$2$0.stop(); 245 | } 246 | }, destroy, this); 247 | }) 248 | }], [{ 249 | key: '_makeConnectionString', 250 | value: function _makeConnectionString(_ref3) { 251 | var _ref3$host = _ref3.host; 252 | var host = _ref3$host === undefined ? '127.0.0.1' : _ref3$host; 253 | var _ref3$port = _ref3.port; 254 | var port = _ref3$port === undefined ? 27017 : _ref3$port; 255 | var _ref3$db = _ref3.db; 256 | var db = _ref3$db === undefined ? 'test' : _ref3$db; 257 | var _ref3$ssl = _ref3.ssl; 258 | var ssl = _ref3$ssl === undefined ? false : _ref3$ssl; 259 | 260 | return 'mongodb://' + host + ':' + port + '/' + db + '?ssl=' + ssl; 261 | } 262 | 263 | /** 264 | * Create ttl and sid indexes 265 | * @param col 266 | * @returns {Promise} 267 | */ 268 | }, { 269 | key: '_ensureIndexes', 270 | value: function _ensureIndexes(col) { 271 | return new _Promise(function (resolve, reject) { 272 | var times = 2; 273 | 274 | function done(err) { 275 | if (err) { 276 | reject(err); 277 | } else if (--times < 1) { 278 | resolve(col); 279 | } 280 | } 281 | 282 | col.ensureIndex({ ttl: 1 }, { expireAfterSeconds: 0 }, done); 283 | col.ensureIndex({ sid: 1 }, { unique: true }, done); 284 | }); 285 | } 286 | }]); 287 | 288 | return MongoStore; 289 | })(_events.EventEmitter); 290 | 291 | exports['default'] = MongoStore; 292 | module.exports = exports['default']; --------------------------------------------------------------------------------