UNPKG

@silverwind/ioredis-mock

Version:

This library emulates ioredis by performing all operations in-memory.

140 lines (108 loc) 4.78 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.customCommand = void 0; exports.defineArgv = defineArgv; exports.defineCommand = defineCommand; exports.defineKeys = defineKeys; exports.defineRedisObject = void 0; var _fengari = _interopRequireDefault(require("fengari")); var _fengariInterop = _interopRequireDefault(require("fengari-interop")); var _command = _interopRequireDefault(require("../command")); var _lua = require("../lua"); var commands = _interopRequireWildcard(require(".")); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const { lua, to_luastring: toLuaString } = _fengari.default; /** * exported to test * * @param {*} vm - object with the lua state (L) and some utils * -> * @param fn - a function returning 0 for non-error and != 0 for error */ const defineRedisObject = vm => fn => { vm.defineGlobalFunction(fn, 'call'); // define redis object with call method // convert nil to false base on https://redis.io/commands/eval#conversion-between-lua-and-redis-data-types vm.luaExecString(` local redis = {} function repair(val) if val == nil then return false end return val end redis.call = function(...) return repair(call(false, ...)) end redis.pcall = function(...) return repair(call(true, ...)) end return redis `); // loads the redis object from the stack into the global table under key 'redis' lua.lua_setglobal(vm.L, toLuaString('redis')); }; exports.defineRedisObject = defineRedisObject; const callToRedisCommand = vm => function callToRedisCommand2() { const rawArgs = vm.extractArgs(); const returnError = rawArgs[0]; let result; try { const args = rawArgs.slice(1); const name = args[0].toLowerCase(); const redisCmd = commands[name].bind(this); result = redisCmd(...args.slice(1)); } catch (err) { if (!returnError) { throw err; } _fengariInterop.default.push(vm.L, ['error', err.toString()]); return 1; } if (!!result || result === 0) { if (Array.isArray(result)) { // fix for one-based indices result.unshift(null); // https://github.com/fengari-lua/fengari-interop/blob/1626687fb15452cdd82ee522955dd1f144ea7a68/src/js.js#L845 result[Symbol.for('__len')] = function () { const arr = this; return arr.length - 1; }; } _fengariInterop.default.push(vm.L, result); return 1; } return 0; }; // exported to test function defineKeys(vm, numberOfKeys, commandArgs) { const keys = commandArgs.slice(0, numberOfKeys); vm.defineGlobalArray(keys, 'KEYS'); } // exported to test function defineArgv(vm, numberOfKeys, commandArgs) { const args = commandArgs.slice(numberOfKeys); vm.defineGlobalArray(args, 'ARGV'); } // exported to test const customCommand = (numberOfKeys, luaCode) => function customCommand2(...luaScriptArgs) { const vm = (0, _lua.init)(); defineRedisObject(vm)(callToRedisCommand(vm).bind(this)); defineKeys.bind(this)(vm, numberOfKeys, luaScriptArgs); defineArgv.bind(this)(vm, numberOfKeys, luaScriptArgs); const topBeforeExecute = lua.lua_gettop(vm.L); vm.luaExecString(luaCode); const retVal = vm.popReturnValue(topBeforeExecute); (0, _lua.dispose)(vm); return retVal; }; exports.customCommand = customCommand; function defineCommand(command, { numberOfKeys, lua: luaCode }) { const cmd = (0, _command.default)(customCommand(numberOfKeys, luaCode).bind(this), command, this); this[command] = cmd; // for multi/pipeline this.customCommands[command] = cmd; }