diff --git a/packages/client/lib/cluster/commands.ts b/packages/client/lib/cluster/commands.ts index dd82e6f314..4a2c7e8503 100644 --- a/packages/client/lib/cluster/commands.ts +++ b/packages/client/lib/cluster/commands.ts @@ -110,6 +110,8 @@ import * as SISMEMBER from '../commands/SISMEMBER'; import * as SMEMBERS from '../commands/SMEMBERS'; import * as SMISMEMBER from '../commands/SMISMEMBER'; import * as SMOVE from '../commands/SMOVE'; +import * as SORT_RO from '../commands/SORT_RO'; +import * as SORT_STORE from '../commands/SORT_STORE'; import * as SORT from '../commands/SORT'; import * as SPOP from '../commands/SPOP'; import * as SRANDMEMBER_COUNT from '../commands/SRANDMEMBER_COUNT'; @@ -408,6 +410,10 @@ export default { smIsMember: SMISMEMBER, SMOVE, sMove: SMOVE, + SORT_RO, + sortRo: SORT_RO, + SORT_STORE, + sortStore: SORT_STORE, SORT, sort: SORT, SPOP, diff --git a/packages/client/lib/commands/SORT.spec.ts b/packages/client/lib/commands/SORT.spec.ts index 637f48876d..4967b020ad 100644 --- a/packages/client/lib/commands/SORT.spec.ts +++ b/packages/client/lib/commands/SORT.spec.ts @@ -70,16 +70,7 @@ describe('SORT', () => { ); }); - it('with STORE', () => { - assert.deepEqual( - transformArguments('key', { - STORE: 'destination' - }), - ['SORT', 'key', 'STORE', 'destination'] - ); - }); - - it('with BY, LIMIT, GET, DIRECTION, ALPHA, STORE', () => { + it('with BY, LIMIT, GET, DIRECTION, ALPHA', () => { assert.deepEqual( transformArguments('key', { BY: 'pattern', @@ -89,10 +80,9 @@ describe('SORT', () => { }, GET: 'pattern', DIRECTION: 'ASC', - ALPHA: true, - STORE: 'destination' + ALPHA: true }), - ['SORT', 'key', 'BY', 'pattern', 'LIMIT', '0', '1', 'GET', 'pattern', 'ASC', 'ALPHA', 'STORE', 'destination'] + ['SORT', 'key', 'BY', 'pattern', 'LIMIT', '0', '1', 'GET', 'pattern', 'ASC', 'ALPHA'] ); }); }); diff --git a/packages/client/lib/commands/SORT.ts b/packages/client/lib/commands/SORT.ts index dfa38dc756..15e95bde67 100644 --- a/packages/client/lib/commands/SORT.ts +++ b/packages/client/lib/commands/SORT.ts @@ -1,56 +1,13 @@ +import { RedisCommandArguments } from '.'; +import { pushSortArguments, SortOptions } from './generic-transformers'; + export const FIRST_KEY_INDEX = 1; -export const IS_READ_ONLY = true; - -interface SortOptions { - BY?: string; - LIMIT?: { - offset: number; - count: number; - }, - GET?: string | Array; - DIRECTION?: 'ASC' | 'DESC'; - ALPHA?: true; - STORE?: string; +export function transformArguments( + key: string, + options?: SortOptions +): RedisCommandArguments { + return pushSortArguments(['SORT', key], options); } -export function transformArguments(key: string, options?: SortOptions): Array { - const args = ['SORT', key]; - - if (options?.BY) { - args.push('BY', options.BY); - } - - if (options?.LIMIT) { - args.push( - 'LIMIT', - options.LIMIT.offset.toString(), - options.LIMIT.count.toString() - ); - } - - if (options?.GET) { - for (const pattern of (typeof options.GET === 'string' ? [options.GET] : options.GET)) { - args.push('GET', pattern); - } - } - - if (options?.DIRECTION) { - args.push(options.DIRECTION); - } - - if (options?.ALPHA) { - args.push('ALPHA'); - } - - if (options?.STORE) { - args.push('STORE', options.STORE); - } - - return args; -} - -// integer when using `STORE` -export function transformReply(reply: Array | number): Array | number { - return reply; -} +export declare function transformReply(): Array; diff --git a/packages/client/lib/commands/SORT_RO.spec.ts b/packages/client/lib/commands/SORT_RO.spec.ts new file mode 100644 index 0000000000..0cc57991b7 --- /dev/null +++ b/packages/client/lib/commands/SORT_RO.spec.ts @@ -0,0 +1,98 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './SORT_RO'; + +describe('SORT_RO', () => { + testUtils.isVersionGreaterThanHook([7, 0]); + + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + transformArguments('key'), + ['SORT_RO', 'key'] + ); + }); + + it('with BY', () => { + assert.deepEqual( + transformArguments('key', { + BY: 'pattern' + }), + ['SORT_RO', 'key', 'BY', 'pattern'] + ); + }); + + it('with LIMIT', () => { + assert.deepEqual( + transformArguments('key', { + LIMIT: { + offset: 0, + count: 1 + } + }), + ['SORT_RO', 'key', 'LIMIT', '0', '1'] + ); + }); + + describe('with GET', () => { + it('string', () => { + assert.deepEqual( + transformArguments('key', { + GET: 'pattern' + }), + ['SORT_RO', 'key', 'GET', 'pattern'] + ); + }); + + it('array', () => { + assert.deepEqual( + transformArguments('key', { + GET: ['1', '2'] + }), + ['SORT_RO', 'key', 'GET', '1', 'GET', '2'] + ); + }); + }); + + it('with DIRECTION', () => { + assert.deepEqual( + transformArguments('key', { + DIRECTION: 'ASC' + }), + ['SORT_RO', 'key', 'ASC'] + ); + }); + + it('with ALPHA', () => { + assert.deepEqual( + transformArguments('key', { + ALPHA: true + }), + ['SORT_RO', 'key', 'ALPHA'] + ); + }); + + it('with BY, LIMIT, GET, DIRECTION, ALPHA', () => { + assert.deepEqual( + transformArguments('key', { + BY: 'pattern', + LIMIT: { + offset: 0, + count: 1 + }, + GET: 'pattern', + DIRECTION: 'ASC', + ALPHA: true, + }), + ['SORT_RO', 'key', 'BY', 'pattern', 'LIMIT', '0', '1', 'GET', 'pattern', 'ASC', 'ALPHA'] + ); + }); + }); + + testUtils.testWithClient('client.sortRo', async client => { + assert.deepEqual( + await client.sortRo('key'), + [] + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/client/lib/commands/SORT_RO.ts b/packages/client/lib/commands/SORT_RO.ts new file mode 100644 index 0000000000..4af7acd80d --- /dev/null +++ b/packages/client/lib/commands/SORT_RO.ts @@ -0,0 +1,15 @@ +import { RedisCommandArguments } from '.'; +import { pushSortArguments, SortOptions } from "./generic-transformers"; + +export const FIRST_KEY_INDEX = 1; + +export const IS_READ_ONLY = true; + +export function transformArguments( + key: string, + options?: SortOptions +): RedisCommandArguments { + return pushSortArguments(['SORT_RO', key], options); +} + +export declare function transformReply(): Array; diff --git a/packages/client/lib/commands/SORT_STORE.spec.ts b/packages/client/lib/commands/SORT_STORE.spec.ts new file mode 100644 index 0000000000..d078135255 --- /dev/null +++ b/packages/client/lib/commands/SORT_STORE.spec.ts @@ -0,0 +1,96 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './SORT_STORE'; + +describe('SORT STORE', () => { + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + transformArguments('source', 'destination'), + ['SORT', 'source', 'STORE', 'destination'] + ); + }); + + it('with BY', () => { + assert.deepEqual( + transformArguments('source', 'destination', { + BY: 'pattern' + }), + ['SORT', 'source', 'BY', 'pattern', 'STORE', 'destination'] + ); + }); + + it('with LIMIT', () => { + assert.deepEqual( + transformArguments('source', 'destination', { + LIMIT: { + offset: 0, + count: 1 + } + }), + ['SORT', 'source', 'LIMIT', '0', '1', 'STORE', 'destination'] + ); + }); + + describe('with GET', () => { + it('string', () => { + assert.deepEqual( + transformArguments('source', 'destination', { + GET: 'pattern' + }), + ['SORT', 'source', 'GET', 'pattern', 'STORE', 'destination'] + ); + }); + + it('array', () => { + assert.deepEqual( + transformArguments('source', 'destination', { + GET: ['1', '2'] + }), + ['SORT', 'source', 'GET', '1', 'GET', '2', 'STORE', 'destination'] + ); + }); + }); + + it('with DIRECTION', () => { + assert.deepEqual( + transformArguments('source', 'destination', { + DIRECTION: 'ASC' + }), + ['SORT', 'source', 'ASC', 'STORE', 'destination'] + ); + }); + + it('with ALPHA', () => { + assert.deepEqual( + transformArguments('source', 'destination', { + ALPHA: true + }), + ['SORT', 'source', 'ALPHA', 'STORE', 'destination'] + ); + }); + + it('with BY, LIMIT, GET, DIRECTION, ALPHA', () => { + assert.deepEqual( + transformArguments('source', 'destination', { + BY: 'pattern', + LIMIT: { + offset: 0, + count: 1 + }, + GET: 'pattern', + DIRECTION: 'ASC', + ALPHA: true + }), + ['SORT', 'source', 'BY', 'pattern', 'LIMIT', '0', '1', 'GET', 'pattern', 'ASC', 'ALPHA', 'STORE', 'destination'] + ); + }); + }); + + testUtils.testWithClient('client.sortStore', async client => { + assert.equal( + await client.sortStore('source', 'destination'), + 0 + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/client/lib/commands/SORT_STORE.ts b/packages/client/lib/commands/SORT_STORE.ts new file mode 100644 index 0000000000..9acaf02317 --- /dev/null +++ b/packages/client/lib/commands/SORT_STORE.ts @@ -0,0 +1,17 @@ +import { RedisCommandArguments } from '.'; +import { SortOptions } from './generic-transformers'; +import { transformArguments as transformSortArguments } from './SORT'; + +export const FIRST_KEY_INDEX = 1; + +export function transformArguments( + source: string, + destination: string, + options?: SortOptions +): RedisCommandArguments { + const args = transformSortArguments(source, options); + args.push('STORE', destination); + return args; +} + +export declare function transformReply(): number; diff --git a/packages/client/lib/commands/generic-transformers.ts b/packages/client/lib/commands/generic-transformers.ts index f138cb0430..7850d22ed4 100644 --- a/packages/client/lib/commands/generic-transformers.ts +++ b/packages/client/lib/commands/generic-transformers.ts @@ -438,6 +438,50 @@ export function transformCommandReply( }; } +export interface SortOptions { + BY?: string; + LIMIT?: { + offset: number; + count: number; + }, + GET?: string | Array; + DIRECTION?: 'ASC' | 'DESC'; + ALPHA?: true; +} + +export function pushSortArguments( + args: RedisCommandArguments, + options?: SortOptions +): RedisCommandArguments { + if (options?.BY) { + args.push('BY', options.BY); + } + + if (options?.LIMIT) { + args.push( + 'LIMIT', + options.LIMIT.offset.toString(), + options.LIMIT.count.toString() + ); + } + + if (options?.GET) { + for (const pattern of (typeof options.GET === 'string' ? [options.GET] : options.GET)) { + args.push('GET', pattern); + } + } + + if (options?.DIRECTION) { + args.push(options.DIRECTION); + } + + if (options?.ALPHA) { + args.push('ALPHA'); + } + + return args; +} + export interface SlotRange { start: number; end: number;