diff --git a/docs/v4-to-v5.md b/docs/v4-to-v5.md index c500815cd6..ffb95cef1f 100644 --- a/docs/v4-to-v5.md +++ b/docs/v4-to-v5.md @@ -182,6 +182,7 @@ Some command arguments/replies have changed to align more closely to data types - `JSON.DEL`: `path` argument moved to `{ path: string; }` [^future-proofing] - `JSON.FORGET`: `path` argument moved to `{ path: string; }` [^future-proofing] - `TS.[M][REV]RANGE`: `enum TimeSeriesBucketTimestamp` -> `const TIME_SERIES_BUCKET_TIMESTAMP` [^enum-to-constants], `enum TimeSeriesReducers` -> `const TIME_SERIES_REDUCERS` [^enum-to-constants], the `ALIGN` argument has been moved into `AGGREGRATION` +- `TS.SYNUPDATE`: `Array>` -> `Record>` [^enum-to-constants]: TODO diff --git a/packages/search/lib/commands/ALIASADD.spec.ts b/packages/search/lib/commands/ALIASADD.spec.ts index 7bb2452838..22a895cae6 100644 --- a/packages/search/lib/commands/ALIASADD.spec.ts +++ b/packages/search/lib/commands/ALIASADD.spec.ts @@ -1,11 +1,24 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './ALIASADD'; +import testUtils, { GLOBAL } from '../test-utils'; +import ALIASADD from './ALIASADD'; +import { SCHEMA_FIELD_TYPE } from './CREATE'; -describe('ALIASADD', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('alias', 'index'), - ['FT.ALIASADD', 'alias', 'index'] - ); - }); +describe('FT.ALIASADD', () => { + it('transformArguments', () => { + assert.deepEqual( + ALIASADD.transformArguments('alias', 'index'), + ['FT.ALIASADD', 'alias', 'index'] + ); + }); + + testUtils.testWithClient('client.ft.aliasAdd', async client => { + const [, reply] = await Promise.all([ + client.ft.create('index', { + field: SCHEMA_FIELD_TYPE.TEXT + }), + client.ft.aliasAdd('alias', 'index') + ]); + + assert.equal(reply, 'OK'); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/ALIASADD.ts b/packages/search/lib/commands/ALIASADD.ts index 552c1add69..648e1fef97 100644 --- a/packages/search/lib/commands/ALIASADD.ts +++ b/packages/search/lib/commands/ALIASADD.ts @@ -1,5 +1,10 @@ -export function transformArguments(name: string, index: string): Array { - return ['FT.ALIASADD', name, index]; -} +import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export declare function transformReply(): 'OK'; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(alias: RedisArgument, index: RedisArgument) { + return ['FT.ALIASADD', alias, index]; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/search/lib/commands/ALIASDEL.spec.ts b/packages/search/lib/commands/ALIASDEL.spec.ts index 5255ba835d..0a308bd769 100644 --- a/packages/search/lib/commands/ALIASDEL.spec.ts +++ b/packages/search/lib/commands/ALIASDEL.spec.ts @@ -1,11 +1,25 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './ALIASDEL'; +import testUtils, { GLOBAL } from '../test-utils'; +import ALIASDEL from './ALIASDEL'; +import { SCHEMA_FIELD_TYPE } from './CREATE'; -describe('ALIASDEL', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('alias', 'index'), - ['FT.ALIASDEL', 'alias', 'index'] - ); - }); +describe('FT.ALIASDEL', () => { + it('transformArguments', () => { + assert.deepEqual( + ALIASDEL.transformArguments('alias'), + ['FT.ALIASDEL', 'alias'] + ); + }); + + testUtils.testWithClient('client.ft.aliasAdd', async client => { + const [, , reply] = await Promise.all([ + client.ft.create('index', { + field: SCHEMA_FIELD_TYPE.TEXT + }), + client.ft.aliasAdd('alias', 'index'), + client.ft.aliasDel('alias') + ]); + + assert.equal(reply, 'OK'); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/ALIASDEL.ts b/packages/search/lib/commands/ALIASDEL.ts index 434b4df3de..40cc45a19d 100644 --- a/packages/search/lib/commands/ALIASDEL.ts +++ b/packages/search/lib/commands/ALIASDEL.ts @@ -1,5 +1,10 @@ -export function transformArguments(name: string, index: string): Array { - return ['FT.ALIASDEL', name, index]; -} +import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; -export declare function transformReply(): 'OK'; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(alias: RedisArgument) { + return ['FT.ALIASDEL', alias]; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/search/lib/commands/ALIASUPDATE.spec.ts b/packages/search/lib/commands/ALIASUPDATE.spec.ts index 79421b1a20..cc0d1439ac 100644 --- a/packages/search/lib/commands/ALIASUPDATE.spec.ts +++ b/packages/search/lib/commands/ALIASUPDATE.spec.ts @@ -1,11 +1,24 @@ import { strict as assert } from 'assert'; -import { transformArguments } from './ALIASUPDATE'; +import testUtils, { GLOBAL } from '../test-utils'; +import ALIASUPDATE from './ALIASUPDATE'; +import { SCHEMA_FIELD_TYPE } from './CREATE'; -describe('ALIASUPDATE', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('alias', 'index'), - ['FT.ALIASUPDATE', 'alias', 'index'] - ); - }); +describe('FT.ALIASUPDATE', () => { + it('transformArguments', () => { + assert.deepEqual( + ALIASUPDATE.transformArguments('alias', 'index'), + ['FT.ALIASUPDATE', 'alias', 'index'] + ); + }); + + testUtils.testWithClient('client.ft.aliasUpdate', async client => { + const [, reply] = await Promise.all([ + client.ft.create('index', { + field: SCHEMA_FIELD_TYPE.TEXT + }), + client.ft.aliasUpdate('alias', 'index') + ]); + + assert.equal(reply, 'OK'); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/ALIASUPDATE.ts b/packages/search/lib/commands/ALIASUPDATE.ts index ac64ef57c3..e2b72cfe64 100644 --- a/packages/search/lib/commands/ALIASUPDATE.ts +++ b/packages/search/lib/commands/ALIASUPDATE.ts @@ -1,5 +1,10 @@ -export function transformArguments(name: string, index: string): Array { - return ['FT.ALIASUPDATE', name, index]; -} +import { SimpleStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types'; -export declare function transformReply(): 'OK'; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(alias: RedisArgument, index: RedisArgument) { + return ['FT.ALIASUPDATE', alias, index]; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/search/lib/commands/CREATE.ts b/packages/search/lib/commands/CREATE.ts index bc7603fe70..98a616f04e 100644 --- a/packages/search/lib/commands/CREATE.ts +++ b/packages/search/lib/commands/CREATE.ts @@ -257,8 +257,8 @@ export interface CreateOptions { } export default { - FIRST_KEY_INDEX: 1, - IS_READ_ONLY: false, + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, transformArguments(index: RedisArgument, schema: RediSearchSchema, options?: CreateOptions) { const args = ['FT.CREATE', index]; diff --git a/packages/search/lib/commands/CURSOR_DEL.spec.ts b/packages/search/lib/commands/CURSOR_DEL.spec.ts index d89725ef80..c5fad7e8e8 100644 --- a/packages/search/lib/commands/CURSOR_DEL.spec.ts +++ b/packages/search/lib/commands/CURSOR_DEL.spec.ts @@ -1,33 +1,32 @@ import { strict as assert } from 'assert'; -import { SchemaFieldTypes } from '.'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './CURSOR_DEL'; +import CURSOR_DEL from './CURSOR_DEL'; +import { SCHEMA_FIELD_TYPE } from './CREATE'; -describe('CURSOR DEL', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('index', 0), - ['FT.CURSOR', 'DEL', 'index', '0'] - ); - }); +describe('FT.CURSOR DEL', () => { + it('transformArguments', () => { + assert.deepEqual( + CURSOR_DEL.transformArguments('index', '0'), + ['FT.CURSOR', 'DEL', 'index', '0'] + ); + }); - testUtils.testWithClient('client.ft.cursorDel', async client => { - const [ ,, { cursor } ] = await Promise.all([ - client.ft.create('idx', { - field: { - type: SchemaFieldTypes.TEXT - } - }), - client.hSet('key', 'field', 'value'), - client.ft.aggregateWithCursor('idx', '*', { - COUNT: 1 - }) - ]); + testUtils.testWithClient('client.ft.cursorDel', async client => { + const [, , { cursor }] = await Promise.all([ + client.ft.create('idx', { + field: { + type: SCHEMA_FIELD_TYPE.TEXT + } + }), + client.hSet('key', 'field', 'value'), + client.ft.aggregateWithCursor('idx', '*', { + COUNT: 1 + }) + ]); - - assert.equal( - await client.ft.cursorDel('idx', cursor), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + assert.equal( + await client.ft.cursorDel('idx', cursor), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/CURSOR_DEL.ts b/packages/search/lib/commands/CURSOR_DEL.ts index 22c850f2a8..7c134454be 100644 --- a/packages/search/lib/commands/CURSOR_DEL.ts +++ b/packages/search/lib/commands/CURSOR_DEL.ts @@ -1,14 +1,10 @@ -import { RedisCommandArgument } from '@redis/client/dist/lib/commands'; +import { SimpleStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments(index: RedisCommandArgument, cursorId: number) { - return [ - 'FT.CURSOR', - 'DEL', - index, - cursorId.toString() - ]; -} - -export declare function transformReply(): 'OK'; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(index: RedisArgument, cursorId: RedisArgument) { + return ['FT.CURSOR', 'DEL', index, cursorId]; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/search/lib/commands/DICTADD.spec.ts b/packages/search/lib/commands/DICTADD.spec.ts index 6aa3c862f2..6baeb6299a 100644 --- a/packages/search/lib/commands/DICTADD.spec.ts +++ b/packages/search/lib/commands/DICTADD.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import DICTADD from './DICTADD'; -describe('DICTADD', () => { +describe('FT.DICTADD', () => { describe('transformArguments', () => { it('string', () => { assert.deepEqual( diff --git a/packages/search/lib/commands/DICTADD.ts b/packages/search/lib/commands/DICTADD.ts index a90e87dcf7..f633d58b1f 100644 --- a/packages/search/lib/commands/DICTADD.ts +++ b/packages/search/lib/commands/DICTADD.ts @@ -3,7 +3,7 @@ import { pushVariadicArguments, RedisVariadicArgument } from '@redis/client/dist export default { FIRST_KEY_INDEX: undefined, - IS_READ_ONLY: false, + IS_READ_ONLY: true, transformArguments(dictionary: RedisArgument, term: RedisVariadicArgument) { return pushVariadicArguments(['FT.DICTADD', dictionary], term); }, diff --git a/packages/search/lib/commands/DICTDEL.spec.ts b/packages/search/lib/commands/DICTDEL.spec.ts index 9d42944d62..328cc98a34 100644 --- a/packages/search/lib/commands/DICTDEL.spec.ts +++ b/packages/search/lib/commands/DICTDEL.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import DICTDEL from './DICTDEL'; -describe('DICTDEL', () => { +describe('FT.DICTDEL', () => { describe('transformArguments', () => { it('string', () => { assert.deepEqual( diff --git a/packages/search/lib/commands/DICTDEL.ts b/packages/search/lib/commands/DICTDEL.ts index e639d3427b..087211751e 100644 --- a/packages/search/lib/commands/DICTDEL.ts +++ b/packages/search/lib/commands/DICTDEL.ts @@ -3,7 +3,7 @@ import { pushVariadicArguments, RedisVariadicArgument } from '@redis/client/dist export default { FIRST_KEY_INDEX: undefined, - IS_READ_ONLY: false, + IS_READ_ONLY: true, transformArguments(dictionary: RedisArgument, term: RedisVariadicArgument) { return pushVariadicArguments(['FT.DICTDEL', dictionary], term); }, diff --git a/packages/search/lib/commands/DICTDUMP.spec.ts b/packages/search/lib/commands/DICTDUMP.spec.ts index 0e50a4a373..bb7eb3db31 100644 --- a/packages/search/lib/commands/DICTDUMP.spec.ts +++ b/packages/search/lib/commands/DICTDUMP.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import DICTDUMP from './DICTDUMP'; -describe('DICTDUMP', () => { +describe('FT.DICTDUMP', () => { it('transformArguments', () => { assert.deepEqual( DICTDUMP.transformArguments('dictionary'), @@ -11,11 +11,11 @@ describe('DICTDUMP', () => { }); testUtils.testWithClient('client.ft.dictDump', async client => { - await client.ft.dictAdd('dictionary', 'string') + const [, reply] = await Promise.all([ + client.ft.dictAdd('dictionary', 'string'), + client.ft.dictDump('dictionary') + ]); - assert.deepEqual( - await client.ft.dictDump('dictionary'), - ['string'] - ); + assert.deepEqual(reply, ['string']); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/DROPINDEX.spec.ts b/packages/search/lib/commands/DROPINDEX.spec.ts index cb6ca192cd..67742c16a1 100644 --- a/packages/search/lib/commands/DROPINDEX.spec.ts +++ b/packages/search/lib/commands/DROPINDEX.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { SchemaFieldTypes } from '.'; import DROPINDEX from './DROPINDEX'; +import { SCHEMA_FIELD_TYPE } from './CREATE'; -describe('DROPINDEX', () => { +describe('FT.DROPINDEX', () => { describe('transformArguments', () => { it('without options', () => { assert.deepEqual( @@ -21,13 +21,13 @@ describe('DROPINDEX', () => { }); testUtils.testWithClient('client.ft.dropIndex', async client => { - await client.ft.create('index', { - field: SchemaFieldTypes.TEXT - }); + const [, reply] = await Promise.all([ + client.ft.create('index', { + field: SCHEMA_FIELD_TYPE.TEXT + }), + client.ft.dropIndex('index') + ]); - assert.equal( - await client.ft.dropIndex('index'), - 'OK' - ); + assert.equal(reply, 'OK'); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/DROPINDEX.ts b/packages/search/lib/commands/DROPINDEX.ts index fe25a79e97..64fe9711e7 100644 --- a/packages/search/lib/commands/DROPINDEX.ts +++ b/packages/search/lib/commands/DROPINDEX.ts @@ -6,7 +6,7 @@ export interface FtDropIndexOptions { export default { FIRST_KEY_INDEX: undefined, - IS_READ_ONLY: false, + IS_READ_ONLY: true, transformArguments(index: RedisArgument, options?: FtDropIndexOptions) { const args = ['FT.DROPINDEX', index]; diff --git a/packages/search/lib/commands/SPELLCHECK.spec.ts b/packages/search/lib/commands/SPELLCHECK.spec.ts index acabbe8a87..a2261004dc 100644 --- a/packages/search/lib/commands/SPELLCHECK.spec.ts +++ b/packages/search/lib/commands/SPELLCHECK.spec.ts @@ -1,80 +1,80 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import { SchemaFieldTypes } from '.'; -import { transformArguments } from './SPELLCHECK'; +import SPELLCHECK from './SPELLCHECK'; -describe('SPELLCHECK', () => { - describe('transformArguments', () => { - it('without options', () => { - assert.deepEqual( - transformArguments('index', 'query'), - ['FT.SPELLCHECK', 'index', 'query'] - ); - }); - - it('with DISTANCE', () => { - assert.deepEqual( - transformArguments('index', 'query', { DISTANCE: 2 }), - ['FT.SPELLCHECK', 'index', 'query', 'DISTANCE', '2'] - ); - }); - - describe('with TERMS', () => { - it('single', () => { - assert.deepEqual( - transformArguments('index', 'query', { - TERMS: { - mode: 'INCLUDE', - dictionary: 'dictionary' - } - }), - ['FT.SPELLCHECK', 'index', 'query', 'TERMS', 'INCLUDE', 'dictionary'] - ); - }); - - it('multiple', () => { - assert.deepEqual( - transformArguments('index', 'query', { - TERMS: [{ - mode: 'INCLUDE', - dictionary: 'include' - }, { - mode: 'EXCLUDE', - dictionary: 'exclude' - }] - }), - ['FT.SPELLCHECK', 'index', 'query', 'TERMS', 'INCLUDE', 'include', 'TERMS', 'EXCLUDE', 'exclude'] - ); - }); - }); - - it('with DIALECT', () => { - assert.deepEqual( - transformArguments('index', 'query', { - DIALECT: 1 - }), - ['FT.SPELLCHECK', 'index', 'query', 'DIALECT', '1'] - ); - }); +describe('FT.SPELLCHECK', () => { + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + SPELLCHECK.transformArguments('index', 'query'), + ['FT.SPELLCHECK', 'index', 'query'] + ); }); - testUtils.testWithClient('client.ft.spellCheck', async client => { - await Promise.all([ - client.ft.create('index', { - field: SchemaFieldTypes.TEXT - }), - client.hSet('key', 'field', 'query') - ]); + it('with DISTANCE', () => { + assert.deepEqual( + SPELLCHECK.transformArguments('index', 'query', { + DISTANCE: 2 + }), + ['FT.SPELLCHECK', 'index', 'query', 'DISTANCE', '2'] + ); + }); + describe('with TERMS', () => { + it('single', () => { assert.deepEqual( - await client.ft.spellCheck('index', 'quer'), - [{ - term: 'quer', - suggestions: [{ - score: 1, - suggestion: 'query' - }] - }] + SPELLCHECK.transformArguments('index', 'query', { + TERMS: { + mode: 'INCLUDE', + dictionary: 'dictionary' + } + }), + ['FT.SPELLCHECK', 'index', 'query', 'TERMS', 'INCLUDE', 'dictionary'] ); - }, GLOBAL.SERVERS.OPEN); + }); + + it('multiple', () => { + assert.deepEqual( + SPELLCHECK.transformArguments('index', 'query', { + TERMS: [{ + mode: 'INCLUDE', + dictionary: 'include' + }, { + mode: 'EXCLUDE', + dictionary: 'exclude' + }] + }), + ['FT.SPELLCHECK', 'index', 'query', 'TERMS', 'INCLUDE', 'include', 'TERMS', 'EXCLUDE', 'exclude'] + ); + }); + }); + + it('with DIALECT', () => { + assert.deepEqual( + SPELLCHECK.transformArguments('index', 'query', { + DIALECT: 1 + }), + ['FT.SPELLCHECK', 'index', 'query', 'DIALECT', '1'] + ); + }); + }); + + testUtils.testWithClient('client.ft.spellCheck', async client => { + const [,, reply] = await Promise.all([ + client.ft.create('index', { + field: SchemaFieldTypes.TEXT + }), + client.hSet('key', 'field', 'query'), + client.ft.spellCheck('index', 'quer') + ]); + + assert.deepEqual(reply, [{ + term: 'quer', + suggestions: [{ + score: 1, + suggestion: 'query' + }] + }]); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/SPELLCHECK.ts b/packages/search/lib/commands/SPELLCHECK.ts index c9317a8b4f..720ed02547 100644 --- a/packages/search/lib/commands/SPELLCHECK.ts +++ b/packages/search/lib/commands/SPELLCHECK.ts @@ -1,62 +1,69 @@ -interface SpellCheckTerms { - mode: 'INCLUDE' | 'EXCLUDE'; - dictionary: string; +import { RedisArgument, CommandArguments, Command } from '@redis/client/dist/lib/RESP/types'; + +export interface Terms { + mode: 'INCLUDE' | 'EXCLUDE'; + dictionary: RedisArgument; } -interface SpellCheckOptions { - DISTANCE?: number; - TERMS?: SpellCheckTerms | Array; - DIALECT?: number; +export interface FtSpellCheckOptions { + DISTANCE?: number; + TERMS?: Terms | Array; + DIALECT?: number; } -export function transformArguments(index: string, query: string, options?: SpellCheckOptions): Array { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(index: RedisArgument, query: RedisArgument, options?: FtSpellCheckOptions) { const args = ['FT.SPELLCHECK', index, query]; if (options?.DISTANCE) { - args.push('DISTANCE', options.DISTANCE.toString()); + args.push('DISTANCE', options.DISTANCE.toString()); } if (options?.TERMS) { - if (Array.isArray(options.TERMS)) { - for (const term of options.TERMS) { - pushTerms(args, term); - } - } else { - pushTerms(args, options.TERMS); + if (Array.isArray(options.TERMS)) { + for (const term of options.TERMS) { + pushTerms(args, term); } + } else { + pushTerms(args, options.TERMS); + } } if (options?.DIALECT) { - args.push('DIALECT', options.DIALECT.toString()); + args.push('DIALECT', options.DIALECT.toString()); } return args; -} - -function pushTerms(args: Array, { mode, dictionary }: SpellCheckTerms): void { - args.push('TERMS', mode, dictionary); -} - -type SpellCheckRawReply = Array<[ - _: string, - term: string, - suggestions: Array<[score: string, suggestion: string]> -]>; - -type SpellCheckReply = Array<{ - term: string, - suggestions: Array<{ - score: number, - suggestion: string - }> -}>; - -export function transformReply(rawReply: SpellCheckRawReply): SpellCheckReply { - return rawReply.map(([, term, suggestions]) => ({ - term, - suggestions: suggestions.map(([score, suggestion]) => ({ - score: Number(score), - suggestion - })) - })); + }, + // TODO + // type SpellCheckRawReply = Array<[ + // _: string, + // term: string, + // suggestions: Array<[score: string, suggestion: string]> + // ]>; + + // type SpellCheckReply = Array<{ + // term: string, + // suggestions: Array<{ + // score: number, + // suggestion: string + // }> + // }>; + + // export function transformReply(rawReply: SpellCheckRawReply): SpellCheckReply { + // return rawReply.map(([, term, suggestions]) => ({ + // term, + // suggestions: suggestions.map(([score, suggestion]) => ({ + // score: Number(score), + // suggestion + // })) + // })); + // } + transformReply: undefined as unknown as () => any +} as const satisfies Command; + +function pushTerms(args: CommandArguments, { mode, dictionary }: Terms) { + args.push('TERMS', mode, dictionary); } diff --git a/packages/search/lib/commands/SUGADD.spec.ts b/packages/search/lib/commands/SUGADD.spec.ts index 391fa51d61..2196ce89e7 100644 --- a/packages/search/lib/commands/SUGADD.spec.ts +++ b/packages/search/lib/commands/SUGADD.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import SUGADD from './SUGADD'; -describe('SUGADD', () => { +describe('FT.SUGADD', () => { describe('transformArguments', () => { it('without options', () => { assert.deepEqual( diff --git a/packages/search/lib/commands/SUGADD.ts b/packages/search/lib/commands/SUGADD.ts index 490dd6d1b3..c4cc1fb53e 100644 --- a/packages/search/lib/commands/SUGADD.ts +++ b/packages/search/lib/commands/SUGADD.ts @@ -7,7 +7,7 @@ export interface FtSugAddOptions { export default { FIRST_KEY_INDEX: undefined, - IS_READ_ONLY: false, + IS_READ_ONLY: true, transformArguments(key: RedisArgument, string: RedisArgument, score: number, options?: FtSugAddOptions) { const args = ['FT.SUGADD', key, string, score.toString()]; diff --git a/packages/search/lib/commands/SUGDEL.spec.ts b/packages/search/lib/commands/SUGDEL.spec.ts index 4d0b72b6d9..5f86ea80b6 100644 --- a/packages/search/lib/commands/SUGDEL.spec.ts +++ b/packages/search/lib/commands/SUGDEL.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import SUGDEL from './SUGDEL'; -describe('SUGDEL', () => { +describe('FT.SUGDEL', () => { it('transformArguments', () => { assert.deepEqual( SUGDEL.transformArguments('key', 'string'), @@ -13,7 +13,7 @@ describe('SUGDEL', () => { testUtils.testWithClient('client.ft.sugDel', async client => { assert.equal( await client.ft.sugDel('key', 'string'), - false + 0 ); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/SUGDEL.ts b/packages/search/lib/commands/SUGDEL.ts index 9311e14c02..ed9a8aef24 100644 --- a/packages/search/lib/commands/SUGDEL.ts +++ b/packages/search/lib/commands/SUGDEL.ts @@ -2,7 +2,7 @@ import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP export default { FIRST_KEY_INDEX: undefined, - IS_READ_ONLY: false, + IS_READ_ONLY: true, transformArguments(key: RedisArgument, string: RedisArgument) { return ['FT.SUGDEL', key, string]; }, diff --git a/packages/search/lib/commands/SUGGET.spec.ts b/packages/search/lib/commands/SUGGET.spec.ts index c24c2ff086..2553077dc6 100644 --- a/packages/search/lib/commands/SUGGET.spec.ts +++ b/packages/search/lib/commands/SUGGET.spec.ts @@ -1,46 +1,46 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SUGGET'; +import SUGGET from './SUGGET'; -describe('SUGGET', () => { - describe('transformArguments', () => { - it('without options', () => { - assert.deepEqual( - transformArguments('key', 'prefix'), - ['FT.SUGGET', 'key', 'prefix'] - ); - }); - - it('with FUZZY', () => { - assert.deepEqual( - transformArguments('key', 'prefix', { FUZZY: true }), - ['FT.SUGGET', 'key', 'prefix', 'FUZZY'] - ); - }); - - it('with MAX', () => { - assert.deepEqual( - transformArguments('key', 'prefix', { MAX: 10 }), - ['FT.SUGGET', 'key', 'prefix', 'MAX', '10'] - ); - }); +describe('FT.SUGGET', () => { + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + SUGGET.transformArguments('key', 'prefix'), + ['FT.SUGGET', 'key', 'prefix'] + ); }); - describe('client.ft.sugGet', () => { - testUtils.testWithClient('null', async client => { - assert.equal( - await client.ft.sugGet('key', 'prefix'), - null - ); - }, GLOBAL.SERVERS.OPEN); - - testUtils.testWithClient('with suggestions', async client => { - await client.ft.sugAdd('key', 'string', 1); - - assert.deepEqual( - await client.ft.sugGet('key', 'string'), - ['string'] - ); - }, GLOBAL.SERVERS.OPEN); + it('with FUZZY', () => { + assert.deepEqual( + SUGGET.transformArguments('key', 'prefix', { FUZZY: true }), + ['FT.SUGGET', 'key', 'prefix', 'FUZZY'] + ); }); + + it('with MAX', () => { + assert.deepEqual( + SUGGET.transformArguments('key', 'prefix', { MAX: 10 }), + ['FT.SUGGET', 'key', 'prefix', 'MAX', '10'] + ); + }); + }); + + describe('client.ft.sugGet', () => { + testUtils.testWithClient('null', async client => { + assert.equal( + await client.ft.sugGet('key', 'prefix'), + null + ); + }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('with suggestions', async client => { + const [, reply] = await Promise.all([ + client.ft.sugAdd('key', 'string', 1), + client.ft.sugGet('key', 's') + ]); + + assert.deepEqual(reply, ['string']); + }, GLOBAL.SERVERS.OPEN); + }); }); diff --git a/packages/search/lib/commands/SUGGET.ts b/packages/search/lib/commands/SUGGET.ts index 558cedeaa0..2dc360da3e 100644 --- a/packages/search/lib/commands/SUGGET.ts +++ b/packages/search/lib/commands/SUGGET.ts @@ -1,22 +1,25 @@ -export const IS_READ_ONLY = true; +import { ArrayReply, BlobStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types'; -export interface SugGetOptions { - FUZZY?: true; - MAX?: number; +export interface FtSugGetOptions { + FUZZY?: boolean; + MAX?: number; } -export function transformArguments(key: string, prefix: string, options?: SugGetOptions): Array { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(key: RedisArgument, prefix: RedisArgument, options?: FtSugGetOptions) { const args = ['FT.SUGGET', key, prefix]; if (options?.FUZZY) { - args.push('FUZZY'); + args.push('FUZZY'); } - if (options?.MAX) { - args.push('MAX', options.MAX.toString()); + if (options?.MAX !== undefined) { + args.push('MAX', options.MAX.toString()); } return args; -} - -export declare function transformReply(): null | Array; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/search/lib/commands/SUGLEN.spec.ts b/packages/search/lib/commands/SUGLEN.spec.ts index 88a140b770..6238b7a324 100644 --- a/packages/search/lib/commands/SUGLEN.spec.ts +++ b/packages/search/lib/commands/SUGLEN.spec.ts @@ -2,7 +2,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import SUGLEN from './SUGLEN'; -describe('SUGLEN', () => { +describe('FT.SUGLEN', () => { it('transformArguments', () => { assert.deepEqual( SUGLEN.transformArguments('key'), diff --git a/packages/search/lib/commands/SYNDUMP.spec.ts b/packages/search/lib/commands/SYNDUMP.spec.ts index 472db54bcf..4b9a3dfae0 100644 --- a/packages/search/lib/commands/SYNDUMP.spec.ts +++ b/packages/search/lib/commands/SYNDUMP.spec.ts @@ -1,24 +1,24 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SYNDUMP'; -import { SchemaFieldTypes } from '.'; +import SYNDUMP from './SYNDUMP'; +import { SCHEMA_FIELD_TYPE } from './CREATE'; -describe('SYNDUMP', () => { - it('transformArguments', () => { - assert.deepEqual( - transformArguments('index'), - ['FT.SYNDUMP', 'index'] - ); - }); +describe('FT.SYNDUMP', () => { + it('transformArguments', () => { + assert.deepEqual( + SYNDUMP.transformArguments('index'), + ['FT.SYNDUMP', 'index'] + ); + }); - testUtils.testWithClient('client.ft.synDump', async client => { - await client.ft.create('index', { - field: SchemaFieldTypes.TEXT - }); + testUtils.testWithClient('client.ft.synDump', async client => { + const [, reply] = await Promise.all([ + client.ft.create('index', { + field: SCHEMA_FIELD_TYPE.TEXT + }), + client.ft.synDump('index') + ]); - assert.deepEqual( - await client.ft.synDump('index'), - [] - ); - }, GLOBAL.SERVERS.OPEN); + assert.deepEqual(reply, []); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/SYNDUMP.ts b/packages/search/lib/commands/SYNDUMP.ts index 5f1e71aaf7..2fe7540fda 100644 --- a/packages/search/lib/commands/SYNDUMP.ts +++ b/packages/search/lib/commands/SYNDUMP.ts @@ -1,5 +1,22 @@ -export function transformArguments(index: string): Array { - return ['FT.SYNDUMP', index]; -} +import { RedisArgument, MapReply, BlobStringReply, ArrayReply, UnwrapReply, Command } from '@redis/client/dist/lib/RESP/types'; -export declare function transformReply(): Array; +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments(index: RedisArgument) { + return ['FT.SYNDUMP', index]; + }, + transformReply: { + 2: (reply: UnwrapReply>>) => { + const result: Record> = {}; + let i = 0; + while (i < reply.length) { + const key = (reply[i++] as unknown as UnwrapReply).toString(), + value = reply[i++] as unknown as ArrayReply; + result[key] = value; + } + return result; + }, + 3: undefined as unknown as () => MapReply> + } +} as const satisfies Command; diff --git a/packages/search/lib/commands/SYNUPDATE.spec.ts b/packages/search/lib/commands/SYNUPDATE.spec.ts index 19ac9b85e5..1dfde97521 100644 --- a/packages/search/lib/commands/SYNUPDATE.spec.ts +++ b/packages/search/lib/commands/SYNUPDATE.spec.ts @@ -1,40 +1,42 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { transformArguments } from './SYNUPDATE'; -import { SchemaFieldTypes } from '.'; +import SYNUPDATE from './SYNUPDATE'; +import { SCHEMA_FIELD_TYPE } from './CREATE'; -describe('SYNUPDATE', () => { - describe('transformArguments', () => { - it('single term', () => { - assert.deepEqual( - transformArguments('index', 'groupId', 'term'), - ['FT.SYNUPDATE', 'index', 'groupId', 'term'] - ); - }); - - it('multiple terms', () => { - assert.deepEqual( - transformArguments('index', 'groupId', ['1', '2']), - ['FT.SYNUPDATE', 'index', 'groupId', '1', '2'] - ); - }); - - it('with SKIPINITIALSCAN', () => { - assert.deepEqual( - transformArguments('index', 'groupId', 'term', { SKIPINITIALSCAN: true }), - ['FT.SYNUPDATE', 'index', 'groupId', 'SKIPINITIALSCAN', 'term'] - ); - }); +describe('FT.SYNUPDATE', () => { + describe('transformArguments', () => { + it('single term', () => { + assert.deepEqual( + SYNUPDATE.transformArguments('index', 'groupId', 'term'), + ['FT.SYNUPDATE', 'index', 'groupId', 'term'] + ); }); - testUtils.testWithClient('client.ft.synUpdate', async client => { - await client.ft.create('index', { - field: SchemaFieldTypes.TEXT - }); + it('multiple terms', () => { + assert.deepEqual( + SYNUPDATE.transformArguments('index', 'groupId', ['1', '2']), + ['FT.SYNUPDATE', 'index', 'groupId', '1', '2'] + ); + }); - assert.equal( - await client.ft.synUpdate('index', 'groupId', 'term'), - 'OK' - ); - }, GLOBAL.SERVERS.OPEN); + it('with SKIPINITIALSCAN', () => { + assert.deepEqual( + SYNUPDATE.transformArguments('index', 'groupId', 'term', { + SKIPINITIALSCAN: true + }), + ['FT.SYNUPDATE', 'index', 'groupId', 'SKIPINITIALSCAN', 'term'] + ); + }); + }); + + testUtils.testWithClient('client.ft.synUpdate', async client => { + const [, reply] = await Promise.all([ + client.ft.create('index', { + field: SCHEMA_FIELD_TYPE.TEXT + }), + client.ft.synUpdate('index', 'groupId', 'term') + ]); + + assert.equal(reply, 'OK'); + }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/SYNUPDATE.ts b/packages/search/lib/commands/SYNUPDATE.ts index 80582759c4..926d8e58e1 100644 --- a/packages/search/lib/commands/SYNUPDATE.ts +++ b/packages/search/lib/commands/SYNUPDATE.ts @@ -1,23 +1,26 @@ -import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; -import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; +import { SimpleStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types'; +import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; -interface SynUpdateOptions { - SKIPINITIALSCAN?: true; +export interface FtSynUpdateOptions { + SKIPINITIALSCAN?: boolean; } -export function transformArguments( - index: string, - groupId: string, - terms: string | Array, - options?: SynUpdateOptions -): RedisCommandArguments { +export default { + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments( + index: RedisArgument, + groupId: RedisArgument, + terms: RedisVariadicArgument, + options?: FtSynUpdateOptions + ) { const args = ['FT.SYNUPDATE', index, groupId]; if (options?.SKIPINITIALSCAN) { - args.push('SKIPINITIALSCAN'); + args.push('SKIPINITIALSCAN'); } return pushVariadicArguments(args, terms); -} - -export declare function transformReply(): 'OK'; + }, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> +} as const satisfies Command; diff --git a/packages/search/lib/commands/TAGVALS.spec.ts b/packages/search/lib/commands/TAGVALS.spec.ts index 52bb66c1ce..5962beecfe 100644 --- a/packages/search/lib/commands/TAGVALS.spec.ts +++ b/packages/search/lib/commands/TAGVALS.spec.ts @@ -1,9 +1,9 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; -import { SchemaFieldTypes } from '.'; import TAGVALS from './TAGVALS'; +import { SCHEMA_FIELD_TYPE } from './CREATE'; -describe('TAGVALS', () => { +describe('FT.TAGVALS', () => { it('transformArguments', () => { assert.deepEqual( TAGVALS.transformArguments('index', '@field'), @@ -12,13 +12,13 @@ describe('TAGVALS', () => { }); testUtils.testWithClient('client.ft.tagVals', async client => { - await client.ft.create('index', { - field: SchemaFieldTypes.TAG - }); + const [, reply] = await Promise.all([ + client.ft.create('index', { + field: SCHEMA_FIELD_TYPE.TAG + }), + client.ft.tagVals('index', 'field') + ]); - assert.deepEqual( - await client.ft.tagVals('index', 'field'), - [] - ); + assert.deepEqual(reply, []); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/search/lib/commands/TAGVALS.ts b/packages/search/lib/commands/TAGVALS.ts index 7c58a1f9d1..8a6e73c97b 100644 --- a/packages/search/lib/commands/TAGVALS.ts +++ b/packages/search/lib/commands/TAGVALS.ts @@ -2,7 +2,7 @@ import { RedisArgument, ArrayReply, SetReply, BlobStringReply, Command } from '@ export default { FIRST_KEY_INDEX: undefined, - IS_READ_ONLY: false, + IS_READ_ONLY: true, transformArguments(index: RedisArgument, fieldName: RedisArgument) { return ['FT.TAGVALS', index, fieldName]; }, diff --git a/packages/search/lib/commands/index.ts b/packages/search/lib/commands/index.ts index 17fb67e047..d4a5c28da7 100644 --- a/packages/search/lib/commands/index.ts +++ b/packages/search/lib/commands/index.ts @@ -2,13 +2,13 @@ import _LIST from './_LIST'; // import ALTER from './ALTER'; // import AGGREGATE_WITHCURSOR from './AGGREGATE_WITHCURSOR'; // import AGGREGATE from './AGGREGATE'; -// import ALIASADD from './ALIASADD'; -// import ALIASDEL from './ALIASDEL'; -// import ALIASUPDATE from './ALIASUPDATE'; +import ALIASADD from './ALIASADD'; +import ALIASDEL from './ALIASDEL'; +import ALIASUPDATE from './ALIASUPDATE'; // import CONFIG_GET from './CONFIG_GET'; // import CONFIG_SET from './CONFIG_SET'; import CREATE from './CREATE'; -// import CURSOR_DEL from './CURSOR_DEL'; +import CURSOR_DEL from './CURSOR_DEL'; // import CURSOR_READ from './CURSOR_READ'; import DICTADD from './DICTADD'; import DICTDEL from './DICTDEL'; @@ -20,16 +20,16 @@ import EXPLAINCLI from './EXPLAINCLI'; // import PROFILESEARCH from './PROFILE_SEARCH'; // import PROFILEAGGREGATE from './PROFILE_AGGREGATE'; // import SEARCH from './SEARCH'; -// import SPELLCHECK from './SPELLCHECK'; +import SPELLCHECK from './SPELLCHECK'; import SUGADD from './SUGADD'; import SUGDEL from './SUGDEL'; // import SUGGET_WITHPAYLOADS from './SUGGET_WITHPAYLOADS'; // import SUGGET_WITHSCORES_WITHPAYLOADS from './SUGGET_WITHSCORES_WITHPAYLOADS'; // import SUGGET_WITHSCORES from './SUGGET_WITHSCORES'; -// import SUGGET from './SUGGET'; +import SUGGET from './SUGGET'; import SUGLEN from './SUGLEN'; -// import SYNDUMP from './SYNDUMP'; -// import SYNUPDATE from './SYNUPDATE'; +import SYNDUMP from './SYNDUMP'; +import SYNUPDATE from './SYNUPDATE'; import TAGVALS from './TAGVALS'; // import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; import { pushOptionalVariadicArgument, pushVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; @@ -45,20 +45,20 @@ export default { // aggregateWithCursor: AGGREGATE_WITHCURSOR, // AGGREGATE, // aggregate: AGGREGATE, - // ALIASADD, - // aliasAdd: ALIASADD, - // ALIASDEL, - // aliasDel: ALIASDEL, - // ALIASUPDATE, - // aliasUpdate: ALIASUPDATE, + ALIASADD, + aliasAdd: ALIASADD, + ALIASDEL, + aliasDel: ALIASDEL, + ALIASUPDATE, + aliasUpdate: ALIASUPDATE, // CONFIG_GET, // configGet: CONFIG_GET, // CONFIG_SET, // configSet: CONFIG_SET, CREATE, create: CREATE, - // CURSOR_DEL, - // cursorDel: CURSOR_DEL, + CURSOR_DEL, + cursorDel: CURSOR_DEL, // CURSOR_READ, // cursorRead: CURSOR_READ, DICTADD, @@ -81,8 +81,8 @@ export default { // profileAggregate: PROFILEAGGREGATE, // SEARCH, // search: SEARCH, - // SPELLCHECK, - // spellCheck: SPELLCHECK, + SPELLCHECK, + spellCheck: SPELLCHECK, SUGADD, sugAdd: SUGADD, SUGDEL, @@ -93,14 +93,14 @@ export default { // sugGetWithScoresWithPayloads: SUGGET_WITHSCORES_WITHPAYLOADS, // SUGGET_WITHSCORES, // sugGetWithScores: SUGGET_WITHSCORES, - // SUGGET, - // sugGet: SUGGET, + SUGGET, + sugGet: SUGGET, SUGLEN, sugLen: SUGLEN, - // SYNDUMP, - // synDump: SYNDUMP, - // SYNUPDATE, - // synUpdate: SYNUPDATE, + SYNDUMP, + synDump: SYNDUMP, + SYNUPDATE, + synUpdate: SYNUPDATE, TAGVALS, tagVals: TAGVALS }; diff --git a/packages/search/package.json b/packages/search/package.json index 29cb9fc8c4..18a2fc8b48 100644 --- a/packages/search/package.json +++ b/packages/search/package.json @@ -5,7 +5,8 @@ "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ - "dist/" + "dist/", + "!dist/tsconfig.tsbuildinfo" ], "scripts": { "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'"