"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
/** !
* koa-redis - index.js
* Copyright(c) 2015
* MIT Licensed
*
* Authors:
* dead_horse <dead_horse@qq.com> (http://deadhorse.me)
*/
/**
* Module dependencies.
*/
var util = require('util');
var _require = require('events'),
EventEmitter = _require.EventEmitter;
var debug = require('debug')('koa-redis');
var Redis = require('ioredis');
var wrap = require('co-wrap-all');
/**
* Initialize redis session middleware with `opts` (see the README for more info):
*
* @param {Object} options
* - {Boolean} isRedisCluster redis is cluster
* - {Object} client redis client (overides all other options except db and duplicate)
* - {String} socket redis connect socket (DEPRECATED: use 'path' instead)
* - {String} db redis db
* - {Boolean} duplicate if own client object, will use node redis's duplicate function and pass other options
* - {String} password redis password
* - {Any} [any] all other options including above are passed to ioredis
* @returns {Object} Redis instance
*/
function RedisStore(options) {
var _this = this;
if (!(this instanceof RedisStore)) {
return new RedisStore(options);
}
EventEmitter.call(this);
options = options || {};
var client;
options.password = options.password || options.auth_pass || options.pass || null; // For backwards compatibility
options.path = options.path || options.socket || null; // For backwards compatibility
if (!options.client) {
//
// TODO: we should probably omit custom options we have
// in this lib from `options` passed to instances below
//
var redisUrl = options.url && options.url.toString();
delete options.url;
if (options.isRedisCluster) {
debug('Initializing Redis Cluster');
delete options.isRedisCluster;
client = new Redis.Cluster(options.nodes, options.clusterOptions);
} else {
debug('Initializing Redis');
delete options.isRedisCluster;
delete options.nodes;
delete options.clusterOptions;
client = redisUrl ? new Redis(redisUrl, options) : new Redis(options);
}
} else if (options.duplicate) {
// Duplicate client and update with options provided
debug('Duplicating provided client with new options (if provided)');
var dupClient = options.client;
delete options.client;
delete options.duplicate;
client = dupClient.duplicate(options); // Useful if you want to use the DB option without adjusting the client DB outside koa-redis
} else {
debug('Using provided client');
client = options.client;
}
if (options.db) {
debug('selecting db %s', options.db);
client.select(options.db);
client.on('connect', function () {
client.send_anyways = true;
client.select(options.db);
client.send_anyways = false;
});
}
['connect', 'ready', 'error', 'close', 'reconnecting', 'end'].forEach(function (name) {
_this.on(name, function () {
return debug(`redis ${name}`);
});
client.on(name, _this.emit.bind(_this, name));
}); // For backwards compatibility
client.on('end', this.emit.bind(this, 'disconnect'));
this.client = client;
Object.defineProperty(this, 'status', {
get() {
return this.client.status;
}
});
Object.defineProperty(this, 'connected', {
get() {
return ['connect', 'ready'].includes(this.status);
}
}); // Support optional serialize and unserialize
this.serialize = typeof options.serialize === 'function' && options.serialize || JSON.stringify;
this.unserialize = typeof options.unserialize === 'function' && options.unserialize || JSON.parse;
}
util.inherits(RedisStore, EventEmitter);
RedisStore.prototype.get =
/*#__PURE__*/
_regenerator.default.mark(function _callee(sid) {
var data;
return _regenerator.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return this.client.get(sid);
case 2:
data = _context.sent;
debug('get session: %s', data || 'none');
if (data) {
_context.next = 6;
break;
}
return _context.abrupt("return", null);
case 6:
_context.prev = 6;
return _context.abrupt("return", this.unserialize(data.toString()));
case 10:
_context.prev = 10;
_context.t0 = _context["catch"](6);
// ignore err
debug('parse session error: %s', _context.t0.message);
case 13:
case "end":
return _context.stop();
}
}
}, _callee, this, [[6, 10]]);
});
RedisStore.prototype.set =
/*#__PURE__*/
_regenerator.default.mark(function _callee2(sid, sess, ttl) {
return _regenerator.default.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
if (typeof ttl === 'number') {
ttl = Math.ceil(ttl / 1000);
}
sess = this.serialize(sess);
if (!ttl) {
_context2.next = 8;
break;
}
debug('SETEX %s %s %s', sid, ttl, sess);
_context2.next = 6;
return this.client.setex(sid, ttl, sess);
case 6:
_context2.next = 11;
break;
case 8:
debug('SET %s %s', sid, sess);
_context2.next = 11;
return this.client.set(sid, sess);
case 11:
debug('SET %s complete', sid);
case 12:
case "end":
return _context2.stop();
}
}
}, _callee2, this);
});
RedisStore.prototype.destroy =
/*#__PURE__*/
_regenerator.default.mark(function _callee3(sid) {
return _regenerator.default.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
debug('DEL %s', sid);
_context3.next = 3;
return this.client.del(sid);
case 3:
debug('DEL %s complete', sid);
case 4:
case "end":
return _context3.stop();
}
}
}, _callee3, this);
});
RedisStore.prototype.quit =
/*#__PURE__*/
_regenerator.default.mark(function _callee4() {
return _regenerator.default.wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
// End connection SAFELY
debug('quitting redis client');
_context4.next = 3;
return this.client.quit();
case 3:
case "end":
return _context4.stop();
}
}
}, _callee4, this);
});
wrap(RedisStore.prototype);
RedisStore.prototype.end = RedisStore.prototype.quit; // End connection SAFELY. The real end() command should never be used, as it cuts off to queue.
module.exports = RedisStore;