From 08193b7ada6767230d99cff974099c37527fcb10 Mon Sep 17 00:00:00 2001 From: Yuki Tanaka Date: Wed, 23 Oct 2024 23:09:17 +0900 Subject: [PATCH] feat: add `nx` and `xx` options to `SetOpts` (#457) --- command.ts | 28 +++++++++++++++++++++++++++- redis.ts | 30 ++++++++++++++++++++++++++---- tests/commands/string.ts | 14 +++++++++++++- 3 files changed, 66 insertions(+), 6 deletions(-) diff --git a/command.ts b/command.ts index 1ab81d67..ab41537a 100644 --- a/command.ts +++ b/command.ts @@ -117,6 +117,10 @@ export type StralgoTarget = "KEYS" | "STRINGS"; export interface SetOpts { ex?: number; px?: number; + /** Sets `NX` option. */ + nx?: boolean; + /** Sets `XX` option. */ + xx?: boolean; /** * Sets `EXAT` option. * @@ -138,7 +142,13 @@ export interface SetOpts { get?: boolean; } +/** + * @deprecated Use {@linkcode SetOpts.nx}/{@linkcode SetOpts.xx} instead. This type will be removed in the future. + */ export interface SetWithModeOpts extends SetOpts { + /** + * @deprecated Use {@linkcode SetOpts.nx}/{@linkcode SetOpts.xx} instead. This option will be removed in the future. + */ mode: "NX" | "XX"; } @@ -345,13 +355,29 @@ export interface RedisCommands { set( key: string, value: RedisValue, - opts?: Omit & { get?: false | null }, + opts?: Omit & { + get?: false | null; + nx?: false | null; + xx?: false | null; + }, ): Promise; set( key: string, value: RedisValue, opts?: (Omit & { get: true }) | SetWithModeOpts, ): Promise; + /** Executes `SET` command with `NX` option enabled. */ + set( + key: string, + value: RedisValue, + opts?: Omit & { nx: true }, + ): Promise; + /** Executes `SET` command with `XX` option enabled. */ + set( + key: string, + value: RedisValue, + opts?: Omit & { xx: true }, + ): Promise; setbit(key: string, offset: number, value: RedisValue): Promise; setex(key: string, seconds: number, value: RedisValue): Promise; setnx(key: string, value: RedisValue): Promise; diff --git a/redis.ts b/redis.ts index 16397104..821ac4be 100644 --- a/redis.ts +++ b/redis.ts @@ -1347,19 +1347,35 @@ class RedisImpl implements Redis { set( key: string, value: RedisValue, - opts?: Omit & { get?: false | null }, + opts?: Omit & { + get?: false | null; + nx?: false | null; + xx?: false | null; + }, ): Promise; set( key: string, value: RedisValue, opts?: (Omit & { get: true }) | SetWithModeOpts, ): Promise; + set( + key: string, + value: RedisValue, + opts?: Omit & { nx: true }, + ): Promise; + set( + key: string, + value: RedisValue, + opts?: Omit & { xx: true }, + ): Promise; set( key: string, value: RedisValue, opts?: - | (Omit & { - get?: true | false | null; + | (Omit & { + get?: boolean | null; + nx?: boolean | null; + xx?: boolean | null; }) | SetWithModeOpts, ) { @@ -1379,7 +1395,13 @@ class RedisImpl implements Redis { } let isAbleToReturnNil = false; - if ((opts as SetWithModeOpts)?.mode) { + if (opts?.nx) { + args.push("NX"); + isAbleToReturnNil = true; + } else if (opts?.xx) { + args.push("XX"); + isAbleToReturnNil = true; + } else if ((opts as SetWithModeOpts)?.mode) { args.push((opts as SetWithModeOpts).mode); isAbleToReturnNil = true; } diff --git a/tests/commands/string.ts b/tests/commands/string.ts index 4ed1d132..ebe8900c 100644 --- a/tests/commands/string.ts +++ b/tests/commands/string.ts @@ -209,7 +209,19 @@ export function stringTests( const prev = "foo"; const v1 = await client.set("setWithNX", prev, { mode: "NX" }); assertEquals(v1, "OK"); - const v2 = await client.set("setWithNX", "bar", { mode: "NX" }); + assertType>(true); + + const v2 = await client.set("setWithNX", "bar", { nx: true }); + assertEquals(v2, null); + assertType>(true); + }); + + it("supports `XX` option", async () => { + const v1 = await client.set("setWithXX", "foo", { mode: "XX" }); + assertEquals(v1, null); + assertType>(true); + + const v2 = await client.set("setWithXX", "foo", { xx: true }); assertEquals(v2, null); assertType>(true); });