From 9441bdb1d944aeda50810e2e3665763503c3961a Mon Sep 17 00:00:00 2001 From: Andrew Carbonetto Date: Fri, 26 Jul 2024 08:46:04 -0700 Subject: [PATCH 01/11] Node: Add ZLEXCOUNT Signed-off-by: Andrew Carbonetto --- node/src/BaseClient.ts | 35 +++++++++++++++++++ node/src/Commands.ts | 13 +++++++ node/src/Transaction.ts | 26 ++++++++++++++ node/tests/SharedTests.ts | 67 +++++++++++++++++++++++++++++++++++++ node/tests/TestUtilities.ts | 3 ++ 5 files changed, 144 insertions(+) diff --git a/node/src/BaseClient.ts b/node/src/BaseClient.ts index d5e038f8b1..d17bccd475 100644 --- a/node/src/BaseClient.ts +++ b/node/src/BaseClient.ts @@ -151,6 +151,7 @@ import { createZIncrBy, createZInterCard, createZInterstore, + createZLexCount, createZMPop, createZMScore, createZPopMax, @@ -3291,6 +3292,40 @@ export class BaseClient { ); } + /** + * Returns the number of members in the sorted set stored at key with scores between + * 'minLex' and 'maxLex'. + * + * See https://valkey.io/commands/zlexcount/ for more details. + * + * @param key - The key of the sorted set. + * @param minLex - The minimum lex to count from. Can be an implementation of {@link InfLexBound} + * representing positive/negative infinity, or {@link LexBoundary} representing a specific lex + * and inclusivity. + * @param maxLex - The maximum lex to count up to. Can be an implementation of {@link InfLexBound} + * representing positive/negative infinity, or {@link LexBoundary} representing a specific lex + * and inclusivity. + * @returns - The number of members in the specified lex range. + * - If 'key' does not exist, it is treated as an empty sorted set, and the command returns '0'. + * - If maxLex less than minLex, '0' is returned. + * + * @example + * ```typescript + * const result = await client.zlexcount("my_sorted_set", {"c", true}, LexBound.POSITIVE_INFINITY); + * console.log(result); // Output: 2 - Indicates that there are 2 members with lex scores between "c" (inclusive) and positive infinity in the sorted set "my_sorted_set". + * + * Long num2 = client.zlexcount("my_sorted_set", new ScoreBoundary("c", true), new ScoreBoundary("k", false)).get(); + * console.log(result); // Output: 1 - Indicates that there is one member with LexBoundary "c" <= score < "k" in the sorted set "my_sorted_set". + * ``` + */ + public zlexcount( + key: string, + minLex: ScoreBoundary, + maxLex: ScoreBoundary, + ): Promise { + return this.createWritePromise(createZLexCount(key, minLex, maxLex)); + } + /** Returns the rank of `member` in the sorted set stored at `key`, with scores ordered from low to high. * See https://valkey.io/commands/zrank for more details. * To get the rank of `member` with its score, see `zrankWithScore`. diff --git a/node/src/Commands.ts b/node/src/Commands.ts index b7a91288a3..cfc9e801ad 100644 --- a/node/src/Commands.ts +++ b/node/src/Commands.ts @@ -1800,6 +1800,19 @@ export function createPersist(key: string): command_request.Command { return createCommand(RequestType.Persist, [key]); } +export function createZLexCount( + key: string, + minLex: ScoreBoundary, + maxLex: ScoreBoundary, +): command_request.Command { + const args = [ + key, + getScoreBoundaryArg(minLex, true), + getScoreBoundaryArg(maxLex, true), + ]; + return createCommand(RequestType.ZLexCount, args); +} + export function createZRank( key: string, member: string, diff --git a/node/src/Transaction.ts b/node/src/Transaction.ts index 3c6e742c3b..97badf7db0 100644 --- a/node/src/Transaction.ts +++ b/node/src/Transaction.ts @@ -170,6 +170,7 @@ import { createZIncrBy, createZInterCard, createZInterstore, + createZLexCount, createZMPop, createZMScore, createZPopMax, @@ -1791,6 +1792,31 @@ export class BaseTransaction> { ); } + /** + * Returns the number of members in the sorted set stored at key with scores between + * 'minLex' and 'maxLex'. + * + * See https://valkey.io/commands/zlexcount/ for more details. + * + * @param key - The key of the sorted set. + * @param minLex - The minimum lex to count from. Can be an implementation of {@link InfLexBound} + * representing positive/negative infinity, or {@link LexBoundary} representing a specific lex + * and inclusivity. + * @param maxLex - The maximum lex to count up to. Can be an implementation of {@link InfLexBound} + * representing positive/negative infinity, or {@link LexBoundary} representing a specific lex + * and inclusivity. + * Command Response - The number of members in the specified lex range. + * - If 'key' does not exist, it is treated as an empty sorted set, and the command returns '0'. + * - If maxLex less than minLex, '0' is returned. + */ + public zlexcount( + key: string, + minLex: ScoreBoundary, + maxLex: ScoreBoundary, + ): T { + return this.addAndReturn(createZLexCount(key, minLex, maxLex)); + } + /** Returns the rank of `member` in the sorted set stored at `key`, with scores ordered from low to high. * See https://valkey.io/commands/zrank for more details. * To get the rank of `member` with its score, see `zrankWithScore`. diff --git a/node/tests/SharedTests.ts b/node/tests/SharedTests.ts index 4173725cde..4dacbcfdbb 100644 --- a/node/tests/SharedTests.ts +++ b/node/tests/SharedTests.ts @@ -4256,6 +4256,73 @@ export function runBaseTests(config: { config.timeout, ); + it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])( + `zlexcount test_%p`, + async (protocol) => { + await runTest(async (client: BaseClient) => { + const key = uuidv4(); + const stringKey = uuidv4(); + const membersScores = { a: 1, b: 2, c: 3 }; + expect(await client.zadd(key, membersScores)).toEqual(3); + + // In range negative to positive infinity. + expect( + await client.zlexcount( + key, + "negativeInfinity", + "positiveInfinity", + ), + ).toEqual(3); + + // In range a (exclusive) to c (inclusive) + expect( + await client.zlexcount( + key, + { value: "a", isInclusive: false }, + "positiveInfinity", + ), + ).toEqual(2); + + // In range negative infinity to c (inclusive) + expect( + await client.zlexcount(key, "negativeInfinity", { + value: "c", + isInclusive: true, + }), + ).toEqual(3); + + // Incorrect range start > end + expect( + await client.zlexcount(key, "positiveInfinity", { + value: "c", + isInclusive: true, + }), + ).toEqual(0); + + // Non-existing key + expect( + await client.zlexcount( + "non_existing_key", + "negativeInfinity", + "positiveInfinity", + ), + ).toEqual(0); + + // Key exists, but it is not a set + expect(await client.set(stringKey, "foo")).toEqual("OK"); + await expect( + client.zlexcount( + stringKey, + "negativeInfinity", + "positiveInfinity", + ), + ).rejects.toThrow(); + await expect(client.xlen(stringKey)).rejects.toThrow(); + }, protocol); + }, + config.timeout, + ); + it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])( "time test_%p", async (protocol) => { diff --git a/node/tests/TestUtilities.ts b/node/tests/TestUtilities.ts index 731ac6740a..bf16026312 100644 --- a/node/tests/TestUtilities.ts +++ b/node/tests/TestUtilities.ts @@ -25,6 +25,7 @@ import { GlideClusterClient, InsertPosition, ListDirection, + Logger, ProtocolVersion, ReturnType, ReturnTypeMap, @@ -727,6 +728,8 @@ export async function transactionTest( baseTransaction.zcount(key8, { value: 2 }, "positiveInfinity"); responseData.push(['zcount(key8, { value: 2 }, "positiveInfinity")', 4]); + baseTransaction.zlexcount(key8, { value: "a" }, "positiveInfinity"); + responseData.push(['zcount(key8, { value: 2 }, "positiveInfinity")', 4]); baseTransaction.zpopmin(key8); responseData.push(["zpopmin(key8)", { member2: 3.0 }]); baseTransaction.zpopmax(key8); From d1e0188c981e8e73152ce7254589a7b86f76491b Mon Sep 17 00:00:00 2001 From: Andrew Carbonetto Date: Fri, 26 Jul 2024 09:01:48 -0700 Subject: [PATCH 02/11] Update for self-review Signed-off-by: Andrew Carbonetto --- CHANGELOG.md | 1 + node/src/BaseClient.ts | 14 +++++--------- node/src/Commands.ts | 3 +++ node/src/Transaction.ts | 8 ++------ 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bb26b2040..58310227bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ * Node: Added ZINCRBY command ([#2009](https://github.com/valkey-io/valkey-glide/pull/2009)) * Node: Added BZMPOP command ([#2018](https://github.com/valkey-io/valkey-glide/pull/2018)) * Node: Added PFMERGE command ([#2053](https://github.com/valkey-io/valkey-glide/pull/2053)) +* Node: Added ZLEXCOUNT command ([#2022](https://github.com/valkey-io/valkey-glide/pull/2022)) #### Breaking Changes * Node: (Refactor) Convert classes to types ([#2005](https://github.com/valkey-io/valkey-glide/pull/2005)) diff --git a/node/src/BaseClient.ts b/node/src/BaseClient.ts index d17bccd475..eeaf46cbbe 100644 --- a/node/src/BaseClient.ts +++ b/node/src/BaseClient.ts @@ -3299,26 +3299,22 @@ export class BaseClient { * See https://valkey.io/commands/zlexcount/ for more details. * * @param key - The key of the sorted set. - * @param minLex - The minimum lex to count from. Can be an implementation of {@link InfLexBound} - * representing positive/negative infinity, or {@link LexBoundary} representing a specific lex - * and inclusivity. - * @param maxLex - The maximum lex to count up to. Can be an implementation of {@link InfLexBound} - * representing positive/negative infinity, or {@link LexBoundary} representing a specific lex - * and inclusivity. + * @param minLex - The minimum lex to count from. Can be positive/negative infinity, or specific lex and inclusivity. + * @param maxLex - The maximum lex to count up to. Can be positive/negative infinity, or specific lex and inclusivity. * @returns - The number of members in the specified lex range. * - If 'key' does not exist, it is treated as an empty sorted set, and the command returns '0'. * - If maxLex less than minLex, '0' is returned. * * @example * ```typescript - * const result = await client.zlexcount("my_sorted_set", {"c", true}, LexBound.POSITIVE_INFINITY); + * const result = await client.zlexcount("my_sorted_set", {value: "c"}, 'positiveInfinity'); * console.log(result); // Output: 2 - Indicates that there are 2 members with lex scores between "c" (inclusive) and positive infinity in the sorted set "my_sorted_set". * - * Long num2 = client.zlexcount("my_sorted_set", new ScoreBoundary("c", true), new ScoreBoundary("k", false)).get(); + * const result = await client.zlexcount("my_sorted_set", {value: "c"}, {value: "k", isInclusive: false}); * console.log(result); // Output: 1 - Indicates that there is one member with LexBoundary "c" <= score < "k" in the sorted set "my_sorted_set". * ``` */ - public zlexcount( + public async zlexcount( key: string, minLex: ScoreBoundary, maxLex: ScoreBoundary, diff --git a/node/src/Commands.ts b/node/src/Commands.ts index cfc9e801ad..566f91ad67 100644 --- a/node/src/Commands.ts +++ b/node/src/Commands.ts @@ -1800,6 +1800,9 @@ export function createPersist(key: string): command_request.Command { return createCommand(RequestType.Persist, [key]); } +/** + * @internal + */ export function createZLexCount( key: string, minLex: ScoreBoundary, diff --git a/node/src/Transaction.ts b/node/src/Transaction.ts index 97badf7db0..b585221f82 100644 --- a/node/src/Transaction.ts +++ b/node/src/Transaction.ts @@ -1799,12 +1799,8 @@ export class BaseTransaction> { * See https://valkey.io/commands/zlexcount/ for more details. * * @param key - The key of the sorted set. - * @param minLex - The minimum lex to count from. Can be an implementation of {@link InfLexBound} - * representing positive/negative infinity, or {@link LexBoundary} representing a specific lex - * and inclusivity. - * @param maxLex - The maximum lex to count up to. Can be an implementation of {@link InfLexBound} - * representing positive/negative infinity, or {@link LexBoundary} representing a specific lex - * and inclusivity. + * @param minLex - The minimum lex to count from. Can be positive/negative infinity, or specific lex and inclusivity. + * @param maxLex - The maximum lex to count up to. Can be positive/negative infinity, or specific lex and inclusivity. * Command Response - The number of members in the specified lex range. * - If 'key' does not exist, it is treated as an empty sorted set, and the command returns '0'. * - If maxLex less than minLex, '0' is returned. From c736c4ca567bb6bcf12b94e03f951636331fe2db Mon Sep 17 00:00:00 2001 From: Andrew Carbonetto Date: Fri, 26 Jul 2024 09:35:35 -0700 Subject: [PATCH 03/11] JavaDoc cleanup Signed-off-by: Andrew Carbonetto --- node/src/BaseClient.ts | 2 +- node/src/Transaction.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/node/src/BaseClient.ts b/node/src/BaseClient.ts index eeaf46cbbe..b0164941a6 100644 --- a/node/src/BaseClient.ts +++ b/node/src/BaseClient.ts @@ -3301,7 +3301,7 @@ export class BaseClient { * @param key - The key of the sorted set. * @param minLex - The minimum lex to count from. Can be positive/negative infinity, or specific lex and inclusivity. * @param maxLex - The maximum lex to count up to. Can be positive/negative infinity, or specific lex and inclusivity. - * @returns - The number of members in the specified lex range. + * @returns The number of members in the specified lex range. * - If 'key' does not exist, it is treated as an empty sorted set, and the command returns '0'. * - If maxLex less than minLex, '0' is returned. * diff --git a/node/src/Transaction.ts b/node/src/Transaction.ts index b585221f82..14f5394e62 100644 --- a/node/src/Transaction.ts +++ b/node/src/Transaction.ts @@ -1801,6 +1801,7 @@ export class BaseTransaction> { * @param key - The key of the sorted set. * @param minLex - The minimum lex to count from. Can be positive/negative infinity, or specific lex and inclusivity. * @param maxLex - The maximum lex to count up to. Can be positive/negative infinity, or specific lex and inclusivity. + * * Command Response - The number of members in the specified lex range. * - If 'key' does not exist, it is treated as an empty sorted set, and the command returns '0'. * - If maxLex less than minLex, '0' is returned. From bbce3cf8728e740059ca833d4fd463c4597f61d4 Mon Sep 17 00:00:00 2001 From: Andrew Carbonetto Date: Fri, 26 Jul 2024 09:40:48 -0700 Subject: [PATCH 04/11] linter Signed-off-by: Andrew Carbonetto --- node/src/Transaction.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/src/Transaction.ts b/node/src/Transaction.ts index 14f5394e62..b4a3dbbbab 100644 --- a/node/src/Transaction.ts +++ b/node/src/Transaction.ts @@ -1801,7 +1801,7 @@ export class BaseTransaction> { * @param key - The key of the sorted set. * @param minLex - The minimum lex to count from. Can be positive/negative infinity, or specific lex and inclusivity. * @param maxLex - The maximum lex to count up to. Can be positive/negative infinity, or specific lex and inclusivity. - * + * * Command Response - The number of members in the specified lex range. * - If 'key' does not exist, it is treated as an empty sorted set, and the command returns '0'. * - If maxLex less than minLex, '0' is returned. From 809251e7f113c4efc505cceaa5738244ca8fa72c Mon Sep 17 00:00:00 2001 From: Andrew Carbonetto Date: Fri, 26 Jul 2024 13:38:54 -0700 Subject: [PATCH 05/11] Update for review Signed-off-by: Andrew Carbonetto --- node/src/BaseClient.ts | 15 +++++++++------ node/src/Transaction.ts | 4 ++-- node/tests/SharedTests.ts | 5 ++--- node/tests/TestUtilities.ts | 5 ++++- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/node/src/BaseClient.ts b/node/src/BaseClient.ts index b0164941a6..eed81e3af7 100644 --- a/node/src/BaseClient.ts +++ b/node/src/BaseClient.ts @@ -3299,19 +3299,22 @@ export class BaseClient { * See https://valkey.io/commands/zlexcount/ for more details. * * @param key - The key of the sorted set. - * @param minLex - The minimum lex to count from. Can be positive/negative infinity, or specific lex and inclusivity. - * @param maxLex - The maximum lex to count up to. Can be positive/negative infinity, or specific lex and inclusivity. + * @param minLex - The minimum lex to count from. Can be positive/negative infinity, or a specific lex and inclusivity. + * @param maxLex - The maximum lex to count up to. Can be positive/negative infinity, or a specific lex and inclusivity. * @returns The number of members in the specified lex range. - * - If 'key' does not exist, it is treated as an empty sorted set, and the command returns '0'. - * - If maxLex less than minLex, '0' is returned. + * If 'key' does not exist, it is treated as an empty sorted set, and the command returns '0'. + * If maxLex is less than minLex, '0' is returned. * * @example * ```typescript - * const result = await client.zlexcount("my_sorted_set", {value: "c"}, 'positiveInfinity'); + * const result = await client.zlexcount("my_sorted_set", {value: "c"}, "positiveInfinity"); * console.log(result); // Output: 2 - Indicates that there are 2 members with lex scores between "c" (inclusive) and positive infinity in the sorted set "my_sorted_set". + * ``` * + * @example + * ```typescript * const result = await client.zlexcount("my_sorted_set", {value: "c"}, {value: "k", isInclusive: false}); - * console.log(result); // Output: 1 - Indicates that there is one member with LexBoundary "c" <= score < "k" in the sorted set "my_sorted_set". + * console.log(result); // Output: 1 - Indicates that there is one member with a lex scores between "c" (inclusive) and "k" (exclusive) in the sorted set "my_sorted_set". * ``` */ public async zlexcount( diff --git a/node/src/Transaction.ts b/node/src/Transaction.ts index b4a3dbbbab..48b3b5c20a 100644 --- a/node/src/Transaction.ts +++ b/node/src/Transaction.ts @@ -1803,8 +1803,8 @@ export class BaseTransaction> { * @param maxLex - The maximum lex to count up to. Can be positive/negative infinity, or specific lex and inclusivity. * * Command Response - The number of members in the specified lex range. - * - If 'key' does not exist, it is treated as an empty sorted set, and the command returns '0'. - * - If maxLex less than minLex, '0' is returned. + * If 'key' does not exist, it is treated as an empty sorted set, and the command returns '0'. + * If maxLex is less than minLex, '0' is returned. */ public zlexcount( key: string, diff --git a/node/tests/SharedTests.ts b/node/tests/SharedTests.ts index 4dacbcfdbb..b7a26c8ef7 100644 --- a/node/tests/SharedTests.ts +++ b/node/tests/SharedTests.ts @@ -4274,7 +4274,7 @@ export function runBaseTests(config: { ), ).toEqual(3); - // In range a (exclusive) to c (inclusive) + // In range a (exclusive) to positive infinity expect( await client.zlexcount( key, @@ -4316,8 +4316,7 @@ export function runBaseTests(config: { "negativeInfinity", "positiveInfinity", ), - ).rejects.toThrow(); - await expect(client.xlen(stringKey)).rejects.toThrow(); + ).rejects.toThrow(RequestError); }, protocol); }, config.timeout, diff --git a/node/tests/TestUtilities.ts b/node/tests/TestUtilities.ts index bf16026312..acc5de4be1 100644 --- a/node/tests/TestUtilities.ts +++ b/node/tests/TestUtilities.ts @@ -729,7 +729,10 @@ export async function transactionTest( baseTransaction.zcount(key8, { value: 2 }, "positiveInfinity"); responseData.push(['zcount(key8, { value: 2 }, "positiveInfinity")', 4]); baseTransaction.zlexcount(key8, { value: "a" }, "positiveInfinity"); - responseData.push(['zcount(key8, { value: 2 }, "positiveInfinity")', 4]); + responseData.push([ + 'zlexcount(key8, { value: "a" }, "positiveInfinity")', + 4, + ]); baseTransaction.zpopmin(key8); responseData.push(["zpopmin(key8)", { member2: 3.0 }]); baseTransaction.zpopmax(key8); From e4ae4fed9fb1a92942bb67f3926bf4e57bbd9524 Mon Sep 17 00:00:00 2001 From: Andrew Carbonetto Date: Fri, 26 Jul 2024 13:58:55 -0700 Subject: [PATCH 06/11] Update for review Signed-off-by: Andrew Carbonetto --- node/src/BaseClient.ts | 3 +-- node/src/Transaction.ts | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/node/src/BaseClient.ts b/node/src/BaseClient.ts index eed81e3af7..7d9a72fd42 100644 --- a/node/src/BaseClient.ts +++ b/node/src/BaseClient.ts @@ -3293,8 +3293,7 @@ export class BaseClient { } /** - * Returns the number of members in the sorted set stored at key with scores between - * 'minLex' and 'maxLex'. + * Returns the number of members in the sorted set stored at 'key' with scores between 'minLex' and 'maxLex'. * * See https://valkey.io/commands/zlexcount/ for more details. * diff --git a/node/src/Transaction.ts b/node/src/Transaction.ts index 48b3b5c20a..abf5a3b193 100644 --- a/node/src/Transaction.ts +++ b/node/src/Transaction.ts @@ -1793,8 +1793,7 @@ export class BaseTransaction> { } /** - * Returns the number of members in the sorted set stored at key with scores between - * 'minLex' and 'maxLex'. + * Returns the number of members in the sorted set stored at'key' with scores between 'minLex' and 'maxLex'. * * See https://valkey.io/commands/zlexcount/ for more details. * From 501acbe6f895d138a420e092b052155d81536bcf Mon Sep 17 00:00:00 2001 From: Andrew Carbonetto Date: Fri, 26 Jul 2024 14:10:53 -0700 Subject: [PATCH 07/11] Update infinity from string to enum Signed-off-by: Andrew Carbonetto --- node/src/BaseClient.ts | 10 ++-- node/src/Commands.ts | 22 +++++-- node/tests/SharedTests.ts | 111 +++++++++++++++++++++--------------- node/tests/TestUtilities.ts | 24 ++++++-- 4 files changed, 106 insertions(+), 61 deletions(-) diff --git a/node/src/BaseClient.ts b/node/src/BaseClient.ts index 7d9a72fd42..42bd32e82a 100644 --- a/node/src/BaseClient.ts +++ b/node/src/BaseClient.ts @@ -2855,7 +2855,7 @@ export class BaseClient { * @example * ```typescript * // Example usage of the zcount method to count members in a sorted set within a score range - * const result = await client.zcount("my_sorted_set", { bound: 5.0, isInclusive: true }, "positiveInfinity"); + * const result = await client.zcount("my_sorted_set", { bound: 5.0, isInclusive: true }, InfScoreBoundary.PositiveInfinity); * console.log(result); // Output: 2 - Indicates that there are 2 members with scores between 5.0 (inclusive) and +inf in the sorted set "my_sorted_set". * ``` * @@ -2899,7 +2899,7 @@ export class BaseClient { * ```typescript * // Example usage of zrange method to retrieve members within a score range in ascending order * const result = await client.zrange("my_sorted_set", { - * start: "negativeInfinity", + * start: InfScoreBoundary.NegativeInfinity, * stop: { value: 3, isInclusive: false }, * type: "byScore", * }); @@ -2941,7 +2941,7 @@ export class BaseClient { * ```typescript * // Example usage of zrangeWithScores method to retrieve members within a score range with their scores * const result = await client.zrangeWithScores("my_sorted_set", { - * start: "negativeInfinity", + * start: InfScoreBoundary.NegativeInfinity, * stop: { value: 3, isInclusive: false }, * type: "byScore", * }); @@ -3271,7 +3271,7 @@ export class BaseClient { * @example * ```typescript * // Example usage of zremRangeByScore method to remove members from a sorted set based on score range - * const result = await client.zremRangeByScore("my_sorted_set", { bound: 5.0, isInclusive: true }, "positiveInfinity"); + * const result = await client.zremRangeByScore("my_sorted_set", { bound: 5.0, isInclusive: true }, InfScoreBoundary.PositiveInfinity); * console.log(result); // Output: 2 - Indicates that 2 members with scores between 5.0 (inclusive) and +inf have been removed from the sorted set "my_sorted_set". * ``` * @@ -3306,7 +3306,7 @@ export class BaseClient { * * @example * ```typescript - * const result = await client.zlexcount("my_sorted_set", {value: "c"}, "positiveInfinity"); + * const result = await client.zlexcount("my_sorted_set", {value: "c"}, InfScoreBoundary.PositiveInfinity); * console.log(result); // Output: 2 - Indicates that there are 2 members with lex scores between "c" (inclusive) and positive infinity in the sorted set "my_sorted_set". * ``` * diff --git a/node/src/Commands.ts b/node/src/Commands.ts index 566f91ad67..6c4d2cc064 100644 --- a/node/src/Commands.ts +++ b/node/src/Commands.ts @@ -1503,15 +1503,25 @@ export function createZMScore( return createCommand(RequestType.ZMScore, [key, ...members]); } -export type ScoreBoundary = +/** + * Defines where to insert new elements into a list. + */ +export enum InfScoreBoundary { /** * Positive infinity bound for sorted set. */ - | `positiveInfinity` + PositiveInfinity = "positiveInfinity", /** * Negative infinity bound for sorted set. */ - | `negativeInfinity` + NegativeInfinity = "negativeInfinity", +} + +export type ScoreBoundary = + /** + * Represents an lower/upper boundary in a sorted set. + */ + | InfScoreBoundary /** * Represents a specific numeric score boundary in a sorted set. */ @@ -1591,9 +1601,11 @@ function getScoreBoundaryArg( score: ScoreBoundary | ScoreBoundary, isLex: boolean = false, ): string { - if (score == "positiveInfinity") { + if (score == InfScoreBoundary.PositiveInfinity) { return isLex ? "+" : "+inf"; - } else if (score == "negativeInfinity") { + } + + if (score == InfScoreBoundary.NegativeInfinity) { return isLex ? "-" : "-inf"; } diff --git a/node/tests/SharedTests.ts b/node/tests/SharedTests.ts index b7a26c8ef7..767a3c9130 100644 --- a/node/tests/SharedTests.ts +++ b/node/tests/SharedTests.ts @@ -27,6 +27,7 @@ import { GeospatialData, GlideClient, GlideClusterClient, + InfScoreBoundary, InfoOptions, InsertPosition, ListDirection, @@ -3261,8 +3262,8 @@ export function runBaseTests(config: { expect( await client.zcount( key1, - "negativeInfinity", - "positiveInfinity", + InfScoreBoundary.NegativeInfinity, + InfScoreBoundary.PositiveInfinity, ), ).toEqual(3); expect( @@ -3280,26 +3281,38 @@ export function runBaseTests(config: { ), ).toEqual(2); expect( - await client.zcount(key1, "negativeInfinity", { - value: 3, - }), + await client.zcount( + key1, + InfScoreBoundary.NegativeInfinity, + { + value: 3, + }, + ), ).toEqual(3); expect( - await client.zcount(key1, "positiveInfinity", { - value: 3, - }), + await client.zcount( + key1, + InfScoreBoundary.PositiveInfinity, + { + value: 3, + }, + ), ).toEqual(0); expect( await client.zcount( "nonExistingKey", - "negativeInfinity", - "positiveInfinity", + InfScoreBoundary.NegativeInfinity, + InfScoreBoundary.PositiveInfinity, ), ).toEqual(0); expect(await client.set(key2, "foo")).toEqual("OK"); await expect( - client.zcount(key2, "negativeInfinity", "positiveInfinity"), + client.zcount( + key2, + InfScoreBoundary.NegativeInfinity, + InfScoreBoundary.PositiveInfinity, + ), ).rejects.toThrow(); }, protocol); }, @@ -3353,14 +3366,14 @@ export function runBaseTests(config: { expect( await client.zrange(key, { - start: "negativeInfinity", + start: InfScoreBoundary.NegativeInfinity, stop: { value: 3, isInclusive: false }, type: "byScore", }), ).toEqual(["one", "two"]); const result = await client.zrangeWithScores(key, { - start: "negativeInfinity", - stop: "positiveInfinity", + start: InfScoreBoundary.NegativeInfinity, + stop: InfScoreBoundary.PositiveInfinity, type: "byScore", }); @@ -3376,7 +3389,7 @@ export function runBaseTests(config: { key, { start: { value: 3, isInclusive: false }, - stop: "negativeInfinity", + stop: InfScoreBoundary.NegativeInfinity, type: "byScore", }, true, @@ -3385,8 +3398,8 @@ export function runBaseTests(config: { expect( await client.zrange(key, { - start: "negativeInfinity", - stop: "positiveInfinity", + start: InfScoreBoundary.NegativeInfinity, + stop: InfScoreBoundary.PositiveInfinity, limit: { offset: 1, count: 2 }, type: "byScore", }), @@ -3396,7 +3409,7 @@ export function runBaseTests(config: { await client.zrange( key, { - start: "negativeInfinity", + start: InfScoreBoundary.NegativeInfinity, stop: { value: 3, isInclusive: false }, type: "byScore", }, @@ -3406,7 +3419,7 @@ export function runBaseTests(config: { expect( await client.zrange(key, { - start: "positiveInfinity", + start: InfScoreBoundary.PositiveInfinity, stop: { value: 3, isInclusive: false }, type: "byScore", }), @@ -3416,7 +3429,7 @@ export function runBaseTests(config: { await client.zrangeWithScores( key, { - start: "negativeInfinity", + start: InfScoreBoundary.NegativeInfinity, stop: { value: 3, isInclusive: false }, type: "byScore", }, @@ -3426,7 +3439,7 @@ export function runBaseTests(config: { expect( await client.zrangeWithScores(key, { - start: "positiveInfinity", + start: InfScoreBoundary.PositiveInfinity, stop: { value: 3, isInclusive: false }, type: "byScore", }), @@ -3446,7 +3459,7 @@ export function runBaseTests(config: { expect( await client.zrange(key, { - start: "negativeInfinity", + start: InfScoreBoundary.NegativeInfinity, stop: { value: "c", isInclusive: false }, type: "byLex", }), @@ -3454,8 +3467,8 @@ export function runBaseTests(config: { expect( await client.zrange(key, { - start: "negativeInfinity", - stop: "positiveInfinity", + start: InfScoreBoundary.NegativeInfinity, + stop: InfScoreBoundary.PositiveInfinity, limit: { offset: 1, count: 2 }, type: "byLex", }), @@ -3466,7 +3479,7 @@ export function runBaseTests(config: { key, { start: { value: "c", isInclusive: false }, - stop: "negativeInfinity", + stop: InfScoreBoundary.NegativeInfinity, type: "byLex", }, true, @@ -3477,7 +3490,7 @@ export function runBaseTests(config: { await client.zrange( key, { - start: "negativeInfinity", + start: InfScoreBoundary.NegativeInfinity, stop: { value: "c", isInclusive: false }, type: "byLex", }, @@ -3487,7 +3500,7 @@ export function runBaseTests(config: { expect( await client.zrange(key, { - start: "positiveInfinity", + start: InfScoreBoundary.PositiveInfinity, stop: { value: "c", isInclusive: false }, type: "byLex", }), @@ -4240,15 +4253,15 @@ export function runBaseTests(config: { await client.zremRangeByScore( key, { value: 1 }, - "negativeInfinity", + InfScoreBoundary.NegativeInfinity, ), ).toEqual(0); expect( await client.zremRangeByScore( "nonExistingKey", - "negativeInfinity", - "positiveInfinity", + InfScoreBoundary.NegativeInfinity, + InfScoreBoundary.PositiveInfinity, ), ).toEqual(0); }, protocol); @@ -4269,8 +4282,8 @@ export function runBaseTests(config: { expect( await client.zlexcount( key, - "negativeInfinity", - "positiveInfinity", + InfScoreBoundary.NegativeInfinity, + InfScoreBoundary.PositiveInfinity, ), ).toEqual(3); @@ -4279,32 +4292,40 @@ export function runBaseTests(config: { await client.zlexcount( key, { value: "a", isInclusive: false }, - "positiveInfinity", + InfScoreBoundary.PositiveInfinity, ), ).toEqual(2); // In range negative infinity to c (inclusive) expect( - await client.zlexcount(key, "negativeInfinity", { - value: "c", - isInclusive: true, - }), + await client.zlexcount( + key, + InfScoreBoundary.NegativeInfinity, + { + value: "c", + isInclusive: true, + }, + ), ).toEqual(3); // Incorrect range start > end expect( - await client.zlexcount(key, "positiveInfinity", { - value: "c", - isInclusive: true, - }), + await client.zlexcount( + key, + InfScoreBoundary.PositiveInfinity, + { + value: "c", + isInclusive: true, + }, + ), ).toEqual(0); // Non-existing key expect( await client.zlexcount( "non_existing_key", - "negativeInfinity", - "positiveInfinity", + InfScoreBoundary.NegativeInfinity, + InfScoreBoundary.PositiveInfinity, ), ).toEqual(0); @@ -4313,8 +4334,8 @@ export function runBaseTests(config: { await expect( client.zlexcount( stringKey, - "negativeInfinity", - "positiveInfinity", + InfScoreBoundary.NegativeInfinity, + InfScoreBoundary.PositiveInfinity, ), ).rejects.toThrow(RequestError); }, protocol); diff --git a/node/tests/TestUtilities.ts b/node/tests/TestUtilities.ts index acc5de4be1..6c4983d2f5 100644 --- a/node/tests/TestUtilities.ts +++ b/node/tests/TestUtilities.ts @@ -23,6 +23,7 @@ import { GeospatialData, GlideClient, GlideClusterClient, + InfScoreBoundary, InsertPosition, ListDirection, Logger, @@ -726,11 +727,22 @@ export async function transactionTest( responseData.push(["zinterstore(key12, [key12, key13])", 2]); } - baseTransaction.zcount(key8, { value: 2 }, "positiveInfinity"); - responseData.push(['zcount(key8, { value: 2 }, "positiveInfinity")', 4]); - baseTransaction.zlexcount(key8, { value: "a" }, "positiveInfinity"); + baseTransaction.zcount( + key8, + { value: 2 }, + InfScoreBoundary.PositiveInfinity, + ); + responseData.push([ + "zcount(key8, { value: 2 }, InfScoreBoundary.PositiveInfinity)", + 4, + ]); + baseTransaction.zlexcount( + key8, + { value: "a" }, + InfScoreBoundary.PositiveInfinity, + ); responseData.push([ - 'zlexcount(key8, { value: "a" }, "positiveInfinity")', + 'zlexcount(key8, { value: "a" }, InfScoreBoundary.PositiveInfinity)', 4, ]); baseTransaction.zpopmin(key8); @@ -741,8 +753,8 @@ export async function transactionTest( responseData.push(["zremRangeByRank(key8, 1, 1)", 1]); baseTransaction.zremRangeByScore( key8, - "negativeInfinity", - "positiveInfinity", + InfScoreBoundary.NegativeInfinity, + InfScoreBoundary.PositiveInfinity, ); responseData.push(["zremRangeByScore(key8, -Inf, +Inf)", 1]); // key8 is now empty From 856a5ed8a5bacd14bc71ae47d5c6231852810649 Mon Sep 17 00:00:00 2001 From: Andrew Carbonetto Date: Fri, 26 Jul 2024 15:52:37 -0700 Subject: [PATCH 08/11] Doc fix Signed-off-by: Andrew Carbonetto --- node/src/Transaction.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/src/Transaction.ts b/node/src/Transaction.ts index abf5a3b193..4f9665a124 100644 --- a/node/src/Transaction.ts +++ b/node/src/Transaction.ts @@ -1793,7 +1793,7 @@ export class BaseTransaction> { } /** - * Returns the number of members in the sorted set stored at'key' with scores between 'minLex' and 'maxLex'. + * Returns the number of members in the sorted set stored at 'key' with scores between 'minLex' and 'maxLex'. * * See https://valkey.io/commands/zlexcount/ for more details. * From 0eefa9e2846dc7f9cf3895fa8d2e2766d4f66dd1 Mon Sep 17 00:00:00 2001 From: Andrew Carbonetto Date: Tue, 30 Jul 2024 17:12:24 -0700 Subject: [PATCH 09/11] Add type to exports Signed-off-by: Andrew Carbonetto --- node/npm/glide/index.ts | 6 ++++-- node/src/BaseClient.ts | 2 +- node/src/Commands.ts | 14 +++++++------- node/src/Transaction.ts | 4 ++-- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/node/npm/glide/index.ts b/node/npm/glide/index.ts index 12997f2547..b64b44aa86 100644 --- a/node/npm/glide/index.ts +++ b/node/npm/glide/index.ts @@ -121,7 +121,8 @@ function initialize() { InsertPosition, SetOptions, ZaddOptions, - ScoreBoundry, + InfScoreBoundary, + ScoreBoundary, UpdateOptions, ProtocolVersion, RangeByIndex, @@ -204,7 +205,8 @@ function initialize() { InsertPosition, SetOptions, ZaddOptions, - ScoreBoundry, + InfScoreBoundary, + ScoreBoundary, UpdateOptions, ProtocolVersion, RangeByIndex, diff --git a/node/src/BaseClient.ts b/node/src/BaseClient.ts index 42bd32e82a..86a965251f 100644 --- a/node/src/BaseClient.ts +++ b/node/src/BaseClient.ts @@ -3313,7 +3313,7 @@ export class BaseClient { * @example * ```typescript * const result = await client.zlexcount("my_sorted_set", {value: "c"}, {value: "k", isInclusive: false}); - * console.log(result); // Output: 1 - Indicates that there is one member with a lex scores between "c" (inclusive) and "k" (exclusive) in the sorted set "my_sorted_set". + * console.log(result); // Output: 1 - Indicates that there is one member with a lex score between "c" (inclusive) and "k" (exclusive) in the sorted set "my_sorted_set". * ``` */ public async zlexcount( diff --git a/node/src/Commands.ts b/node/src/Commands.ts index 6c4d2cc064..de261bafea 100644 --- a/node/src/Commands.ts +++ b/node/src/Commands.ts @@ -1503,20 +1503,20 @@ export function createZMScore( return createCommand(RequestType.ZMScore, [key, ...members]); } -/** - * Defines where to insert new elements into a list. - */ export enum InfScoreBoundary { /** * Positive infinity bound for sorted set. */ - PositiveInfinity = "positiveInfinity", + PositiveInfinity = "+", /** * Negative infinity bound for sorted set. */ - NegativeInfinity = "negativeInfinity", + NegativeInfinity = "-", } +/** + * Defines where to insert new elements into a list. + */ export type ScoreBoundary = /** * Represents an lower/upper boundary in a sorted set. @@ -1602,11 +1602,11 @@ function getScoreBoundaryArg( isLex: boolean = false, ): string { if (score == InfScoreBoundary.PositiveInfinity) { - return isLex ? "+" : "+inf"; + return InfScoreBoundary.PositiveInfinity.toString() + (isLex ? "" : "inf"); } if (score == InfScoreBoundary.NegativeInfinity) { - return isLex ? "-" : "-inf"; + return InfScoreBoundary.NegativeInfinity.toString() + (isLex ? "" : "inf"); } if (score.isInclusive == false) { diff --git a/node/src/Transaction.ts b/node/src/Transaction.ts index 4f9665a124..f920abee2f 100644 --- a/node/src/Transaction.ts +++ b/node/src/Transaction.ts @@ -1798,8 +1798,8 @@ export class BaseTransaction> { * See https://valkey.io/commands/zlexcount/ for more details. * * @param key - The key of the sorted set. - * @param minLex - The minimum lex to count from. Can be positive/negative infinity, or specific lex and inclusivity. - * @param maxLex - The maximum lex to count up to. Can be positive/negative infinity, or specific lex and inclusivity. + * @param minLex - The minimum lex to count from. Can be positive/negative infinity, or a specific lex and inclusivity. + * @param maxLex - The maximum lex to count up to. Can be positive/negative infinity, or a specific lex and inclusivity. * * Command Response - The number of members in the specified lex range. * If 'key' does not exist, it is treated as an empty sorted set, and the command returns '0'. From 469a1f4347e69e6e4e86790761970659f4c05c5d Mon Sep 17 00:00:00 2001 From: Andrew Carbonetto Date: Wed, 31 Jul 2024 13:29:38 -0700 Subject: [PATCH 10/11] linter Signed-off-by: Andrew Carbonetto --- node/src/Commands.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/node/src/Commands.ts b/node/src/Commands.ts index de261bafea..6588d7acda 100644 --- a/node/src/Commands.ts +++ b/node/src/Commands.ts @@ -1602,11 +1602,15 @@ function getScoreBoundaryArg( isLex: boolean = false, ): string { if (score == InfScoreBoundary.PositiveInfinity) { - return InfScoreBoundary.PositiveInfinity.toString() + (isLex ? "" : "inf"); + return ( + InfScoreBoundary.PositiveInfinity.toString() + (isLex ? "" : "inf") + ); } if (score == InfScoreBoundary.NegativeInfinity) { - return InfScoreBoundary.NegativeInfinity.toString() + (isLex ? "" : "inf"); + return ( + InfScoreBoundary.NegativeInfinity.toString() + (isLex ? "" : "inf") + ); } if (score.isInclusive == false) { From 68b2de34bb8380af1f890d715df87e3dce0e3455 Mon Sep 17 00:00:00 2001 From: Andrew Carbonetto Date: Wed, 31 Jul 2024 15:02:32 -0700 Subject: [PATCH 11/11] Remove import Signed-off-by: Andrew Carbonetto --- node/tests/TestUtilities.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/node/tests/TestUtilities.ts b/node/tests/TestUtilities.ts index 6c4983d2f5..eb68eeb9ac 100644 --- a/node/tests/TestUtilities.ts +++ b/node/tests/TestUtilities.ts @@ -26,7 +26,6 @@ import { InfScoreBoundary, InsertPosition, ListDirection, - Logger, ProtocolVersion, ReturnType, ReturnTypeMap,