diff --git a/packages/client/lib/commands/GEOADD.spec.ts b/packages/client/lib/commands/GEOADD.spec.ts index 6425c881c9..3b9584aed0 100644 --- a/packages/client/lib/commands/GEOADD.spec.ts +++ b/packages/client/lib/commands/GEOADD.spec.ts @@ -1,95 +1,100 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GEOADD'; +import GEOADD from './GEOADD'; describe('GEOADD', () => { - describe('transformArguments', () => { - it('one member', () => { - assert.deepEqual( - transformArguments('key', { - member: 'member', - longitude: 1, - latitude: 2 - }), - ['GEOADD', 'key', '1', '2', 'member'] - ); - }); - - it('multiple members', () => { - assert.deepEqual( - transformArguments('key', [{ - longitude: 1, - latitude: 2, - member: '3', - }, { - longitude: 4, - latitude: 5, - member: '6', - }]), - ['GEOADD', 'key', '1', '2', '3', '4', '5', '6'] - ); - }); - - it('with NX', () => { - assert.deepEqual( - transformArguments('key', { - longitude: 1, - latitude: 2, - member: 'member' - }, { - NX: true - }), - ['GEOADD', 'key', 'NX', '1', '2', 'member'] - ); - }); - - it('with CH', () => { - assert.deepEqual( - transformArguments('key', { - longitude: 1, - latitude: 2, - member: 'member' - }, { - CH: true - }), - ['GEOADD', 'key', 'CH', '1', '2', 'member'] - ); - }); - - it('with XX, CH', () => { - assert.deepEqual( - transformArguments('key', { - longitude: 1, - latitude: 2, - member: 'member' - }, { - XX: true, - CH: true - }), - ['GEOADD', 'key', 'XX', 'CH', '1', '2', 'member'] - ); - }); + describe('transformArguments', () => { + it('one member', () => { + assert.deepEqual( + GEOADD.transformArguments('key', { + member: 'member', + longitude: 1, + latitude: 2 + }), + ['GEOADD', 'key', '1', '2', 'member'] + ); }); - testUtils.testWithClient('client.geoAdd', async client => { - assert.equal( - await client.geoAdd('key', { - member: 'member', - longitude: 1, - latitude: 2 - }), - 1 - ); - }, GLOBAL.SERVERS.OPEN); + it('multiple members', () => { + assert.deepEqual( + GEOADD.transformArguments('key', [{ + longitude: 1, + latitude: 2, + member: '3', + }, { + longitude: 4, + latitude: 5, + member: '6', + }]), + ['GEOADD', 'key', '1', '2', '3', '4', '5', '6'] + ); + }); - testUtils.testWithCluster('cluster.geoAdd', async cluster => { - assert.equal( - await cluster.geoAdd('key', { - member: 'member', - longitude: 1, - latitude: 2 - }), - 1 - ); - }, GLOBAL.CLUSTERS.OPEN); + it('with condition', () => { + assert.deepEqual( + GEOADD.transformArguments('key', { + longitude: 1, + latitude: 2, + member: 'member' + }, { + condition: 'NX' + }), + ['GEOADD', 'key', 'NX', '1', '2', 'member'] + ); + }); + + it('with NX (backwards compatibility)', () => { + assert.deepEqual( + GEOADD.transformArguments('key', { + longitude: 1, + latitude: 2, + member: 'member' + }, { + NX: true + }), + ['GEOADD', 'key', 'NX', '1', '2', 'member'] + ); + }); + + it('with CH', () => { + assert.deepEqual( + GEOADD.transformArguments('key', { + longitude: 1, + latitude: 2, + member: 'member' + }, { + CH: true + }), + ['GEOADD', 'key', 'CH', '1', '2', 'member'] + ); + }); + + it('with condition, CH', () => { + assert.deepEqual( + GEOADD.transformArguments('key', { + longitude: 1, + latitude: 2, + member: 'member' + }, { + condition: 'XX', + CH: true + }), + ['GEOADD', 'key', 'XX', 'CH', '1', '2', 'member'] + ); + }); + }); + + testUtils.testAll('geoAdd', async client => { + assert.equal( + await client.geoAdd('key', { + member: 'member', + longitude: 1, + latitude: 2 + }), + 1 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEOADD.ts b/packages/client/lib/commands/GEOADD.ts index 2a34b5d560..f89f6b80e8 100644 --- a/packages/client/lib/commands/GEOADD.ts +++ b/packages/client/lib/commands/GEOADD.ts @@ -1,12 +1,12 @@ -import { CommandArguments, RedisArgument, NumberReply, Command } from '../RESP/types'; -import { GeoCoordinates } from './generic-transformers'; +import { RedisArgument, CommandArguments, NumberReply, Command } from '../RESP/types'; +import { GeoCoordinates } from './GEOSEARCH'; -interface GeoMember extends GeoCoordinates { +export interface GeoMember extends GeoCoordinates { member: RedisArgument; } -interface GeoAddOptions { - condition: 'NX' | 'XX'; +export interface GeoAddOptions { + condition?: 'NX' | 'XX'; /** * @deprecated Use `{ condition: 'NX' }` instead. */ diff --git a/packages/client/lib/commands/GEODIST.spec.ts b/packages/client/lib/commands/GEODIST.spec.ts index bbc62480ee..2e0af2a957 100644 --- a/packages/client/lib/commands/GEODIST.spec.ts +++ b/packages/client/lib/commands/GEODIST.spec.ts @@ -1,57 +1,54 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GEODIST'; +import GEODIST from './GEODIST'; describe('GEODIST', () => { - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('key', '1', '2'), - ['GEODIST', 'key', '1', '2'] - ); - }); - - it('with unit', () => { - assert.deepEqual( - transformArguments('key', '1', '2', 'm'), - ['GEODIST', 'key', '1', '2', 'm'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + GEODIST.transformArguments('key', '1', '2'), + ['GEODIST', 'key', '1', '2'] + ); }); - describe('client.geoDist', () => { - testUtils.testWithClient('null', async client => { - assert.equal( - await client.geoDist('key', '1', '2'), - null - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('with value', async client => { - const [, dist] = await Promise.all([ - client.geoAdd('key', [{ - member: '1', - longitude: 1, - latitude: 1 - }, { - member: '2', - longitude: 2, - latitude: 2 - }]), - client.geoDist('key', '1', '2') - ]); - - assert.equal( - dist, - 157270.0561 - ); - }, GLOBAL.SERVERS.OPEN); + it('with unit', () => { + assert.deepEqual( + GEODIST.transformArguments('key', '1', '2', 'm'), + ['GEODIST', 'key', '1', '2', 'm'] + ); }); + }); - testUtils.testWithCluster('cluster.geoDist', async cluster => { - assert.equal( - await cluster.geoDist('key', '1', '2'), - null - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('geoDist null', async client => { + assert.equal( + await client.geoDist('key', '1', '2'), + null + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); + + testUtils.testAll('geoDist with member', async client => { + const [, dist] = await Promise.all([ + client.geoAdd('key', [{ + member: '1', + longitude: 1, + latitude: 1 + }, { + member: '2', + longitude: 2, + latitude: 2 + }]), + client.geoDist('key', '1', '2') + ]); + + assert.equal( + dist, + 157270.0561 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEODIST.ts b/packages/client/lib/commands/GEODIST.ts index da6dee1b77..dc5bcf1f12 100644 --- a/packages/client/lib/commands/GEODIST.ts +++ b/packages/client/lib/commands/GEODIST.ts @@ -13,7 +13,7 @@ export default { const args = ['GEODIST', key, member1, member2]; if (unit) { - args.push(unit); + args.push(unit); } return args; diff --git a/packages/client/lib/commands/GEOHASH.spec.ts b/packages/client/lib/commands/GEOHASH.spec.ts index c421c148f4..0d575b487a 100644 --- a/packages/client/lib/commands/GEOHASH.spec.ts +++ b/packages/client/lib/commands/GEOHASH.spec.ts @@ -1,35 +1,31 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GEOHASH'; +import GEOHASH from './GEOHASH'; describe('GEOHASH', () => { - describe('transformArguments', () => { - it('single member', () => { - assert.deepEqual( - transformArguments('key', 'member'), - ['GEOHASH', 'key', 'member'] - ); - }); - - it('multiple members', () => { - assert.deepEqual( - transformArguments('key', ['1', '2']), - ['GEOHASH', 'key', '1', '2'] - ); - }); + describe('transformArguments', () => { + it('single member', () => { + assert.deepEqual( + GEOHASH.transformArguments('key', 'member'), + ['GEOHASH', 'key', 'member'] + ); }); - testUtils.testWithClient('client.geoHash', async client => { - assert.deepEqual( - await client.geoHash('key', 'member'), - [null] - ); - }, GLOBAL.SERVERS.OPEN); + it('multiple members', () => { + assert.deepEqual( + GEOHASH.transformArguments('key', ['1', '2']), + ['GEOHASH', 'key', '1', '2'] + ); + }); + }); - testUtils.testWithCluster('cluster.geoHash', async cluster => { - assert.deepEqual( - await cluster.geoHash('key', 'member'), - [null] - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('geoHash', async client => { + assert.deepEqual( + await client.geoHash('key', 'member'), + [null] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEOPOS.spec.ts b/packages/client/lib/commands/GEOPOS.spec.ts index 9c08ccd08f..297faba490 100644 --- a/packages/client/lib/commands/GEOPOS.spec.ts +++ b/packages/client/lib/commands/GEOPOS.spec.ts @@ -1,73 +1,51 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './GEOPOS'; +import GEOPOS from './GEOPOS'; describe('GEOPOS', () => { - describe('transformArguments', () => { - it('single member', () => { - assert.deepEqual( - transformArguments('key', 'member'), - ['GEOPOS', 'key', 'member'] - ); - }); - - it('multiple members', () => { - assert.deepEqual( - transformArguments('key', ['1', '2']), - ['GEOPOS', 'key', '1', '2'] - ); - }); + describe('transformArguments', () => { + it('single member', () => { + assert.deepEqual( + GEOPOS.transformArguments('key', 'member'), + ['GEOPOS', 'key', 'member'] + ); }); - describe('transformReply', () => { - it('null', () => { - assert.deepEqual( - transformReply([null]), - [null] - ); - }); + it('multiple members', () => { + assert.deepEqual( + GEOPOS.transformArguments('key', ['1', '2']), + ['GEOPOS', 'key', '1', '2'] + ); + }); + }); - it('with member', () => { - assert.deepEqual( - transformReply([['1', '2']]), - [{ - longitude: '1', - latitude: '2' - }] - ); - }); + testUtils.testAll('geoPos null', async client => { + assert.deepEqual( + await client.geoPos('key', 'member'), + [null] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); + + testUtils.testAll('geoPos with member', async client => { + const coordinates = { + longitude: '-122.06429868936538696', + latitude: '37.37749628831998194' + }; + + await client.geoAdd('key', { + member: 'member', + ...coordinates }); - describe('client.geoPos', () => { - testUtils.testWithClient('null', async client => { - assert.deepEqual( - await client.geoPos('key', 'member'), - [null] - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('with member', async client => { - const coordinates = { - longitude: '-122.06429868936538696', - latitude: '37.37749628831998194' - }; - - await client.geoAdd('key', { - member: 'member', - ...coordinates - }); - - assert.deepEqual( - await client.geoPos('key', 'member'), - [coordinates] - ); - }, GLOBAL.SERVERS.OPEN); - }); - - testUtils.testWithCluster('cluster.geoPos', async cluster => { - assert.deepEqual( - await cluster.geoPos('key', 'member'), - [null] - ); - }, GLOBAL.CLUSTERS.OPEN); + assert.deepEqual( + await client.geoPos('key', 'member'), + [coordinates] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEORADIUS.spec.ts b/packages/client/lib/commands/GEORADIUS.spec.ts index 786b266502..2897586487 100644 --- a/packages/client/lib/commands/GEORADIUS.spec.ts +++ b/packages/client/lib/commands/GEORADIUS.spec.ts @@ -1,35 +1,28 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GEORADIUS'; +import GEORADIUS from './GEORADIUS'; describe('GEORADIUS', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', { - longitude: 1, - latitude: 2 - }, 3 , 'm'), - ['GEORADIUS', 'key', '1', '2', '3', 'm'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + GEORADIUS.transformArguments('key', { + longitude: 1, + latitude: 2 + }, 3, 'm'), + ['GEORADIUS', 'key', '1', '2', '3', 'm'] + ); + }); - testUtils.testWithClient('client.geoRadius', async client => { - assert.deepEqual( - await client.geoRadius('key', { - longitude: 1, - latitude: 2 - }, 3 , 'm'), - [] - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.geoRadius', async cluster => { - assert.deepEqual( - await cluster.geoRadius('key', { - longitude: 1, - latitude: 2 - }, 3 , 'm'), - [] - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('geoRadius', async client => { + assert.deepEqual( + await client.geoRadius('key', { + longitude: 1, + latitude: 2 + }, 3, 'm'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEORADIUS.ts b/packages/client/lib/commands/GEORADIUS.ts index 4b5af7a078..e777432f09 100644 --- a/packages/client/lib/commands/GEORADIUS.ts +++ b/packages/client/lib/commands/GEORADIUS.ts @@ -1,25 +1,32 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoSearchOptions, GeoCoordinates, pushGeoRadiusArguments, GeoUnits } from './generic-transformers'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import { GeoCoordinates, GeoUnits, GeoSearchOptions, pushGeoSearchOptions } from './GEOSEARCH'; -// export const FIRST_KEY_INDEX = 1; +export function transformGeoRadiusArguments( + command: RedisArgument, + key: RedisArgument, + from: GeoCoordinates, + radius: number, + unit: GeoUnits, + options?: GeoSearchOptions +) { + const args = [ + command, + key, + from.longitude.toString(), + from.latitude.toString(), + radius.toString(), + unit + ]; -// export const IS_READ_ONLY = true; + pushGeoSearchOptions(args, options); -// export function transformArguments( -// key: RedisCommandArgument, -// coordinates: GeoCoordinates, -// radius: number, -// unit: GeoUnits, -// options?: GeoSearchOptions -// ): RedisCommandArguments { -// return pushGeoRadiusArguments( -// ['GEORADIUS'], -// key, -// coordinates, -// radius, -// unit, -// options -// ); -// } + return args; +} + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments: transformGeoRadiusArguments.bind(undefined, 'GEORADIUS'), + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; -// export declare function transformReply(): Array; diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER.spec.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER.spec.ts index 8cc4212c83..b44a649bce 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER.spec.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER.spec.ts @@ -1,26 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GEORADIUSBYMEMBER'; +import GEORADIUSBYMEMBER from './GEORADIUSBYMEMBER'; describe('GEORADIUSBYMEMBER', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'member', 3 , 'm'), - ['GEORADIUSBYMEMBER', 'key', 'member', '3', 'm'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + GEORADIUSBYMEMBER.transformArguments('key', 'member', 3, 'm'), + ['GEORADIUSBYMEMBER', 'key', 'member', '3', 'm'] + ); + }); - testUtils.testWithClient('client.geoRadiusByMember', async client => { - assert.deepEqual( - await client.geoRadiusByMember('key', 'member', 3 , 'm'), - [] - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.geoRadiusByMember', async cluster => { - assert.deepEqual( - await cluster.geoRadiusByMember('key', 'member', 3 , 'm'), - [] - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('geoRadiusByMember', async client => { + assert.deepEqual( + await client.geoRadiusByMember('key', 'member', 3, 'm'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER.ts index ab6950ac8d..13b52a3063 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER.ts @@ -1,25 +1,30 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoSearchOptions, pushGeoRadiusArguments, GeoUnits } from './generic-transformers'; +import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import { GeoUnits, GeoSearchOptions, pushGeoSearchOptions } from './GEOSEARCH'; -// export const FIRST_KEY_INDEX = 1; +export function transformGeoRadiusByMemberArguments( + command: RedisArgument, + key: RedisArgument, + from: RedisArgument, + radius: number, + unit: GeoUnits, + options?: GeoSearchOptions +) { + const args = [ + command, + key, + from, + radius.toString(), + unit + ]; -// export const IS_READ_ONLY = true; + pushGeoSearchOptions(args, options); -// export function transformArguments( -// key: RedisCommandArgument, -// member: string, -// radius: number, -// unit: GeoUnits, -// options?: GeoSearchOptions -// ): RedisCommandArguments { -// return pushGeoRadiusArguments( -// ['GEORADIUSBYMEMBER'], -// key, -// member, -// radius, -// unit, -// options -// ); -// } + return args; +} -// export declare function transformReply(): Array; +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments: transformGeoRadiusByMemberArguments.bind(undefined, 'GEORADIUSBYMEMBER'), + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBERSTORE.spec.ts b/packages/client/lib/commands/GEORADIUSBYMEMBERSTORE.spec.ts deleted file mode 100644 index 100ecc0336..0000000000 --- a/packages/client/lib/commands/GEORADIUSBYMEMBERSTORE.spec.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './GEORADIUSBYMEMBERSTORE'; - -describe('GEORADIUSBYMEMBERSTORE', () => { - describe('transformArguments', () => { - it('STORE', () => { - assert.deepEqual( - transformArguments('key', 'member', 3 , 'm', 'dest', { - SORT: 'ASC', - COUNT: { - value: 1, - ANY: true - } - }), - ['GEORADIUSBYMEMBER', 'key', 'member', '3', 'm', 'ASC', 'COUNT', '1', 'ANY', 'STORE', 'dest'] - ); - }); - - it('STOREDIST', () => { - assert.deepEqual( - transformArguments('key', 'member', 3 , 'm', 'dest', { STOREDIST: true }), - ['GEORADIUSBYMEMBER', 'key', 'member', '3', 'm', 'STOREDIST', 'dest'] - ); - }); - }); - - testUtils.testWithClient('client.geoRadiusByMemberStore', async client => { - await client.geoAdd('source', { - longitude: 1, - latitude: 1, - member: 'member' - }); - - assert.equal( - await client.geoRadiusByMemberStore('source', 'member', 3 , 'm', 'dest'), - 1 - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.geoRadiusByMemberStore', async cluster => { - await cluster.geoAdd('{tag}source', { - longitude: 1, - latitude: 1, - member: 'member' - }); - - assert.equal( - await cluster.geoRadiusByMemberStore('{tag}source', 'member', 3 , 'm','{tag}destination'), - 1 - ); - }, GLOBAL.CLUSTERS.OPEN); -}); diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBERSTORE.ts b/packages/client/lib/commands/GEORADIUSBYMEMBERSTORE.ts deleted file mode 100644 index ea1674cf3f..0000000000 --- a/packages/client/lib/commands/GEORADIUSBYMEMBERSTORE.ts +++ /dev/null @@ -1,25 +0,0 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoUnits, GeoRadiusStoreOptions, pushGeoRadiusStoreArguments } from './generic-transformers'; - -// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEORADIUSBYMEMBER'; - -// export function transformArguments( -// key: RedisCommandArgument, -// member: string, -// radius: number, -// unit: GeoUnits, -// destination: RedisCommandArgument, -// options?: GeoRadiusStoreOptions, -// ): RedisCommandArguments { -// return pushGeoRadiusStoreArguments( -// ['GEORADIUSBYMEMBER'], -// key, -// member, -// radius, -// unit, -// destination, -// options -// ); -// } - -// export declare function transformReply(): number diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_RO.spec.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_RO.spec.ts index f3a47856e8..47e4dabbbc 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER_RO.spec.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_RO.spec.ts @@ -1,26 +1,22 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GEORADIUSBYMEMBER_RO'; +import GEORADIUSBYMEMBER_RO from './GEORADIUSBYMEMBER_RO'; describe('GEORADIUSBYMEMBER_RO', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'member', 3 , 'm'), - ['GEORADIUSBYMEMBER_RO', 'key', 'member', '3', 'm'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + GEORADIUSBYMEMBER_RO.transformArguments('key', 'member', 3, 'm'), + ['GEORADIUSBYMEMBER_RO', 'key', 'member', '3', 'm'] + ); + }); - testUtils.testWithClient('client.geoRadiusByMemberRo', async client => { - assert.deepEqual( - await client.geoRadiusByMemberRo('key', 'member', 3 , 'm'), - [] - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.geoRadiusByMemberRo', async cluster => { - assert.deepEqual( - await cluster.geoRadiusByMemberRo('key', 'member', 3 , 'm'), - [] - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('geoRadiusByMemberRo', async client => { + assert.deepEqual( + await client.geoRadiusByMemberRo('key', 'member', 3, 'm'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_RO.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_RO.ts index 1ad9450ae3..7f85ed15df 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER_RO.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_RO.ts @@ -1,25 +1,9 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoSearchOptions, pushGeoRadiusArguments, GeoUnits } from './generic-transformers'; +import { Command } from '../RESP/types'; +import GEORADIUSBYMEMBER, { transformGeoRadiusByMemberArguments } from './GEORADIUSBYMEMBER'; -// export const FIRST_KEY_INDEX = 1; - -// export const IS_READ_ONLY = true; - -// export function transformArguments( -// key: RedisCommandArgument, -// member: string, -// radius: number, -// unit: GeoUnits, -// options?: GeoSearchOptions -// ): RedisCommandArguments { -// return pushGeoRadiusArguments( -// ['GEORADIUSBYMEMBER_RO'], -// key, -// member, -// radius, -// unit, -// options -// ); -// } - -// export declare function transformReply(): Array; +export default { + FIRST_KEY_INDEX: GEORADIUSBYMEMBER.FIRST_KEY_INDEX, + IS_READ_ONLY: true, + transformArguments: transformGeoRadiusByMemberArguments.bind(undefined, 'GEORADIUSBYMEMBER_RO'), + transformReply: GEORADIUSBYMEMBER.transformReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_RO_WITH.spec.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_RO_WITH.spec.ts index 7904a76399..166088495e 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER_RO_WITH.spec.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_RO_WITH.spec.ts @@ -1,31 +1,44 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { RedisCommandArguments } from '.'; -import { GeoReplyWith } from './generic-transformers'; -import { transformArguments } from './GEORADIUSBYMEMBER_RO_WITH'; +import GEORADIUSBYMEMBER_RO_WITH from './GEORADIUSBYMEMBER_RO_WITH'; +import { CommandArguments } from '../RESP/types'; +import { GEO_REPLY_WITH } from './GEOSEARCH_WITH'; describe('GEORADIUSBYMEMBER_RO WITH', () => { - it('transformArguments', () => { - const expectedReply: RedisCommandArguments = ['GEORADIUSBYMEMBER_RO', 'key', 'member', '3', 'm', 'WITHDIST']; - expectedReply.preserve = ['WITHDIST']; + it('transformArguments', () => { + const expectedReply: CommandArguments = ['GEORADIUSBYMEMBER_RO', 'key', 'member', '3', 'm', 'WITHDIST']; + expectedReply.preserve = ['WITHDIST']; - assert.deepEqual( - transformArguments('key', 'member', 3 , 'm', [GeoReplyWith.DISTANCE]), - expectedReply - ); - }); + assert.deepEqual( + GEORADIUSBYMEMBER_RO_WITH.transformArguments('key', 'member', 3, 'm', [ + GEO_REPLY_WITH.DISTANCE + ]), + expectedReply + ); + }); - testUtils.testWithClient('client.geoRadiusByMemberRoWith', async client => { - assert.deepEqual( - await client.geoRadiusByMemberRoWith('key', 'member', 3 , 'm', [GeoReplyWith.DISTANCE]), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('geoRadiusByMemberRoWith', async client => { + const [, reply] = await Promise.all([ + client.geoAdd('key', { + member: 'member', + longitude: 1, + latitude: 2 + }), + client.geoRadiusByMemberRoWith('key', 'member', 1, 'm', [ + GEO_REPLY_WITH.HASH, + GEO_REPLY_WITH.DISTANCE, + GEO_REPLY_WITH.COORDINATES + ]) + ]); - testUtils.testWithCluster('cluster.geoRadiusByMemberRoWith', async cluster => { - assert.deepEqual( - await cluster.geoRadiusByMemberRoWith('key', 'member', 3 , 'm', [GeoReplyWith.DISTANCE]), - [] - ); - }, GLOBAL.CLUSTERS.OPEN); + assert.equal(reply.length, 1); + assert.equal(reply[0].member, 'member'); + assert.equal(typeof reply[0].distance, 'string'); + assert.equal(typeof reply[0].hash, 'number'); + assert.equal(typeof reply[0].coordinates?.longitude, 'string'); + assert.equal(typeof reply[0].coordinates?.latitude, 'string'); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_RO_WITH.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_RO_WITH.ts index 116bb9200f..5fb945a1f9 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER_RO_WITH.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_RO_WITH.ts @@ -1,30 +1,9 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoReplyWith, GeoSearchOptions, GeoUnits } from './generic-transformers'; -// import { transformArguments as geoRadiusTransformArguments } from './GEORADIUSBYMEMBER_RO'; +import { Command } from '../RESP/types'; +import GEORADIUSBYMEMBER_WITH, { transformGeoRadiusByMemberWithArguments } from './GEORADIUSBYMEMBER_WITH'; -// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEORADIUSBYMEMBER_RO'; - -// export function transformArguments( -// key: RedisCommandArgument, -// member: string, -// radius: number, -// unit: GeoUnits, -// replyWith: Array, -// options?: GeoSearchOptions -// ): RedisCommandArguments { -// const args: RedisCommandArguments = geoRadiusTransformArguments( -// key, -// member, -// radius, -// unit, -// options -// ); - -// args.push(...replyWith); - -// args.preserve = replyWith; - -// return args; -// } - -// export { transformGeoMembersWithReply as transformReply } from './generic-transformers'; +export default { + FIRST_KEY_INDEX: GEORADIUSBYMEMBER_WITH.FIRST_KEY_INDEX, + IS_READ_ONLY: true, + transformArguments: transformGeoRadiusByMemberWithArguments.bind(undefined, 'GEORADIUSBYMEMBER_RO'), + transformReply: GEORADIUSBYMEMBER_WITH.transformReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_STORE.spec.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_STORE.spec.ts new file mode 100644 index 0000000000..6eab34211a --- /dev/null +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_STORE.spec.ts @@ -0,0 +1,39 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import GEORADIUSBYMEMBER_STORE from './GEORADIUSBYMEMBER_STORE'; + +describe('GEORADIUSBYMEMBER STORE', () => { + describe('transformArguments', () => { + it('STORE', () => { + assert.deepEqual( + GEORADIUSBYMEMBER_STORE.transformArguments('key', 'member', 3, 'm', 'destination'), + ['GEORADIUSBYMEMBER', 'key', 'member', '3', 'm', 'STORE', 'destination'] + ); + }); + + it('STOREDIST', () => { + assert.deepEqual( + GEORADIUSBYMEMBER_STORE.transformArguments('key', 'member', 3, 'm', 'destination', { + STOREDIST: true + }), + ['GEORADIUSBYMEMBER', 'key', 'member', '3', 'm', 'STOREDIST', 'destination'] + ); + }); + }); + + testUtils.testAll('geoRadiusByMemberStore', async client => { + const [, reply] = await Promise.all([ + client.geoAdd('{tag}source', { + longitude: 1, + latitude: 2, + member: 'member' + }), + client.geoRadiusByMemberStore('{tag}source', 'member', 3, 'm', '{tag}destination') + ]); + + assert.equal(reply, 1); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_STORE.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_STORE.ts new file mode 100644 index 0000000000..9041996311 --- /dev/null +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_STORE.ts @@ -0,0 +1,31 @@ +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import GEORADIUSBYMEMBER, { transformGeoRadiusByMemberArguments } from './GEORADIUSBYMEMBER'; +import { GeoSearchOptions, GeoUnits } from './GEOSEARCH'; + +export interface GeoRadiusStoreOptions extends GeoSearchOptions { + STOREDIST?: boolean; +} + +export default { + FIRST_KEY_INDEX: GEORADIUSBYMEMBER.FIRST_KEY_INDEX, + IS_READ_ONLY: GEORADIUSBYMEMBER.IS_READ_ONLY, + transformArguments( + key: RedisArgument, + from: RedisArgument, + radius: number, + unit: GeoUnits, + destination: RedisArgument, + options?: GeoRadiusStoreOptions + ) { + const args = transformGeoRadiusByMemberArguments('GEORADIUSBYMEMBER', key, from, radius, unit, options); + + if (options?.STOREDIST) { + args.push('STOREDIST', destination); + } else { + args.push('STORE', destination); + } + + return args; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.spec.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.spec.ts index 24bffd9e89..3160c65cfb 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.spec.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.spec.ts @@ -1,31 +1,44 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { RedisCommandArguments } from '.'; -import { GeoReplyWith } from './generic-transformers'; -import { transformArguments } from './GEORADIUSBYMEMBER_WITH'; +import GEORADIUSBYMEMBER_WITH from './GEORADIUSBYMEMBER_WITH'; +import { CommandArguments } from '../RESP/types'; +import { GEO_REPLY_WITH } from './GEOSEARCH_WITH'; describe('GEORADIUSBYMEMBER WITH', () => { - it('transformArguments', () => { - const expectedReply: RedisCommandArguments = ['GEORADIUSBYMEMBER', 'key', 'member', '3', 'm', 'WITHDIST']; - expectedReply.preserve = ['WITHDIST']; + it('transformArguments', () => { + const expectedReply: CommandArguments = ['GEORADIUSBYMEMBER', 'key', 'member', '3', 'm', 'WITHDIST']; + expectedReply.preserve = ['WITHDIST']; - assert.deepEqual( - transformArguments('key', 'member', 3 , 'm', [GeoReplyWith.DISTANCE]), - expectedReply - ); - }); + assert.deepEqual( + GEORADIUSBYMEMBER_WITH.transformArguments('key', 'member', 3, 'm', [ + GEO_REPLY_WITH.DISTANCE + ]), + expectedReply + ); + }); - testUtils.testWithClient('client.geoRadiusByMemberWith', async client => { - assert.deepEqual( - await client.geoRadiusByMemberWith('key', 'member', 3 , 'm', [GeoReplyWith.DISTANCE]), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('geoRadiusByMemberWith', async client => { + const [, reply] = await Promise.all([ + client.geoAdd('key', { + member: 'member', + longitude: 1, + latitude: 2 + }), + client.geoRadiusByMemberWith('key', 'member', 1, 'm', [ + GEO_REPLY_WITH.HASH, + GEO_REPLY_WITH.DISTANCE, + GEO_REPLY_WITH.COORDINATES + ]) + ]); - testUtils.testWithCluster('cluster.geoRadiusByMemberWith', async cluster => { - assert.deepEqual( - await cluster.geoRadiusByMemberWith('key', 'member', 3 , 'm', [GeoReplyWith.DISTANCE]), - [] - ); - }, GLOBAL.CLUSTERS.OPEN); + assert.equal(reply.length, 1); + assert.equal(reply[0].member, 'member'); + assert.equal(typeof reply[0].distance, 'string'); + assert.equal(typeof reply[0].hash, 'number'); + assert.equal(typeof reply[0].coordinates!.longitude, 'string'); + assert.equal(typeof reply[0].coordinates!.latitude, 'string'); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.ts b/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.ts index 09bb5bbbb4..31480430b5 100644 --- a/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.ts +++ b/packages/client/lib/commands/GEORADIUSBYMEMBER_WITH.ts @@ -1,30 +1,36 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoReplyWith, GeoSearchOptions, GeoUnits } from './generic-transformers'; -// import { transformArguments as transformGeoRadiusArguments } from './GEORADIUSBYMEMBER'; +import { RedisArgument, CommandArguments, ArrayReply, BlobStringReply, Command } from '../RESP/types'; +import GEORADIUSBYMEMBER from './GEORADIUSBYMEMBER'; +import { GeoSearchOptions, GeoUnits, pushGeoSearchOptions } from './GEOSEARCH'; +import GEOSEARCH_WITH, { GeoReplyWith } from './GEOSEARCH_WITH'; -// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEORADIUSBYMEMBER'; +export function transformGeoRadiusByMemberWithArguments( + command: RedisArgument, + key: RedisArgument, + from: RedisArgument, + radius: number, + unit: GeoUnits, + replyWith: Array, + options?: GeoSearchOptions +) { + const args: CommandArguments = [ + command, + key, + from, + radius.toString(), + unit + ]; -// export function transformArguments( -// key: RedisCommandArgument, -// member: string, -// radius: number, -// unit: GeoUnits, -// replyWith: Array, -// options?: GeoSearchOptions -// ): RedisCommandArguments { -// const args: RedisCommandArguments = transformGeoRadiusArguments( -// key, -// member, -// radius, -// unit, -// options -// ); + pushGeoSearchOptions(args, options); -// args.push(...replyWith); + args.push(...replyWith); + args.preserve = replyWith; -// args.preserve = replyWith; + return args; +} -// return args; -// } - -// export { transformGeoMembersWithReply as transformReply } from './generic-transformers'; +export default { + FIRST_KEY_INDEX: GEORADIUSBYMEMBER.FIRST_KEY_INDEX, + IS_READ_ONLY: GEORADIUSBYMEMBER.IS_READ_ONLY, + transformArguments: transformGeoRadiusByMemberWithArguments.bind(undefined, 'GEORADIUSBYMEMBER'), + transformReply: GEOSEARCH_WITH.transformReply +} as const satisfies Command; \ No newline at end of file diff --git a/packages/client/lib/commands/GEORADIUSSTORE.spec.ts b/packages/client/lib/commands/GEORADIUSSTORE.spec.ts deleted file mode 100644 index 4c6372732e..0000000000 --- a/packages/client/lib/commands/GEORADIUSSTORE.spec.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { strict as assert } from 'assert'; -import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './GEORADIUSSTORE'; - -describe('GEORADIUSSTORE', () => { - describe('transformArguments', () => { - it('STORE', () => { - assert.deepEqual( - transformArguments('key', {longitude: 1, latitude: 2}, 3 , 'm', 'dest', { - SORT: 'ASC', - COUNT: { - value: 1, - ANY: true - } - }), - ['GEORADIUS', 'key', '1', '2', '3', 'm', 'ASC', 'COUNT', '1', 'ANY', 'STORE', 'dest'] - ); - }); - - it('STOREDIST', () => { - assert.deepEqual( - transformArguments('key', {longitude: 1, latitude: 2}, 3 , 'm', 'dest', { STOREDIST: true }), - ['GEORADIUS', 'key', '1', '2', '3', 'm', 'STOREDIST', 'dest'] - ); - }); - }); - - testUtils.testWithClient('client.geoRadiusStore', async client => { - await client.geoAdd('source', { - longitude: 1, - latitude: 1, - member: 'member' - }); - - assert.equal( - await client.geoRadiusStore('source', {longitude: 1, latitude: 1}, 3 , 'm', 'dest'), - 1 - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.geoRadiusStore', async cluster => { - await cluster.geoAdd('{tag}source', { - longitude: 1, - latitude: 1, - member: 'member' - }); - - assert.equal( - await cluster.geoRadiusStore('{tag}source', {longitude: 1, latitude: 1}, 3 , 'm', '{tag}destination'), - 1 - ); - }, GLOBAL.CLUSTERS.OPEN); -}); diff --git a/packages/client/lib/commands/GEORADIUSSTORE.ts b/packages/client/lib/commands/GEORADIUSSTORE.ts deleted file mode 100644 index 0344525964..0000000000 --- a/packages/client/lib/commands/GEORADIUSSTORE.ts +++ /dev/null @@ -1,25 +0,0 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoCoordinates, GeoUnits, GeoRadiusStoreOptions, pushGeoRadiusStoreArguments } from './generic-transformers'; - -// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEORADIUS'; - -// export function transformArguments( -// key: RedisCommandArgument, -// coordinates: GeoCoordinates, -// radius: number, -// unit: GeoUnits, -// destination: RedisCommandArgument, -// options?: GeoRadiusStoreOptions, -// ): RedisCommandArguments { -// return pushGeoRadiusStoreArguments( -// ['GEORADIUS'], -// key, -// coordinates, -// radius, -// unit, -// destination, -// options -// ); -// } - -// export declare function transformReply(): number; diff --git a/packages/client/lib/commands/GEORADIUS_RO.spec.ts b/packages/client/lib/commands/GEORADIUS_RO.spec.ts index b3cdca18d3..6f6aeb80e6 100644 --- a/packages/client/lib/commands/GEORADIUS_RO.spec.ts +++ b/packages/client/lib/commands/GEORADIUS_RO.spec.ts @@ -1,35 +1,28 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GEORADIUS_RO'; +import GEORADIUS_RO from './GEORADIUS_RO'; describe('GEORADIUS_RO', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', { - longitude: 1, - latitude: 2 - }, 3 , 'm'), - ['GEORADIUS_RO', 'key', '1', '2', '3', 'm'] - ); - }); + it('transformArguments', () => { + assert.deepEqual( + GEORADIUS_RO.transformArguments('key', { + longitude: 1, + latitude: 2 + }, 3, 'm'), + ['GEORADIUS_RO', 'key', '1', '2', '3', 'm'] + ); + }); - testUtils.testWithClient('client.geoRadiusRo', async client => { - assert.deepEqual( - await client.geoRadiusRo('key', { - longitude: 1, - latitude: 2 - }, 3 , 'm'), - [] - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.geoRadiusRo', async cluster => { - assert.deepEqual( - await cluster.geoRadiusRo('key', { - longitude: 1, - latitude: 2 - }, 3 , 'm'), - [] - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('geoRadiusRo', async client => { + assert.deepEqual( + await client.geoRadiusRo('key', { + longitude: 1, + latitude: 2 + }, 3, 'm'), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEORADIUS_RO.ts b/packages/client/lib/commands/GEORADIUS_RO.ts index d9c01007ed..be8bb4b530 100644 --- a/packages/client/lib/commands/GEORADIUS_RO.ts +++ b/packages/client/lib/commands/GEORADIUS_RO.ts @@ -1,25 +1,9 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoSearchOptions, GeoCoordinates, pushGeoRadiusArguments, GeoUnits } from './generic-transformers'; +import { Command } from '../RESP/types'; +import GEORADIUS, { transformGeoRadiusArguments } from './GEORADIUS'; -// export const FIRST_KEY_INDEX = 1; - -// export const IS_READ_ONLY = true; - -// export function transformArguments( -// key: RedisCommandArgument, -// coordinates: GeoCoordinates, -// radius: number, -// unit: GeoUnits, -// options?: GeoSearchOptions -// ): RedisCommandArguments { -// return pushGeoRadiusArguments( -// ['GEORADIUS_RO'], -// key, -// coordinates, -// radius, -// unit, -// options -// ); -// } - -// export declare function transformReply(): Array; +export default { + FIRST_KEY_INDEX: GEORADIUS.FIRST_KEY_INDEX, + IS_READ_ONLY: true, + transformArguments: transformGeoRadiusArguments.bind(undefined, 'GEORADIUS_RO'), + transformReply: GEORADIUS.transformReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GEORADIUS_RO_WITH.spec.ts b/packages/client/lib/commands/GEORADIUS_RO_WITH.spec.ts index 21b00ff90b..639b191702 100644 --- a/packages/client/lib/commands/GEORADIUS_RO_WITH.spec.ts +++ b/packages/client/lib/commands/GEORADIUS_RO_WITH.spec.ts @@ -1,40 +1,48 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { RedisCommandArguments } from '.'; -import { GeoReplyWith } from './generic-transformers'; -import { transformArguments } from './GEORADIUS_RO_WITH'; +import GEORADIUS_RO_WITH from './GEORADIUS_RO_WITH'; +import { GEO_REPLY_WITH } from './GEOSEARCH_WITH'; +import { CommandArguments } from '../RESP/types'; describe('GEORADIUS_RO WITH', () => { - it('transformArguments', () => { - const expectedReply: RedisCommandArguments = ['GEORADIUS_RO', 'key', '1', '2', '3', 'm', 'WITHDIST']; - expectedReply.preserve = ['WITHDIST']; + it('transformArguments', () => { + const expectedReply: CommandArguments = ['GEORADIUS_RO', 'key', '1', '2', '3', 'm', 'WITHDIST']; + expectedReply.preserve = ['WITHDIST']; - assert.deepEqual( - transformArguments('key', { - longitude: 1, - latitude: 2 - }, 3 , 'm', [GeoReplyWith.DISTANCE]), - expectedReply - ); - }); + assert.deepEqual( + GEORADIUS_RO_WITH.transformArguments('key', { + longitude: 1, + latitude: 2 + }, 3, 'm', [GEO_REPLY_WITH.DISTANCE]), + expectedReply + ); + }); - testUtils.testWithClient('client.geoRadiusRoWith', async client => { - assert.deepEqual( - await client.geoRadiusRoWith('key', { - longitude: 1, - latitude: 2 - }, 3 , 'm', [GeoReplyWith.DISTANCE]), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('geoRadiusRoWith', async client => { + const [, reply] = await Promise.all([ + client.geoAdd('key', { + member: 'member', + longitude: 1, + latitude: 2 + }), + client.geoRadiusRoWith('key', { + longitude: 1, + latitude: 2 + }, 1, 'm', [ + GEO_REPLY_WITH.HASH, + GEO_REPLY_WITH.DISTANCE, + GEO_REPLY_WITH.COORDINATES + ]) + ]); - testUtils.testWithCluster('cluster.geoRadiusReadOnlyWith', async cluster => { - assert.deepEqual( - await cluster.geoRadiusRoWith('key', { - longitude: 1, - latitude: 2 - }, 3 , 'm', [GeoReplyWith.DISTANCE]), - [] - ); - }, GLOBAL.CLUSTERS.OPEN); + assert.equal(reply.length, 1); + assert.equal(reply[0].member, 'member'); + assert.equal(typeof reply[0].distance, 'string'); + assert.equal(typeof reply[0].hash, 'number'); + assert.equal(typeof reply[0].coordinates!.longitude, 'string'); + assert.equal(typeof reply[0].coordinates!.latitude, 'string'); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEORADIUS_RO_WITH.ts b/packages/client/lib/commands/GEORADIUS_RO_WITH.ts index 156f5cfa9f..37cf594ce9 100644 --- a/packages/client/lib/commands/GEORADIUS_RO_WITH.ts +++ b/packages/client/lib/commands/GEORADIUS_RO_WITH.ts @@ -1,30 +1,9 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoReplyWith, GeoSearchOptions, GeoCoordinates, GeoUnits } from './generic-transformers'; -// import { transformArguments as transformGeoRadiusRoArguments } from './GEORADIUS_RO'; +import { Command } from '../RESP/types'; +import GEORADIUS_WITH, { transformGeoRadiusWithArguments } from './GEORADIUS_WITH'; -// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEORADIUS_RO'; - -// export function transformArguments( -// key: RedisCommandArgument, -// coordinates: GeoCoordinates, -// radius: number, -// unit: GeoUnits, -// replyWith: Array, -// options?: GeoSearchOptions -// ): RedisCommandArguments { -// const args: RedisCommandArguments = transformGeoRadiusRoArguments( -// key, -// coordinates, -// radius, -// unit, -// options -// ); - -// args.push(...replyWith); - -// args.preserve = replyWith; - -// return args; -// } - -// export { transformGeoMembersWithReply as transformReply } from './generic-transformers'; +export default { + FIRST_KEY_INDEX: GEORADIUS_WITH.FIRST_KEY_INDEX, + IS_READ_ONLY: true, + transformArguments: transformGeoRadiusWithArguments.bind(undefined, 'GEORADIUS_RO'), + transformReply: GEORADIUS_WITH.transformReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GEORADIUS_STORE.spec.ts b/packages/client/lib/commands/GEORADIUS_STORE.spec.ts new file mode 100644 index 0000000000..3fff9bc43d --- /dev/null +++ b/packages/client/lib/commands/GEORADIUS_STORE.spec.ts @@ -0,0 +1,48 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import GEORADIUS_STORE from './GEORADIUS_STORE'; + +describe('GEORADIUS STORE', () => { + describe('transformArguments', () => { + it('STORE', () => { + assert.deepEqual( + GEORADIUS_STORE.transformArguments('key', { + longitude: 1, + latitude: 2 + }, 3, 'm', 'destination'), + ['GEORADIUS', 'key', '1', '2', '3', 'm', 'STORE', 'destination'] + ); + }); + + it('STOREDIST', () => { + assert.deepEqual( + GEORADIUS_STORE.transformArguments('key', { + longitude: 1, + latitude: 2 + }, 3, 'm', 'destination', { + STOREDIST: true + }), + ['GEORADIUS', 'key', '1', '2', '3', 'm', 'STOREDIST', 'destination'] + ); + }); + }); + + testUtils.testAll('geoRadiusStore', async client => { + const [, reply] = await Promise.all([ + client.geoAdd('{tag}source', { + longitude: 1, + latitude: 2, + member: 'member' + }), + client.geoRadiusStore('{tag}source', { + longitude: 1, + latitude: 2 + }, 1, 'm', '{tag}destination') + ]); + + assert.equal(reply, 1); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/GEORADIUS_STORE.ts b/packages/client/lib/commands/GEORADIUS_STORE.ts new file mode 100644 index 0000000000..3a553ebf8b --- /dev/null +++ b/packages/client/lib/commands/GEORADIUS_STORE.ts @@ -0,0 +1,31 @@ +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import GEORADIUS, { transformGeoRadiusArguments } from './GEORADIUS'; +import { GeoCoordinates, GeoSearchOptions, GeoUnits } from './GEOSEARCH'; + +export interface GeoRadiusStoreOptions extends GeoSearchOptions { + STOREDIST?: boolean; +} + +export default { + FIRST_KEY_INDEX: GEORADIUS.FIRST_KEY_INDEX, + IS_READ_ONLY: GEORADIUS.IS_READ_ONLY, + transformArguments( + key: RedisArgument, + from: GeoCoordinates, + radius: number, + unit: GeoUnits, + destination: RedisArgument, + options?: GeoRadiusStoreOptions + ) { + const args = transformGeoRadiusArguments('GEORADIUS', key, from, radius, unit, options); + + if (options?.STOREDIST) { + args.push('STOREDIST', destination); + } else { + args.push('STORE', destination); + } + + return args; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GEORADIUS_WITH.spec.ts b/packages/client/lib/commands/GEORADIUS_WITH.spec.ts index 44366198be..2219aa8490 100644 --- a/packages/client/lib/commands/GEORADIUS_WITH.spec.ts +++ b/packages/client/lib/commands/GEORADIUS_WITH.spec.ts @@ -1,40 +1,48 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { RedisCommandArguments } from '.'; -import { GeoReplyWith } from './generic-transformers'; -import { transformArguments } from './GEORADIUS_WITH'; +import GEORADIUS_WITH from './GEORADIUS_WITH'; +import { GEO_REPLY_WITH } from './GEOSEARCH_WITH'; +import { CommandArguments } from '../RESP/types'; describe('GEORADIUS WITH', () => { - it('transformArguments', () => { - const expectedReply: RedisCommandArguments = ['GEORADIUS', 'key', '1', '2', '3', 'm', 'WITHDIST']; - expectedReply.preserve = ['WITHDIST']; + it('transformArguments', () => { + const expectedReply: CommandArguments = ['GEORADIUS', 'key', '1', '2', '3', 'm', 'WITHDIST']; + expectedReply.preserve = ['WITHDIST']; - assert.deepEqual( - transformArguments('key', { - longitude: 1, - latitude: 2 - }, 3 , 'm', [GeoReplyWith.DISTANCE]), - expectedReply - ); - }); + assert.deepEqual( + GEORADIUS_WITH.transformArguments('key', { + longitude: 1, + latitude: 2 + }, 3, 'm', [GEO_REPLY_WITH.DISTANCE]), + expectedReply + ); + }); - testUtils.testWithClient('client.geoRadiusWith', async client => { - assert.deepEqual( - await client.geoRadiusWith('key', { - longitude: 1, - latitude: 2 - }, 3 , 'm', [GeoReplyWith.DISTANCE]), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('geoRadiusWith', async client => { + const [, reply] = await Promise.all([ + client.geoAdd('key', { + member: 'member', + longitude: 1, + latitude: 2 + }), + client.geoRadiusWith('key', { + longitude: 1, + latitude: 2 + }, 1, 'm', [ + GEO_REPLY_WITH.HASH, + GEO_REPLY_WITH.DISTANCE, + GEO_REPLY_WITH.COORDINATES + ]) + ]); - testUtils.testWithCluster('cluster.geoRadiusWith', async cluster => { - assert.deepEqual( - await cluster.geoRadiusWith('key', { - longitude: 1, - latitude: 2 - }, 3 , 'm', [GeoReplyWith.DISTANCE]), - [] - ); - }, GLOBAL.CLUSTERS.OPEN); + assert.equal(reply.length, 1); + assert.equal(reply[0].member, 'member'); + assert.equal(typeof reply[0].distance, 'string'); + assert.equal(typeof reply[0].hash, 'number'); + assert.equal(typeof reply[0].coordinates?.longitude, 'string'); + assert.equal(typeof reply[0].coordinates?.latitude, 'string'); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEORADIUS_WITH.ts b/packages/client/lib/commands/GEORADIUS_WITH.ts index d41132ce2d..d72d8d4932 100644 --- a/packages/client/lib/commands/GEORADIUS_WITH.ts +++ b/packages/client/lib/commands/GEORADIUS_WITH.ts @@ -1,30 +1,33 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoReplyWith, GeoSearchOptions, GeoCoordinates, GeoUnits } from './generic-transformers'; -// import { transformArguments as transformGeoRadiusArguments } from './GEORADIUS'; +import { CommandArguments, Command, RedisArgument } from '../RESP/types'; +import GEORADIUS, { transformGeoRadiusArguments } from './GEORADIUS'; +import { GeoCoordinates, GeoSearchOptions, GeoUnits } from './GEOSEARCH'; +import GEOSEARCH_WITH, { GeoReplyWith } from './GEOSEARCH_WITH'; -// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEORADIUS'; +export function transformGeoRadiusWithArguments( + command: RedisArgument, + key: RedisArgument, + from: GeoCoordinates, + radius: number, + unit: GeoUnits, + replyWith: Array, + options?: GeoSearchOptions +) { + const args: CommandArguments = transformGeoRadiusArguments( + command, + key, + from, + radius, + unit, + options + ); + args.push(...replyWith); + args.preserve = replyWith; + return args; +} -// export function transformArguments( -// key: RedisCommandArgument, -// coordinates: GeoCoordinates, -// radius: number, -// unit: GeoUnits, -// replyWith: Array, -// options?: GeoSearchOptions -// ): RedisCommandArguments { -// const args: RedisCommandArguments = transformGeoRadiusArguments( -// key, -// coordinates, -// radius, -// unit, -// options -// ); - -// args.push(...replyWith); - -// args.preserve = replyWith; - -// return args; -// } - -// export { transformGeoMembersWithReply as transformReply } from './generic-transformers'; +export default { + FIRST_KEY_INDEX: GEORADIUS.FIRST_KEY_INDEX, + IS_READ_ONLY: GEORADIUS.IS_READ_ONLY, + transformArguments: transformGeoRadiusWithArguments.bind(undefined, 'GEORADIUS'), + transformReply: GEOSEARCH_WITH.transformReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GEOSEARCH.spec.ts b/packages/client/lib/commands/GEOSEARCH.spec.ts index ec0d4bcc4f..7f06d646b1 100644 --- a/packages/client/lib/commands/GEOSEARCH.spec.ts +++ b/packages/client/lib/commands/GEOSEARCH.spec.ts @@ -1,37 +1,87 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './GEOSEARCH'; +import GEOSEARCH from './GEOSEARCH'; describe('GEOSEARCH', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - it('transformArguments', () => { - assert.deepEqual( - transformArguments('key', 'member', { - radius: 1, - unit: 'm' - }), - ['GEOSEARCH', 'key', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm'] - ); + describe('transformArguments', () => { + it('FROMMEMBER, BYRADIUS, without options', () => { + assert.deepEqual( + GEOSEARCH.transformArguments('key', 'member', { + radius: 1, + unit: 'm' + }), + ['GEOSEARCH', 'key', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm'] + ); }); - testUtils.testWithClient('client.geoSearch', async client => { - assert.deepEqual( - await client.geoSearch('key', 'member', { - radius: 1, - unit: 'm' - }), - [] - ); - }, GLOBAL.SERVERS.OPEN); + it('FROMLONLAT, BYBOX, without options', () => { + assert.deepEqual( + GEOSEARCH.transformArguments('key', { + longitude: 1, + latitude: 2 + }, { + width: 1, + height: 2, + unit: 'm' + }), + ['GEOSEARCH', 'key', 'FROMLONLAT', '1', '2', 'BYBOX', '1', '2', 'm'] + ); + }); - testUtils.testWithCluster('cluster.geoSearch', async cluster => { + it('with SORT', () => { + assert.deepEqual( + GEOSEARCH.transformArguments('key', 'member', { + radius: 1, + unit: 'm' + }, { + SORT: 'ASC' + }), + ['GEOSEARCH', 'key', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm', 'ASC'] + ); + }); + + describe('with COUNT', () => { + it('number', () => { assert.deepEqual( - await cluster.geoSearch('key', 'member', { - radius: 1, - unit: 'm' - }), - [] + GEOSEARCH.transformArguments('key', 'member', { + radius: 1, + unit: 'm' + }, { + COUNT: 1 + }), + ['GEOSEARCH', 'key', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm', 'COUNT', '1'] ); - }, GLOBAL.CLUSTERS.OPEN); + }); + + it('with ANY', () => { + assert.deepEqual( + GEOSEARCH.transformArguments('key', 'member', { + radius: 1, + unit: 'm' + }, { + COUNT: { + value: 1, + ANY: true + } + }), + ['GEOSEARCH', 'key', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm', 'COUNT', '1', 'ANY'] + ); + }); + }); + }); + + testUtils.testAll('geoSearch', async client => { + assert.deepEqual( + await client.geoSearch('key', 'member', { + radius: 1, + unit: 'm' + }), + [] + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEOSEARCH.ts b/packages/client/lib/commands/GEOSEARCH.ts index 31a65ee8dc..4e81f361dd 100644 --- a/packages/client/lib/commands/GEOSEARCH.ts +++ b/packages/client/lib/commands/GEOSEARCH.ts @@ -1,17 +1,98 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoSearchFrom, GeoSearchBy, GeoSearchOptions, pushGeoSearchArguments } from './generic-transformers'; +import { RedisArgument, CommandArguments, ArrayReply, BlobStringReply, Command } from '../RESP/types'; -// export const FIRST_KEY_INDEX = 1; +export type GeoUnits = 'm' | 'km' | 'mi' | 'ft'; -// export const IS_READ_ONLY = true; +export interface GeoCoordinates { + longitude: RedisArgument | number; + latitude: RedisArgument | number; +} -// export function transformArguments( -// key: RedisCommandArgument, -// from: GeoSearchFrom, -// by: GeoSearchBy, -// options?: GeoSearchOptions -// ): RedisCommandArguments { -// return pushGeoSearchArguments(['GEOSEARCH'], key, from, by, options); -// } +export type GeoSearchFrom = RedisArgument | GeoCoordinates; -// export declare function transformReply(): Array; +export interface GeoSearchByRadius { + radius: number; + unit: GeoUnits; +} + +export interface GeoSearchByBox { + width: number; + height: number; + unit: GeoUnits; +} + +export type GeoSearchBy = GeoSearchByRadius | GeoSearchByBox; + +export function pushGeoSearchArguments( + args: CommandArguments, + key: RedisArgument, + from: GeoSearchFrom, + by: GeoSearchBy, + options?: GeoSearchOptions +) { + args.push(key); + + if (typeof from === 'string' || from instanceof Buffer) { + args.push('FROMMEMBER', from); + } else { + args.push('FROMLONLAT', from.longitude.toString(), from.latitude.toString()); + } + + if ('radius' in by) { + args.push('BYRADIUS', by.radius.toString(), by.unit); + } else { + args.push('BYBOX', by.width.toString(), by.height.toString(), by.unit); + } + + if (options?.SORT) { + args.push(options.SORT); + } + + pushGeoSearchOptions(args, options); + + return args; +} + +export type GeoCountArgument = number | { + value: number; + ANY?: boolean; +}; + +export interface GeoSearchOptions { + SORT?: 'ASC' | 'DESC'; + COUNT?: GeoCountArgument; +} + +export function pushGeoSearchOptions( + args: CommandArguments, + options?: GeoSearchOptions +) { + if (options?.SORT) { + args.push(options.SORT); + } + + if (options?.COUNT) { + if (typeof options.COUNT === 'number') { + args.push('COUNT', options.COUNT.toString()); + } else { + args.push('COUNT', options.COUNT.value.toString()); + + if (options.COUNT.ANY) { + args.push('ANY'); + } + } + } +} + +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments( + key: RedisArgument, + from: GeoSearchFrom, + by: GeoSearchBy, + options?: GeoSearchOptions + ) { + return pushGeoSearchArguments(['GEOSEARCH'], key, from, by, options); + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GEOSEARCHSTORE.spec.ts b/packages/client/lib/commands/GEOSEARCHSTORE.spec.ts index eb32fa134e..6b270af8dc 100644 --- a/packages/client/lib/commands/GEOSEARCHSTORE.spec.ts +++ b/packages/client/lib/commands/GEOSEARCHSTORE.spec.ts @@ -1,81 +1,44 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments, transformReply } from './GEOSEARCHSTORE'; +import GEOSEARCHSTORE from './GEOSEARCHSTORE'; describe('GEOSEARCHSTORE', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - describe('transformArguments', () => { - it('simple', () => { - assert.deepEqual( - transformArguments('destination', 'source', 'member', { - radius: 1, - unit: 'm' - }, { - SORT: 'ASC', - COUNT: { - value: 1, - ANY: true - } - }), - ['GEOSEARCHSTORE', 'destination', 'source', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm', 'ASC', 'COUNT', '1', 'ANY'] - ); - }); - - it('with STOREDIST', () => { - assert.deepEqual( - transformArguments('destination', 'source', 'member', { - radius: 1, - unit: 'm' - }, { - SORT: 'ASC', - COUNT: { - value: 1, - ANY: true - }, - STOREDIST: true - }), - ['GEOSEARCHSTORE', 'destination', 'source', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm', 'ASC', 'COUNT', '1', 'ANY', 'STOREDIST'] - ); - }); + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + GEOSEARCHSTORE.transformArguments('source', 'destination', 'member', { + radius: 1, + unit: 'm' + }), + ['GEOSEARCHSTORE', 'source', 'destination', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm'] + ); }); - it('transformReply with empty array (https://github.com/redis/redis/issues/9261)', () => { - assert.throws( - () => (transformReply as any)([]), - TypeError - ); + it('with STOREDIST', () => { + assert.deepEqual( + GEOSEARCHSTORE.transformArguments('destination', 'source', 'member', { + radius: 1, + unit: 'm' + }, { + STOREDIST: true + }), + ['GEOSEARCHSTORE', 'destination', 'source', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm', 'STOREDIST'] + ); }); + }); - testUtils.testWithClient('client.geoSearchStore', async client => { - await client.geoAdd('source', { - longitude: 1, - latitude: 1, - member: 'member' - }); - - assert.equal( - await client.geoSearchStore('destination', 'source', 'member', { - radius: 1, - unit: 'm' - }), - 1 - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithCluster('cluster.geoSearchStore', async cluster => { - await cluster.geoAdd('{tag}source', { - longitude: 1, - latitude: 1, - member: 'member' - }); - - assert.equal( - await cluster.geoSearchStore('{tag}destination', '{tag}source', 'member', { - radius: 1, - unit: 'm' - }), - 1 - ); - }, GLOBAL.CLUSTERS.OPEN); + testUtils.testAll('geoSearchStore', async client => { + assert.equal( + await client.geoSearchStore('{tag}destination', '{tag}source', 'member', { + radius: 1, + unit: 'm' + }), + 0 + ); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEOSEARCHSTORE.ts b/packages/client/lib/commands/GEOSEARCHSTORE.ts index a8cdb82d71..1563556021 100644 --- a/packages/client/lib/commands/GEOSEARCHSTORE.ts +++ b/packages/client/lib/commands/GEOSEARCHSTORE.ts @@ -1,38 +1,27 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoSearchFrom, GeoSearchBy, GeoSearchOptions, pushGeoSearchArguments } from './generic-transformers'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; +import { GeoSearchFrom, GeoSearchBy, GeoSearchOptions, pushGeoSearchArguments } from './GEOSEARCH'; -// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEOSEARCH'; +export interface GeoSearchStoreOptions extends GeoSearchOptions { + STOREDIST?: boolean; +} -// interface GeoSearchStoreOptions extends GeoSearchOptions { -// STOREDIST?: true; -// } +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: false, + transformArguments( + destination: RedisArgument, + source: RedisArgument, + from: GeoSearchFrom, + by: GeoSearchBy, + options?: GeoSearchStoreOptions + ) { + const args = pushGeoSearchArguments(['GEOSEARCHSTORE', destination], source, from, by, options); -// export function transformArguments( -// destination: RedisCommandArgument, -// source: RedisCommandArgument, -// from: GeoSearchFrom, -// by: GeoSearchBy, -// options?: GeoSearchStoreOptions -// ): RedisCommandArguments { -// const args = pushGeoSearchArguments( -// ['GEOSEARCHSTORE', destination], -// source, -// from, -// by, -// options -// ); + if (options?.STOREDIST) { + args.push('STOREDIST'); + } -// if (options?.STOREDIST) { -// args.push('STOREDIST'); -// } - -// return args; -// } - -// export function transformReply(reply: number): number { -// if (typeof reply !== 'number') { -// throw new TypeError(`https://github.com/redis/redis/issues/9261`); -// } - -// return reply; -// } + return args; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/GEOSEARCH_WITH.spec.ts b/packages/client/lib/commands/GEOSEARCH_WITH.spec.ts index c1f5213775..a01f47d287 100644 --- a/packages/client/lib/commands/GEOSEARCH_WITH.spec.ts +++ b/packages/client/lib/commands/GEOSEARCH_WITH.spec.ts @@ -1,42 +1,49 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { RedisCommandArguments } from '.'; -import { GeoReplyWith } from './generic-transformers'; -import { transformArguments } from './GEOSEARCH_WITH'; +import GEOSEARCH_WITH, { GEO_REPLY_WITH } from './GEOSEARCH_WITH'; +import { CommandArguments } from '../RESP/types'; describe('GEOSEARCH WITH', () => { - testUtils.isVersionGreaterThanHook([6, 2]); + testUtils.isVersionGreaterThanHook([6, 2]); - it('transformArguments', () => { - const expectedReply: RedisCommandArguments = ['GEOSEARCH', 'key', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm', 'WITHDIST']; - expectedReply.preserve = ['WITHDIST']; + it('transformArguments', () => { + const expectedReply: CommandArguments = ['GEOSEARCH', 'key', 'FROMMEMBER', 'member', 'BYRADIUS', '1', 'm', 'WITHDIST']; + expectedReply.preserve = ['WITHDIST']; - assert.deepEqual( - transformArguments('key', 'member', { - radius: 1, - unit: 'm' - }, [GeoReplyWith.DISTANCE]), - expectedReply - ); - }); + assert.deepEqual( + GEOSEARCH_WITH.transformArguments('key', 'member', { + radius: 1, + unit: 'm' + }, [GEO_REPLY_WITH.DISTANCE]), + expectedReply + ); + }); - testUtils.testWithClient('client.geoSearchWith', async client => { - assert.deepEqual( - await client.geoSearchWith('key', 'member', { - radius: 1, - unit: 'm' - }, [GeoReplyWith.DISTANCE]), - [] - ); - }, GLOBAL.SERVERS.OPEN); + testUtils.testAll('.geoSearchWith', async client => { + const [ , reply ] = await Promise.all([ + client.geoAdd('key', { + member: 'member', + longitude: 1, + latitude: 2 + }), + client.geoSearchWith('key', 'member', { + radius: 1, + unit: 'm' + }, [ + GEO_REPLY_WITH.HASH, + GEO_REPLY_WITH.DISTANCE, + GEO_REPLY_WITH.COORDINATES + ]) + ]); - testUtils.testWithCluster('cluster.geoSearchWith', async cluster => { - assert.deepEqual( - await cluster.geoSearchWith('key', 'member', { - radius: 1, - unit: 'm' - }, [GeoReplyWith.DISTANCE]), - [] - ); - }, GLOBAL.CLUSTERS.OPEN); + assert.equal(reply.length, 1); + assert.equal(reply[0].member, 'member'); + assert.equal(typeof reply[0].distance, 'string'); + assert.equal(typeof reply[0].hash, 'number'); + assert.equal(typeof reply[0].coordinates!.longitude, 'string'); + assert.equal(typeof reply[0].coordinates!.latitude, 'string'); + }, { + client: GLOBAL.SERVERS.OPEN, + cluster: GLOBAL.CLUSTERS.OPEN + }); }); diff --git a/packages/client/lib/commands/GEOSEARCH_WITH.ts b/packages/client/lib/commands/GEOSEARCH_WITH.ts index e706b08b9e..7dfb65c34c 100644 --- a/packages/client/lib/commands/GEOSEARCH_WITH.ts +++ b/packages/client/lib/commands/GEOSEARCH_WITH.ts @@ -1,23 +1,71 @@ -// import { RedisCommandArgument, RedisCommandArguments } from '.'; -// import { GeoSearchFrom, GeoSearchBy, GeoReplyWith, GeoSearchOptions } from './generic-transformers'; -// import { transformArguments as geoSearchTransformArguments } from './GEOSEARCH'; +import { ArrayReply, BlobStringReply, NumberReply, DoubleReply, Command, RedisArgument } from '../RESP/types'; +import GEOSEARCH, { GeoSearchBy, GeoSearchFrom, GeoSearchOptions } from './GEOSEARCH'; -// export { FIRST_KEY_INDEX, IS_READ_ONLY } from './GEOSEARCH'; +export const GEO_REPLY_WITH = { + DISTANCE: 'WITHDIST', + HASH: 'WITHHASH', + COORDINATES: 'WITHCOORD' +} as const; -// export function transformArguments( -// key: RedisCommandArgument, -// from: GeoSearchFrom, -// by: GeoSearchBy, -// replyWith: Array, -// options?: GeoSearchOptions -// ): RedisCommandArguments { -// const args: RedisCommandArguments = geoSearchTransformArguments(key, from, by, options); +export type GeoReplyWith = typeof GEO_REPLY_WITH[keyof typeof GEO_REPLY_WITH]; -// args.push(...replyWith); +export interface GeoReplyWithMember { + member: BlobStringReply; + distance?: BlobStringReply; + hash?: NumberReply; + coordinates?: { + longitude: DoubleReply; + latitude: DoubleReply; + }; +} -// args.preserve = replyWith; +export default { + FIRST_KEY_INDEX: GEOSEARCH.FIRST_KEY_INDEX, + IS_READ_ONLY: GEOSEARCH.IS_READ_ONLY, + transformArguments( + key: RedisArgument, + from: GeoSearchFrom, + by: GeoSearchBy, + replyWith: Array, + options?: GeoSearchOptions + ) { + const args = GEOSEARCH.transformArguments(key, from, by, options); + args.push(...replyWith); + args.preserve = replyWith; + return args; + }, + transformReply( + reply: ArrayReply<[BlobStringReply, ...Array]>, + replyWith: Array + ) { + const replyWithSet = new Set(replyWith); + let index = 0; + const distanceIndex = replyWithSet.has(GEO_REPLY_WITH.DISTANCE) && ++index, + hashIndex = replyWithSet.has(GEO_REPLY_WITH.HASH) && ++index, + coordinatesIndex = replyWithSet.has(GEO_REPLY_WITH.COORDINATES) && ++index; + + return reply.map(raw => { + const item: GeoReplyWithMember = { + member: raw[0] + }; -// return args; -// } + if (distanceIndex) { + item.distance = raw[distanceIndex]; + } + + if (hashIndex) { + item.hash = raw[hashIndex]; + } + + if (coordinatesIndex) { + const [longitude, latitude] = raw[coordinatesIndex]; + item.coordinates = { + longitude, + latitude + }; + } -// export { transformGeoMembersWithReply as transformReply } from './generic-transformers'; + return item; + }); + } +} as const satisfies Command; diff --git a/packages/client/lib/commands/index.ts b/packages/client/lib/commands/index.ts index e3985f82f8..e359018ff5 100644 --- a/packages/client/lib/commands/index.ts +++ b/packages/client/lib/commands/index.ts @@ -45,6 +45,23 @@ import DECR from './DECR'; import DECRBY from './DECRBY'; import DEL from './DEL'; import DUMP from './DUMP'; +import GEOADD from './GEOADD'; +import GEODIST from './GEODIST'; +import GEOHASH from './GEOHASH'; +import GEOPOS from './GEOPOS'; +import GEORADIUS_RO_WITH from './GEORADIUS_RO_WITH'; +import GEORADIUS_RO from './GEORADIUS_RO'; +import GEORADIUS_STORE from './GEORADIUS_STORE'; +import GEORADIUS_WITH from './GEORADIUS_WITH'; +import GEORADIUS from './GEORADIUS'; +import GEORADIUSBYMEMBER_RO_WITH from './GEORADIUSBYMEMBER_RO_WITH'; +import GEORADIUSBYMEMBER_RO from './GEORADIUSBYMEMBER_RO'; +import GEORADIUSBYMEMBER_STORE from './GEORADIUSBYMEMBER_STORE'; +import GEORADIUSBYMEMBER_WITH from './GEORADIUSBYMEMBER_WITH'; +import GEORADIUSBYMEMBER from './GEORADIUSBYMEMBER'; +import GEOSEARCH_WITH from './GEOSEARCH_WITH'; +import GEOSEARCH from './GEOSEARCH'; +import GEOSEARCHSTORE from './GEOSEARCHSTORE'; import GET from './GET'; import GETBIT from './GETBIT'; import GETDEL from './GETDEL'; @@ -290,6 +307,40 @@ export default { del: DEL, DUMP, dump: DUMP, + GEOADD, + geoAdd: GEOADD, + GEODIST, + geoDist: GEODIST, + GEOHASH, + geoHash: GEOHASH, + GEOPOS, + geoPos: GEOPOS, + GEORADIUS_RO_WITH, + geoRadiusRoWith: GEORADIUS_RO_WITH, + GEORADIUS_RO, + geoRadiusRo: GEORADIUS_RO, + GEORADIUS_STORE, + geoRadiusStore: GEORADIUS_STORE, + GEORADIUS_WITH, + geoRadiusWith: GEORADIUS_WITH, + GEORADIUS, + geoRadius: GEORADIUS, + GEORADIUSBYMEMBER_RO_WITH, + geoRadiusByMemberRoWith: GEORADIUSBYMEMBER_RO_WITH, + GEORADIUSBYMEMBER_RO, + geoRadiusByMemberRo: GEORADIUSBYMEMBER_RO, + GEORADIUSBYMEMBER_STORE, + geoRadiusByMemberStore: GEORADIUSBYMEMBER_STORE, + GEORADIUSBYMEMBER_WITH, + geoRadiusByMemberWith: GEORADIUSBYMEMBER_WITH, + GEORADIUSBYMEMBER, + geoRadiusByMember: GEORADIUSBYMEMBER, + GEOSEARCH_WITH, + geoSearchWith: GEOSEARCH_WITH, + GEOSEARCH, + geoSearch: GEOSEARCH, + GEOSEARCHSTORE, + geoSearchStore: GEOSEARCHSTORE, GET, get: GET, GETBIT,