You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-09 00:22:08 +03:00
update docs, add 6.0.x to the tests matrix, add eslint, npm update, fix some commands, fix some types
Co-authored-by: Simon Prickett <simon@crudworks.org>
This commit is contained in:
12
.eslintrc.json
Normal file
12
.eslintrc.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"root": true,
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
]
|
||||
}
|
2
.github/workflows/tests.yml
vendored
2
.github/workflows/tests.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node-version: [12.x, 14.x, 16.x]
|
||||
redis-version: [5.x, 6.x]
|
||||
redis-version: [5.x, 6.0.x, 6.2.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2.3.4
|
||||
|
57
README.md
57
README.md
@@ -57,7 +57,7 @@ createClient({
|
||||
});
|
||||
```
|
||||
|
||||
You can also use discrete parameters, UNIX sockets, and even TLS to connect. Details can be found in in the [Wiki](https://github.com/redis/node-redis/wiki/lib.socket#RedisSocketOptions).
|
||||
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
|
||||
|
||||
@@ -227,32 +227,34 @@ import { createClient, defineScript } from 'redis';
|
||||
})();
|
||||
```
|
||||
|
||||
### Cluster
|
||||
### Disconnecting
|
||||
|
||||
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 non-clustered client:
|
||||
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
|
||||
import { createCluster } from 'redis';
|
||||
const [ping, get, quit] = await Promise.all([
|
||||
client.ping(),
|
||||
client.get('key'),
|
||||
client.quit()
|
||||
]); // ['PONG', null, 'OK']
|
||||
|
||||
(async () => {
|
||||
const cluster = createCluster({
|
||||
rootNodes: [
|
||||
{
|
||||
url: 'redis://10.0.0.1:30001'
|
||||
},
|
||||
{
|
||||
url: 'redis://10.0.0.2:30002'
|
||||
try {
|
||||
await client.get('key');
|
||||
} catch (err) {
|
||||
// ClosedClient Error
|
||||
}
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
cluster.on('error', (err) => console.log('Redis Cluster Error', err));
|
||||
#### `.disconnect()`
|
||||
|
||||
await cluster.connect();
|
||||
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.
|
||||
|
||||
await cluster.set('key', 'value');
|
||||
const value = await cluster.get('key');
|
||||
})();
|
||||
```typescript
|
||||
await client.disconnect();
|
||||
```
|
||||
|
||||
### Auto-Pipelining
|
||||
@@ -273,6 +275,23 @@ await Promise.all([
|
||||
]);
|
||||
```
|
||||
|
||||
### 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.
|
||||
|
||||
## Contributing
|
||||
|
||||
If you'd like to contribute, check out the [contributing guide](CONTRIBUTING.md).
|
||||
|
@@ -5,9 +5,9 @@
|
||||
Node Redis is generally backwards compatible with very few exceptions, so we recommend users to always use the latest version to experience stability, performance and security.
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 4.0.x | :white_check_mark: |
|
||||
| 3.1.x | :white_check_mark: |
|
||||
|---------|--------------------|
|
||||
| 4.0.z | :heavy_check_mark: |
|
||||
| 3.1.z | :heavy_check_mark: |
|
||||
| < 3.1 | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
54
docs/clustering.md
Normal file
54
docs/clustering.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# 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 | |
|
||||
|
||||
## 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.
|
@@ -6,20 +6,20 @@ import { RedisCommandRawReply } from '../commands';
|
||||
export interface QueueCommandOptions {
|
||||
asap?: boolean;
|
||||
chainId?: symbol;
|
||||
signal?: any; // TODO: `AbortSignal` type is incorrect
|
||||
signal?: AbortSignal;
|
||||
}
|
||||
|
||||
interface CommandWaitingToBeSent extends CommandWaitingForReply {
|
||||
args: Array<string | Buffer>;
|
||||
chainId?: symbol;
|
||||
abort?: {
|
||||
signal: any; // TODO: `AbortSignal` type is incorrect
|
||||
signal: AbortSignal;
|
||||
listener(): void;
|
||||
};
|
||||
}
|
||||
|
||||
interface CommandWaitingForReply {
|
||||
resolve(reply?: any): void;
|
||||
resolve(reply?: unknown): void;
|
||||
reject(err: Error): void;
|
||||
channelsCounter?: number;
|
||||
bufferMode?: boolean;
|
||||
@@ -135,7 +135,8 @@ export default class RedisCommandsQueue {
|
||||
signal: options.signal,
|
||||
listener
|
||||
};
|
||||
options.signal.addEventListener('abort', listener, {
|
||||
// AbortSignal type is incorrent
|
||||
(options.signal as any).addEventListener('abort', listener, {
|
||||
once: true
|
||||
});
|
||||
}
|
||||
|
@@ -229,5 +229,5 @@ export default {
|
||||
UNWATCH,
|
||||
unwatch: UNWATCH,
|
||||
WAIT,
|
||||
wait: WAIT,
|
||||
wait: WAIT
|
||||
};
|
||||
|
@@ -611,8 +611,9 @@ describe('Client', () => {
|
||||
const promise = assert.rejects(client.connect(), ConnectionTimeoutError),
|
||||
start = process.hrtime.bigint();
|
||||
|
||||
while (process.hrtime.bigint() - start < 1_000_000) {
|
||||
// block the event loop for 1ms, to make sure the connection will timeout
|
||||
while (process.hrtime.bigint() - start < 1_000_000) {}
|
||||
}
|
||||
|
||||
await promise;
|
||||
} catch (err) {
|
||||
|
@@ -34,16 +34,16 @@ type WithCommands = {
|
||||
};
|
||||
|
||||
export type WithModules<M extends RedisModules> = {
|
||||
[P in keyof M]: {
|
||||
[P in keyof M as M[P] extends never ? never : P]: {
|
||||
[C in keyof M[P]]: RedisClientCommandSignature<M[P][C]>;
|
||||
};
|
||||
};
|
||||
|
||||
export type WithScripts<S extends RedisScripts> = {
|
||||
[P in keyof S]: RedisClientCommandSignature<S[P]>;
|
||||
[P in keyof S as S[P] extends never ? never : P]: RedisClientCommandSignature<S[P]>;
|
||||
};
|
||||
|
||||
export type RedisClientType<M extends RedisModules = {}, S extends RedisScripts = {}> =
|
||||
export type RedisClientType<M extends RedisModules = Record<string, never>, S extends RedisScripts = Record<string, never>> =
|
||||
RedisClient<M, S> & WithCommands & WithModules<M> & WithScripts<S>;
|
||||
|
||||
export type InstantiableRedisClient<M extends RedisModules, S extends RedisScripts> =
|
||||
@@ -53,12 +53,14 @@ export interface ClientCommandOptions extends QueueCommandOptions {
|
||||
isolated?: boolean;
|
||||
}
|
||||
|
||||
type ClientLegacyCallback = (err: Error | null, reply?: RedisCommandRawReply) => void;
|
||||
|
||||
export default class RedisClient<M extends RedisModules, S extends RedisScripts> extends EventEmitter {
|
||||
static commandOptions(options: ClientCommandOptions): CommandOptions<ClientCommandOptions> {
|
||||
return commandOptions(options);
|
||||
}
|
||||
|
||||
static extend<M extends RedisModules = {}, S extends RedisScripts = {}>(plugins?: RedisPlugins<M, S>): InstantiableRedisClient<M, S> {
|
||||
static extend<M extends RedisModules = Record<string, never>, S extends RedisScripts = Record<string, never>>(plugins?: RedisPlugins<M, S>): InstantiableRedisClient<M, S> {
|
||||
const Client = <any>extendWithModulesAndScripts({
|
||||
BaseClass: RedisClient,
|
||||
modules: plugins?.modules,
|
||||
@@ -74,14 +76,14 @@ export default class RedisClient<M extends RedisModules, S extends RedisScripts>
|
||||
return Client;
|
||||
}
|
||||
|
||||
static create<M extends RedisModules = {}, S extends RedisScripts = {}>(options?: RedisClientOptions<M, S>): RedisClientType<M, S> {
|
||||
static create<M extends RedisModules = Record<string, never>, S extends RedisScripts = Record<string, never>>(options?: RedisClientOptions<M, S>): RedisClientType<M, S> {
|
||||
return new (RedisClient.extend(options))(options);
|
||||
}
|
||||
|
||||
static parseURL(url: string): RedisClientOptions<{}, {}> {
|
||||
static parseURL(url: string): RedisClientOptions<Record<string, never>, Record<string, never>> {
|
||||
// https://www.iana.org/assignments/uri-schemes/prov/redis
|
||||
const { hostname, port, protocol, username, password, pathname } = new URL(url),
|
||||
parsed: RedisClientOptions<{}, {}> = {
|
||||
parsed: RedisClientOptions<Record<string, never>, Record<string, never>> = {
|
||||
socket: {
|
||||
host: hostname
|
||||
}
|
||||
@@ -245,10 +247,12 @@ export default class RedisClient<M extends RedisModules, S extends RedisScripts>
|
||||
|
||||
(this as any).#v4.sendCommand = this.#sendCommand.bind(this);
|
||||
(this as any).sendCommand = (...args: Array<unknown>): void => {
|
||||
const callback = typeof args[args.length - 1] === 'function' ? args[args.length - 1] as Function : undefined,
|
||||
const callback = typeof args[args.length - 1] === 'function' ?
|
||||
args[args.length - 1] as ClientLegacyCallback :
|
||||
undefined,
|
||||
actualArgs = !callback ? args : args.slice(0, -1);
|
||||
this.#sendCommand(actualArgs.flat() as Array<string>)
|
||||
.then((reply: unknown) => {
|
||||
.then((reply: RedisCommandRawReply) => {
|
||||
if (!callback) return;
|
||||
|
||||
// https://github.com/NodeRedis/node-redis#commands:~:text=minimal%20parsing
|
||||
@@ -435,17 +439,12 @@ export default class RedisClient<M extends RedisModules, S extends RedisScripts>
|
||||
|
||||
this.#socket.cork();
|
||||
|
||||
while (true) {
|
||||
while (!this.#socket.writableNeedDrain) {
|
||||
const args = this.#queue.getCommandToSend();
|
||||
if (args === undefined) break;
|
||||
|
||||
let writeResult;
|
||||
for (const toWrite of encodeCommand(args)) {
|
||||
writeResult = this.#socket.write(toWrite);
|
||||
}
|
||||
|
||||
if (!writeResult) {
|
||||
break;
|
||||
this.#socket.write(toWrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -11,16 +11,16 @@ type WithCommands<M extends RedisModules, S extends RedisScripts> = {
|
||||
};
|
||||
|
||||
type WithModules<M extends RedisModules, S extends RedisScripts> = {
|
||||
[P in keyof M]: {
|
||||
[P in keyof M as M[P] extends never ? never : P]: {
|
||||
[C in keyof M[P]]: RedisClientMultiCommandSignature<M[P][C], M, S>;
|
||||
};
|
||||
};
|
||||
|
||||
type WithScripts<M extends RedisModules, S extends RedisScripts> = {
|
||||
[P in keyof S]: RedisClientMultiCommandSignature<S[P], M, S>
|
||||
[P in keyof S as S[P] extends never ? never : P]: RedisClientMultiCommandSignature<S[P], M, S>
|
||||
};
|
||||
|
||||
export type RedisClientMultiCommandType<M extends RedisModules = {}, S extends RedisScripts = {}> =
|
||||
export type RedisClientMultiCommandType<M extends RedisModules = Record<string, never>, S extends RedisScripts = Record<string, never>> =
|
||||
RedisClientMultiCommand & WithCommands<M, S> & WithModules<M, S> & WithScripts<M, S>;
|
||||
|
||||
export type RedisClientMultiExecutor = (queue: Array<RedisMultiQueuedCommand>, chainId?: symbol) => Promise<Array<RedisCommandRawReply>>;
|
||||
|
@@ -234,7 +234,6 @@ export default class RedisSocket extends EventEmitter {
|
||||
|
||||
this.#isOpen = false;
|
||||
|
||||
|
||||
try {
|
||||
await fn();
|
||||
await this.disconnect(true);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import COMMANDS from './commands';
|
||||
import { RedisCommand, RedisCommandArguments, RedisCommandReply, RedisModules, RedisScript, RedisScripts } from '../commands';
|
||||
import { RedisCommand, RedisCommandArguments, RedisCommandReply, RedisModules, RedisPlugins, RedisScript, RedisScripts } from '../commands';
|
||||
import { ClientCommandOptions, RedisClientCommandSignature, RedisClientOptions, RedisClientType, WithModules, WithScripts } from '../client';
|
||||
import RedisClusterSlots, { ClusterNode } from './cluster-slots';
|
||||
import { extendWithModulesAndScripts, transformCommandArguments, transformCommandReply, extendWithCommands } from '../commander';
|
||||
@@ -7,14 +7,9 @@ import { EventEmitter } from 'events';
|
||||
import RedisClusterMultiCommand, { RedisClusterMultiCommandType } from './multi-command';
|
||||
import { RedisMultiQueuedCommand } from '../multi-command';
|
||||
|
||||
export type RedisClusterClientOptions = Omit<RedisClientOptions<{}, {}>, 'modules' | 'scripts'>;
|
||||
export type RedisClusterClientOptions = Omit<RedisClientOptions<Record<string, never>, Record<string, never>>, 'modules' | 'scripts'>;
|
||||
|
||||
export interface RedisClusterPlugins<M extends RedisModules, S extends RedisScripts> {
|
||||
modules?: M;
|
||||
scripts?: S;
|
||||
}
|
||||
|
||||
export interface RedisClusterOptions<M extends RedisModules, S extends RedisScripts> extends RedisClusterPlugins<M, S> {
|
||||
export interface RedisClusterOptions<M extends RedisModules, S extends RedisScripts> extends RedisPlugins<M, S> {
|
||||
rootNodes: Array<RedisClusterClientOptions>;
|
||||
defaults?: Partial<RedisClusterClientOptions>;
|
||||
useReplicas?: boolean;
|
||||
@@ -25,10 +20,10 @@ type WithCommands = {
|
||||
[P in keyof typeof COMMANDS]: RedisClientCommandSignature<(typeof COMMANDS)[P]>;
|
||||
};
|
||||
|
||||
export type RedisClusterType<M extends RedisModules = {}, S extends RedisScripts = {}> =
|
||||
export type RedisClusterType<M extends RedisModules = Record<string, never>, S extends RedisScripts = Record<string, never>> =
|
||||
RedisCluster<M, S> & WithCommands & WithModules<M> & WithScripts<S>;
|
||||
|
||||
export default class RedisCluster<M extends RedisModules = {}, S extends RedisScripts = {}> extends EventEmitter {
|
||||
export default class RedisCluster<M extends RedisModules = Record<string, never>, S extends RedisScripts = Record<string, never>> extends EventEmitter {
|
||||
static extractFirstKey(command: RedisCommand, originalArgs: Array<unknown>, redisArgs: RedisCommandArguments): string | Buffer | undefined {
|
||||
if (command.FIRST_KEY_INDEX === undefined) {
|
||||
return undefined;
|
||||
@@ -39,7 +34,7 @@ export default class RedisCluster<M extends RedisModules = {}, S extends RedisSc
|
||||
return command.FIRST_KEY_INDEX(...originalArgs);
|
||||
}
|
||||
|
||||
static create<M extends RedisModules = {}, S extends RedisScripts = {}>(options?: RedisClusterOptions<M, S>): RedisClusterType<M, S> {
|
||||
static create<M extends RedisModules = Record<string, never>, S extends RedisScripts = Record<string, never>>(options?: RedisClusterOptions<M, S>): RedisClusterType<M, S> {
|
||||
return new (<any>extendWithModulesAndScripts({
|
||||
BaseClass: RedisCluster,
|
||||
modules: options?.modules,
|
||||
|
@@ -12,16 +12,16 @@ type WithCommands<M extends RedisModules, S extends RedisScripts> = {
|
||||
};
|
||||
|
||||
type WithModules<M extends RedisModules, S extends RedisScripts> = {
|
||||
[P in keyof M]: {
|
||||
[P in keyof M as M[P] extends never ? never : P]: {
|
||||
[C in keyof M[P]]: RedisClusterMultiCommandSignature<M[P][C], M, S>;
|
||||
};
|
||||
};
|
||||
|
||||
type WithScripts<M extends RedisModules, S extends RedisScripts> = {
|
||||
[P in keyof S]: RedisClusterMultiCommandSignature<S[P], M, S>
|
||||
[P in keyof S as S[P] extends never ? never : P]: RedisClusterMultiCommandSignature<S[P], M, S>
|
||||
};
|
||||
|
||||
export type RedisClusterMultiCommandType<M extends RedisModules = {}, S extends RedisScripts = {}> =
|
||||
export type RedisClusterMultiCommandType<M extends RedisModules = Record<string, never>, S extends RedisScripts = Record<string, never>> =
|
||||
RedisClusterMultiCommand & WithCommands<M, S> & WithModules<M, S> & WithScripts<M, S>;
|
||||
|
||||
export type RedisClusterMultiExecutor = (queue: Array<RedisMultiQueuedCommand>, firstKey?: string | Buffer, chainId?: symbol) => Promise<Array<RedisCommandRawReply>>;
|
||||
|
@@ -6,4 +6,4 @@ export function transformArguments(): RedisCommandArguments {
|
||||
return ['COMMAND', 'COUNT'];
|
||||
}
|
||||
|
||||
declare function transformReply(): number;
|
||||
export declare function transformReply(): number;
|
||||
|
@@ -6,4 +6,4 @@ export function transformArguments(args: Array<string>): RedisCommandArguments {
|
||||
return ['COMMAND', 'GETKEYS', ...args];
|
||||
}
|
||||
|
||||
declare function transformReply(): Array<string>;
|
||||
export declare function transformReply(): Array<string>;
|
||||
|
@@ -2,43 +2,27 @@ import { RedisCommandArguments } from '.';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
interface EX {
|
||||
type MaximumOneOf<T, K extends keyof T = keyof T> =
|
||||
K extends keyof T ? { [P in K]?: T[K] } & Partial<Record<Exclude<keyof T, K>, never>> : never;
|
||||
|
||||
type SetTTL = MaximumOneOf<{
|
||||
EX: number;
|
||||
}
|
||||
|
||||
interface PX {
|
||||
PX: number
|
||||
}
|
||||
|
||||
interface EXAT {
|
||||
PX: number;
|
||||
EXAT: number;
|
||||
}
|
||||
|
||||
interface PXAT {
|
||||
PXAT: number;
|
||||
}
|
||||
|
||||
interface KEEPTTL {
|
||||
KEEPTTL: true;
|
||||
}
|
||||
}>;
|
||||
|
||||
type SetTTL = EX | PX | EXAT | PXAT | KEEPTTL | {};
|
||||
|
||||
interface NX {
|
||||
type SetGuards = MaximumOneOf<{
|
||||
NX: true;
|
||||
}
|
||||
|
||||
interface XX {
|
||||
XX: true;
|
||||
}
|
||||
|
||||
type SetGuards = NX | XX | {};
|
||||
}>;
|
||||
|
||||
interface SetCommonOptions {
|
||||
GET: true
|
||||
GET?: true;
|
||||
}
|
||||
|
||||
type SetOptions = SetTTL & SetGuards & (SetCommonOptions | {});
|
||||
type SetOptions = SetTTL & SetGuards & SetCommonOptions;
|
||||
|
||||
export function transformArguments(key: string | Buffer, value: string | Buffer, options?: SetOptions): RedisCommandArguments {
|
||||
const args = ['SET', key, value];
|
||||
@@ -47,25 +31,25 @@ export function transformArguments(key: string | Buffer, value: string | Buffer,
|
||||
return args;
|
||||
}
|
||||
|
||||
if ('EX' in options) {
|
||||
if (options.EX) {
|
||||
args.push('EX', options.EX.toString());
|
||||
} else if ('PX' in options) {
|
||||
} else if (options.PX) {
|
||||
args.push('PX', options.PX.toString());
|
||||
} else if ('EXAT' in options) {
|
||||
} else if (options.EXAT) {
|
||||
args.push('EXAT', options.EXAT.toString());
|
||||
} else if ('PXAT' in options) {
|
||||
} else if (options.PXAT) {
|
||||
args.push('PXAT', options.PXAT.toString());
|
||||
} else if ((<KEEPTTL>options).KEEPTTL) {
|
||||
} else if (options.KEEPTTL) {
|
||||
args.push('KEEPTTL');
|
||||
}
|
||||
|
||||
if ((<NX>options).NX) {
|
||||
if (options.NX) {
|
||||
args.push('NX');
|
||||
} else if ((<XX>options).XX) {
|
||||
} else if (options.XX) {
|
||||
args.push('XX');
|
||||
}
|
||||
|
||||
if ((<SetCommonOptions>options).GET) {
|
||||
if (options.GET) {
|
||||
args.push('GET');
|
||||
}
|
||||
|
||||
|
2075
package-lock.json
generated
2075
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@@ -14,6 +14,7 @@
|
||||
"scripts": {
|
||||
"test": "nyc -r text-summary -r html mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'",
|
||||
"build": "tsc",
|
||||
"lint": "eslint ./*.ts ./lib/**/*.ts",
|
||||
"documentation": "typedoc"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -26,20 +27,23 @@
|
||||
"@istanbuljs/nyc-config-typescript": "^1.0.1",
|
||||
"@tsconfig/node12": "^1.0.9",
|
||||
"@types/mocha": "^9.0.0",
|
||||
"@types/node": "^16.10.3",
|
||||
"@types/node": "^16.11.1",
|
||||
"@types/sinon": "^10.0.4",
|
||||
"@types/which": "^2.0.1",
|
||||
"@types/yallist": "^4.0.1",
|
||||
"mocha": "^9.1.2",
|
||||
"@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.5",
|
||||
"typedoc": "^0.22.6",
|
||||
"typedoc-github-wiki-theme": "^0.6.0",
|
||||
"typedoc-plugin-markdown": "^3.11.3",
|
||||
"typescript": "^4.4.3",
|
||||
"typescript": "^4.4.4",
|
||||
"which": "^2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
|
Reference in New Issue
Block a user