node-valkey
Advanced tools
Comparing version 1.0.2 to 1.0.3
{ | ||
"name": "node-valkey", | ||
"description": "A modern, high performance valkey client", | ||
"version": "1.0.2", | ||
"description": "A modern, high performance Valkey client", | ||
"version": "1.0.3", | ||
"license": "MIT", | ||
@@ -26,8 +26,8 @@ "main": "./dist/index.js", | ||
"dependencies": { | ||
"@redis/bloom": "1.2.0", | ||
"@redis/client": "1.5.14", | ||
"@redis/graph": "1.1.1", | ||
"@redis/json": "1.0.6", | ||
"@redis/search": "1.1.6", | ||
"@redis/time-series": "1.0.5" | ||
"@valkey/bloom": "1.0.0", | ||
"@valkey/client": "1.0.0", | ||
"@valkey/graph": "1.0.0", | ||
"@valkey/json": "1.0.0", | ||
"@valkey/search": "1.0.0", | ||
"@valkey/time-series": "1.0.0" | ||
}, | ||
@@ -49,4 +49,4 @@ "devDependencies": { | ||
"keywords": [ | ||
"redis" | ||
"valkey" | ||
] | ||
} |
230
README.md
@@ -1,26 +0,39 @@ | ||
# Node-Valkey | ||
# node-valkey | ||
A robust, performance-focused and full-featured Redis client for Node.js. This is a friendly fork of ioredis after this [commit](https://github.com/redis/node-redis/commit/dbf8f59a47573e6a1c75b78e566af8c493015d5d). | ||
> [!NOTE] | ||
> Since the Valkey project might diverge from Valkey when it comes to its API, I've decided to create a fork of node-valkey. | ||
> In case the Valkey project wants me to move the maintenance of this to them, please contact me. | ||
> This project is not affiliated with or endorsed by the Valkey project. | ||
Supports Redis >= 2.6.12. Completely compatible with Redis 7.x. | ||
[![Tests](https://img.shields.io/github/actions/workflow/status/mat-sz/node-valkey/tests.yml?branch=master)](https://github.com/mat-sz/node-valkey/actions/workflows/tests.yml) | ||
[![Coverage](https://codecov.io/gh/mat-sz/node-valkey/branch/master/graph/badge.svg?token=xcfqHhJC37)](https://codecov.io/gh/mat-sz/node-valkey) | ||
[![License](https://img.shields.io/github/license/mat-sz/node-valkey.svg)](https://github.com/mat-sz/node-valkey/blob/master/LICENSE) | ||
node-valkey is a modern, high performance [Valkey](https://valkey.io) client for Node.js. | ||
## Packages | ||
| Name | Description | | ||
| --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| [valkey](./) | [![Downloads](https://img.shields.io/npm/dm/valkey.svg)](https://www.npmjs.com/package/valkey) [![Version](https://img.shields.io/npm/v/valkey.svg)](https://www.npmjs.com/package/valkey) | | ||
| [@valkey/client](./packages/client) | [![Downloads](https://img.shields.io/npm/dm/@valkey/client.svg)](https://www.npmjs.com/package/@valkey/client) [![Version](https://img.shields.io/npm/v/@valkey/client.svg)](https://www.npmjs.com/package/@valkey/client) [![Docs](https://img.shields.io/badge/-documentation-dc382c)](https://valkey.js.org/documentation/client/) | | ||
| [@valkey/bloom](./packages/bloom) | [![Downloads](https://img.shields.io/npm/dm/@valkey/bloom.svg)](https://www.npmjs.com/package/@valkey/bloom) [![Version](https://img.shields.io/npm/v/@valkey/bloom.svg)](https://www.npmjs.com/package/@valkey/bloom) [![Docs](https://img.shields.io/badge/-documentation-dc382c)](https://valkey.js.org/documentation/bloom/) [Valkey Bloom](https://oss.valkey.com/valkeybloom/) commands | | ||
| [@valkey/graph](./packages/graph) | [![Downloads](https://img.shields.io/npm/dm/@valkey/graph.svg)](https://www.npmjs.com/package/@valkey/graph) [![Version](https://img.shields.io/npm/v/@valkey/graph.svg)](https://www.npmjs.com/package/@valkey/graph) [![Docs](https://img.shields.io/badge/-documentation-dc382c)](https://valkey.js.org/documentation/graph/) [Valkey Graph](https://oss.valkey.com/valkeygraph/) commands | | ||
| [@valkey/json](./packages/json) | [![Downloads](https://img.shields.io/npm/dm/@valkey/json.svg)](https://www.npmjs.com/package/@valkey/json) [![Version](https://img.shields.io/npm/v/@valkey/json.svg)](https://www.npmjs.com/package/@valkey/json) [![Docs](https://img.shields.io/badge/-documentation-dc382c)](https://valkey.js.org/documentation/json/) [Valkey JSON](https://oss.valkey.com/valkeyjson/) commands | | ||
| [@valkey/search](./packages/search) | [![Downloads](https://img.shields.io/npm/dm/@valkey/search.svg)](https://www.npmjs.com/package/@valkey/search) [![Version](https://img.shields.io/npm/v/@valkey/search.svg)](https://www.npmjs.com/package/@valkey/search) [![Docs](https://img.shields.io/badge/-documentation-dc382c)](https://valkey.js.org/documentation/search/) [RediSearch](https://oss.valkey.com/valkeyearch/) commands | | ||
| [@valkey/time-series](./packages/time-series) | [![Downloads](https://img.shields.io/npm/dm/@valkey/time-series.svg)](https://www.npmjs.com/package/@valkey/time-series) [![Version](https://img.shields.io/npm/v/@valkey/time-series.svg)](https://www.npmjs.com/package/@valkey/time-series) [![Docs](https://img.shields.io/badge/-documentation-dc382c)](https://valkey.js.org/documentation/time-series/) [Valkey Time-Series](https://oss.valkey.com/valkeytimeseries/) commands | | ||
## Installation | ||
Start a redis via docker: | ||
Start a Valkey instance via docker: | ||
``` bash | ||
docker run -p 6379:6379 -it redis/redis-stack-server:latest | ||
``` | ||
> [!NOTE] | ||
> An official Docker image for Valkey is not available yet. | ||
To install node-redis, simply: | ||
To install node-valkey, simply: | ||
```bash | ||
npm install redis | ||
npm install valkey | ||
``` | ||
> :warning: The new interface is clean and cool, but if you have an existing codebase, you'll want to read the [migration guide](./docs/v3-to-v4.md). | ||
Looking for a high-level library to handle object mapping? See [redis-om-node](https://github.com/redis/redis-om-node)! | ||
## Usage | ||
@@ -31,18 +44,18 @@ | ||
```typescript | ||
import { createClient } from 'redis'; | ||
import { createClient } from "valkey"; | ||
const client = await createClient() | ||
.on('error', err => console.log('Redis Client Error', err)) | ||
.on("error", (err) => console.log("Valkey Client Error", err)) | ||
.connect(); | ||
await client.set('key', 'value'); | ||
const value = await client.get('key'); | ||
await client.set("key", "value"); | ||
const value = await client.get("key"); | ||
await client.disconnect(); | ||
``` | ||
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]`: | ||
The above code connects to localhost on port 6379. To connect to a different host or port, use a connection string in the format `valkey[s]://[[username][:password]@][host][:port][/db-number]`: | ||
```typescript | ||
createClient({ | ||
url: 'redis://alice:foobared@awesome.redis.server:6380' | ||
url: "valkey://alice:foobared@awesome.valkey.server:6380", | ||
}); | ||
@@ -53,16 +66,16 @@ ``` | ||
To check if the the client is connected and ready to send commands, use `client.isReady` which returns a boolean. `client.isOpen` is also available. This returns `true` when the client's underlying socket is open, and `false` when it isn't (for example when the client is still connecting or reconnecting after a network error). | ||
To check if the the client is connected and ready to send commands, use `client.isReady` which returns a boolean. `client.isOpen` is also available. This returns `true` when the client's underlying socket is open, and `false` when it isn't (for example when the client is still connecting or reconnecting after a network error). | ||
### Redis Commands | ||
### Valkey Commands | ||
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.): | ||
There is built-in support for all of the out-of-the-box Valkey commands. They are exposed using the raw Valkey command names (`HSET`, `HGETALL`, etc.) and a friendlier camel-cased version (`hSet`, `hGetAll`, etc.): | ||
```typescript | ||
// raw Redis commands | ||
await client.HSET('key', 'field', 'value'); | ||
await client.HGETALL('key'); | ||
// raw Valkey commands | ||
await client.HSET("key", "field", "value"); | ||
await client.HGETALL("key"); | ||
// friendly JavaScript commands | ||
await client.hSet('key', 'field', 'value'); | ||
await client.hGetAll('key'); | ||
await client.hSet("key", "field", "value"); | ||
await client.hGetAll("key"); | ||
``` | ||
@@ -73,5 +86,5 @@ | ||
```typescript | ||
await client.set('key', 'value', { | ||
await client.set("key", "value", { | ||
EX: 10, | ||
NX: true | ||
NX: true, | ||
}); | ||
@@ -83,4 +96,4 @@ ``` | ||
```typescript | ||
await client.hGetAll('key'); // { field1: 'value1', field2: 'value2' } | ||
await client.hVals('key'); // ['value1', 'value2'] | ||
await client.hGetAll("key"); // { field1: 'value1', field2: 'value2' } | ||
await client.hVals("key"); // ['value1', 'value2'] | ||
``` | ||
@@ -91,17 +104,14 @@ | ||
```typescript | ||
await client.hSet('key', 'field', Buffer.from('value')); // 'OK' | ||
await client.hGetAll( | ||
commandOptions({ returnBuffers: true }), | ||
'key' | ||
); // { field: <Buffer 76 61 6c 75 65> } | ||
await client.hSet("key", "field", Buffer.from("value")); // 'OK' | ||
await client.hGetAll(commandOptions({ returnBuffers: true }), "key"); // { field: <Buffer 76 61 6c 75 65> } | ||
``` | ||
### Unsupported Redis Commands | ||
### Unsupported Valkey Commands | ||
If you want to run commands and/or use arguments that Node Redis doesn't know about (yet!) use `.sendCommand()`: | ||
If you want to run commands and/or use arguments that Node Valkey doesn't know about (yet!) use `.sendCommand()`: | ||
```typescript | ||
await client.sendCommand(['SET', 'key', 'value', 'NX']); // 'OK' | ||
await client.sendCommand(["SET", "key", "value", "NX"]); // 'OK' | ||
await client.sendCommand(['HGETALL', 'key']); // ['key1', 'field1', 'key2', 'field2'] | ||
await client.sendCommand(["HGETALL", "key"]); // ['key1', 'field1', 'key2', 'field2'] | ||
``` | ||
@@ -111,15 +121,15 @@ | ||
Start a [transaction](https://redis.io/topics/transactions) by calling `.multi()`, then chaining your commands. When you're done, call `.exec()` and you'll get an array back with your results: | ||
Start a transaction by calling `.multi()`, then chaining your commands. When you're done, call `.exec()` and you'll get an array back with your results: | ||
```typescript | ||
await client.set('another-key', 'another-value'); | ||
await client.set("another-key", "another-value"); | ||
const [setKeyReply, otherKeyValue] = await client | ||
.multi() | ||
.set('key', 'value') | ||
.get('another-key') | ||
.set("key", "value") | ||
.get("another-key") | ||
.exec(); // ['OK', 'another-value'] | ||
``` | ||
You can also [watch](https://redis.io/topics/transactions#optimistic-locking-using-check-and-set) keys by calling `.watch()`. Your transaction will abort if any of the watched keys change. | ||
You can also watch keys by calling `.watch()`. Your transaction will abort if any of the watched keys change. | ||
@@ -135,11 +145,7 @@ To dig deeper into transactions, check out the [Isolated Execution Guide](./docs/isolated-execution.md). | ||
```typescript | ||
import { commandOptions } from 'redis'; | ||
import { commandOptions } from "valkey"; | ||
const blPopPromise = client.blPop( | ||
commandOptions({ isolated: true }), | ||
'key', | ||
0 | ||
); | ||
const blPopPromise = client.blPop(commandOptions({ isolated: true }), "key", 0); | ||
await client.lPush('key', ['1', '2']); | ||
await client.lPush("key", ["1", "2"]); | ||
@@ -157,3 +163,3 @@ await blPopPromise; // '2' | ||
[`SCAN`](https://redis.io/commands/scan) results can be looped over using [async iterators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator): | ||
`SCAN` results can be looped over using [async iterators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator): | ||
@@ -170,5 +176,8 @@ ```typescript | ||
```typescript | ||
for await (const { field, value } of client.hScanIterator('hash')) {} | ||
for await (const member of client.sScanIterator('set')) {} | ||
for await (const { score, value } of client.zScanIterator('sorted-set')) {} | ||
for await (const { field, value } of client.hScanIterator("hash")) { | ||
} | ||
for await (const member of client.sScanIterator("set")) { | ||
} | ||
for await (const { score, value } of client.zScanIterator("sorted-set")) { | ||
} | ||
``` | ||
@@ -180,15 +189,15 @@ | ||
client.scanIterator({ | ||
TYPE: 'string', // `SCAN` only | ||
MATCH: 'patter*', | ||
COUNT: 100 | ||
TYPE: "string", // `SCAN` only | ||
MATCH: "patter*", | ||
COUNT: 100, | ||
}); | ||
``` | ||
### [Programmability](https://redis.io/docs/manual/programmability/) | ||
### Programmability | ||
Redis provides a programming interface allowing code execution on the redis server. | ||
Valkey provides a programming interface allowing code execution on the valkey server. | ||
#### [Functions](https://redis.io/docs/manual/programmability/functions-intro/) | ||
#### Functions | ||
The following example retrieves a key in redis, returning the value of the key, incremented by an integer. For example, if your key _foo_ has the value _17_ and we run `add('foo', 25)`, it returns the answer to Life, the Universe and Everything. | ||
The following example retrieves a key in valkey, returning the value of the key, incremented by an integer. For example, if your key _foo_ has the value _17_ and we run `add('foo', 25)`, it returns the answer to Life, the Universe and Everything. | ||
@@ -198,5 +207,5 @@ ```lua | ||
redis.register_function { | ||
valkey.register_function { | ||
function_name = 'add', | ||
callback = function(keys, args) return redis.call('GET', keys[1]) + args[1] end, | ||
callback = function(keys, args) return valkey.call('GET', keys[1]) + args[1] end, | ||
flags = { 'no-writes' } | ||
@@ -206,12 +215,12 @@ } | ||
Here is the same example, but in a format that can be pasted into the `redis-cli`. | ||
Here is the same example, but in a format that can be pasted into the `valkey-cli`. | ||
``` | ||
FUNCTION LOAD "#!lua name=library\nredis.register_function{function_name=\"add\", callback=function(keys, args) return redis.call('GET', keys[1])+args[1] end, flags={\"no-writes\"}}" | ||
FUNCTION LOAD "#!lua name=library\nvalkey.register_function{function_name=\"add\", callback=function(keys, args) return valkey.call('GET', keys[1])+args[1] end, flags={\"no-writes\"}}" | ||
``` | ||
Load the prior redis function on the _redis server_ before running the example below. | ||
Load the prior valkey function on the _valkey server_ before running the example below. | ||
```typescript | ||
import { createClient } from 'redis'; | ||
import { createClient } from "valkey"; | ||
@@ -228,6 +237,6 @@ const client = createClient({ | ||
return reply; | ||
} | ||
} | ||
} | ||
} | ||
}, | ||
}, | ||
}, | ||
}, | ||
}); | ||
@@ -237,7 +246,7 @@ | ||
await client.set('key', '1'); | ||
await client.library.add('key', 2); // 3 | ||
await client.set("key", "1"); | ||
await client.library.add("key", 2); // 3 | ||
``` | ||
#### [Lua Scripts](https://redis.io/docs/manual/programmability/eval-intro/) | ||
#### Lua Scripts | ||
@@ -247,3 +256,3 @@ The following is an end-to-end example of the prior concept. | ||
```typescript | ||
import { createClient, defineScript } from 'redis'; | ||
import { createClient, defineScript } from "valkey"; | ||
@@ -254,4 +263,3 @@ const client = createClient({ | ||
NUMBER_OF_KEYS: 1, | ||
SCRIPT: | ||
'return redis.call("GET", KEYS[1]) + ARGV[1];', | ||
SCRIPT: 'return valkey.call("GET", KEYS[1]) + ARGV[1];', | ||
transformArguments(key: string, toAdd: number): Array<string> { | ||
@@ -262,5 +270,5 @@ return [key, toAdd.toString()]; | ||
return reply; | ||
} | ||
}) | ||
} | ||
}, | ||
}), | ||
}, | ||
}); | ||
@@ -270,4 +278,4 @@ | ||
await client.set('key', '1'); | ||
await client.add('key', 2); // 3 | ||
await client.set("key", "1"); | ||
await client.add("key", 2); // 3 | ||
``` | ||
@@ -277,7 +285,7 @@ | ||
There are two functions that disconnect a client from the Redis server. In most scenarios you should use `.quit()` to ensure that pending commands are sent to Redis before closing a connection. | ||
There are two functions that disconnect a client from the Valkey server. In most scenarios you should use `.quit()` to ensure that pending commands are sent to Valkey before closing a connection. | ||
#### `.QUIT()`/`.quit()` | ||
Gracefully close a client's connection to Redis, by sending the [`QUIT`](https://redis.io/commands/quit) command to the server. Before quitting, the client executes any remaining commands in its queue, and will receive replies from Redis for each of them. | ||
Gracefully close a client's connection to Valkey, by sending the `QUIT` command to the server. Before quitting, the client executes any remaining commands in its queue, and will receive replies from Valkey for each of them. | ||
@@ -287,8 +295,8 @@ ```typescript | ||
client.ping(), | ||
client.get('key'), | ||
client.quit() | ||
client.get("key"), | ||
client.quit(), | ||
]); // ['PONG', null, 'OK'] | ||
try { | ||
await client.get('key'); | ||
await client.get("key"); | ||
} catch (err) { | ||
@@ -301,3 +309,3 @@ // ClosedClient Error | ||
Forcibly close a client's connection to Redis immediately. Calling `disconnect` will not send further pending commands to the Redis server, or wait for or parse outstanding responses. | ||
Forcibly close a client's connection to Valkey immediately. Calling `disconnect` will not send further pending commands to the Valkey server, or wait for or parse outstanding responses. | ||
@@ -310,7 +318,7 @@ ```typescript | ||
Node Redis will automatically pipeline requests that are made during the same "tick". | ||
Node Valkey will automatically pipeline requests that are made during the same "tick". | ||
```typescript | ||
client.set('Tm9kZSBSZWRpcw==', 'users:1'); | ||
client.sAdd('users:1:tokens', 'Tm9kZSBSZWRpcw=='); | ||
client.set("Tm9kZSBSZWRpcw==", "users:1"); | ||
client.sAdd("users:1:tokens", "Tm9kZSBSZWRpcw=="); | ||
``` | ||
@@ -322,4 +330,4 @@ | ||
await Promise.all([ | ||
client.set('Tm9kZSBSZWRpcw==', 'users:1'), | ||
client.sAdd('users:1:tokens', 'Tm9kZSBSZWRpcw==') | ||
client.set("Tm9kZSBSZWRpcw==", "users:1"), | ||
client.sAdd("users:1:tokens", "Tm9kZSBSZWRpcw=="), | ||
]); | ||
@@ -330,16 +338,16 @@ ``` | ||
Check out the [Clustering Guide](./docs/clustering.md) when using Node Redis to connect to a Redis Cluster. | ||
Check out the [Clustering Guide](./docs/clustering.md) when using Node Valkey to connect to a Valkey Cluster. | ||
### Events | ||
The Node Redis client class is an Nodejs EventEmitter and it emits an event each time the network status changes: | ||
The Node Valkey client class is an Nodejs EventEmitter and it emits an event each time the network status changes: | ||
| Name | When | Listener arguments | | ||
|-------------------------|------------------------------------------------------------------------------------|------------------------------------------------------------| | ||
| `connect` | Initiating a connection to the server | *No arguments* | | ||
| `ready` | Client is ready to use | *No arguments* | | ||
| `end` | Connection has been closed (via `.quit()` or `.disconnect()`) | *No arguments* | | ||
| `error` | An error has occurred—usually a network issue such as "Socket closed unexpectedly" | `(error: Error)` | | ||
| `reconnecting` | Client is trying to reconnect to the server | *No arguments* | | ||
| `sharded-channel-moved` | See [here](./docs/pub-sub.md#sharded-channel-moved-event) | See [here](./docs/pub-sub.md#sharded-channel-moved-event) | | ||
| Name | When | Listener arguments | | ||
| ----------------------- | ---------------------------------------------------------------------------------- | --------------------------------------------------------- | | ||
| `connect` | Initiating a connection to the server | _No arguments_ | | ||
| `ready` | Client is ready to use | _No arguments_ | | ||
| `end` | Connection has been closed (via `.quit()` or `.disconnect()`) | _No arguments_ | | ||
| `error` | An error has occurred—usually a network issue such as "Socket closed unexpectedly" | `(error: Error)` | | ||
| `reconnecting` | Client is trying to reconnect to the server | _No arguments_ | | ||
| `sharded-channel-moved` | See [here](./docs/pub-sub.md#sharded-channel-moved-event) | See [here](./docs/pub-sub.md#sharded-channel-moved-event) | | ||
@@ -350,8 +358,8 @@ > :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#events_error_events) for more details. | ||
## Supported Redis versions | ||
## Supported Valkey versions | ||
Node Redis is supported with the following versions of Redis: | ||
Node Valkey is supported with the following versions of Valkey: | ||
| Version | Supported | | ||
|---------|--------------------| | ||
| ------- | ------------------ | | ||
| 7.0.z | :heavy_check_mark: | | ||
@@ -363,3 +371,3 @@ | 6.2.z | :heavy_check_mark: | | ||
> Node Redis should work with older versions of Redis, but it is not fully tested and we cannot offer support. | ||
> Node Valkey should work with older versions of Valkey, but it is not fully tested and we cannot offer support. | ||
@@ -370,5 +378,5 @@ ## Contributing | ||
Thank you to all the people who already contributed to Node Redis! | ||
Thank you to all the people who already contributed to Node Valkey! | ||
[![Contributors](https://contrib.rocks/image?repo=redis/node-redis)](https://github.com/redis/node-redis/graphs/contributors) | ||
[![Contributors](https://contrib.rocks/image?repo=valkey/node-valkey)](https://github.com/valkey/node-valkey/graphs/contributors) | ||
@@ -375,0 +383,0 @@ ## License |
18977
359
+ Added@valkey/bloom@1.0.0
+ Added@valkey/client@1.0.0
+ Added@valkey/graph@1.0.0
+ Added@valkey/json@1.0.0
+ Added@valkey/search@1.0.0
+ Added@valkey/time-series@1.0.0
+ Added@valkey/bloom@1.0.0(transitive)
+ Added@valkey/client@1.0.0(transitive)
+ Added@valkey/graph@1.0.0(transitive)
+ Added@valkey/json@1.0.0(transitive)
+ Added@valkey/search@1.0.0(transitive)
+ Added@valkey/time-series@1.0.0(transitive)
- Removed@redis/bloom@1.2.0
- Removed@redis/client@1.5.14
- Removed@redis/graph@1.1.1
- Removed@redis/json@1.0.6
- Removed@redis/search@1.1.6
- Removed@redis/time-series@1.0.5
- Removed@redis/bloom@1.2.0(transitive)
- Removed@redis/client@1.5.14(transitive)
- Removed@redis/graph@1.1.1(transitive)
- Removed@redis/json@1.0.6(transitive)
- Removed@redis/search@1.1.6(transitive)
- Removed@redis/time-series@1.0.5(transitive)