0
# Redis Commands
1
2
Redis 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.
3
4
## Package Information
5
6
- **Package Name**: redis-commands
7
- **Package Type**: npm
8
- **Language**: JavaScript
9
- **Installation**: `npm install redis-commands`
10
11
## Core Imports
12
13
```javascript
14
const commands = require('redis-commands');
15
```
16
17
For ES modules:
18
19
```javascript
20
import * as commands from 'redis-commands';
21
```
22
23
## Basic Usage
24
25
```javascript
26
const commands = require('redis-commands');
27
28
// Check if a command exists
29
if (commands.exists('set')) {
30
console.log('SET command is supported');
31
}
32
33
// Check command flags
34
if (commands.hasFlag('get', 'readonly')) {
35
console.log('GET is a read-only command');
36
}
37
38
// Get key indexes for proper key handling
39
const keyIndexes = commands.getKeyIndexes('mget', ['key1', 'key2', 'key3']);
40
console.log(keyIndexes); // [0, 1, 2] - all arguments are keys
41
42
// List all available commands
43
console.log(`Total commands: ${commands.list.length}`);
44
commands.list.forEach(cmd => console.log(cmd));
45
```
46
47
## Architecture
48
49
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:
50
51
- **Command Database**: Complete Redis command metadata including arity, flags, and key position information
52
- **Flag Processing**: Runtime flag lookup system that processes command flags into indexed structures for fast access
53
- **Key Extraction Engine**: Sophisticated algorithm that handles different Redis command patterns to extract key positions from arguments
54
55
The library supports special command patterns including:
56
- **Variable key commands** (EVAL, EVALSHA): Keys determined by count parameters
57
- **Complex commands** (SORT): Optional external key parsing with pattern matching
58
- **Multi-operation commands** (ZUNIONSTORE, ZINTERSTORE): Multiple key types (destination + sources)
59
- **Stream commands** (XREAD, XREADGROUP): Keys extracted from STREAMS arguments
60
61
## Capabilities
62
63
### Command List
64
65
Access to the complete list of Redis commands in lowercase format.
66
67
```javascript { .api }
68
/**
69
* Array containing all Redis command names in lowercase
70
* @type {string[]}
71
*/
72
list
73
```
74
75
### Command Existence Check
76
77
Verify if a Redis command exists in the supported command set.
78
79
```javascript { .api }
80
/**
81
* Check if the Redis command exists
82
* @param {string} commandName - The command name to check
83
* @returns {boolean} True if command exists, false otherwise
84
*/
85
function exists(commandName)
86
```
87
88
**Usage Examples:**
89
90
```javascript
91
// Case-sensitive - commands must be lowercase
92
commands.exists('set'); // true
93
commands.exists('get'); // true
94
commands.exists('SET'); // false - must be lowercase
95
commands.exists('unknown'); // false
96
```
97
98
### Command Flag Validation
99
100
Check if a Redis command has specific flags or properties.
101
102
```javascript { .api }
103
/**
104
* Check if the command has the specified flag
105
* @param {string} commandName - The command name
106
* @param {string} flag - The flag to check (e.g., 'readonly', 'write', 'noscript', 'loading', 'denyoom', 'fast', 'admin', etc.)
107
* @returns {boolean} True if command has the flag, false otherwise
108
* @throws {Error} When commandName is unknown
109
*/
110
function hasFlag(commandName, flag)
111
```
112
113
**Common Flags:**
114
- `readonly` - Command only reads data
115
- `write` - Command writes/modifies data
116
- `denyoom` - Command denied when Redis is out of memory
117
- `admin` - Administrative command
118
- `noscript` - Cannot be used in Lua scripts
119
- `loading` - Can be used during Redis loading
120
- `stale` - Can work with stale data
121
- `fast` - Fast command execution
122
- `skip_slowlog` - Skip slow query log
123
- `skip_monitor` - Skip monitoring
124
- `no_auth` - No authentication required
125
126
**Usage Examples:**
127
128
```javascript
129
// Check if commands are read-only
130
commands.hasFlag('get', 'readonly'); // true
131
commands.hasFlag('set', 'readonly'); // false
132
commands.hasFlag('set', 'write'); // true
133
134
// Check administrative commands
135
commands.hasFlag('flushdb', 'admin'); // true
136
137
// Error handling
138
try {
139
commands.hasFlag('unknown', 'readonly');
140
} catch (error) {
141
console.log(error.message); // "Unknown command unknown"
142
}
143
```
144
145
### Key Index Extraction
146
147
Extract the indexes of key arguments from Redis command arguments for proper key handling in Redis clusters and sharding.
148
149
```javascript { .api }
150
/**
151
* Get indexes of keys in the command arguments
152
* @param {string} commandName - The Redis command name
153
* @param {string[]} args - The command arguments array
154
* @param {object} [options] - Optional configuration
155
* @param {boolean} [options.parseExternalKey] - Parse external keys for SORT command (default: false)
156
* @returns {number[]} Array of indexes pointing to key arguments in the args array
157
* @throws {Error} When commandName is unknown
158
* @throws {Error} When args is not an array
159
*/
160
function getKeyIndexes(commandName, args, options)
161
```
162
163
**Usage Examples:**
164
165
```javascript
166
// Simple key commands
167
commands.getKeyIndexes('get', ['mykey']);
168
// Returns: [0] - first argument is the key
169
170
commands.getKeyIndexes('set', ['mykey', 'value']);
171
// Returns: [0] - first argument is the key
172
173
// Multiple key commands
174
commands.getKeyIndexes('mget', ['key1', 'key2', 'key3']);
175
// Returns: [0, 1, 2] - all arguments are keys
176
177
commands.getKeyIndexes('mset', ['key1', 'val1', 'key2', 'val2']);
178
// Returns: [0, 2] - keys are at even indexes
179
180
// Complex commands with variable key patterns
181
commands.getKeyIndexes('eval', ['script', '2', 'key1', 'key2', 'arg1']);
182
// Returns: [2, 3] - keys follow the key count parameter
183
184
commands.getKeyIndexes('zunionstore', ['dest', '2', 'set1', 'set2', 'WEIGHTS', '1', '2']);
185
// Returns: [0, 2, 3] - destination key and source keys
186
187
// SORT command with external key parsing
188
commands.getKeyIndexes('sort', ['mylist', 'BY', 'weight_*', 'GET', 'name_*'], {
189
parseExternalKey: true
190
});
191
// Returns key indexes including external key references
192
193
// Commands with no keys
194
commands.getKeyIndexes('ping', []);
195
// Returns: [] - PING has no key arguments
196
197
// Error handling
198
try {
199
commands.getKeyIndexes('get', 'not-an-array');
200
} catch (error) {
201
console.log(error.message); // "Expect args to be an array"
202
}
203
204
try {
205
commands.getKeyIndexes('unknown', []);
206
} catch (error) {
207
console.log(error.message); // "Unknown command unknown"
208
}
209
```
210
211
**Special Command Handling:**
212
213
The library includes special logic for complex commands:
214
215
- **EVAL/EVALSHA**: Keys determined by the key count parameter
216
- **SORT**: Supports external key parsing with `parseExternalKey` option
217
- **MIGRATE**: Handles both single key and KEYS list variants
218
- **XREAD/XREADGROUP**: Extracts keys from STREAMS arguments
219
- **ZUNIONSTORE/ZINTERSTORE**: Includes destination and source keys
220
221
**Advanced Usage Examples:**
222
223
```javascript
224
// Redis Cluster key validation
225
function validateKeysForCluster(commandName, args) {
226
const keyIndexes = commands.getKeyIndexes(commandName, args);
227
const keys = keyIndexes.map(index => args[index]);
228
229
// In Redis Cluster, all keys in a multi-key command must hash to the same slot
230
if (keys.length > 1) {
231
console.log(`Multi-key command ${commandName} uses keys:`, keys);
232
// Additional cluster slot validation would go here
233
}
234
235
return keys;
236
}
237
238
// Redis proxy command filtering
239
function isReadOnlyCommand(commandName) {
240
return commands.exists(commandName) && commands.hasFlag(commandName, 'readonly');
241
}
242
243
// Route read-only commands to read replicas
244
function routeCommand(commandName, args) {
245
if (isReadOnlyCommand(commandName)) {
246
return routeToReadReplica(commandName, args);
247
} else {
248
return routeToMaster(commandName, args);
249
}
250
}
251
252
// Memory usage optimization - deny commands that could cause OOM
253
function checkMemoryConstraints(commandName) {
254
if (commands.hasFlag(commandName, 'denyoom')) {
255
if (getMemoryUsage() > MEMORY_THRESHOLD) {
256
throw new Error(`Command ${commandName} denied due to memory constraints`);
257
}
258
}
259
}
260
```
261
262
## Types
263
264
```javascript { .api }
265
/**
266
* Configuration options for getKeyIndexes function
267
* @typedef {Object} GetKeyIndexesOptions
268
* @property {boolean} [parseExternalKey=false] - Parse external keys for SORT command
269
*/
270
271
/**
272
* Redis command metadata structure (internal use)
273
* @typedef {Object} CommandMetadata
274
* @property {number} arity - Number of arguments (-N means at least N arguments)
275
* @property {string[]} flags - Array of command flags/properties
276
* @property {number} keyStart - Starting index for keys in arguments (1-based)
277
* @property {number} keyStop - Ending index for keys in arguments (1-based, 0 means no keys)
278
* @property {number} step - Step size for key iteration
279
*/
280
```
281
282
## Error Handling
283
284
The library throws `Error` objects for invalid inputs:
285
286
- **Unknown command**: When `commandName` doesn't exist in the command database
287
- **Invalid arguments**: When `args` parameter is not an array for `getKeyIndexes()`
288
289
```javascript
290
// Handle unknown commands
291
try {
292
commands.hasFlag('invalidcmd', 'readonly');
293
} catch (error) {
294
if (error.message.includes('Unknown command')) {
295
console.log('Command not supported');
296
}
297
}
298
299
// Handle invalid arguments
300
try {
301
commands.getKeyIndexes('get', 'invalid');
302
} catch (error) {
303
if (error.message.includes('Expect args to be an array')) {
304
console.log('Arguments must be an array');
305
}
306
}
307
```