blob: 8b584377b0b0ec7cfc2564c7cc19a71b03e5180d [file] [log] [blame]
'use strict'
var commands = require('./commands.json')
/**
* Redis command list
*
* All commands are lowercased.
*
* @var {string[]}
* @public
*/
exports.list = Object.keys(commands)
var flags = {}
exports.list.forEach(function (commandName) {
flags[commandName] = commands[commandName].flags.reduce(function (flags, flag) {
flags[flag] = true
return flags
}, {})
})
/**
* Check if the command exists
*
* @param {string} commandName - the command name
* @return {boolean} result
* @public
*/
exports.exists = function (commandName) {
return Boolean(commands[commandName])
}
/**
* Check if the command has the flag
*
* Some of possible flags: readonly, noscript, loading
* @param {string} commandName - the command name
* @param {string} flag - the flag to check
* @return {boolean} result
* @public
*/
exports.hasFlag = function (commandName, flag) {
if (!flags[commandName]) {
throw new Error('Unknown command ' + commandName)
}
return Boolean(flags[commandName][flag])
}
/**
* Get indexes of keys in the command arguments
*
* @param {string} commandName - the command name
* @param {string[]} args - the arguments of the command
* @param {object} [options] - options
* @param {boolean} [options.parseExternalKey] - parse external keys
* @return {number[]} - the list of the index
* @public
*
* @example
* ```javascript
* getKeyIndexes('set', ['key', 'value']) // [0]
* getKeyIndexes('mget', ['key1', 'key2']) // [0, 1]
* ```
*/
exports.getKeyIndexes = function (commandName, args, options) {
var command = commands[commandName]
if (!command) {
throw new Error('Unknown command ' + commandName)
}
if (!Array.isArray(args)) {
throw new Error('Expect args to be an array')
}
var keys = []
var i, keyStart, keyStop, parseExternalKey
switch (commandName) {
case 'zunionstore':
case 'zinterstore':
keys.push(0)
// fall through
case 'eval':
case 'evalsha':
keyStop = Number(args[1]) + 2
for (i = 2; i < keyStop; i++) {
keys.push(i)
}
break
case 'sort':
parseExternalKey = options && options.parseExternalKey
keys.push(0)
for (i = 1; i < args.length - 1; i++) {
if (typeof args[i] !== 'string') {
continue
}
var directive = args[i].toUpperCase()
if (directive === 'GET') {
i += 1
if (args[i] !== '#') {
if (parseExternalKey) {
keys.push([i, getExternalKeyNameLength(args[i])])
} else {
keys.push(i)
}
}
} else if (directive === 'BY') {
i += 1
if (parseExternalKey) {
keys.push([i, getExternalKeyNameLength(args[i])])
} else {
keys.push(i)
}
} else if (directive === 'STORE') {
i += 1
keys.push(i)
}
}
break
case 'migrate':
if (args[2] === '') {
for (i = 5; i < args.length - 1; i++) {
if (args[i].toUpperCase() === 'KEYS') {
for (var j = i + 1; j < args.length; j++) {
keys.push(j)
}
break
}
}
} else {
keys.push(2)
}
break
default:
// step has to be at least one in this case, otherwise the command does not contain a key
if (command.step > 0) {
keyStart = command.keyStart - 1
keyStop = command.keyStop > 0 ? command.keyStop : args.length + command.keyStop + 1
for (i = keyStart; i < keyStop; i += command.step) {
keys.push(i)
}
}
break
}
return keys
}
function getExternalKeyNameLength (key) {
if (typeof key !== 'string') {
key = String(key)
}
var hashPos = key.indexOf('->')
return hashPos === -1 ? key.length : hashPos
}