@silverwind/ioredis-mock
Version:
This library emulates ioredis by performing all operations in-memory.
146 lines (115 loc) • 4.53 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Command = void 0;
exports.default = command;
exports.isInSubscriberMode = isInSubscriberMode;
exports.isNotConnected = isNotConnected;
exports.processArguments = processArguments;
exports.processReply = processReply;
exports.safelyExecuteCommand = safelyExecuteCommand;
exports.throwIfCommandIsNotAllowed = throwIfCommandIsNotAllowed;
exports.throwIfInSubscriberMode = throwIfInSubscriberMode;
exports.throwIfNotConnected = throwIfNotConnected;
var _lodash = _interopRequireDefault(require("lodash"));
var _standardAsCallback = _interopRequireDefault(require("standard-as-callback"));
var _ioredis = require("ioredis");
var _promiseContainer = _interopRequireDefault(require("./promise-container"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function isInSubscriberMode(RedisMock) {
if (RedisMock.channels === undefined) {
return false;
}
return RedisMock.subscriberMode;
}
function isNotConnected(RedisMock) {
if (RedisMock.connected === undefined) {
return false;
}
return !RedisMock.connected;
}
function throwIfInSubscriberMode(commandName, RedisMock) {
if (isInSubscriberMode(RedisMock)) {
const allowedCommands = ['subscribe', 'psubscribe', 'unsubscribe', 'punsubscribe', 'ping', 'quit', 'disconnect'];
if (allowedCommands.indexOf(commandName) > -1) {// command is allowed -> do not throw
} else {
throw new Error('Connection in subscriber mode, only subscriber commands may be used');
}
}
}
function throwIfNotConnected(commandName, RedisMock) {
if (isNotConnected(RedisMock)) {
if (commandName !== 'connect' && commandName !== 'defineCommand') {
throw new Error("Stream isn't writeable and enableOfflineQueue options is false");
}
}
}
function throwIfCommandIsNotAllowed(commandName, RedisMock) {
throwIfInSubscriberMode(commandName, RedisMock);
throwIfNotConnected(commandName, RedisMock);
}
const Command = {
// eslint-disable-next-line no-underscore-dangle
transformers: _ioredis.Command._transformer,
setArgumentTransformer: (name, func) => {
Command.transformers.argument[name] = func;
},
setReplyTransformer: (name, func) => {
Command.transformers.reply[name] = func;
}
};
/**
* Transform non-buffer arguments to strings to simulate real ioredis behavior
* @param {any} arg the argument to transform
*/
exports.Command = Command;
const argMapper = arg => {
if (arg === null || arg === undefined) return '';
return arg instanceof Buffer ? arg : arg.toString();
};
function processArguments(args, commandName) {
// fast return, the defineCommand command requires NO transformation of args
if (commandName === 'defineCommand') return args;
let commandArgs = args ? _lodash.default.flatten(args) : [];
if (Command.transformers.argument[commandName]) {
commandArgs = Command.transformers.argument[commandName](args);
}
commandArgs = commandArgs.map(argMapper);
return commandArgs;
}
function processReply(result, commandName) {
if (Command.transformers.reply[commandName]) {
// ioredis' reply transformer seems to receive array of arrays for
// the hgetall command, emulate this
let newResult = result;
if (commandName === 'hgetall') {
newResult = _lodash.default.flatten(Object.entries(result));
}
return Command.transformers.reply[commandName](newResult);
}
return result;
}
function safelyExecuteCommand(commandEmulator, commandName, RedisMock, ...commandArgs) {
throwIfCommandIsNotAllowed(commandName, RedisMock);
const result = commandEmulator(...commandArgs);
return processReply(result, commandName);
}
function command(commandEmulator, commandName, RedisMock) {
return (...args) => {
const lastArgIndex = args.length - 1;
let callback = args[lastArgIndex];
if (typeof callback !== 'function') {
callback = undefined;
} else {
// eslint-disable-next-line no-param-reassign
args.length = lastArgIndex;
}
const commandArgs = processArguments(args, commandName, RedisMock);
if (commandName === 'defineCommand') {
return safelyExecuteCommand(commandEmulator, commandName, RedisMock, ...commandArgs);
}
const Promise = _promiseContainer.default.get();
return (0, _standardAsCallback.default)(new Promise(resolve => resolve(safelyExecuteCommand(commandEmulator, commandName, RedisMock, ...commandArgs))), callback);
};
}