redis 5.0.0 → 5.1.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 CHANGED
@@ -1,195 +1,322 @@
1
1
  # Node-Redis
2
2
 
3
+ [![Tests](https://img.shields.io/github/actions/workflow/status/redis/node-redis/tests.yml?branch=master)](https://github.com/redis/node-redis/actions/workflows/tests.yml)
4
+ [![Coverage](https://codecov.io/gh/redis/node-redis/branch/master/graph/badge.svg?token=xcfqHhJC37)](https://codecov.io/gh/redis/node-redis)
5
+ [![License](https://img.shields.io/github/license/redis/node-redis.svg)](https://github.com/redis/node-redis/blob/master/LICENSE)
6
+
7
+ [![Discord](https://img.shields.io/discord/697882427875393627.svg?style=social&logo=discord)](https://discord.gg/redis)
8
+ [![Twitch](https://img.shields.io/twitch/status/redisinc?style=social)](https://www.twitch.tv/redisinc)
9
+ [![YouTube](https://img.shields.io/youtube/channel/views/UCD78lHSwYqMlyetR0_P4Vig?style=social)](https://www.youtube.com/redisinc)
10
+ [![Twitter](https://img.shields.io/twitter/follow/redisinc?style=social)](https://twitter.com/redisinc)
11
+
12
+ node-redis is a modern, high performance [Redis](https://redis.io) client for Node.js.
13
+
14
+ ## How do I Redis?
15
+
16
+ [Learn for free at Redis University](https://university.redis.com/)
17
+
18
+ [Build faster with the Redis Launchpad](https://launchpad.redis.com/)
19
+
20
+ [Try the Redis Cloud](https://redis.com/try-free/)
21
+
22
+ [Dive in developer tutorials](https://developer.redis.com/)
23
+
24
+ [Join the Redis community](https://redis.com/community/)
25
+
26
+ [Work at Redis](https://redis.com/company/careers/jobs/)
27
+
28
+ ## Installation
29
+
30
+ Start a redis via docker:
31
+
32
+ ```bash
33
+ docker run -p 6379:6379 -d redis:8.0-rc1
34
+ ```
35
+
36
+ To install node-redis, simply:
37
+
38
+ ```bash
39
+ npm install redis
40
+ ```
41
+ > "redis" is the "whole in one" package that includes all the other packages. If you only need a subset of the commands,
42
+ > you can install the individual packages. See the list below.
43
+
44
+ ## Packages
45
+
46
+ | Name | Description |
47
+ | ---------------------------------------------- | ------------------------------------------------------------------------------------------- |
48
+ | [`redis`](../redis) | The client with all the ["redis-stack"](https://github.com/redis-stack/redis-stack) modules |
49
+ | [`@redis/client`](../client) | The base clients (i.e `RedisClient`, `RedisCluster`, etc.) |
50
+ | [`@redis/bloom`](../bloom) | [Redis Bloom](https://redis.io/docs/data-types/probabilistic/) commands |
51
+ | [`@redis/json`](../json) | [Redis JSON](https://redis.io/docs/data-types/json/) commands |
52
+ | [`@redis/search`](../search) | [RediSearch](https://redis.io/docs/interact/search-and-query/) commands |
53
+ | [`@redis/time-series`](../time-series) | [Redis Time-Series](https://redis.io/docs/data-types/timeseries/) commands |
54
+ | [`@redis/entraid`](../entraid) | Secure token-based authentication for Redis clients using Microsoft Entra ID |
55
+
56
+ > Looking for a high-level library to handle object mapping?
57
+ > See [redis-om-node](https://github.com/redis/redis-om-node)!
58
+
59
+
3
60
  ## Usage
4
61
 
5
62
  ### Basic Example
6
63
 
7
- ```javascript
8
- import { createClient } from 'redis';
64
+ ```typescript
65
+ import { createClient } from "redis";
9
66
 
10
67
  const client = await createClient()
11
- .on('error', err => console.log('Redis Client Error', err))
68
+ .on("error", (err) => console.log("Redis Client Error", err))
12
69
  .connect();
13
70
 
14
- await client.set('key', 'value');
15
- const value = await client.get('key');
16
- await client.close();
71
+ await client.set("key", "value");
72
+ const value = await client.get("key");
73
+ client.destroy();
17
74
  ```
18
75
 
19
- > :warning: You **MUST** listen to `error` events. If a client doesn't have at least one `error` listener registered and an `error` occurs, that error will be thrown and the Node.js process will exit. See the [`EventEmitter` docs](https://nodejs.org/api/events.html#error-events) for more details.
20
-
21
- The above code connects to localhost on port 6379. To connect to a different host or port, use a connection string in the format `redis[s]://[[username][:password]@][host][:port][/db-number]`:
76
+ The above code connects to localhost on port 6379. To connect to a different host or port, use a connection string in
77
+ the format `redis[s]://[[username][:password]@][host][:port][/db-number]`:
22
78
 
23
- ```javascript
79
+ ```typescript
24
80
  createClient({
25
- url: 'redis://alice:foobared@awesome.redis.server:6380'
81
+ url: "redis://alice:foobared@awesome.redis.server:6380",
26
82
  });
27
83
  ```
28
84
 
29
- You can also use discrete parameters, UNIX sockets, and even TLS to connect. Details can be found in the [client configuration guide](../../docs/client-configuration.md).
85
+ You can also use discrete parameters, UNIX sockets, and even TLS to connect. Details can be found in
86
+ the [client configuration guide](../../docs/client-configuration.md).
87
+
88
+ To check if the the client is connected and ready to send commands, use `client.isReady` which returns a boolean.
89
+ `client.isOpen` is also available. This returns `true` when the client's underlying socket is open, and `false` when it
90
+ isn't (for example when the client is still connecting or reconnecting after a network error).
30
91
 
31
92
  ### Redis Commands
32
93
 
33
- There is built-in support for all of the [out-of-the-box Redis commands](https://redis.io/commands). They are exposed using the raw Redis command names (`HSET`, `HGETALL`, etc.) and a friendlier camel-cased version (`hSet`, `hGetAll`, etc.):
94
+ There is built-in support for all of the [out-of-the-box Redis commands](https://redis.io/commands). They are exposed
95
+ using the raw Redis command names (`HSET`, `HGETALL`, etc.) and a friendlier camel-cased version (`hSet`, `hGetAll`,
96
+ etc.):
34
97
 
35
- ```javascript
98
+ ```typescript
36
99
  // raw Redis commands
37
- await client.HSET('key', 'field', 'value');
38
- await client.HGETALL('key');
100
+ await client.HSET("key", "field", "value");
101
+ await client.HGETALL("key");
39
102
 
40
103
  // friendly JavaScript commands
41
- await client.hSet('key', 'field', 'value');
42
- await client.hGetAll('key');
104
+ await client.hSet("key", "field", "value");
105
+ await client.hGetAll("key");
43
106
  ```
44
107
 
45
108
  Modifiers to commands are specified using a JavaScript object:
46
109
 
47
- ```javascript
48
- await client.set('key', 'value', {
49
- expiration: {
50
- type: 'EX',
51
- value: 10
52
- },
53
- condition: 'NX'
110
+ ```typescript
111
+ await client.set("key", "value", {
112
+ EX: 10,
113
+ NX: true,
54
114
  });
55
115
  ```
56
116
 
57
- > NOTE: command modifiers that change the reply type (e.g. `WITHSCORES` for `ZDIFF`) are exposed as separate commands (e.g. `ZDIFF_WITHSCORES`/`zDiffWithScores`).
58
-
59
- Replies will be mapped to useful data structures:
117
+ Replies will be transformed into useful data structures:
60
118
 
61
- ```javascript
62
- await client.hGetAll('key'); // { field1: 'value1', field2: 'value2' }
63
- await client.hVals('key'); // ['value1', 'value2']
119
+ ```typescript
120
+ await client.hGetAll("key"); // { field1: 'value1', field2: 'value2' }
121
+ await client.hVals("key"); // ['value1', 'value2']
64
122
  ```
65
123
 
66
- > NOTE: you can change the default type mapping. See the [Type Mapping](../../docs/command-options.md#type-mapping) documentation for more information.
124
+ `Buffer`s are supported as well:
125
+
126
+ ```typescript
127
+ const client = createClient().withTypeMapping({
128
+ [RESP_TYPES.BLOB_STRING]: Buffer
129
+ });
130
+
131
+ await client.hSet("key", "field", Buffer.from("value")); // 'OK'
132
+ await client.hGet("key", "field"); // { field: <Buffer 76 61 6c 75 65> }
133
+
134
+ ```
67
135
 
68
136
  ### Unsupported Redis Commands
69
137
 
70
138
  If you want to run commands and/or use arguments that Node Redis doesn't know about (yet!) use `.sendCommand()`:
71
139
 
72
- ```javascript
73
- await client.sendCommand(['SET', 'key', 'value', 'EX', '10', 'NX']); // 'OK'
74
- await client.sendCommand(['HGETALL', 'key']); // ['key1', 'field1', 'key2', 'field2']
140
+ ```typescript
141
+ await client.sendCommand(["SET", "key", "value", "NX"]); // 'OK'
142
+
143
+ await client.sendCommand(["HGETALL", "key"]); // ['key1', 'field1', 'key2', 'field2']
75
144
  ```
76
145
 
77
- ### Disconnecting
146
+ ### Transactions (Multi/Exec)
78
147
 
79
- #### `.close()`
148
+ Start a [transaction](https://redis.io/topics/transactions) by calling `.multi()`, then chaining your commands. When
149
+ you're done, call `.exec()` and you'll get an array back with your results:
80
150
 
81
- Gracefully close a client's connection to Redis.
82
- Wait for commands in process, but reject any new commands.
151
+ ```typescript
152
+ await client.set("another-key", "another-value");
83
153
 
84
- ```javascript
85
- const [ping, get] = await Promise.all([
86
- client.ping(),
87
- client.get('key'),
88
- client.close()
89
- ]); // ['PONG', null]
90
-
91
- try {
92
- await client.get('key');
93
- } catch (err) {
94
- // ClientClosedError
95
- }
154
+ const [setKeyReply, otherKeyValue] = await client
155
+ .multi()
156
+ .set("key", "value")
157
+ .get("another-key")
158
+ .exec(); // ['OK', 'another-value']
96
159
  ```
97
160
 
98
- > `.close()` is just like `.quit()` which was depreacted v5. See the [relevant section in the migration guide](../../docs/v4-to-v5.md#Quit-VS-Disconnect) for more information.
161
+ You can also [watch](https://redis.io/topics/transactions#optimistic-locking-using-check-and-set) keys by calling
162
+ `.watch()`. Your transaction will abort if any of the watched keys change.
99
163
 
100
- #### `.destroy()`
101
164
 
102
- Forcibly close a client's connection to Redis.
165
+ ### Blocking Commands
166
+
167
+ In v4, `RedisClient` had the ability to create a pool of connections using an "Isolation Pool" on top of the "main"
168
+ connection. However, there was no way to use the pool without a "main" connection:
169
+
170
+ ```javascript
171
+ const client = await createClient()
172
+ .on("error", (err) => console.error(err))
173
+ .connect();
174
+
175
+ await client.ping(client.commandOptions({ isolated: true }));
176
+ ```
177
+
178
+ In v5 we've extracted this pool logic into its own class—`RedisClientPool`:
103
179
 
104
180
  ```javascript
105
- try {
106
- const promise = Promise.all([
107
- client.ping(),
108
- client.get('key')
109
- ]);
181
+ const pool = await createClientPool()
182
+ .on("error", (err) => console.error(err))
183
+ .connect();
110
184
 
111
- client.destroy();
185
+ await pool.ping();
186
+ ```
112
187
 
113
- await promise;
114
- } catch (err) {
115
- // DisconnectsClientError
188
+
189
+ ### Pub/Sub
190
+
191
+ See the [Pub/Sub overview](../../docs/pub-sub.md).
192
+
193
+ ### Scan Iterator
194
+
195
+ [`SCAN`](https://redis.io/commands/scan) results can be looped over
196
+ using [async iterators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator):
197
+
198
+ ```typescript
199
+ for await (const key of client.scanIterator()) {
200
+ // use the key!
201
+ await client.get(key);
116
202
  }
203
+ ```
204
+
205
+ This works with `HSCAN`, `SSCAN`, and `ZSCAN` too:
117
206
 
118
- try {
119
- await client.get('key');
120
- } catch (err) {
121
- // ClientClosedError
207
+ ```typescript
208
+ for await (const { field, value } of client.hScanIterator("hash")) {
209
+ }
210
+ for await (const member of client.sScanIterator("set")) {
211
+ }
212
+ for await (const { score, value } of client.zScanIterator("sorted-set")) {
122
213
  }
123
214
  ```
124
215
 
125
- > `.destroy()` is just like `.disconnect()` which was depreated in v5. See the [relevant section in the migration guide](../../docs/v4-to-v5.md#Quit-VS-Disconnect) for more information.
216
+ You can override the default options by providing a configuration object:
217
+
218
+ ```typescript
219
+ client.scanIterator({
220
+ TYPE: "string", // `SCAN` only
221
+ MATCH: "patter*",
222
+ COUNT: 100,
223
+ });
224
+ ```
225
+
226
+ ### Disconnecting
227
+
228
+ The `QUIT` command has been deprecated in Redis 7.2 and should now also be considered deprecated in Node-Redis. Instead
229
+ of sending a `QUIT` command to the server, the client can simply close the network connection.
230
+
231
+ `client.QUIT/quit()` is replaced by `client.close()`. and, to avoid confusion, `client.disconnect()` has been renamed to
232
+ `client.destroy()`.
233
+
234
+ ```typescript
235
+ client.destroy();
236
+ ```
237
+ ### Client Side Caching
238
+
239
+ Node Redis v5 adds support for [Client Side Caching](https://redis.io/docs/manual/client-side-caching/), which enables clients to cache query results locally. The Redis server will notify the client when cached results are no longer valid.
240
+
241
+ ```typescript
242
+ // Enable client side caching with RESP3
243
+ const client = createClient({
244
+ RESP: 3,
245
+ clientSideCache: {
246
+ ttl: 0, // Time-to-live (0 = no expiration)
247
+ maxEntries: 0, // Maximum entries (0 = unlimited)
248
+ evictPolicy: "LRU" // Eviction policy: "LRU" or "FIFO"
249
+ }
250
+ });
251
+ ```
252
+
253
+ See the [V5 documentation](../../docs/v5.md#client-side-caching) for more details and advanced usage.
126
254
 
127
255
  ### Auto-Pipelining
128
256
 
129
257
  Node Redis will automatically pipeline requests that are made during the same "tick".
130
258
 
131
- ```javascript
132
- client.set('Tm9kZSBSZWRpcw==', 'users:1');
133
- client.sAdd('users:1:tokens', 'Tm9kZSBSZWRpcw==');
259
+ ```typescript
260
+ client.set("Tm9kZSBSZWRpcw==", "users:1");
261
+ client.sAdd("users:1:tokens", "Tm9kZSBSZWRpcw==");
134
262
  ```
135
263
 
136
- Of course, if you don't do something with your Promises you're certain to get [unhandled Promise exceptions](https://nodejs.org/api/process.html#process_event_unhandledrejection). To take advantage of auto-pipelining and handle your Promises, use `Promise.all()`.
264
+ Of course, if you don't do something with your Promises you're certain to
265
+ get [unhandled Promise exceptions](https://nodejs.org/api/process.html#process_event_unhandledrejection). To take
266
+ advantage of auto-pipelining and handle your Promises, use `Promise.all()`.
137
267
 
138
- ```javascript
268
+ ```typescript
139
269
  await Promise.all([
140
- client.set('Tm9kZSBSZWRpcw==', 'users:1'),
141
- client.sAdd('users:1:tokens', 'Tm9kZSBSZWRpcw==')
270
+ client.set("Tm9kZSBSZWRpcw==", "users:1"),
271
+ client.sAdd("users:1:tokens", "Tm9kZSBSZWRpcw=="),
142
272
  ]);
143
273
  ```
144
274
 
145
- ### Connection State
275
+ ### Programmability
146
276
 
147
- To client exposes 2 `boolean`s that track the client state:
148
- 1. `isOpen` - the client is either connecting or connected.
149
- 2. `isReady` - the client is connected and ready to send
277
+ See the [Programmability overview](../../docs/programmability.md).
150
278
 
151
- ### Events
279
+ ### Clustering
152
280
 
153
- The client extends `EventEmitter` and emits the following events:
281
+ Check out the [Clustering Guide](../../docs/clustering.md) when using Node Redis to connect to a Redis Cluster.
154
282
 
155
- | Name | When | Listener arguments |
156
- |-------------------------|------------------------------------------------------------------------------------|------------------------------------------------------------|
157
- | `connect` | Initiating a connection to the server | *No arguments* |
158
- | `ready` | Client is ready to use | *No arguments* |
159
- | `end` | Connection has been closed (via `.quit()` or `.disconnect()`) | *No arguments* |
160
- | `error` | An error has occurred—usually a network issue such as "Socket closed unexpectedly" | `(error: Error)` |
161
- | `reconnecting` | Client is trying to reconnect to the server | *No arguments* |
162
- | `sharded-channel-moved` | See [here](../../docs/pub-sub.md#sharded-channel-moved-event) | See [here](../../docs/pub-sub.md#sharded-channel-moved-event) |
283
+ ### Events
284
+
285
+ The Node Redis client class is an Nodejs EventEmitter and it emits an event each time the network status changes:
163
286
 
164
- > :warning: You **MUST** listen to `error` events. If a client doesn't have at least one `error` listener registered and an `error` occurs, that error will be thrown and the Node.js process will exit. See the [`EventEmitter` docs](https://nodejs.org/api/events.html#error-events) for more details.
287
+ | Name | When | Listener arguments |
288
+ | ----------------------- | ---------------------------------------------------------------------------------- | --------------------------------------------------------- |
289
+ | `connect` | Initiating a connection to the server | _No arguments_ |
290
+ | `ready` | Client is ready to use | _No arguments_ |
291
+ | `end` | Connection has been closed (via `.disconnect()`) | _No arguments_ |
292
+ | `error` | An error has occurred—usually a network issue such as "Socket closed unexpectedly" | `(error: Error)` |
293
+ | `reconnecting` | Client is trying to reconnect to the server | _No arguments_ |
294
+ | `sharded-channel-moved` | See [here](../../docs/pub-sub.md#sharded-channel-moved-event) | See [here](../../docs/pub-sub.md#sharded-channel-moved-event) |
165
295
 
166
- ### Read more
296
+ > :warning: You **MUST** listen to `error` events. If a client doesn't have at least one `error` listener registered and
297
+ > an `error` occurs, that error will be thrown and the Node.js process will exit. See the [ > `EventEmitter` docs](https://nodejs.org/api/events.html#events_error_events) for more details.
167
298
 
168
- - [Transactions (`MULTI`/`EXEC`)](../../docs/transactions.md).
169
- - [Pub/Sub](../../docs/pub-sub.md).
170
- - [Scan Iterators](../../docs/scan-iterators.md).
171
- - [Programmability](../../docs/programmability.md).
172
- - [Command Options](../../docs/command-options.md).
173
- - [Pool](../../docs/pool.md).
174
- - [Clustering](../../docs/clustering.md).
175
- - [Sentinel](../../docs/sentinel.md).
176
- - [FAQ](../../docs/FAQ.md).
299
+ > The client will not emit [any other events](../../docs/v3-to-v4.md#all-the-removed-events) beyond those listed above.
177
300
 
178
301
  ## Supported Redis versions
179
302
 
180
303
  Node Redis is supported with the following versions of Redis:
181
304
 
182
305
  | Version | Supported |
183
- |---------|--------------------|
306
+ | ------- | ------------------ |
307
+ | 8.0.z | :heavy_check_mark: |
308
+ | 7.4.z | :heavy_check_mark: |
184
309
  | 7.2.z | :heavy_check_mark: |
185
- | 7.0.z | :heavy_check_mark: |
186
- | 6.2.z | :heavy_check_mark: |
187
- | 6.0.z | :heavy_check_mark: |
188
- | 5.0.z | :heavy_check_mark: |
189
- | < 5.0 | :x: |
310
+ | < 7.2 | :x: |
190
311
 
191
312
  > Node Redis should work with older versions of Redis, but it is not fully tested and we cannot offer support.
192
313
 
314
+ ## Migration
315
+
316
+ - [From V3 to V4](../../docs/v3-to-v4.md)
317
+ - [From V4 to V5](../../docs/v4-to-v5.md)
318
+ - [V5](../../docs/v5.md)
319
+
193
320
  ## Contributing
194
321
 
195
322
  If you'd like to contribute, check out the [contributing guide](../../CONTRIBUTING.md).