"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 (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;