diff --git a/packages/client/lib/commands/ZADD.spec.ts b/packages/client/lib/commands/ZADD.spec.ts index 722856caa8..9f684237e1 100644 --- a/packages/client/lib/commands/ZADD.spec.ts +++ b/packages/client/lib/commands/ZADD.spec.ts @@ -115,19 +115,7 @@ describe('ZADD', () => { ); }); - it('with INCR', () => { - assert.deepEqual( - ZADD.transformArguments('key', { - value: '1', - score: 1 - }, { - INCR: true - }), - ['ZADD', 'key', 'INCR', '1', '1'] - ); - }); - - it('with condition, comparison, CH, INCR', () => { + it('with condition, comparison, CH', () => { assert.deepEqual( ZADD.transformArguments('key', { value: '1', @@ -135,10 +123,9 @@ describe('ZADD', () => { }, { condition: 'XX', comparison: 'LT', - CH: true, - INCR: true + CH: true }), - ['ZADD', 'key', 'XX', 'LT', 'CH', 'INCR', '1', '1'] + ['ZADD', 'key', 'XX', 'LT', 'CH', '1', '1'] ); }); }); diff --git a/packages/client/lib/commands/ZADD.ts b/packages/client/lib/commands/ZADD.ts index 49a839fb6f..ff729f4f9c 100644 --- a/packages/client/lib/commands/ZADD.ts +++ b/packages/client/lib/commands/ZADD.ts @@ -1,4 +1,4 @@ -import { RedisArgument, NumberReply, DoubleReply, Command } from '../RESP/types'; +import { RedisArgument, NumberReply, DoubleReply, Command, CommandArguments } from '../RESP/types'; import { ZMember, transformDoubleArgument, transformDoubleReply } from './generic-transformers'; export interface ZAddOptions { @@ -21,7 +21,6 @@ export interface ZAddOptions { */ GT?: boolean; CH?: boolean; - INCR?: boolean; } export default { @@ -53,26 +52,29 @@ export default { args.push('CH'); } - if (options?.INCR) { - args.push('INCR'); - } - - if (Array.isArray(members)) { - for (const member of members) { - pushMember(args, member); - } - } else { - pushMember(args, members); - } + pushMembers(args, members); return args; }, transformReply: { 2: transformDoubleReply, - 3: undefined as unknown as () => NumberReply | DoubleReply + 3: undefined as unknown as () => NumberReply } } as const satisfies Command; +export function pushMembers( + args: CommandArguments, + members: ZMember | Array +) { + if (Array.isArray(members)) { + for (const member of members) { + pushMember(args, member); + } + } else { + pushMember(args, members); + } +} + function pushMember(args: Array, member: ZMember) { args.push( transformDoubleArgument(member.score), diff --git a/packages/client/lib/commands/ZADD_INCR.spec.ts b/packages/client/lib/commands/ZADD_INCR.spec.ts new file mode 100644 index 0000000000..b2fab832ee --- /dev/null +++ b/packages/client/lib/commands/ZADD_INCR.spec.ts @@ -0,0 +1,93 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import ZADD_INCR from './ZADD_INCR'; + +describe('ZADD INCR', () => { + describe('transformArguments', () => { + it('single member', () => { + assert.deepEqual( + ZADD_INCR.transformArguments('key', { + value: '1', + score: 1 + }), + ['ZADD', 'key', 'INCR', '1', '1'] + ); + }); + + it('multiple members', () => { + assert.deepEqual( + ZADD_INCR.transformArguments('key', [{ + value: '1', + score: 1 + }, { + value: '2', + score: 2 + }]), + ['ZADD', 'key', 'INCR', '1', '1', '2', '2'] + ); + }); + + it('with condition', () => { + assert.deepEqual( + ZADD_INCR.transformArguments('key', { + value: '1', + score: 1 + }, { + condition: 'NX' + }), + ['ZADD', 'key', 'NX', 'INCR', '1', '1'] + ); + }); + + it('with comparison', () => { + assert.deepEqual( + ZADD_INCR.transformArguments('key', { + value: '1', + score: 1 + }, { + comparison: 'LT' + }), + ['ZADD', 'key', 'LT', 'INCR', '1', '1'] + ); + }); + + it('with CH', () => { + assert.deepEqual( + ZADD_INCR.transformArguments('key', { + value: '1', + score: 1 + }, { + CH: true + }), + ['ZADD', 'key', 'CH', 'INCR', '1', '1'] + ); + }); + + it('with condition, comparison, CH', () => { + assert.deepEqual( + ZADD_INCR.transformArguments('key', { + value: '1', + score: 1 + }, { + condition: 'XX', + comparison: 'LT', + CH: true + }), + ['ZADD', 'key', 'XX', 'LT', 'CH', 'INCR', '1', '1'] + ); + }); + }); + + testUtils.testAll('zAddIncr', async client => { + assert.equal( + await client.zAddIncr('key', { + value: '1', + score: 1 + }), + 1 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/ZADD_INCR.ts b/packages/client/lib/commands/ZADD_INCR.ts new file mode 100644 index 0000000000..a278b2ee89 --- /dev/null +++ b/packages/client/lib/commands/ZADD_INCR.ts @@ -0,0 +1,42 @@ +import { RedisArgument, DoubleReply, NullReply, Command } from '../RESP/types'; +import { pushMembers } from './ZADD'; +import { ZMember, transformDoubleArgument, transformNullableDoubleReply } from './generic-transformers'; + +export interface ZAddOptions { + condition?: 'NX' | 'XX'; + comparison?: 'LT' | 'GT'; + CH?: boolean; +} + +export default { + FIRST_KEY_INDEX: 1, + transformArguments( + key: RedisArgument, + members: ZMember | Array, + options?: ZAddOptions + ) { + const args = ['ZADD', key]; + + if (options?.condition) { + args.push(options.condition); + } + + if (options?.comparison) { + args.push(options.comparison); + } + + if (options?.CH) { + args.push('CH'); + } + + args.push('INCR'); + + pushMembers(args, members); + + return args; + }, + transformReply: { + 2: transformNullableDoubleReply, + 3: undefined as unknown as () => DoubleReply | NullReply + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZDIFF_WITHSCORES.ts b/packages/client/lib/commands/ZDIFF_WITHSCORES.ts index 0fa1a6d271..f971e82857 100644 --- a/packages/client/lib/commands/ZDIFF_WITHSCORES.ts +++ b/packages/client/lib/commands/ZDIFF_WITHSCORES.ts @@ -1,19 +1,14 @@ -import { ArrayReply, BlobStringReply, Command, NumberReply } from '../RESP/types'; +import { Command } from '../RESP/types'; import ZDIFF from './ZDIFF'; -import { transformSortedSetWithScoresReply } from './generic-transformers'; +import { transformSortedSetReply } from './generic-transformers'; export default { - FIRST_KEY_INDEX: 2, - IS_READ_ONLY: true, - transformArguments(keys: Parameters[0]) { - const args = ZDIFF.transformArguments(keys); - args.push('WITHSCORES'); - return args; + FIRST_KEY_INDEX: ZDIFF.FIRST_KEY_INDEX, + IS_READ_ONLY: ZDIFF.IS_READ_ONLY, + transformArguments(...args: Parameters) { + const redisArgs = ZDIFF.transformArguments(...args); + redisArgs.push('WITHSCORES'); + return redisArgs; }, - transformReply: { - 2: transformSortedSetWithScoresReply, - 3: (reply: ArrayReply<[BlobStringReply, NumberReply]>) => { - return reply.map(([value, score]) => ({ value, score })); - } - } + transformReply: transformSortedSetReply } as const satisfies Command; diff --git a/packages/client/lib/commands/ZINTERSTORE.ts b/packages/client/lib/commands/ZINTERSTORE.ts index 9188b0d90f..941ddd68e5 100644 --- a/packages/client/lib/commands/ZINTERSTORE.ts +++ b/packages/client/lib/commands/ZINTERSTORE.ts @@ -1,12 +1,13 @@ import { RedisArgument, NumberReply, Command } from '../RESP/types'; -import { pushZInterArguments, ZInterKeyAndWeight, ZInterKeys, ZInterOptions } from './ZINTER'; +import { pushZInterArguments, ZInterOptions } from './ZINTER'; +import { ZKeys } from './generic-transformers'; export default { FIRST_KEY_INDEX: 1, transformArguments( destination: RedisArgument, - keys: ZInterKeys | ZInterKeys, + keys: ZKeys, options?: ZInterOptions ) { return pushZInterArguments(['ZINTERSTORE', destination], keys, options); diff --git a/packages/client/lib/commands/ZINTER_WITHSCORES.ts b/packages/client/lib/commands/ZINTER_WITHSCORES.ts index 0761625145..b287649fbc 100644 --- a/packages/client/lib/commands/ZINTER_WITHSCORES.ts +++ b/packages/client/lib/commands/ZINTER_WITHSCORES.ts @@ -1,22 +1,6 @@ -// import { RedisCommandArguments } from '.'; -// import { transformArguments as transformZInterArguments } from './ZINTER'; - -// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './ZINTER'; - -// export function transformArguments(...args: Parameters): RedisCommandArguments { -// return [ -// ...transformZInterArguments(...args), -// 'WITHSCORES' -// ]; -// } - - - -// // transformSortedSetWithScoresReply - -import { ArrayReply, BlobStringReply, Command, DoubleReply } from '../RESP/types'; +import { Command } from '../RESP/types'; import ZINTER from './ZINTER'; -import { transformSortedSetWithScoresReply } from './generic-transformers'; +import { transformSortedSetReply } from './generic-transformers'; export default { FIRST_KEY_INDEX: ZINTER.FIRST_KEY_INDEX, @@ -26,13 +10,5 @@ export default { redisArgs.push('WITHSCORES'); return redisArgs; }, - transformReply: { - 2: transformSortedSetWithScoresReply, - 3: (reply: ArrayReply<[BlobStringReply, DoubleReply]>) => { - return reply.map(([member, score]) => ({ - member, - score - })); - } - } + transformReply: transformSortedSetReply } as const satisfies Command; diff --git a/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts b/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts index 2a90a6af3f..2cca62bae2 100644 --- a/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts +++ b/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.spec.ts @@ -1,33 +1,36 @@ -// import { strict as assert } from 'assert'; -// import testUtils, { GLOBAL } from '../test-utils'; -// import { transformArguments } from './ZRANGEBYSCORE_WITHSCORES'; +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import ZRANGEBYSCORE_WITHSCORES from './ZRANGEBYSCORE_WITHSCORES'; -// describe('ZRANGEBYSCORE WITHSCORES', () => { -// describe('transformArguments', () => { -// it('simple', () => { -// assert.deepEqual( -// transformArguments('src', 0, 1), -// ['ZRANGEBYSCORE', 'src', '0', '1', 'WITHSCORES'] -// ); -// }); +describe('ZRANGEBYSCORE WITHSCORES', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + ZRANGEBYSCORE_WITHSCORES.transformArguments('src', 0, 1), + ['ZRANGEBYSCORE', 'src', '0', '1', 'WITHSCORES'] + ); + }); -// it('with LIMIT', () => { -// assert.deepEqual( -// transformArguments('src', 0, 1, { -// LIMIT: { -// offset: 0, -// count: 1 -// } -// }), -// ['ZRANGEBYSCORE', 'src', '0', '1', 'LIMIT', '0', '1', 'WITHSCORES'] -// ); -// }); -// }); + it('with LIMIT', () => { + assert.deepEqual( + ZRANGEBYSCORE_WITHSCORES.transformArguments('src', 0, 1, { + LIMIT: { + offset: 0, + count: 1 + } + }), + ['ZRANGEBYSCORE', 'src', '0', '1', 'LIMIT', '0', '1', 'WITHSCORES'] + ); + }); + }); -// testUtils.testWithClient('client.zRangeByScoreWithScores', async client => { -// assert.deepEqual( -// await client.zRangeByScoreWithScores('src', 0, 1), -// [] -// ); -// }, GLOBAL.SERVERS.OPEN); -// }); + testUtils.testAll('zRangeByScoreWithScores', async client => { + assert.deepEqual( + await client.zRangeByScoreWithScores('src', 0, 1), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.ts b/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.ts index 1cd2df10f0..bfbe09c6e2 100644 --- a/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.ts +++ b/packages/client/lib/commands/ZRANGEBYSCORE_WITHSCORES.ts @@ -1,18 +1,14 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { ZRangeByScoreOptions, transformArguments as transformZRangeByScoreArguments } from './ZRANGEBYSCORE'; +import { Command } from '../RESP/types'; +import ZRANGEBYSCORE from './ZRANGEBYSCORE'; +import { transformSortedSetReply } from './generic-transformers'; -// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './ZRANGEBYSCORE'; - -// export function transformArguments( -// key: RedisCommandArgument, -// min: string | number, -// max: string | number, -// options?: ZRangeByScoreOptions -// ): RedisCommandArguments { -// return [ -// ...transformZRangeByScoreArguments(key, min, max, options), -// 'WITHSCORES' -// ]; -// } - -// export { transformSortedSetWithScoresReply as transformReply } from './generic-transformers'; +export default { + FIRST_KEY_INDEX: ZRANGEBYSCORE.FIRST_KEY_INDEX, + IS_READ_ONLY: ZRANGEBYSCORE.IS_READ_ONLY, + transformArguments(...args: Parameters) { + const redisArgs = ZRANGEBYSCORE.transformArguments(...args); + redisArgs.push('WITHSCORES'); + return redisArgs; + }, + transformReply: transformSortedSetReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/ZUNIONSTORE.spec.ts b/packages/client/lib/commands/ZUNIONSTORE.spec.ts index ca436dbd06..9b6454f232 100644 --- a/packages/client/lib/commands/ZUNIONSTORE.spec.ts +++ b/packages/client/lib/commands/ZUNIONSTORE.spec.ts @@ -6,27 +6,41 @@ describe('ZUNIONSTORE', () => { describe('transformArguments', () => { it('key (string)', () => { assert.deepEqual( - ZUNIONSTORE.transformArguments('destination', 'key'), + ZUNIONSTORE.transformArguments('destination', 'source'), ['ZUNIONSTORE', 'destination', '1', 'key'] ); }); - it('keys (array)', () => { + it('keys (Array)', () => { assert.deepEqual( ZUNIONSTORE.transformArguments('destination', ['1', '2']), ['ZUNIONSTORE', 'destination', '2', '1', '2'] ); }); - it('with WEIGHTS', () => { + it('key & weight', () => { assert.deepEqual( - ZUNIONSTORE.transformArguments('destination', 'key', { - WEIGHTS: [1] + ZUNIONSTORE.transformArguments('destination', { + key: 'key', + weight: 1 }), ['ZUNIONSTORE', 'destination', '1', 'key', 'WEIGHTS', '1'] ); }); + it('keys & weights', () => { + assert.deepEqual( + ZUNIONSTORE.transformArguments('destination', [{ + key: 'a', + weight: 1 + }, { + key: 'b', + weight: 2 + }]), + ['ZUNIONSTORE', 'destination', '2', 'a', 'b', 'WEIGHTS', '1', '2'] + ); + }); + it('with AGGREGATE', () => { assert.deepEqual( ZUNIONSTORE.transformArguments('destination', 'key', { @@ -35,16 +49,6 @@ describe('ZUNIONSTORE', () => { ['ZUNIONSTORE', 'destination', '1', 'key', 'AGGREGATE', 'SUM'] ); }); - - it('with WEIGHTS, AGGREGATE', () => { - assert.deepEqual( - ZUNIONSTORE.transformArguments('destination', 'key', { - WEIGHTS: [1], - AGGREGATE: 'SUM' - }), - ['ZUNIONSTORE', 'destination', '1', 'key', 'WEIGHTS', '1', 'AGGREGATE', 'SUM'] - ); - }); }); testUtils.testAll('zUnionStore', async client => { diff --git a/packages/client/lib/commands/ZUNION_WITHSCORES.spec.ts b/packages/client/lib/commands/ZUNION_WITHSCORES.spec.ts index 41442bb646..75283c0bc3 100644 --- a/packages/client/lib/commands/ZUNION_WITHSCORES.spec.ts +++ b/packages/client/lib/commands/ZUNION_WITHSCORES.spec.ts @@ -9,14 +9,14 @@ describe('ZUNION WITHSCORES', () => { it('key (string)', () => { assert.deepEqual( ZUNION_WITHSCORES.transformArguments('key'), - ['ZUNION', '1', 'key'] + ['ZUNION', '1', 'key', 'WITHSCORES'] ); }); it('keys (Array)', () => { assert.deepEqual( ZUNION_WITHSCORES.transformArguments(['1', '2']), - ['ZUNION', '2', '1', '2'] + ['ZUNION', '2', '1', '2', 'WITHSCORES'] ); }); @@ -26,7 +26,7 @@ describe('ZUNION WITHSCORES', () => { key: 'key', weight: 1 }), - ['ZUNION', '1', 'key', 'WEIGHTS', '1'] + ['ZUNION', '1', 'key', 'WEIGHTS', '1', 'WITHSCORES'] ); }); @@ -39,7 +39,7 @@ describe('ZUNION WITHSCORES', () => { key: 'b', weight: 2 }]), - ['ZUNION', '2', 'a', 'b', 'WEIGHTS', '1', '2'] + ['ZUNION', '2', 'a', 'b', 'WEIGHTS', '1', '2', 'WITHSCORES'] ); }); diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index a83177138b..397ae7ff22 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -186,6 +186,7 @@ import XDEL from './XDEL'; import XSETID from './XSETID'; import XTRIM from './XTRIM'; import XLEN from './XLEN'; +import ZADD_INCR from './ZADD_INCR'; import ZADD from './ZADD'; import ZCARD from './ZCARD'; import ZCOUNT from './ZCOUNT'; @@ -204,6 +205,7 @@ import ZRANDMEMBER_COUNT from './ZRANDMEMBER_COUNT'; import ZRANDMEMBER from './ZRANDMEMBER'; import ZRANGE from './ZRANGE'; import ZRANGEBYLEX from './ZRANGEBYLEX'; +import ZRANGEBYSCORE_WITHSCORES from './ZRANGEBYSCORE_WITHSCORES'; import ZRANGEBYSCORE from './ZRANGEBYSCORE'; import ZREMRANGEBYSCORE from './ZREMRANGEBYSCORE'; import ZRANK from './ZRANK'; @@ -596,6 +598,8 @@ export default { xTrim: XTRIM, XLEN, xLen: XLEN, + ZADD_INCR, + zAddIncr: ZADD_INCR, ZADD, zAdd: ZADD, ZCARD, @@ -632,6 +636,8 @@ export default { zRange: ZRANGE, ZRANGEBYLEX, zRangeByLex: ZRANGEBYLEX, + ZRANGEBYSCORE_WITHSCORES, + zRangeByScoreWithScores: ZRANGEBYSCORE_WITHSCORES, ZRANGEBYSCORE, zRangeByScore: ZRANGEBYSCORE, ZRANK,