node-red-contrib-redis-variable 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,769 @@
1
+ # node-red-contrib-redis-variable
2
+
3
+ A comprehensive Node-RED node for Redis operations with flexible connection management and modern features.
4
+
5
+ **Developed by Andrii Lototskyi**
6
+
7
+ ## 🚀 Features
8
+
9
+ ### 🔧 **Flexible Connection Management**
10
+ - **Multiple Input Types**: Host, port, database, username, password support string values, flow/global context, and environment variables
11
+ - **Secure Credentials**: String values stored encrypted in Node-RED credentials
12
+ - **Runtime Resolution**: Context and environment variables resolved at runtime
13
+ - **SSL/TLS Support**: Full SSL/TLS encryption with client certificates and custom CAs
14
+ - **Advanced Configuration**: JSON-based advanced options for Redis client
15
+
16
+ ### 📊 **Comprehensive Redis Operations**
17
+
18
+ #### **Universal Payload Interface**
19
+ - **Flexible Input**: All operations use `msg.payload` for parameters
20
+ - **Simple Format**: Single keys can be passed as strings
21
+ - **Object Format**: Complex operations use structured objects
22
+ - **Consistent Returns**: Standardized response format across all operations
23
+
24
+ #### **Basic Operations**
25
+ - **GET** - Retrieve value by key
26
+ - **SET** - Store value with optional TTL
27
+ - **DEL** - Delete single or multiple keys
28
+ - **EXISTS** - Check if single or multiple keys exist
29
+
30
+ #### **TTL Operations**
31
+ - **TTL** - Get remaining time to live in seconds
32
+ - **EXPIRE** - Set expiration time for existing key
33
+ - **PERSIST** - Remove expiration from key
34
+
35
+ #### **Counter Operations**
36
+ - **INCR** - Increment value by 1
37
+ - **DECR** - Decrement value by 1
38
+ - **INCRBY** - Increment value by N
39
+ - **DECRBY** - Decrement value by N
40
+
41
+ #### **List Operations**
42
+ - **LPUSH** - Add element to beginning of list
43
+ - **RPUSH** - Add element to end of list
44
+ - **LPOP** - Remove and return first element
45
+ - **RPOP** - Remove and return last element
46
+ - **LLEN** - Get list length
47
+ - **LRANGE** - Get range of elements
48
+
49
+ #### **Hash Operations**
50
+ - **HSET** - Set hash field value (single or multiple fields)
51
+ - **HGET** - Get hash field value
52
+ - **HGETALL** - Get all hash fields and values
53
+ - **HDEL** - Delete hash field(s)
54
+
55
+ #### **Pub/Sub Operations**
56
+ - **PUBLISH** - Publish message to channel
57
+
58
+ ## Installation
59
+
60
+ ```bash
61
+ npm install node-red-contrib-redis-variable
62
+ ```
63
+
64
+ Or install directly through the Node-RED palette manager.
65
+
66
+ ## Configuration
67
+
68
+ ### Redis Configuration Node
69
+
70
+ The Redis configuration node supports flexible connection parameters:
71
+
72
+ #### Connection Settings
73
+ - **Host**: Redis server hostname or IP address
74
+ - **Port**: Redis server port (default: 6379)
75
+ - **Database**: Redis database number (default: 0)
76
+ - **Cluster Mode**: Enable for Redis Cluster deployments
77
+
78
+ #### Authentication
79
+ - **Username**: Redis username (Redis 6.0+ ACL support)
80
+ - **Password**: Redis password for authentication
81
+
82
+ #### Credential Sources
83
+ All connection parameters support multiple input types:
84
+ - **String**: Direct value stored securely in Node-RED credentials
85
+ - **Flow Context**: Retrieved from flow context variables
86
+ - **Global Context**: Retrieved from global context variables
87
+ - **Environment Variable**: Retrieved from environment variables
88
+
89
+ #### Advanced Options
90
+ JSON object with additional ioredis connection options:
91
+ ```json
92
+ {
93
+ "connectTimeout": 10000,
94
+ "lazyConnect": true,
95
+ "keepAlive": 30000,
96
+ "family": 4,
97
+ "retryDelayOnFailover": 100
98
+ }
99
+ ```
100
+
101
+ #### SSL/TLS Configuration
102
+ The module provides comprehensive SSL/TLS support for secure Redis connections:
103
+
104
+ ##### SSL Settings
105
+ - **Enable SSL/TLS**: Enable secure connection to Redis server
106
+ - **Verify Certificate**: Validate server certificates (recommended for production)
107
+ - **Client Certificate**: Client certificate for mutual TLS authentication
108
+ - **Private Key**: Private key corresponding to client certificate
109
+ - **CA Certificate**: Certificate Authority certificate for custom CAs
110
+
111
+ ##### SSL Examples
112
+
113
+ **Basic SSL (server verification only):**
114
+ ```
115
+ Enable SSL/TLS: ✓
116
+ Verify Certificate: ✓
117
+ Client Certificate: (empty)
118
+ Private Key: (empty)
119
+ CA Certificate: (empty)
120
+ ```
121
+
122
+ **Mutual TLS (client + server authentication):**
123
+ ```
124
+ Enable SSL/TLS: ✓
125
+ Verify Certificate: ✓
126
+ Client Certificate: Your client certificate
127
+ Private Key: Your private key
128
+ CA Certificate: Custom CA if needed
129
+ ```
130
+
131
+ **Self-signed certificates:**
132
+ ```
133
+ Enable SSL/TLS: ✓
134
+ Verify Certificate: ✗ (disable for self-signed)
135
+ CA Certificate: Your self-signed CA
136
+ ```
137
+
138
+ **Environment-based SSL configuration:**
139
+ ```
140
+ Enable SSL/TLS: ✓
141
+ Client Certificate Type: Environment Variable → TLS_CLIENT_CERT
142
+ Private Key Type: Environment Variable → TLS_PRIVATE_KEY
143
+ CA Certificate Type: Environment Variable → TLS_CA_CERT
144
+ ```
145
+
146
+ ### Example Configurations
147
+
148
+ #### Environment-based Configuration
149
+ ```
150
+ Host: Environment Variable → REDIS_HOST
151
+ Port: Environment Variable → REDIS_PORT
152
+ Password: Environment Variable → REDIS_PASSWORD
153
+ ```
154
+
155
+ #### Context-based Configuration
156
+ ```
157
+ Host: Global Context → redis_config.host
158
+ Port: Global Context → redis_config.port
159
+ Password: Flow Context → redis_password
160
+ ```
161
+
162
+ ## Operations
163
+
164
+ **Universal Payload Interface**: All Redis operations use a unified `msg.payload` interface. Parameters can be passed as simple strings (for single keys) or as objects with specific properties. This provides flexibility while maintaining simplicity.
165
+
166
+ ### Basic Operations
167
+
168
+ #### GET - Retrieve Value
169
+ ```javascript
170
+ // Simple key format
171
+ msg.payload = "user:123";
172
+ // Returns: { payload: "stored_value" }
173
+
174
+ // Object format
175
+ msg.payload = {
176
+ key: "user:123"
177
+ };
178
+ // Returns: { payload: "stored_value" }
179
+ ```
180
+
181
+ #### SET - Store Value
182
+ ```javascript
183
+ // Simple SET
184
+ msg.payload = {
185
+ key: "user:123",
186
+ value: "John Doe"
187
+ };
188
+ // Returns: { payload: { success: true, result: "OK", ttl: null } }
189
+
190
+ // SET with TTL
191
+ msg.payload = {
192
+ key: "session:abc123",
193
+ value: { userId: 42, role: "admin" },
194
+ ttl: 3600
195
+ };
196
+ // Returns: { payload: { success: true, result: "OK", ttl: 3600 } }
197
+ ```
198
+
199
+ #### DEL - Delete Key
200
+ ```javascript
201
+ // Delete single key
202
+ msg.payload = {
203
+ key: "mykey"
204
+ };
205
+ // Or simple format
206
+ msg.payload = "mykey";
207
+ // Returns: { payload: { success: true, deleted: 1, keys: ["mykey"] } }
208
+
209
+ // Delete multiple keys
210
+ msg.payload = {
211
+ keys: ["key1", "key2", "key3"]
212
+ };
213
+ // Returns: { payload: { success: true, deleted: 3, keys: ["key1", "key2", "key3"] } }
214
+ ```
215
+
216
+ #### EXISTS - Check Key Existence
217
+ ```javascript
218
+ // Check single key
219
+ msg.payload = "mykey";
220
+ // Or object format
221
+ msg.payload = {
222
+ key: "mykey"
223
+ };
224
+ // Returns: { payload: { exists: true, count: 1, keys: ["mykey"] } }
225
+
226
+ // Check multiple keys
227
+ msg.payload = {
228
+ keys: ["key1", "key2", "key3"]
229
+ };
230
+ // Returns: { payload: { exists: true, count: 2, keys: ["key1", "key2", "key3"] } }
231
+ ```
232
+
233
+ #### TTL - Get Time To Live
234
+ ```javascript
235
+ msg.payload = "mykey";
236
+ // Returns: { payload: { key: "mykey", ttl: 3600, status: "expires in 3600 seconds" } }
237
+ ```
238
+
239
+ #### EXPIRE - Set Key Expiration
240
+ ```javascript
241
+ msg.payload = {
242
+ key: "mykey",
243
+ ttl: 3600
244
+ };
245
+ // Returns: { payload: { success: true, key: "mykey", ttl: 3600, message: "Expiration set" } }
246
+ ```
247
+
248
+ #### PERSIST - Remove Expiration
249
+ ```javascript
250
+ msg.payload = "mykey";
251
+ // Returns: { payload: { success: true, key: "mykey", message: "Expiration removed" } }
252
+ ```
253
+
254
+ #### INCR/DECR - Increment/Decrement
255
+ ```javascript
256
+ // Simple increment
257
+ msg.payload = "counter";
258
+ // Returns: { payload: { key: "counter", value: 1 } }
259
+
260
+ // Increment by amount
261
+ msg.payload = {
262
+ key: "score",
263
+ amount: 10
264
+ };
265
+ // Returns: { payload: { key: "score", value: 110, increment: 10 } }
266
+ ```
267
+
268
+ ### List Operations
269
+
270
+ #### LPUSH/RPUSH - Add to List
271
+ ```javascript
272
+ msg.payload = {
273
+ key: "mylist",
274
+ value: "item1"
275
+ };
276
+ // Returns: { payload: { success: true, key: "mylist", length: 1, operation: "lpush" } }
277
+ ```
278
+
279
+ #### LPOP/RPOP - Remove from List
280
+ ```javascript
281
+ msg.payload = "mylist";
282
+ // Returns: { payload: "item1" }
283
+ ```
284
+
285
+ #### LLEN - Get List Length
286
+ ```javascript
287
+ msg.payload = "mylist";
288
+ // Returns: { payload: { key: "mylist", length: 5 } }
289
+ ```
290
+
291
+ #### LRANGE - Get List Range
292
+ ```javascript
293
+ msg.payload = {
294
+ key: "mylist",
295
+ start: 0,
296
+ stop: -1
297
+ };
298
+ // Returns: { payload: { key: "mylist", range: {start: 0, stop: -1}, values: ["item1", "item2", "item3"], count: 3 } }
299
+ ```
300
+
301
+ #### BLPOP/BRPOP - Blocking Pop
302
+ Configure timeout in node settings. These operations run continuously and emit messages when items are available.
303
+
304
+ ### Hash Operations
305
+
306
+ #### HSET - Set Hash Field
307
+ ```javascript
308
+ // Single field
309
+ msg.payload = {
310
+ key: "myhash",
311
+ field: "name",
312
+ value: "John"
313
+ };
314
+ // Returns: { payload: { success: true, key: "myhash", field: "name", created: true } }
315
+
316
+ // Multiple fields
317
+ msg.payload = {
318
+ key: "myhash",
319
+ fields: {
320
+ name: "John",
321
+ age: 30,
322
+ city: "New York"
323
+ }
324
+ };
325
+ // Returns: { payload: { success: true, key: "myhash", fields: ["name", "age", "city"], created: 3 } }
326
+ ```
327
+
328
+ #### HGET - Get Hash Field
329
+ ```javascript
330
+ msg.payload = {
331
+ key: "myhash",
332
+ field: "name"
333
+ };
334
+ // Returns: { payload: "John" }
335
+ ```
336
+
337
+ #### HGETALL - Get All Hash Fields
338
+ ```javascript
339
+ msg.payload = "myhash";
340
+ // Returns: { payload: { name: "John", age: "30", city: "New York" } }
341
+ ```
342
+
343
+ #### HDEL - Delete Hash Field
344
+ ```javascript
345
+ // Delete single field
346
+ msg.payload = {
347
+ key: "myhash",
348
+ field: "age"
349
+ };
350
+ // Returns: { payload: { success: true, key: "myhash", deleted: 1, fields: ["age"] } }
351
+
352
+ // Delete multiple fields
353
+ msg.payload = {
354
+ key: "myhash",
355
+ fields: ["age", "city"]
356
+ };
357
+ // Returns: { payload: { success: true, key: "myhash", deleted: 2, fields: ["age", "city"] } }
358
+ ```
359
+
360
+ ### Pub/Sub Operations
361
+
362
+ #### PUBLISH - Publish Message
363
+ ```javascript
364
+ msg.payload = {
365
+ channel: "mychannel",
366
+ message: "Hello World"
367
+ };
368
+ // Returns: { payload: { success: true, channel: "mychannel", subscribers: 2, message: "Hello World" } }
369
+ ```
370
+
371
+ #### SUBSCRIBE - Subscribe to Channel
372
+ Configure channel in node settings. Messages are automatically emitted:
373
+ ```javascript
374
+ // Received message format:
375
+ {
376
+ topic: "mychannel",
377
+ payload: "Hello World"
378
+ }
379
+ ```
380
+
381
+ #### PSUBSCRIBE - Pattern Subscribe
382
+ Configure pattern in node settings (e.g., "news.*"):
383
+ ```javascript
384
+ // Received message format:
385
+ {
386
+ pattern: "news.*",
387
+ topic: "news.sports",
388
+ payload: "Sports update"
389
+ }
390
+ ```
391
+
392
+ ### Advanced Operations
393
+
394
+ #### Lua Script Execution
395
+ ```javascript
396
+ // Configure Lua script in node editor:
397
+ // return redis.call('GET', KEYS[1])
398
+
399
+ msg.payload = ["mykey"]; // Array of keys and arguments
400
+ // Returns: { payload: "script_result" }
401
+ ```
402
+
403
+ #### Redis Instance in Context
404
+ Stores Redis client in flow or global context for direct access:
405
+ ```javascript
406
+ // Access stored instance
407
+ const redis = flow.get("redis_client");
408
+ const result = await redis.get("mykey");
409
+ ```
410
+
411
+ ## 🔄 Automatic JSON Handling
412
+
413
+ The module automatically detects and handles JSON data without any configuration:
414
+
415
+ ### 🤖 Smart Detection
416
+ - **Objects**: JavaScript objects are automatically serialized to JSON strings when storing
417
+ - **JSON Strings**: Valid JSON strings are automatically parsed back to objects when retrieving
418
+ - **Simple Values**: Strings, numbers, and other simple types are handled as-is
419
+ - **Arrays**: Each item in Redis lists is automatically parsed if it's valid JSON
420
+
421
+ ### 📝 Examples
422
+
423
+ #### Storing Objects
424
+ ```javascript
425
+ msg.payload = {
426
+ key: "user:123",
427
+ value: {
428
+ name: "John Doe",
429
+ age: 30,
430
+ preferences: {
431
+ theme: "dark",
432
+ language: "en"
433
+ }
434
+ }
435
+ };
436
+ // Automatically stored as: '{"name":"John Doe","age":30,"preferences":{"theme":"dark","language":"en"}}'
437
+ ```
438
+
439
+ #### Retrieving Objects
440
+ ```javascript
441
+ msg.payload = "user:123";
442
+ // Returns: {
443
+ // "name": "John Doe",
444
+ // "age": 30,
445
+ // "preferences": {
446
+ // "theme": "dark",
447
+ // "language": "en"
448
+ // }
449
+ // }
450
+ ```
451
+
452
+ #### Mixed Data Types
453
+ ```javascript
454
+ // Store simple string
455
+ msg.payload = {
456
+ key: "message",
457
+ value: "Hello World"
458
+ };
459
+ // Returns: "Hello World"
460
+
461
+ // Store number
462
+ msg.payload = {
463
+ key: "count",
464
+ value: 42
465
+ };
466
+ // Returns: "42"
467
+
468
+ // Store object
469
+ msg.payload = {
470
+ key: "config",
471
+ value: {
472
+ debug: true,
473
+ timeout: 5000
474
+ }
475
+ };
476
+ // Returns: {debug: true, timeout: 5000}
477
+ ```
478
+
479
+ ## Connection Management
480
+
481
+ ### Connection Pooling
482
+ - Connections are automatically pooled and reused across nodes
483
+ - Each configuration creates a single connection pool
484
+ - Connections are automatically cleaned up when nodes are removed
485
+
486
+ ### Blocking Operations
487
+ For blocking operations (BLPOP, BRPOP, Lua scripts), enable "Force new connection" to prevent blocking other operations.
488
+
489
+ ### Error Handling
490
+ All operations include comprehensive error handling:
491
+ ```javascript
492
+ // Error response format:
493
+ {
494
+ payload: {
495
+ error: "Connection failed: ECONNREFUSED"
496
+ }
497
+ }
498
+ ```
499
+
500
+ ## Security Best Practices
501
+
502
+ 1. **Use Environment Variables**: Store sensitive credentials in environment variables
503
+ 2. **Enable Redis AUTH**: Always use password authentication in production
504
+ 3. **Use Redis ACLs**: Implement fine-grained access control (Redis 6.0+)
505
+ 4. **Enable SSL/TLS**: Use encrypted connections for production environments
506
+ 5. **Verify Certificates**: Always verify server certificates in production
507
+ 6. **Secure Certificate Storage**: Store certificates and keys in environment variables or secure context
508
+ 7. **Network Security**: Use TLS/SSL for connections over untrusted networks
509
+ 8. **Principle of Least Privilege**: Grant minimal required permissions
510
+
511
+ ## Examples
512
+
513
+ ### Basic Key-Value Storage
514
+ ```javascript
515
+ // Store user session
516
+ msg.payload = {
517
+ key: "session:abc123",
518
+ value: {
519
+ userId: 456,
520
+ loginTime: new Date().toISOString(),
521
+ permissions: ["read", "write"]
522
+ },
523
+ ttl: 3600 // 1 hour expiration
524
+ };
525
+ ```
526
+
527
+ ### Message Queue with Lists
528
+ ```javascript
529
+ // Producer - Add task to queue
530
+ msg.payload = {
531
+ key: "task_queue",
532
+ value: {
533
+ id: "task_001",
534
+ type: "email",
535
+ data: { to: "user@example.com", subject: "Welcome" }
536
+ }
537
+ };
538
+
539
+ // Consumer (using BLPOP)
540
+ // Configure BLPOP operation in node settings
541
+ // Automatically receives tasks as they're added
542
+ ```
543
+
544
+ ### Caching with Expiration
545
+ ```javascript
546
+ // Cache API response for 1 hour
547
+ msg.payload = {
548
+ key: "api_cache:users",
549
+ value: apiResponse,
550
+ ttl: 3600 // 1 hour
551
+ };
552
+ ```
553
+
554
+ ### Real-time Notifications
555
+ ```javascript
556
+ // Publisher
557
+ msg.payload = {
558
+ channel: "notifications:user:123",
559
+ message: {
560
+ type: "message",
561
+ from: "user:456",
562
+ content: "Hello there!"
563
+ }
564
+ };
565
+
566
+ // Subscriber automatically receives notifications
567
+ ```
568
+
569
+ ## 📖 Usage Examples
570
+
571
+ ### Basic Operations
572
+
573
+ #### GET Operation
574
+ ```javascript
575
+ // Simple format
576
+ msg.payload = "user:123";
577
+
578
+ // Object format
579
+ msg.payload = {
580
+ key: "user:123"
581
+ };
582
+ // Returns: "John Doe" (or stored value)
583
+ ```
584
+
585
+ #### SET Operation
586
+ ```javascript
587
+ // Simple SET
588
+ msg.payload = {
589
+ key: "user:123",
590
+ value: "John Doe"
591
+ };
592
+
593
+ // SET with TTL (expires in 1 hour)
594
+ msg.payload = {
595
+ key: "session:abc123",
596
+ value: {userId: 42, role: "admin"},
597
+ ttl: 3600
598
+ };
599
+ // Returns: { success: true, result: "OK", ttl: 3600 }
600
+ ```
601
+
602
+ #### DELETE Operations
603
+ ```javascript
604
+ // Delete single key
605
+ msg.payload = {
606
+ key: "temp:data"
607
+ };
608
+
609
+ // Delete multiple keys
610
+ msg.payload = {
611
+ keys: ["cache:page1", "cache:page2", "temp:data"]
612
+ };
613
+ // Returns: { success: true, deleted: 3, keys: [...] }
614
+ ```
615
+
616
+ ### TTL Operations
617
+
618
+ #### Check TTL
619
+ ```javascript
620
+ msg.payload = "session:abc123";
621
+ // Returns: { key: "session:abc123", ttl: 2847, status: "expires in 2847 seconds" }
622
+ ```
623
+
624
+ #### Set Expiration
625
+ ```javascript
626
+ msg.payload = {
627
+ key: "temp:data",
628
+ ttl: 1800
629
+ };
630
+ // Returns: { success: true, key: "temp:data", ttl: 1800, message: "Expiration set" }
631
+ ```
632
+
633
+ #### Remove Expiration
634
+ ```javascript
635
+ msg.payload = "permanent:key";
636
+ // Returns: { success: true, key: "permanent:key", message: "Expiration removed" }
637
+ ```
638
+
639
+ ### Counter Operations
640
+
641
+ #### Increment Counter
642
+ ```javascript
643
+ // Simple increment
644
+ msg.payload = "page:views";
645
+ // Returns: { key: "page:views", value: 1547 }
646
+
647
+ // Increment by amount
648
+ msg.payload = {
649
+ key: "score:player1",
650
+ amount: 100
651
+ };
652
+ // Returns: { key: "score:player1", value: 2350, increment: 100 }
653
+ ```
654
+
655
+ ### List Operations
656
+
657
+ #### Add to List
658
+ ```javascript
659
+ msg.payload = {
660
+ key: "queue:tasks",
661
+ value: {
662
+ task: "process_order",
663
+ id: 12345
664
+ }
665
+ };
666
+ // Returns: { success: true, key: "queue:tasks", length: 8, operation: "lpush" }
667
+ ```
668
+
669
+ #### Get List Range
670
+ ```javascript
671
+ msg.payload = {
672
+ key: "queue:tasks",
673
+ start: 0,
674
+ stop: 4
675
+ };
676
+ // Returns: { key: "queue:tasks", range: {start: 0, stop: 4}, values: [...], count: 5 }
677
+ ```
678
+
679
+ #### Pop from List
680
+ ```javascript
681
+ msg.payload = "queue:tasks";
682
+ // Returns: {"task": "process_order", "id": 12345} (first item)
683
+ ```
684
+
685
+ ### Hash Operations
686
+
687
+ #### Set Hash Fields
688
+ ```javascript
689
+ // Single field
690
+ msg.payload = {
691
+ key: "user:123",
692
+ field: "email",
693
+ value: "john.doe@example.com"
694
+ };
695
+ // Returns: { success: true, key: "user:123", field: "email", created: true }
696
+
697
+ // Multiple fields
698
+ msg.payload = {
699
+ key: "user:123",
700
+ fields: {
701
+ name: "John Doe",
702
+ age: 30,
703
+ city: "New York",
704
+ active: true
705
+ }
706
+ };
707
+ // Returns: { success: true, key: "user:123", fields: ["name", "age", "city", "active"], created: 4 }
708
+ ```
709
+
710
+ #### Get Hash Data
711
+ ```javascript
712
+ // Get single field
713
+ msg.payload = {
714
+ key: "user:123",
715
+ field: "email"
716
+ };
717
+ // Returns: "john.doe@example.com"
718
+
719
+ // Get all fields
720
+ msg.payload = "user:123";
721
+ // Returns: { name: "John Doe", age: "30", city: "New York", email: "john.doe@example.com", active: "true" }
722
+ ```
723
+
724
+ ### Pub/Sub Operations
725
+
726
+ #### Publish Message
727
+ ```javascript
728
+ msg.payload = {
729
+ channel: "notifications",
730
+ message: {
731
+ type: "alert",
732
+ text: "System maintenance in 5 minutes",
733
+ timestamp: "2024-01-15T10:30:00Z"
734
+ }
735
+ };
736
+ // Returns: { success: true, channel: "notifications", subscribers: 3, message: "..." }
737
+ ```
738
+
739
+ ## Troubleshooting
740
+
741
+ ### Common Issues
742
+
743
+ 1. **Connection Refused**: Check Redis server is running and accessible
744
+ 2. **Authentication Failed**: Verify username/password configuration
745
+ 3. **Timeout Errors**: Increase connection timeout in advanced options
746
+ 4. **Memory Issues**: Monitor Redis memory usage and configure appropriate limits
747
+
748
+ ### Debug Mode
749
+ Enable Node-RED debug mode to see detailed connection and operation logs:
750
+ ```bash
751
+ DEBUG=redis* node-red
752
+ ```
753
+
754
+ ## Contributing
755
+
756
+ Contributions are welcome! Please read the contributing guidelines and submit pull requests to the GitHub repository.
757
+
758
+ ## License
759
+
760
+ MIT License - see LICENSE file for details.
761
+
762
+ ## Changelog
763
+
764
+ ### v1.0.0
765
+ - Initial release
766
+ - Complete Redis operations support
767
+ - Flexible connection management
768
+ - Modern ioredis integration
769
+ - Comprehensive documentation