Redis commands library providing command metadata, validation, and key extraction utilities
npx @tessl/cli install tessl/npm-redis-commands@1.7.0Redis Commands is a Node.js library that provides comprehensive metadata and utilities for all Redis commands. It enables Redis client libraries and applications to programmatically validate commands, check command flags, and extract key indexes from command arguments without hardcoding command lists or properties.
npm install redis-commandsconst commands = require('redis-commands');For ES modules:
import * as commands from 'redis-commands';const commands = require('redis-commands');
// Check if a command exists
if (commands.exists('set')) {
console.log('SET command is supported');
}
// Check command flags
if (commands.hasFlag('get', 'readonly')) {
console.log('GET is a read-only command');
}
// Get key indexes for proper key handling
const keyIndexes = commands.getKeyIndexes('mget', ['key1', 'key2', 'key3']);
console.log(keyIndexes); // [0, 1, 2] - all arguments are keys
// List all available commands
console.log(`Total commands: ${commands.list.length}`);
commands.list.forEach(cmd => console.log(cmd));Redis Commands is built around a comprehensive command database stored in commands.json that contains metadata for all Redis commands. The library provides three main components:
The library supports special command patterns including:
Access to the complete list of Redis commands in lowercase format.
/**
* Array containing all Redis command names in lowercase
* @type {string[]}
*/
listVerify if a Redis command exists in the supported command set.
/**
* Check if the Redis command exists
* @param {string} commandName - The command name to check
* @returns {boolean} True if command exists, false otherwise
*/
function exists(commandName)Usage Examples:
// Case-sensitive - commands must be lowercase
commands.exists('set'); // true
commands.exists('get'); // true
commands.exists('SET'); // false - must be lowercase
commands.exists('unknown'); // falseCheck if a Redis command has specific flags or properties.
/**
* Check if the command has the specified flag
* @param {string} commandName - The command name
* @param {string} flag - The flag to check (e.g., 'readonly', 'write', 'noscript', 'loading', 'denyoom', 'fast', 'admin', etc.)
* @returns {boolean} True if command has the flag, false otherwise
* @throws {Error} When commandName is unknown
*/
function hasFlag(commandName, flag)Common Flags:
readonly - Command only reads datawrite - Command writes/modifies datadenyoom - Command denied when Redis is out of memoryadmin - Administrative commandnoscript - Cannot be used in Lua scriptsloading - Can be used during Redis loadingstale - Can work with stale datafast - Fast command executionskip_slowlog - Skip slow query logskip_monitor - Skip monitoringno_auth - No authentication requiredUsage Examples:
// Check if commands are read-only
commands.hasFlag('get', 'readonly'); // true
commands.hasFlag('set', 'readonly'); // false
commands.hasFlag('set', 'write'); // true
// Check administrative commands
commands.hasFlag('flushdb', 'admin'); // true
// Error handling
try {
commands.hasFlag('unknown', 'readonly');
} catch (error) {
console.log(error.message); // "Unknown command unknown"
}Extract the indexes of key arguments from Redis command arguments for proper key handling in Redis clusters and sharding.
/**
* Get indexes of keys in the command arguments
* @param {string} commandName - The Redis command name
* @param {string[]} args - The command arguments array
* @param {object} [options] - Optional configuration
* @param {boolean} [options.parseExternalKey] - Parse external keys for SORT command (default: false)
* @returns {number[]} Array of indexes pointing to key arguments in the args array
* @throws {Error} When commandName is unknown
* @throws {Error} When args is not an array
*/
function getKeyIndexes(commandName, args, options)Usage Examples:
// Simple key commands
commands.getKeyIndexes('get', ['mykey']);
// Returns: [0] - first argument is the key
commands.getKeyIndexes('set', ['mykey', 'value']);
// Returns: [0] - first argument is the key
// Multiple key commands
commands.getKeyIndexes('mget', ['key1', 'key2', 'key3']);
// Returns: [0, 1, 2] - all arguments are keys
commands.getKeyIndexes('mset', ['key1', 'val1', 'key2', 'val2']);
// Returns: [0, 2] - keys are at even indexes
// Complex commands with variable key patterns
commands.getKeyIndexes('eval', ['script', '2', 'key1', 'key2', 'arg1']);
// Returns: [2, 3] - keys follow the key count parameter
commands.getKeyIndexes('zunionstore', ['dest', '2', 'set1', 'set2', 'WEIGHTS', '1', '2']);
// Returns: [0, 2, 3] - destination key and source keys
// SORT command with external key parsing
commands.getKeyIndexes('sort', ['mylist', 'BY', 'weight_*', 'GET', 'name_*'], {
parseExternalKey: true
});
// Returns key indexes including external key references
// Commands with no keys
commands.getKeyIndexes('ping', []);
// Returns: [] - PING has no key arguments
// Error handling
try {
commands.getKeyIndexes('get', 'not-an-array');
} catch (error) {
console.log(error.message); // "Expect args to be an array"
}
try {
commands.getKeyIndexes('unknown', []);
} catch (error) {
console.log(error.message); // "Unknown command unknown"
}Special Command Handling:
The library includes special logic for complex commands:
parseExternalKey optionAdvanced Usage Examples:
// Redis Cluster key validation
function validateKeysForCluster(commandName, args) {
const keyIndexes = commands.getKeyIndexes(commandName, args);
const keys = keyIndexes.map(index => args[index]);
// In Redis Cluster, all keys in a multi-key command must hash to the same slot
if (keys.length > 1) {
console.log(`Multi-key command ${commandName} uses keys:`, keys);
// Additional cluster slot validation would go here
}
return keys;
}
// Redis proxy command filtering
function isReadOnlyCommand(commandName) {
return commands.exists(commandName) && commands.hasFlag(commandName, 'readonly');
}
// Route read-only commands to read replicas
function routeCommand(commandName, args) {
if (isReadOnlyCommand(commandName)) {
return routeToReadReplica(commandName, args);
} else {
return routeToMaster(commandName, args);
}
}
// Memory usage optimization - deny commands that could cause OOM
function checkMemoryConstraints(commandName) {
if (commands.hasFlag(commandName, 'denyoom')) {
if (getMemoryUsage() > MEMORY_THRESHOLD) {
throw new Error(`Command ${commandName} denied due to memory constraints`);
}
}
}/**
* Configuration options for getKeyIndexes function
* @typedef {Object} GetKeyIndexesOptions
* @property {boolean} [parseExternalKey=false] - Parse external keys for SORT command
*/
/**
* Redis command metadata structure (internal use)
* @typedef {Object} CommandMetadata
* @property {number} arity - Number of arguments (-N means at least N arguments)
* @property {string[]} flags - Array of command flags/properties
* @property {number} keyStart - Starting index for keys in arguments (1-based)
* @property {number} keyStop - Ending index for keys in arguments (1-based, 0 means no keys)
* @property {number} step - Step size for key iteration
*/The library throws Error objects for invalid inputs:
commandName doesn't exist in the command databaseargs parameter is not an array for getKeyIndexes()// Handle unknown commands
try {
commands.hasFlag('invalidcmd', 'readonly');
} catch (error) {
if (error.message.includes('Unknown command')) {
console.log('Command not supported');
}
}
// Handle invalid arguments
try {
commands.getKeyIndexes('get', 'invalid');
} catch (error) {
if (error.message.includes('Expect args to be an array')) {
console.log('Arguments must be an array');
}
}