From 0672ea3f6d0494d7229b1a86c8204492a97c86fc Mon Sep 17 00:00:00 2001 From: tjzhang-BQ <111323543+tjzhang-BQ@users.noreply.github.com> Date: Fri, 26 Jul 2024 12:55:21 -0700 Subject: [PATCH] Add command HStrlen (#2020) * Add command HStrlen --- CHANGELOG.md | 1 + node/src/BaseClient.ts | 21 +++++++++++++++++++++ node/src/Commands.ts | 10 ++++++++++ node/src/Transaction.ts | 15 +++++++++++++++ node/tests/SharedTests.ts | 27 +++++++++++++++++++++++++++ node/tests/TestUtilities.ts | 2 ++ 6 files changed, 76 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10e2e3cf99..9c129c304c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -131,6 +131,7 @@ * Node: Added ZRevRank command ([#1977](https://github.com/valkey-io/valkey-glide/pull/1977)) * Node: Added GeoDist command ([#1988](https://github.com/valkey-io/valkey-glide/pull/1988)) * Node: Added GeoHash command ([#1997](https://github.com/valkey-io/valkey-glide/pull/1997)) +* Node: Added HStrlen command ([#2020](https://github.com/valkey-io/valkey-glide/pull/2020)) #### Breaking Changes * Node: Update XREAD to return a Map of Map ([#1494](https://github.com/valkey-io/valkey-glide/pull/1494)) diff --git a/node/src/BaseClient.ts b/node/src/BaseClient.ts index ef25d8be0e..636b352825 100644 --- a/node/src/BaseClient.ts +++ b/node/src/BaseClient.ts @@ -64,6 +64,7 @@ import { createHMGet, createHSet, createHSetNX, + createHStrlen, createHVals, createIncr, createIncrBy, @@ -1393,6 +1394,26 @@ export class BaseClient { return this.createWritePromise(createHVals(key)); } + /** + * Returns the string length of the value associated with `field` in the hash stored at `key`. + * + * See https://valkey.io/commands/hstrlen/ for details. + * + * @param key - The key of the hash. + * @param field - The field in the hash. + * @returns The string length or `0` if `field` or `key` does not exist. + * + * @example + * ```typescript + * await client.hset("my_hash", {"field": "value"}); + * const result = await client.hstrlen("my_hash", "field"); + * console.log(result); // Output: 5 + * ``` + */ + public hstrlen(key: string, field: string): Promise { + return this.createWritePromise(createHStrlen(key, field)); + } + /** Inserts all the specified values at the head of the list stored at `key`. * `elements` are inserted one after the other to the head of the list, from the leftmost element to the rightmost element. * If `key` does not exist, it is created as empty list before performing the push operations. diff --git a/node/src/Commands.ts b/node/src/Commands.ts index 4c1c6254c3..d67e6031f9 100644 --- a/node/src/Commands.ts +++ b/node/src/Commands.ts @@ -2249,3 +2249,13 @@ export function createZIncrBy( member, ]); } + +/** + * @internal + */ +export function createHStrlen( + key: string, + field: string, +): command_request.Command { + return createCommand(RequestType.HStrlen, [key, field]); +} diff --git a/node/src/Transaction.ts b/node/src/Transaction.ts index b945655cbb..8c8f391b24 100644 --- a/node/src/Transaction.ts +++ b/node/src/Transaction.ts @@ -73,6 +73,7 @@ import { createHMGet, createHSet, createHSetNX, + createHStrlen, createHVals, createIncr, createIncrBy, @@ -680,6 +681,20 @@ export class BaseTransaction> { return this.addAndReturn(createHVals(key)); } + /** + * Returns the string length of the value associated with `field` in the hash stored at `key`. + * + * See https://valkey.io/commands/hstrlen/ for details. + * + * @param key - The key of the hash. + * @param field - The field in the hash. + * + * Command Response - The string length or `0` if `field` or `key` does not exist. + */ + public hstrlen(key: string, field: string): T { + return this.addAndReturn(createHStrlen(key, field)); + } + /** Inserts all the specified values at the head of the list stored at `key`. * `elements` are inserted one after the other to the head of the list, from the leftmost element to the rightmost element. * If `key` does not exist, it is created as empty list before performing the push operations. diff --git a/node/tests/SharedTests.ts b/node/tests/SharedTests.ts index 81fb10e214..3e1fba7147 100644 --- a/node/tests/SharedTests.ts +++ b/node/tests/SharedTests.ts @@ -1102,6 +1102,33 @@ export function runBaseTests(config: { config.timeout, ); + it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])( + `hstrlen test_%p`, + async (protocol) => { + await runTest(async (client: BaseClient) => { + const key1 = uuidv4(); + const key2 = uuidv4(); + const field = uuidv4(); + + expect(await client.hset(key1, { field: "value" })).toBe(1); + expect(await client.hstrlen(key1, "field")).toBe(5); + + // missing value + expect(await client.hstrlen(key1, "nonExistingField")).toBe(0); + + // missing key + expect(await client.hstrlen(key2, "field")).toBe(0); + + // key exists but holds non hash type value + checkSimple(await client.set(key2, "value")).toEqual("OK"); + await expect(client.hstrlen(key2, field)).rejects.toThrow( + RequestError, + ); + }, protocol); + }, + config.timeout, + ); + it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])( `lpush, lpop and lrange with existing and non existing key_%p`, async (protocol) => { diff --git a/node/tests/TestUtilities.ts b/node/tests/TestUtilities.ts index 17ce37c6f6..e589213359 100644 --- a/node/tests/TestUtilities.ts +++ b/node/tests/TestUtilities.ts @@ -439,6 +439,8 @@ export async function transactionTest( responseData.push(["del([key1])", 1]); baseTransaction.hset(key4, { [field]: value }); responseData.push(["hset(key4, { [field]: value })", 1]); + baseTransaction.hstrlen(key4, field); + responseData.push(["hstrlen(key4, field)", value.length]); baseTransaction.hlen(key4); responseData.push(["hlen(key4)", 1]); baseTransaction.hsetnx(key4, field, value);