You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-12-25 00:40:59 +03:00
fix #1714 - update README(s)
This commit is contained in:
@@ -4,6 +4,8 @@ import { RedisClientOptions, RedisClientType } from '@redis/client/dist/lib/clie
|
||||
import RedisJSON from '@redis/json';
|
||||
import RediSearch from '@redis/search';
|
||||
|
||||
export * from '@redis/search';
|
||||
|
||||
const modules = {
|
||||
json: RedisJSON,
|
||||
ft: RediSearch
|
||||
@@ -17,3 +19,4 @@ export function createClient<S extends RedisScripts = Record<string, never>>(
|
||||
modules
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
"version": "4.0.0-rc.3",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.ts",
|
||||
"types": "./dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@redis/client": "^4.0.0-rc",
|
||||
"@redis/client": "^1.0.0-rc",
|
||||
"@redis/json": "^1.0.0-rc",
|
||||
"@redis/search": "^1.0.0-rc"
|
||||
},
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016-present Node Redis contributors.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -1,294 +0,0 @@
|
||||
<p align="center">
|
||||
<a href="https://github.com/redis/node-redis">
|
||||
<img width="128" src="https://static.invertase.io/assets/node_redis_logo.png" />
|
||||
</a>
|
||||
<h2 align="center">Node Redis</h2>
|
||||
</p>
|
||||
|
||||
<div align="center">
|
||||
<a href="https://codecov.io/gh/redis/node-redis" >
|
||||
<img src="https://codecov.io/gh/redis/node-redis/branch/master/graph/badge.svg?token=xcfqHhJC37" alt="Coverage"/>
|
||||
</a>
|
||||
<a href="https://www.npmjs.com/package/redis/v/next">
|
||||
<img src="https://img.shields.io/npm/dm/redis.svg" alt="Downloads"/>
|
||||
</a>
|
||||
<a href="https://www.npmjs.com/package/redis/v/next">
|
||||
<img src="https://img.shields.io/npm/v/redis/next.svg" alt="Version"/>
|
||||
</a>
|
||||
<a href="https://discord.gg/XMMVgxUm">
|
||||
<img src="https://img.shields.io/discord/697882427875393627" alt="Chat"/>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install redis@next
|
||||
```
|
||||
|
||||
> :warning: The new interface is clean and cool, but if you have an existing code base, you'll want to read the [migration guide](./docs/v3-to-v4.md).
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```typescript
|
||||
import { createClient } from 'redis';
|
||||
|
||||
(async () => {
|
||||
const client = createClient();
|
||||
|
||||
client.on('error', (err) => console.log('Redis Client Error', err));
|
||||
|
||||
await client.connect();
|
||||
|
||||
await client.set('key', 'value');
|
||||
const value = await client.get('key');
|
||||
})();
|
||||
```
|
||||
|
||||
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]`:
|
||||
|
||||
```typescript
|
||||
createClient({
|
||||
url: 'redis://alice:foobared@awesome.redis.server:6380'
|
||||
});
|
||||
```
|
||||
|
||||
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).
|
||||
|
||||
### Redis 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.):
|
||||
|
||||
```typescript
|
||||
// raw Redis commands
|
||||
await client.HSET('key', 'field', 'value');
|
||||
await client.HGETALL('key');
|
||||
|
||||
// friendly JavaScript commands
|
||||
await client.hSet('key', 'field', 'value');
|
||||
await client.hGetAll('key');
|
||||
```
|
||||
|
||||
Modifiers to commands are specified using a JavaScript object:
|
||||
|
||||
```typescript
|
||||
await client.set('key', 'value', {
|
||||
EX: 10,
|
||||
NX: true
|
||||
});
|
||||
```
|
||||
|
||||
Replies will be transformed into useful data structures:
|
||||
|
||||
```typescript
|
||||
await client.hGetAll('key'); // { field1: 'value1', field2: 'value2' }
|
||||
await client.hVals('key'); // ['value1', 'value2']
|
||||
```
|
||||
|
||||
### Unsupported Redis Commands
|
||||
|
||||
If you want to run commands and/or use arguments that Node Redis doesn't know about (yet!) use `.sendCommand()`:
|
||||
|
||||
```typescript
|
||||
await client.sendCommand(['SET', 'key', 'value', 'NX']); // 'OK'
|
||||
|
||||
await client.sendCommand(['HGETALL', 'key']); // ['key1', 'field1', 'key2', 'field2']
|
||||
```
|
||||
|
||||
### Transactions (Multi/Exec)
|
||||
|
||||
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:
|
||||
|
||||
```typescript
|
||||
await client.set('another-key', 'another-value');
|
||||
|
||||
const [setKeyReply, otherKeyValue] = await client
|
||||
.multi()
|
||||
.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.
|
||||
|
||||
To dig deeper into transactions, check out the [Isolated Execution Guide](./docs/isolated-execution.md).
|
||||
|
||||
### Blocking Commands
|
||||
|
||||
Any command can be run on a new connection by specifying the `isolated` option. The newly created connection is closed when the command's `Promise` is fulfilled.
|
||||
|
||||
This pattern works especially well for blocking commands—such as `BLPOP` and `BLMOVE`:
|
||||
|
||||
```typescript
|
||||
import { commandOptions } from 'redis';
|
||||
|
||||
const blPopPromise = client.blPop(commandOptions({ isolated: true }), 'key', 0);
|
||||
|
||||
await client.lPush('key', ['1', '2']);
|
||||
|
||||
await blPopPromise; // '2'
|
||||
```
|
||||
|
||||
To learn more about isolated execution, check out the [guide](./docs/isolated-execution.md).
|
||||
|
||||
### Pub/Sub
|
||||
|
||||
Subscribing to a channel requires a dedicated stand-alone connection. You can easily get one by `.duplicate()`ing an existing Redis connection.
|
||||
|
||||
```typescript
|
||||
const subscriber = client.duplicate();
|
||||
|
||||
await subscriber.connect();
|
||||
```
|
||||
|
||||
Once you have one, simply subscribe and unsubscribe as needed:
|
||||
|
||||
```typescript
|
||||
await subscriber.subscribe('channel', (message) => {
|
||||
console.log(message); // 'message'
|
||||
});
|
||||
|
||||
await subscriber.pSubscribe('channe*', (message, channel) => {
|
||||
console.log(message, channel); // 'message', 'channel'
|
||||
});
|
||||
|
||||
await subscriber.unsubscribe('channel');
|
||||
|
||||
await subscriber.pUnsubscribe('channe*');
|
||||
```
|
||||
|
||||
Publish a message on a channel:
|
||||
|
||||
```typescript
|
||||
await publisher.publish('channel', 'message');
|
||||
```
|
||||
|
||||
### Scan Iterator
|
||||
|
||||
[`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):
|
||||
|
||||
```typescript
|
||||
for await (const key of client.scanIterator()) {
|
||||
// use the key!
|
||||
await client.get(key);
|
||||
}
|
||||
```
|
||||
|
||||
This works with `HSCAN`, `SSCAN`, and `ZSCAN` too:
|
||||
|
||||
```typescript
|
||||
for await (const { field, value } of client.hScanIterator('hash')) {}
|
||||
for await (const member of client.sScanIterator('set')) {}
|
||||
for await (const { score, member } of client.zScanIterator('sorted-set')) {}
|
||||
```
|
||||
|
||||
You can override the default options by providing a configuration object:
|
||||
|
||||
```typescript
|
||||
client.scanIterator({
|
||||
TYPE: 'string', // `SCAN` only
|
||||
MATCH: 'patter*',
|
||||
COUNT: 100
|
||||
});
|
||||
```
|
||||
|
||||
### Lua Scripts
|
||||
|
||||
Define new functions using [Lua scripts](https://redis.io/commands/eval) which execute on the Redis server:
|
||||
|
||||
```typescript
|
||||
import { createClient, defineScript } from 'redis';
|
||||
|
||||
(async () => {
|
||||
const client = createClient({
|
||||
scripts: {
|
||||
add: defineScript({
|
||||
NUMBER_OF_KEYS: 1,
|
||||
SCRIPT:
|
||||
'local val = redis.pcall("GET", KEYS[1]);' +
|
||||
'return val + ARGV[1];',
|
||||
transformArguments(key: string, toAdd: number): Array<string> {
|
||||
return [key, toAdd.toString()];
|
||||
},
|
||||
transformReply(reply: number): number {
|
||||
return reply;
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
await client.connect();
|
||||
|
||||
await client.set('key', '1');
|
||||
await client.add('key', 2); // 3
|
||||
})();
|
||||
```
|
||||
|
||||
### Disconnecting
|
||||
|
||||
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.
|
||||
|
||||
#### `.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.
|
||||
|
||||
```typescript
|
||||
const [ping, get, quit] = await Promise.all([
|
||||
client.ping(),
|
||||
client.get('key'),
|
||||
client.quit()
|
||||
]); // ['PONG', null, 'OK']
|
||||
|
||||
try {
|
||||
await client.get('key');
|
||||
} catch (err) {
|
||||
// ClosedClient Error
|
||||
}
|
||||
```
|
||||
|
||||
#### `.disconnect()`
|
||||
|
||||
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.
|
||||
|
||||
```typescript
|
||||
await client.disconnect();
|
||||
```
|
||||
|
||||
### Auto-Pipelining
|
||||
|
||||
Node Redis will automatically pipeline requests that are made during the same "tick".
|
||||
|
||||
```typescript
|
||||
client.set('Tm9kZSBSZWRpcw==', 'users:1');
|
||||
client.sAdd('users:1:tokens', 'Tm9kZSBSZWRpcw==');
|
||||
```
|
||||
|
||||
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()`.
|
||||
|
||||
```typescript
|
||||
await Promise.all([
|
||||
client.set('Tm9kZSBSZWRpcw==', 'users:1'),
|
||||
client.sAdd('users:1:tokens', 'Tm9kZSBSZWRpcw==')
|
||||
]);
|
||||
```
|
||||
|
||||
### Clustering
|
||||
|
||||
Check out the [Clustering Guide](./docs/clustering.md) when using Node Redis to connect to a Redis Cluster.
|
||||
|
||||
## Supported Redis versions
|
||||
|
||||
Node Redis is supported with the following versions of Redis:
|
||||
|
||||
| Version | Supported |
|
||||
|---------|--------------------|
|
||||
| 6.2.z | :heavy_check_mark: |
|
||||
| 6.0.z | :heavy_check_mark: |
|
||||
| 5.y.z | :heavy_check_mark: |
|
||||
| < 5.0 | :x: |
|
||||
|
||||
> Node Redis should work with older versions of Redis, but it is not fully tested and we cannot offer support.
|
||||
@@ -1,13 +0,0 @@
|
||||
# F.A.Q.
|
||||
|
||||
Nobody has *actually* asked these questions. But, we needed somewhere to put all the important bits and bobs that didn't fit anywhere else. So, here you go!
|
||||
|
||||
## What happens when the network goes down?
|
||||
|
||||
When a socket closed unexpectedly, all the commands that were already sent will reject as they might have been executed on the server. The rest will remain queued in memory until a new socket is established. If the client is closed—either by returning an error from [`reconnectStrategy`](./client-configuration.md#reconnect-strategy) or by manually calling `.disconnect()`—they will be rejected.
|
||||
|
||||
## How are commands batched?
|
||||
|
||||
Commands are pipelined using [`queueMicrotask`](https://nodejs.org/api/globals.html#globals_queuemicrotask_callback).
|
||||
|
||||
If `socket.write()` returns `false`—meaning that ["all or part of the data was queued in user memory"](https://nodejs.org/api/net.html#net_socket_write_data_encoding_callback:~:text=all%20or%20part%20of%20the%20data%20was%20queued%20in%20user%20memory)—the commands will stack in memory until the [`drain`](https://nodejs.org/api/net.html#net_event_drain) event is fired.
|
||||
@@ -1,32 +0,0 @@
|
||||
# `createClient` configuration
|
||||
|
||||
| Property | Default | Description |
|
||||
|--------------------------|------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| url | | `redis[s]://[[username][:password]@][host][:port][/db-number]` (see [`redis`](https://www.iana.org/assignments/uri-schemes/prov/redis) and [`rediss`](https://www.iana.org/assignments/uri-schemes/prov/rediss) IANA registration for more details) |
|
||||
| socket | | Object defining socket connection properties |
|
||||
| socket.host | `'localhost'` | Hostname to connect to |
|
||||
| socket.port | `6379` | Port to connect to |
|
||||
| socket.path | | UNIX Socket to connect to |
|
||||
| socket.connectTimeout | `5000` | The timeout for connecting to the Redis Server (in milliseconds) |
|
||||
| socket.noDelay | `true` | Enable/disable the use of [`Nagle's algorithm`](https://nodejs.org/api/net.html#net_socket_setnodelay_nodelay) |
|
||||
| socket.keepAlive | `5000` | Enable/disable the [`keep-alive`](https://nodejs.org/api/net.html#net_socket_setkeepalive_enable_initialdelay) functionality |
|
||||
| socket.tls | | Set to `true` to enable [TLS Configuration](https://nodejs.org/api/tls.html#tls_tls_connect_options_callback) |
|
||||
| socket.reconnectStrategy | `retries => Math.min(retries * 50, 500)` | A function containing the [Reconnect Strategy](#reconnect-strategy) logic |
|
||||
| username | | ACL username ([see ACL guide](https://redis.io/topics/acl)) |
|
||||
| password | | ACL password or the old "--requirepass" password |
|
||||
| database | | Database number to connect to (see [`SELECT`](https://redis.io/commands/select) command) |
|
||||
| modules | | Object defining which [Redis Modules](../../README.md#modules) to include |
|
||||
| scripts | | Object defining Lua Scripts to use with this client (see [Lua Scripts](../README.md#lua-scripts)) |
|
||||
| commandsQueueMaxLength | | Maximum length of the client's internal command queue |
|
||||
| readonly | `false` | Connect in [`READONLY`](https://redis.io/commands/readonly) mode |
|
||||
| legacyMode | `false` | Maintain some backwards compatibility (see the [Migration Guide](v3-to-v4.md)) |
|
||||
| isolationPoolOptions | | See the [Isolated Execution Guide](./isolated-execution.md) |
|
||||
|
||||
## Reconnect Strategy
|
||||
|
||||
You can implement a custom reconnect strategy as a function that should:
|
||||
|
||||
- Receives the number of retries attempted so far.
|
||||
- Should return `number | Error`:
|
||||
- `number`: the time in milliseconds to wait before trying to reconnect again.
|
||||
- `Error`: close the client and flush the commands queue.
|
||||
@@ -1,56 +0,0 @@
|
||||
# Clustering
|
||||
|
||||
## Basic Example
|
||||
|
||||
Connecting to a cluster is a bit different. Create the client by specifying some (or all) of the nodes in your cluster and then use it like a regular client instance:
|
||||
|
||||
```typescript
|
||||
import { createCluster } from 'redis';
|
||||
|
||||
(async () => {
|
||||
const cluster = createCluster({
|
||||
rootNodes: [
|
||||
{
|
||||
url: 'redis://10.0.0.1:30001'
|
||||
},
|
||||
{
|
||||
url: 'redis://10.0.0.2:30002'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
cluster.on('error', (err) => console.log('Redis Cluster Error', err));
|
||||
|
||||
await cluster.connect();
|
||||
|
||||
await cluster.set('key', 'value');
|
||||
const value = await cluster.get('key');
|
||||
})();
|
||||
```
|
||||
|
||||
## `createCluster` configuration
|
||||
|
||||
> See the [client configuration](./client-configuration.md) page for the `rootNodes` and `defaults` configuration schemas.
|
||||
|
||||
| Property | Default | Description |
|
||||
|------------------------|---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| rootNodes | | An array of root nodes that are part of the cluster, which will be used to get the cluster topology. Each element in the array is a client configuration object. There is no need to specify every node in the cluster, 3 should be enough to reliably connect and obtain the cluster configuration from the server |
|
||||
| defaults | | The default configuration values for every client in the cluster. Use this for example when specifying an ACL user to connect with |
|
||||
| useReplicas | `false` | When `true`, distribute load by executing readonly commands (such as `GET`, `GEOSEARCH`, etc.) across all cluster nodes. When `false`, only use master nodes |
|
||||
| maxCommandRedirections | `16` | The maximum number of times a command will be redirected due to `MOVED` or `ASK` errors |
|
||||
| modules | | Object defining which [Redis Modules](../../README.md#modules) to include |
|
||||
| scripts | | Object defining Lua Scripts to use with this client (see [Lua Scripts](../README.md#lua-scripts)) |
|
||||
|
||||
## Command Routing
|
||||
|
||||
### Commands that operate on Redis Keys
|
||||
|
||||
Commands such as `GET`, `SET`, etc. will be routed by the first key, for instance `MGET 1 2 3` will be routed by the key `1`.
|
||||
|
||||
### [Server Commands](https://redis.io/commands#server)
|
||||
|
||||
Admin commands such as `MEMORY STATS`, `FLUSHALL`, etc. are not attached to the cluster, and should be executed on a specific node using `.getSlot()` or `.getAllMasters()`.
|
||||
|
||||
### "Forwarded Commands"
|
||||
|
||||
Some commands (e.g. `PUBLISH`) are forwarded to other cluster nodes by the Redis server. The client will send these commands to a random node in order to spread the load across the cluster.
|
||||
@@ -1,67 +0,0 @@
|
||||
# Isolated Execution
|
||||
|
||||
Sometimes you want to run your commands on an exclusive connection. There are a few reasons to do this:
|
||||
|
||||
- You're using [transactions]() and need to `WATCH` a key or keys for changes.
|
||||
- You want to run a blocking command that will take over the connection, such as `BLPOP` or `BLMOVE`.
|
||||
- You're using the `MONITOR` command which also takes over a connection.
|
||||
|
||||
Below are several examples of how to use isolated execution.
|
||||
|
||||
> NOTE: Behind the scences we're using [`generic-pool`](https://www.npmjs.com/package/generic-pool) to provide a pool of connections that can be isolated. Go there to learn more.
|
||||
|
||||
## The Simple Secnario
|
||||
|
||||
This just isolates execution on a single connection. Do what you want with that connection:
|
||||
|
||||
```typescript
|
||||
await client.executeIsolated(async isolatedClient => {
|
||||
await isolatedClient.set('key', 'value');
|
||||
await isolatedClient.get('key');
|
||||
});
|
||||
```
|
||||
|
||||
## Transactions
|
||||
|
||||
Things get a little more complex with transactions. Here we are `.watch()`ing some keys. If the keys change during the transaction, a `WatchError` is thrown when `.exec()` is called:
|
||||
|
||||
```typescript
|
||||
try {
|
||||
await client.executeIsolated(async isolatedClient => {
|
||||
await isolatedClient.watch('key');
|
||||
|
||||
const multi = isolatedClient.multi()
|
||||
.ping()
|
||||
.get('key');
|
||||
|
||||
if (Math.random() > 0.5) {
|
||||
await isolatedClient.watch('another-key');
|
||||
multi.set('another-key', await isolatedClient.get('another-key') / 2);
|
||||
}
|
||||
|
||||
return multi.exec();
|
||||
});
|
||||
} catch (err) {
|
||||
if (err instanceof WatchError) {
|
||||
// the transaction aborted
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Blocking Commands
|
||||
|
||||
For blocking commands, you can execute a tidy little one-liner:
|
||||
|
||||
```typescript
|
||||
await client.executeIsolated(isolatedClient => isolatedClient.blPop('key'));
|
||||
```
|
||||
|
||||
Or, you can just run the command directly, and provide the `isolated` option:
|
||||
|
||||
```typescript
|
||||
await client.blPop(
|
||||
commandOptions({ isolated: true }),
|
||||
'key'
|
||||
);
|
||||
```
|
||||
@@ -1,35 +0,0 @@
|
||||
# v3 to v4 Migration Guide
|
||||
|
||||
Version 4 of Node Redis is a major refactor. While we have tried to maintain backwards compatibility where possible, several interfaces have changed. Read this guide to understand the differences and how to implement version 4 in your application.
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
See the [Change Log](../CHANGELOG.md).
|
||||
|
||||
## Promises
|
||||
|
||||
Node Redis now uses native [Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) by default for all functions.
|
||||
|
||||
## Legacy Mode
|
||||
|
||||
Use legacy mode to preserve the backwards compatibility of commands while still getting access to the updated experience:
|
||||
|
||||
```typescript
|
||||
const client = createClient({
|
||||
legacyMode: true
|
||||
});
|
||||
|
||||
// legacy mode
|
||||
client.set('key', 'value', 'NX', (err, reply) => {
|
||||
// ...
|
||||
});
|
||||
|
||||
// version 4 interface is still accessible
|
||||
await client.v4.set('key', 'value', {
|
||||
NX: true
|
||||
});
|
||||
```
|
||||
|
||||
## `createClient`
|
||||
|
||||
The configuration object passed to `createClient` has changed significantly with this release. See the [client configuration guide](./client-configuration.md) for details.
|
||||
@@ -1,75 +0,0 @@
|
||||
# Node Redis: Examples
|
||||
|
||||
This folder contains example scripts showing how to use Node Redis in different scenarios.
|
||||
|
||||
| File Name | Description |
|
||||
|-----------------------------|--------------------------------------|
|
||||
| `connect-as-acl-user.js` | Connect to Redis 6 using an ACL user |
|
||||
| `blocking-list-pop.js` | Block until an element is pushed to a list |
|
||||
| `lua-multi-incr.js` | Define a custom lua script that allows you to perform INCRBY on multiple keys |
|
||||
| `command-with-modifiers.js` | Define a script that allows to run a command with several modifiers |
|
||||
| `set-scan.js` | An example script that shows how to use the SSCAN iterator functionality |
|
||||
|
||||
## Contributing
|
||||
|
||||
We'd love to see more examples here. If you have an idea that you'd like to see included here, submit a Pull Request and we'll be sure to review it! Don't forget to check out our [contributing guide](../CONTRIBUTING.md).
|
||||
|
||||
## Setup
|
||||
|
||||
To set up the examples folder so that you can run an example / develop one of your own:
|
||||
|
||||
```
|
||||
$ git clone https://github.com/redis/node-redis.git
|
||||
$ cd node-redis
|
||||
$ npm install && npm run build
|
||||
$ cd examples
|
||||
$ npm install
|
||||
```
|
||||
|
||||
### Coding Guidelines for Examples
|
||||
|
||||
When adding a new example, please follow these guidelines:
|
||||
|
||||
* Add your code in a single JavaScript or TypeScript file per example, directly in the `examples` folder
|
||||
* Do not introduce other dependencies in your example
|
||||
* Give your `.js` file a meaningful name using `-` separators e.g. `adding-to-a-stream.js` / `adding-to-a-stream.ts`
|
||||
* Indent your code using 2 spaces
|
||||
* Use the single line `//` comment style and comment your code
|
||||
* Add a comment at the top of your `.js` / `.ts` file describing what your example does
|
||||
* Add a comment at the top of your `.js` / `.ts` file describing any Redis commands that need to be run to set up data for your example (try and keep this minimal)
|
||||
* Use semicolons
|
||||
* Use `async` and `await`
|
||||
* Use single quotes, `'hello'` not `"hello"`
|
||||
* Place your example code in a single `async` function where possible, named according to the file name e.g. `add-to-stream.js` would contain `const addtoStream = async () => { ... };`, and call this function at the end of the file e.g. `addToStream();`
|
||||
* Unless your example requires a connection string, assume Redis is on the default localhost port 6379 with no password
|
||||
* Use meaningful example data, let's not use `foo`, `bar`, `baz` etc!
|
||||
* Leave an empty line at the end of your `.js` file
|
||||
* Update this `README.md` file to add your example to the table
|
||||
|
||||
Use [connect-as-acl-user.js](connect-as-acl-user.js) as a guide to develop a well formatted example script.
|
||||
|
||||
### Example Template
|
||||
|
||||
Here's a starter template for adding a new example, imagine this is stored in `do-something.js`:
|
||||
|
||||
```javascript
|
||||
// This comment should describe what the example does
|
||||
// and can extend to multiple lines.
|
||||
|
||||
// Set up the data in redis-cli using these commands:
|
||||
// <add your command(s) here, one per line>
|
||||
|
||||
import { createClient } from 'redis';
|
||||
|
||||
async function doSomething() {
|
||||
const client = createClient();
|
||||
|
||||
await client.connect();
|
||||
|
||||
// Add your example code here...
|
||||
|
||||
await client.quit();
|
||||
}
|
||||
|
||||
doSomething();
|
||||
```
|
||||
@@ -1,32 +0,0 @@
|
||||
// This example shows how to use the blocking LPUSH command.
|
||||
|
||||
// This code shows how to run with isolation the blPop Command to block the script while waiting for a value to be pushed to the list.
|
||||
// The script will be blocked until the LPUSH command is executed.
|
||||
// After which we log the list and quit the client.
|
||||
|
||||
import { createClient, commandOptions } from 'redis';
|
||||
|
||||
async function blockingListPop() {
|
||||
const client = createClient();
|
||||
|
||||
await client.connect();
|
||||
|
||||
const keyName = 'keyName';
|
||||
|
||||
const blpopPromise = client.blPop(
|
||||
commandOptions({ isolated: true }),
|
||||
keyName,
|
||||
0
|
||||
);
|
||||
|
||||
await client.lPush(keyName, 'value');
|
||||
|
||||
await blpopPromise;
|
||||
|
||||
console.log('blpopPromise resolved');
|
||||
console.log(keyName);
|
||||
|
||||
await client.quit();
|
||||
}
|
||||
|
||||
blockingListPop();
|
||||
@@ -1,32 +0,0 @@
|
||||
// Define a custom script that shows example of SET command
|
||||
// with several modifiers.
|
||||
|
||||
import { createClient } from 'redis';
|
||||
|
||||
async function commandWithModifiers() {
|
||||
const client = createClient();
|
||||
|
||||
await client.connect();
|
||||
await client.del('mykey');
|
||||
|
||||
let result = await client.set('mykey', 'myvalue', {
|
||||
EX: 60,
|
||||
GET: true
|
||||
}
|
||||
);
|
||||
|
||||
console.log(result); //nil
|
||||
|
||||
result = await client.set('mykey', 'newvalue', {
|
||||
EX: 60,
|
||||
GET: true
|
||||
}
|
||||
);
|
||||
|
||||
console.log(result); //myvalue
|
||||
|
||||
await client.quit();
|
||||
}
|
||||
|
||||
commandWithModifiers();
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
// Connect to Redis 6.x as an ACL user. Attempt to run a command
|
||||
// that the user is allowed to execute, and a command that the
|
||||
// user is not allowed to execute.
|
||||
|
||||
// Create the test user in redis-cli with this command:
|
||||
// acl setuser testuser on >testpassword +ping
|
||||
|
||||
import { createClient } from 'redis';
|
||||
|
||||
async function connectWithACLUser() {
|
||||
const client = createClient({
|
||||
url: 'redis://testuser:testpassword@127.0.0.1:6379'
|
||||
});
|
||||
|
||||
await client.connect();
|
||||
|
||||
// Returns PONG
|
||||
console.log(`Response from PING command: ${await client.ping()}`);
|
||||
|
||||
try {
|
||||
// This will error as this user is not allowed to run this command...
|
||||
console.log(`Response from GET command: ${await client.get('somekey')}`);
|
||||
} catch (e) {
|
||||
console.log(`GET command failed: ${e.message}`);
|
||||
}
|
||||
|
||||
await client.quit();
|
||||
}
|
||||
|
||||
connectWithACLUser();
|
||||
@@ -1,31 +0,0 @@
|
||||
// Define a custome lua script that accepts two keys and an amount to
|
||||
// increment each of them by
|
||||
|
||||
import { createClient, defineScript } from 'redis';
|
||||
|
||||
async function luaMultiIncr() {
|
||||
const client = createClient({
|
||||
scripts: {
|
||||
mincr: defineScript({
|
||||
NUMBER_OF_KEYS: 2,
|
||||
SCRIPT:
|
||||
'return {' +
|
||||
'redis.pcall("INCRBY", KEYS[1], ARGV[1]),' +
|
||||
'redis.pcall("INCRBY", KEYS[2], ARGV[1])' +
|
||||
'}',
|
||||
transformArguments(key1, key2, increment) {
|
||||
return [key1, key2, increment.toString()];
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
await client.connect();
|
||||
|
||||
await client.set('mykey', '5');
|
||||
console.log(await client.mincr('mykey', 'myotherkey', 10)); // [ 15, 10 ]
|
||||
|
||||
await client.quit();
|
||||
}
|
||||
|
||||
luaMultiIncr();
|
||||
87
packages/client/examples/package-lock.json
generated
87
packages/client/examples/package-lock.json
generated
@@ -1,87 +0,0 @@
|
||||
{
|
||||
"name": "node-redis-examples",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "node-redis-examples",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"redis": "../"
|
||||
}
|
||||
},
|
||||
"..": {
|
||||
"version": "4.0.0-rc.3",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cluster-key-slot": "1.1.0",
|
||||
"generic-pool": "3.8.2",
|
||||
"redis-parser": "3.0.0",
|
||||
"yallist": "4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@istanbuljs/nyc-config-typescript": "^1.0.1",
|
||||
"@tsconfig/node12": "^1.0.9",
|
||||
"@types/mocha": "^9.0.0",
|
||||
"@types/node": "^16.11.1",
|
||||
"@types/sinon": "^10.0.4",
|
||||
"@types/which": "^2.0.1",
|
||||
"@types/yallist": "^4.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.1.0",
|
||||
"@typescript-eslint/parser": "^5.1.0",
|
||||
"eslint": "^8.0.1",
|
||||
"mocha": "^9.1.3",
|
||||
"nyc": "^15.1.0",
|
||||
"release-it": "^14.11.6",
|
||||
"sinon": "^11.1.2",
|
||||
"source-map-support": "^0.5.20",
|
||||
"ts-node": "^10.3.0",
|
||||
"typedoc": "^0.22.6",
|
||||
"typedoc-github-wiki-theme": "^0.6.0",
|
||||
"typedoc-plugin-markdown": "^3.11.3",
|
||||
"typescript": "^4.4.4",
|
||||
"which": "^2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/redis": {
|
||||
"resolved": "..",
|
||||
"link": true
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"redis": {
|
||||
"version": "file:..",
|
||||
"requires": {
|
||||
"@istanbuljs/nyc-config-typescript": "^1.0.1",
|
||||
"@tsconfig/node12": "^1.0.9",
|
||||
"@types/mocha": "^9.0.0",
|
||||
"@types/node": "^16.11.1",
|
||||
"@types/sinon": "^10.0.4",
|
||||
"@types/which": "^2.0.1",
|
||||
"@types/yallist": "^4.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.1.0",
|
||||
"@typescript-eslint/parser": "^5.1.0",
|
||||
"cluster-key-slot": "1.1.0",
|
||||
"eslint": "^8.0.1",
|
||||
"generic-pool": "3.8.2",
|
||||
"mocha": "^9.1.3",
|
||||
"nyc": "^15.1.0",
|
||||
"redis-parser": "3.0.0",
|
||||
"release-it": "^14.11.6",
|
||||
"sinon": "^11.1.2",
|
||||
"source-map-support": "^0.5.20",
|
||||
"ts-node": "^10.3.0",
|
||||
"typedoc": "^0.22.6",
|
||||
"typedoc-github-wiki-theme": "^0.6.0",
|
||||
"typedoc-plugin-markdown": "^3.11.3",
|
||||
"typescript": "^4.4.4",
|
||||
"which": "^2.0.2",
|
||||
"yallist": "4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"name": "node-redis-examples",
|
||||
"version": "1.0.0",
|
||||
"description": "node-redis 4 example script",
|
||||
"main": "index.js",
|
||||
"private": true,
|
||||
"type": "module"
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
// An example script that shows how to use the SSCAN iterator functionality to retrieve the contents of a Redis set.
|
||||
// Create the set in redis-cli with this command:
|
||||
// sadd setName a b c d e f g h i j k l m n o p q
|
||||
|
||||
import { createClient } from 'redis';
|
||||
|
||||
async function setScan() {
|
||||
const client = createClient();
|
||||
await client.connect();
|
||||
|
||||
const setName = 'setName';
|
||||
for await (const member of client.sScanIterator(setName)) {
|
||||
console.log(member);
|
||||
}
|
||||
|
||||
await client.quit();
|
||||
}
|
||||
|
||||
setScan();
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@redis/client",
|
||||
"version": "4.0.0-rc.3",
|
||||
"version": "1.0.0-rc",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { pushVerdictArguments } from '@redis/client/lib/commands/generic-transformers';
|
||||
import { pushVerdictArguments } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"build": "tsc"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^4.0.0-rc"
|
||||
"@redis/client": "^1.0.0-rc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@istanbuljs/nyc-config-typescript": "^1.0.1",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { RedisSearchLanguages, SchemaFieldTypes, SchemaTextFieldPhonetics, transformArguments } from './CREATE';
|
||||
import { SchemaFieldTypes, SchemaTextFieldPhonetics, transformArguments } from './CREATE';
|
||||
import { RedisSearchLanguages } from '.';
|
||||
|
||||
describe('CREATE', () => {
|
||||
describe('transformArguments', () => {
|
||||
@@ -111,6 +112,20 @@ describe('CREATE', () => {
|
||||
['FT.CREATE', 'index', 'SCHEMA', 'field', 'TAG', 'SEPERATOR', 'seperator']
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
|
||||
it('with CASESENSITIVE', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('index', {
|
||||
field: {
|
||||
type: SchemaFieldTypes.TAG,
|
||||
CASESENSITIVE: true
|
||||
}
|
||||
}),
|
||||
['FT.CREATE', 'index', 'SCHEMA', 'field', 'TAG', 'CASESENSITIVE']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with generic options', () => {
|
||||
@@ -126,18 +141,6 @@ describe('CREATE', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('with CASESENSITIVE', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('index', {
|
||||
field: {
|
||||
type: SchemaFieldTypes.TEXT,
|
||||
CASESENSITIVE: true
|
||||
}
|
||||
}),
|
||||
['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'CASESENSITIVE']
|
||||
);
|
||||
});
|
||||
|
||||
describe('with SORTABLE', () => {
|
||||
it('true', () => {
|
||||
assert.deepEqual(
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
import { pushOptionalVerdictArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||
import { PropertyName } from '.';
|
||||
import { RedisSearchLanguages, PropertyName } from '.';
|
||||
|
||||
export enum SchemaFieldTypes {
|
||||
TEXT = 'TEXT',
|
||||
NUMERIC = 'NUMERIC',
|
||||
GEO = 'GEO',
|
||||
TAG = 'TAG',
|
||||
TAG = 'TAG'
|
||||
}
|
||||
|
||||
type CreateSchemaField<T extends SchemaFieldTypes, E = Record<string, never>> = T | ({
|
||||
type: T;
|
||||
AS?: string;
|
||||
CASESENSITIVE?: true;
|
||||
SORTABLE?: true | 'UNF';
|
||||
NOINDEX?: true;
|
||||
} & E);
|
||||
@@ -35,6 +34,7 @@ type CreateSchemaGeoField = CreateSchemaField<SchemaFieldTypes.GEO>;
|
||||
|
||||
type CreateSchemaTagField = CreateSchemaField<SchemaFieldTypes.TAG, {
|
||||
SEPERATOR?: string;
|
||||
CASESENSITIVE?: true;
|
||||
}>;
|
||||
|
||||
interface CreateSchema {
|
||||
@@ -45,34 +45,6 @@ interface CreateSchema {
|
||||
CreateSchemaTagField
|
||||
}
|
||||
|
||||
export enum RedisSearchLanguages {
|
||||
ARABIC = 'Arabic',
|
||||
BASQUE = 'Basque',
|
||||
CATALANA = 'Catalan',
|
||||
DANISH = 'Danish',
|
||||
DUTCH = 'Dutch',
|
||||
ENGLISH = 'English',
|
||||
FINNISH = 'Finnish',
|
||||
FRENCH = 'French',
|
||||
GERMAN = 'German',
|
||||
GREEK = 'Greek',
|
||||
HUNGARIAN = 'Hungarian',
|
||||
INDONESAIN = 'Indonesian',
|
||||
IRISH = 'Irish',
|
||||
ITALIAN = 'Italian',
|
||||
LITHUANIAN = 'Lithuanian',
|
||||
NEPALI = 'Nepali',
|
||||
NORWEIGAN = 'Norwegian',
|
||||
PORTUGUESE = 'Portuguese',
|
||||
ROMANIAN = 'Romanian',
|
||||
RUSSIAN = 'Russian',
|
||||
SPANISH = 'Spanish',
|
||||
SWEDISH = 'Swedish',
|
||||
TAMIL = 'Tamil',
|
||||
TURKISH = 'Turkish',
|
||||
CHINESE = 'Chinese'
|
||||
}
|
||||
|
||||
interface CreateOptions {
|
||||
ON?: 'HASH' | 'JSON';
|
||||
PREFIX?: string | Array<string>;
|
||||
@@ -196,11 +168,11 @@ export function transformArguments(index: string, schema: CreateSchema, options?
|
||||
args.push('SEPERATOR', fieldOptions.SEPERATOR);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
if (fieldOptions.CASESENSITIVE) {
|
||||
args.push('CASESENSITIVE');
|
||||
}
|
||||
|
||||
if (fieldOptions.CASESENSITIVE) {
|
||||
args.push('CASESENSITIVE');
|
||||
break;
|
||||
}
|
||||
|
||||
if (fieldOptions.SORTABLE) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { RedisSearchLanguages } from '.';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { RedisSearchLanguages, SchemaFieldTypes } from './CREATE';
|
||||
import { SchemaFieldTypes } from './CREATE';
|
||||
import { transformArguments } from './SEARCH';
|
||||
|
||||
describe('SEARCH', () => {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
|
||||
import { pushOptionalVerdictArgument, pushVerdictArgument, transformReplyTuples } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||
import { type } from 'os';
|
||||
import { PropertyName, pushSortByArguments, SortByOptions } from '.';
|
||||
import { RedisSearchLanguages } from './CREATE';
|
||||
import { RedisSearchLanguages, PropertyName, pushSortByArguments, SortByOptions } from '.';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
@@ -41,7 +39,7 @@ interface SearchOptions {
|
||||
TAGS?: {
|
||||
open: string;
|
||||
close: string;
|
||||
}
|
||||
};
|
||||
};
|
||||
SLOP?: number;
|
||||
INORDER?: true;
|
||||
|
||||
@@ -87,6 +87,34 @@ export default {
|
||||
tagVals: TAGVALS
|
||||
};
|
||||
|
||||
export enum RedisSearchLanguages {
|
||||
ARABIC = 'Arabic',
|
||||
BASQUE = 'Basque',
|
||||
CATALANA = 'Catalan',
|
||||
DANISH = 'Danish',
|
||||
DUTCH = 'Dutch',
|
||||
ENGLISH = 'English',
|
||||
FINNISH = 'Finnish',
|
||||
FRENCH = 'French',
|
||||
GERMAN = 'German',
|
||||
GREEK = 'Greek',
|
||||
HUNGARIAN = 'Hungarian',
|
||||
INDONESAIN = 'Indonesian',
|
||||
IRISH = 'Irish',
|
||||
ITALIAN = 'Italian',
|
||||
LITHUANIAN = 'Lithuanian',
|
||||
NEPALI = 'Nepali',
|
||||
NORWEIGAN = 'Norwegian',
|
||||
PORTUGUESE = 'Portuguese',
|
||||
ROMANIAN = 'Romanian',
|
||||
RUSSIAN = 'Russian',
|
||||
SPANISH = 'Spanish',
|
||||
SWEDISH = 'Swedish',
|
||||
TAMIL = 'Tamil',
|
||||
TURKISH = 'Turkish',
|
||||
CHINESE = 'Chinese'
|
||||
}
|
||||
|
||||
export type PropertyName = `${'@' | '$.'}${string}`;
|
||||
|
||||
export type SortByOptions = PropertyName | {
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
export { default } from './commands';
|
||||
|
||||
export { SchemaFieldTypes, SchemaTextFieldPhonetics } from './commands/CREATE';
|
||||
export { AggregateSteps, AggregateGroupByReducers } from './commands/AGGREGATE';
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"build": "tsc"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^4.0.0-rc"
|
||||
"@redis/client": "^1.0.0-rc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@istanbuljs/nyc-config-typescript": "^1.0.1",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { createConnection } from 'net';
|
||||
import { once } from 'events';
|
||||
import { RedisModules, RedisScripts } from '@redis/client/lib/commands';
|
||||
import RedisClient, { RedisClientType } from '@redis/client/lib/client';
|
||||
import { promiseTimeout } from '@redis/client/lib/utils';
|
||||
import { RedisModules, RedisScripts } from '@redis/client/dist/lib/commands';
|
||||
import RedisClient, { RedisClientType } from '@redis/client/dist/lib/client';
|
||||
import { promiseTimeout } from '@redis/client/dist/lib/utils';
|
||||
import path from 'path';
|
||||
import { promisify } from 'util';
|
||||
import { exec } from 'child_process';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { RedisModules, RedisScripts } from '@redis/client/lib/commands';
|
||||
import RedisClient, { RedisClientOptions, RedisClientType } from '@redis/client/lib/client';
|
||||
import RedisCluster, { RedisClusterOptions, RedisClusterType } from '@redis/client/lib/cluster';
|
||||
import { RedisModules, RedisScripts } from '@redis/client/dist/lib/commands';
|
||||
import RedisClient, { RedisClientOptions, RedisClientType } from '@redis/client/dist/lib/client';
|
||||
import RedisCluster, { RedisClusterOptions, RedisClusterType } from '@redis/client/dist/lib/cluster';
|
||||
import { RedisServerDockerConfig, spawnRedisServer, spawnRedisCluster } from './dockers';
|
||||
import yargs from 'yargs';
|
||||
import { hideBin } from 'yargs/helpers';
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"test": "echo \"TODO\""
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^4.0.0-rc"
|
||||
"@redis/client": "^1.0.0-rc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@istanbuljs/nyc-config-typescript": "^1.0.1",
|
||||
|
||||
Reference in New Issue
Block a user