1
0
mirror of https://github.com/redis/node-redis.git synced 2025-08-06 02:15:48 +03:00

new "transform arguments" API for better key and metadata extraction (#2733)

* Parser support with all commands

* remove "dist" from all imports for consistency

* address most of my review comments

* small tweak to multi type mapping handling

* tweak multi commands / fix addScript cases

* nits

* addressed all in person review comments

* revert addCommand/addScript changes to multi-commands

addCommand needs to be there for sendCommand like ability within a multi.

If its there, it might as well be used by createCommand() et al, to avoid repeating code.

addScript is there (even though only used once), but now made private to keep the logic for bookkeeping near each other.
This commit is contained in:
Shaya Potter
2024-10-31 18:16:59 +02:00
committed by GitHub
parent 5ace34b9c9
commit 4708736f3b
1016 changed files with 6347 additions and 6542 deletions

View File

@@ -1,19 +1,20 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import AGGREGATE from './AGGREGATE';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('AGGREGATE', () => {
describe('transformArguments', () => {
it('without options', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*'),
parseArgs(AGGREGATE, 'index', '*'),
['FT.AGGREGATE', 'index', '*']
);
});
it('with VERBATIM', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
VERBATIM: true
}),
['FT.AGGREGATE', 'index', '*', 'VERBATIM']
@@ -22,7 +23,7 @@ describe('AGGREGATE', () => {
it('with ADDSCORES', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', { ADDSCORES: true }),
parseArgs(AGGREGATE, 'index', '*', { ADDSCORES: true }),
['FT.AGGREGATE', 'index', '*', 'ADDSCORES']
);
});
@@ -32,7 +33,7 @@ describe('AGGREGATE', () => {
describe('without alias', () => {
it('string', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
LOAD: '@property'
}),
['FT.AGGREGATE', 'index', '*', 'LOAD', '1', '@property']
@@ -41,7 +42,7 @@ describe('AGGREGATE', () => {
it('{ identifier: string }', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
LOAD: {
identifier: '@property'
}
@@ -53,7 +54,7 @@ describe('AGGREGATE', () => {
it('with alias', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
LOAD: {
identifier: '@property',
AS: 'alias'
@@ -66,7 +67,7 @@ describe('AGGREGATE', () => {
it('multiple', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
LOAD: ['@1', '@2']
}),
['FT.AGGREGATE', 'index', '*', 'LOAD', '2', '@1', '@2']
@@ -80,7 +81,7 @@ describe('AGGREGATE', () => {
describe('without properties', () => {
it('without alias', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
STEPS: [{
type: 'GROUPBY',
REDUCE: {
@@ -94,7 +95,7 @@ describe('AGGREGATE', () => {
it('with alias', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
STEPS: [{
type: 'GROUPBY',
REDUCE: {
@@ -111,7 +112,7 @@ describe('AGGREGATE', () => {
describe('with properties', () => {
it('single', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
STEPS: [{
type: 'GROUPBY',
properties: '@property',
@@ -126,7 +127,7 @@ describe('AGGREGATE', () => {
it('multiple', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
STEPS: [{
type: 'GROUPBY',
properties: ['@1', '@2'],
@@ -143,7 +144,7 @@ describe('AGGREGATE', () => {
it('COUNT_DISTINCT', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
STEPS: [{
type: 'GROUPBY',
REDUCE: {
@@ -158,7 +159,7 @@ describe('AGGREGATE', () => {
it('COUNT_DISTINCTISH', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
STEPS: [{
type: 'GROUPBY',
REDUCE: {
@@ -173,7 +174,7 @@ describe('AGGREGATE', () => {
it('SUM', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
STEPS: [{
type: 'GROUPBY',
REDUCE: {
@@ -188,7 +189,7 @@ describe('AGGREGATE', () => {
it('MIN', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
STEPS: [{
type: 'GROUPBY',
REDUCE: {
@@ -203,7 +204,7 @@ describe('AGGREGATE', () => {
it('MAX', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
STEPS: [{
type: 'GROUPBY',
REDUCE: {
@@ -218,7 +219,7 @@ describe('AGGREGATE', () => {
it('AVG', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
STEPS: [{
type: 'GROUPBY',
REDUCE: {
@@ -230,10 +231,9 @@ describe('AGGREGATE', () => {
['FT.AGGREGATE', 'index', '*', 'GROUPBY', '0', 'REDUCE', 'AVG', '1', '@property']
);
});
it('STDDEV', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
STEPS: [{
type: 'GROUPBY',
REDUCE: {
@@ -248,7 +248,7 @@ describe('AGGREGATE', () => {
it('QUANTILE', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
STEPS: [{
type: 'GROUPBY',
REDUCE: {
@@ -264,7 +264,7 @@ describe('AGGREGATE', () => {
it('TOLIST', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
STEPS: [{
type: 'GROUPBY',
REDUCE: {
@@ -280,7 +280,7 @@ describe('AGGREGATE', () => {
describe('FIRST_VALUE', () => {
it('simple', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
STEPS: [{
type: 'GROUPBY',
REDUCE: {
@@ -297,7 +297,7 @@ describe('AGGREGATE', () => {
describe('without direction', () => {
it('string', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
STEPS: [{
type: 'GROUPBY',
REDUCE: {
@@ -314,7 +314,7 @@ describe('AGGREGATE', () => {
it('{ property: string }', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
STEPS: [{
type: 'GROUPBY',
REDUCE: {
@@ -333,7 +333,7 @@ describe('AGGREGATE', () => {
it('with direction', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
STEPS: [{
type: 'GROUPBY',
REDUCE: {
@@ -354,7 +354,7 @@ describe('AGGREGATE', () => {
it('RANDOM_SAMPLE', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
STEPS: [{
type: 'GROUPBY',
REDUCE: {
@@ -372,7 +372,7 @@ describe('AGGREGATE', () => {
describe('SORTBY', () => {
it('string', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
STEPS: [{
type: 'SORTBY',
BY: '@by'
@@ -384,7 +384,7 @@ describe('AGGREGATE', () => {
it('Array', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
STEPS: [{
type: 'SORTBY',
BY: ['@1', '@2']
@@ -396,7 +396,7 @@ describe('AGGREGATE', () => {
it('with MAX', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
STEPS: [{
type: 'SORTBY',
BY: '@by',
@@ -410,7 +410,7 @@ describe('AGGREGATE', () => {
describe('APPLY', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
STEPS: [{
type: 'APPLY',
expression: '@field + 1',
@@ -423,7 +423,7 @@ describe('AGGREGATE', () => {
describe('LIMIT', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
STEPS: [{
type: 'LIMIT',
from: 0,
@@ -436,7 +436,7 @@ describe('AGGREGATE', () => {
describe('FILTER', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
STEPS: [{
type: 'FILTER',
expression: '@field != ""'
@@ -449,7 +449,7 @@ describe('AGGREGATE', () => {
it('with PARAMS', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
PARAMS: {
param: 'value'
}
@@ -460,7 +460,7 @@ describe('AGGREGATE', () => {
it('with DIALECT', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', {
parseArgs(AGGREGATE, 'index', '*', {
DIALECT: 1
}),
['FT.AGGREGATE', 'index', '*', 'DIALECT', '1']
@@ -469,7 +469,7 @@ describe('AGGREGATE', () => {
it('with TIMEOUT', () => {
assert.deepEqual(
AGGREGATE.transformArguments('index', '*', { TIMEOUT: 10 }),
parseArgs(AGGREGATE, 'index', '*', { TIMEOUT: 10 }),
['FT.AGGREGATE', 'index', '*', 'TIMEOUT', '10']
);
});

View File

@@ -1,7 +1,8 @@
import { ArrayReply, BlobStringReply, Command, MapReply, NumberReply, RedisArgument, ReplyUnion, TypeMapping, UnwrapReply } from '@redis/client/dist/lib/RESP/types';
import { CommandParser } from '@redis/client/lib/client/parser';
import { ArrayReply, BlobStringReply, Command, MapReply, NumberReply, RedisArgument, ReplyUnion, TypeMapping, UnwrapReply } from '@redis/client/lib/RESP/types';
import { RediSearchProperty } from './CREATE';
import { FtSearchParams, pushParamsArgument } from './SEARCH';
import { pushVariadicArgument, transformTuplesReply } from '@redis/client/dist/lib/commands/generic-transformers';
import { FtSearchParams, parseParamsArgument } from './SEARCH';
import { transformTuplesReply } from '@redis/client/lib/commands/generic-transformers';
type LoadField = RediSearchProperty | {
identifier: RediSearchProperty;
@@ -137,12 +138,12 @@ export interface AggregateReply {
};
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: false,
transformArguments(index: RedisArgument, query: RedisArgument, options?: FtAggregateOptions) {
const args = ['FT.AGGREGATE', index, query];
parseCommand(parser: CommandParser, index: RedisArgument, query: RedisArgument, options?: FtAggregateOptions) {
parser.push('FT.AGGREGATE', index, query);
return pushAggregateOptions(args, options);
return parseAggregateOptions(parser, options);
},
transformReply: {
2: (rawReply: AggregateRawReply, preserve?: any, typeMapping?: TypeMapping): AggregateReply => {
@@ -163,17 +164,17 @@ export default {
unstableResp3: true
} as const satisfies Command;
export function pushAggregateOptions(args: Array<RedisArgument>, options?: FtAggregateOptions) {
export function parseAggregateOptions(parser: CommandParser , options?: FtAggregateOptions) {
if (options?.VERBATIM) {
args.push('VERBATIM');
parser.push('VERBATIM');
}
if (options?.ADDSCORES) {
args.push('ADDSCORES');
parser.push('ADDSCORES');
}
if (options?.LOAD) {
const length = args.push('LOAD', '');
const args: Array<RedisArgument> = [];
if (Array.isArray(options.LOAD)) {
for (const load of options.LOAD) {
@@ -183,36 +184,37 @@ export function pushAggregateOptions(args: Array<RedisArgument>, options?: FtAgg
pushLoadField(args, options.LOAD);
}
args[length - 1] = (args.length - length).toString();
parser.push('LOAD');
parser.pushVariadicWithLength(args);
}
if (options?.TIMEOUT !== undefined) {
args.push('TIMEOUT', options.TIMEOUT.toString());
parser.push('TIMEOUT', options.TIMEOUT.toString());
}
if (options?.STEPS) {
for (const step of options.STEPS) {
args.push(step.type);
parser.push(step.type);
switch (step.type) {
case FT_AGGREGATE_STEPS.GROUPBY:
if (!step.properties) {
args.push('0');
parser.push('0');
} else {
pushVariadicArgument(args, step.properties);
parser.pushVariadicWithLength(step.properties);
}
if (Array.isArray(step.REDUCE)) {
for (const reducer of step.REDUCE) {
pushGroupByReducer(args, reducer);
parseGroupByReducer(parser, reducer);
}
} else {
pushGroupByReducer(args, step.REDUCE);
parseGroupByReducer(parser, step.REDUCE);
}
break;
case FT_AGGREGATE_STEPS.SORTBY:
const length = args.push('');
const args: Array<RedisArgument> = [];
if (Array.isArray(step.BY)) {
for (const by of step.BY) {
@@ -226,32 +228,30 @@ export function pushAggregateOptions(args: Array<RedisArgument>, options?: FtAgg
args.push('MAX', step.MAX.toString());
}
args[length - 1] = (args.length - length).toString();
parser.pushVariadicWithLength(args);
break;
case FT_AGGREGATE_STEPS.APPLY:
args.push(step.expression, 'AS', step.AS);
parser.push(step.expression, 'AS', step.AS);
break;
case FT_AGGREGATE_STEPS.LIMIT:
args.push(step.from.toString(), step.size.toString());
parser.push(step.from.toString(), step.size.toString());
break;
case FT_AGGREGATE_STEPS.FILTER:
args.push(step.expression);
parser.push(step.expression);
break;
}
}
}
pushParamsArgument(args, options?.PARAMS);
parseParamsArgument(parser, options?.PARAMS);
if (options?.DIALECT !== undefined) {
args.push('DIALECT', options.DIALECT.toString());
parser.push('DIALECT', options.DIALECT.toString());
}
return args;
}
function pushLoadField(args: Array<RedisArgument>, toLoad: LoadField) {
@@ -266,12 +266,12 @@ function pushLoadField(args: Array<RedisArgument>, toLoad: LoadField) {
}
}
function pushGroupByReducer(args: Array<RedisArgument>, reducer: GroupByReducers) {
args.push('REDUCE', reducer.type);
function parseGroupByReducer(parser: CommandParser, reducer: GroupByReducers) {
parser.push('REDUCE', reducer.type);
switch (reducer.type) {
case FT_AGGREGATE_GROUP_BY_REDUCERS.COUNT:
args.push('0');
parser.push('0');
break;
case FT_AGGREGATE_GROUP_BY_REDUCERS.COUNT_DISTINCT:
@@ -282,15 +282,16 @@ function pushGroupByReducer(args: Array<RedisArgument>, reducer: GroupByReducers
case FT_AGGREGATE_GROUP_BY_REDUCERS.AVG:
case FT_AGGREGATE_GROUP_BY_REDUCERS.STDDEV:
case FT_AGGREGATE_GROUP_BY_REDUCERS.TOLIST:
args.push('1', reducer.property);
parser.push('1', reducer.property);
break;
case FT_AGGREGATE_GROUP_BY_REDUCERS.QUANTILE:
args.push('2', reducer.property, reducer.quantile.toString());
parser.push('2', reducer.property, reducer.quantile.toString());
break;
case FT_AGGREGATE_GROUP_BY_REDUCERS.FIRST_VALUE: {
const length = args.push('', reducer.property) - 1;
const args: Array<RedisArgument> = [reducer.property];
if (reducer.BY) {
args.push('BY');
if (typeof reducer.BY === 'string' || reducer.BY instanceof Buffer) {
@@ -303,17 +304,17 @@ function pushGroupByReducer(args: Array<RedisArgument>, reducer: GroupByReducers
}
}
args[length - 1] = (args.length - length).toString();
parser.pushVariadicWithLength(args);
break;
}
case FT_AGGREGATE_GROUP_BY_REDUCERS.RANDOM_SAMPLE:
args.push('2', reducer.property, reducer.sampleSize.toString());
parser.push('2', reducer.property, reducer.sampleSize.toString());
break;
}
if (reducer.AS) {
args.push('AS', reducer.AS);
parser.push('AS', reducer.AS);
}
}

View File

@@ -1,19 +1,20 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import AGGREGATE_WITHCURSOR from './AGGREGATE_WITHCURSOR';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('AGGREGATE WITHCURSOR', () => {
describe('transformArguments', () => {
it('without options', () => {
assert.deepEqual(
AGGREGATE_WITHCURSOR.transformArguments('index', '*'),
parseArgs(AGGREGATE_WITHCURSOR, 'index', '*'),
['FT.AGGREGATE', 'index', '*', 'WITHCURSOR']
);
});
it('with COUNT', () => {
assert.deepEqual(
AGGREGATE_WITHCURSOR.transformArguments('index', '*', {
parseArgs(AGGREGATE_WITHCURSOR, 'index', '*', {
COUNT: 1
}),
['FT.AGGREGATE', 'index', '*', 'WITHCURSOR', 'COUNT', '1']
@@ -22,7 +23,7 @@ describe('AGGREGATE WITHCURSOR', () => {
it('with MAXIDLE', () => {
assert.deepEqual(
AGGREGATE_WITHCURSOR.transformArguments('index', '*', {
parseArgs(AGGREGATE_WITHCURSOR, 'index', '*', {
MAXIDLE: 1
}),
['FT.AGGREGATE', 'index', '*', 'WITHCURSOR', 'MAXIDLE', '1']

View File

@@ -1,4 +1,5 @@
import { RedisArgument, Command, ReplyUnion, NumberReply } from '@redis/client/dist/lib/RESP/types';
import { CommandParser } from '@redis/client/lib/client/parser';
import { RedisArgument, Command, ReplyUnion, NumberReply } from '@redis/client/lib/RESP/types';
import AGGREGATE, { AggregateRawReply, AggregateReply, FtAggregateOptions } from './AGGREGATE';
export interface FtAggregateWithCursorOptions extends FtAggregateOptions {
@@ -17,21 +18,18 @@ export interface AggregateWithCursorReply extends AggregateReply {
}
export default {
FIRST_KEY_INDEX: AGGREGATE.FIRST_KEY_INDEX,
IS_READ_ONLY: AGGREGATE.IS_READ_ONLY,
transformArguments(index: RedisArgument, query: RedisArgument, options?: FtAggregateWithCursorOptions) {
const args = AGGREGATE.transformArguments(index, query, options);
args.push('WITHCURSOR');
parseCommand(parser: CommandParser, index: RedisArgument, query: RedisArgument, options?: FtAggregateWithCursorOptions) {
AGGREGATE.parseCommand(parser, index, query, options);
parser.push('WITHCURSOR');
if (options?.COUNT !== undefined) {
args.push('COUNT', options.COUNT.toString());
parser.push('COUNT', options.COUNT.toString());
}
if(options?.MAXIDLE !== undefined) {
args.push('MAXIDLE', options.MAXIDLE.toString());
parser.push('MAXIDLE', options.MAXIDLE.toString());
}
return args;
},
transformReply: {
2: (reply: AggregateWithCursorRawReply): AggregateWithCursorReply => {
@@ -44,4 +42,3 @@ export default {
},
unstableResp3: true
} as const satisfies Command;

View File

@@ -2,11 +2,12 @@ import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import ALIASADD from './ALIASADD';
import { SCHEMA_FIELD_TYPE } from './CREATE';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.ALIASADD', () => {
it('transformArguments', () => {
assert.deepEqual(
ALIASADD.transformArguments('alias', 'index'),
parseArgs(ALIASADD, 'alias', 'index'),
['FT.ALIASADD', 'alias', 'index']
);
});

View File

@@ -1,10 +1,11 @@
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
import { CommandParser } from '@redis/client/lib/client/parser';
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/lib/RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(alias: RedisArgument, index: RedisArgument) {
return ['FT.ALIASADD', alias, index];
parseCommand(parser: CommandParser, alias: RedisArgument, index: RedisArgument) {
parser.push('FT.ALIASADD', alias, index);
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -2,11 +2,12 @@ import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import ALIASDEL from './ALIASDEL';
import { SCHEMA_FIELD_TYPE } from './CREATE';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.ALIASDEL', () => {
it('transformArguments', () => {
assert.deepEqual(
ALIASDEL.transformArguments('alias'),
parseArgs(ALIASDEL, 'alias'),
['FT.ALIASDEL', 'alias']
);
});

View File

@@ -1,10 +1,11 @@
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
import { CommandParser } from '@redis/client/lib/client/parser';
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/lib/RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(alias: RedisArgument) {
return ['FT.ALIASDEL', alias];
parseCommand(parser: CommandParser, alias: RedisArgument) {
parser.push('FT.ALIASDEL', alias);
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -2,11 +2,12 @@ import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import ALIASUPDATE from './ALIASUPDATE';
import { SCHEMA_FIELD_TYPE } from './CREATE';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.ALIASUPDATE', () => {
it('transformArguments', () => {
assert.deepEqual(
ALIASUPDATE.transformArguments('alias', 'index'),
parseArgs(ALIASUPDATE, 'alias', 'index'),
['FT.ALIASUPDATE', 'alias', 'index']
);
});

View File

@@ -1,10 +1,11 @@
import { SimpleStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types';
import { CommandParser } from '@redis/client/lib/client/parser';
import { SimpleStringReply, Command, RedisArgument } from '@redis/client/lib/RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(alias: RedisArgument, index: RedisArgument) {
return ['FT.ALIASUPDATE', alias, index];
parseCommand(parser: CommandParser, alias: RedisArgument, index: RedisArgument) {
parser.push('FT.ALIASUPDATE', alias, index);
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -2,12 +2,13 @@ import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import ALTER from './ALTER';
import { SCHEMA_FIELD_TYPE } from './CREATE';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.ALTER', () => {
describe('transformArguments', () => {
it('with NOINDEX', () => {
assert.deepEqual(
ALTER.transformArguments('index', {
parseArgs(ALTER, 'index', {
field: {
type: SCHEMA_FIELD_TYPE.TEXT,
NOINDEX: true,

View File

@@ -1,13 +1,13 @@
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
import { RediSearchSchema, pushSchema } from './CREATE';
import { CommandParser } from '@redis/client/lib/client/parser';
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/lib/RESP/types';
import { RediSearchSchema, parseSchema } from './CREATE';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(index: RedisArgument, schema: RediSearchSchema) {
const args = ['FT.ALTER', index, 'SCHEMA', 'ADD'];
pushSchema(args, schema);
return args;
parseCommand(parser: CommandParser, index: RedisArgument, schema: RediSearchSchema) {
parser.push('FT.ALTER', index, 'SCHEMA', 'ADD');
parseSchema(parser, schema);
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,11 +1,12 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import CONFIG_GET from './CONFIG_GET';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.CONFIG GET', () => {
it('transformArguments', () => {
assert.deepEqual(
CONFIG_GET.transformArguments('TIMEOUT'),
parseArgs(CONFIG_GET, 'TIMEOUT'),
['FT.CONFIG', 'GET', 'TIMEOUT']
);
});

View File

@@ -1,10 +1,11 @@
import { ArrayReply, TuplesReply, BlobStringReply, NullReply, UnwrapReply, Command } from '@redis/client/dist/lib/RESP/types';
import { CommandParser } from '@redis/client/lib/client/parser';
import { ArrayReply, TuplesReply, BlobStringReply, NullReply, UnwrapReply, Command } from '@redis/client/lib/RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(option: string) {
return ['FT.CONFIG', 'GET', option];
parseCommand(parser: CommandParser, option: string) {
parser.push('FT.CONFIG', 'GET', option);
},
transformReply(reply: UnwrapReply<ArrayReply<TuplesReply<[BlobStringReply, BlobStringReply | NullReply]>>>) {
const transformedReply: Record<string, BlobStringReply | NullReply> = Object.create(null);

View File

@@ -1,11 +1,12 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import CONFIG_SET from './CONFIG_SET';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.CONFIG SET', () => {
it('transformArguments', () => {
assert.deepEqual(
CONFIG_SET.transformArguments('TIMEOUT', '500'),
parseArgs(CONFIG_SET, 'TIMEOUT', '500'),
['FT.CONFIG', 'SET', 'TIMEOUT', '500']
);
});

View File

@@ -1,14 +1,15 @@
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
import { CommandParser } from '@redis/client/lib/client/parser';
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/lib/RESP/types';
// using `string & {}` to avoid TS widening the type to `string`
// TODO
type FtConfigProperties = 'a' | 'b' | (string & {}) | Buffer;
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(property: FtConfigProperties, value: RedisArgument) {
return ['FT.CONFIG', 'SET', property, value];
parseCommand(parser: CommandParser, property: FtConfigProperties, value: RedisArgument) {
parser.push('FT.CONFIG', 'SET', property, value);
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,12 +1,13 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import CREATE, { SCHEMA_FIELD_TYPE, SCHEMA_TEXT_FIELD_PHONETIC, SCHEMA_VECTOR_FIELD_ALGORITHM, REDISEARCH_LANGUAGE } from './CREATE';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.CREATE', () => {
describe('transformArguments', () => {
it('simple', () => {
assert.deepEqual(
CREATE.transformArguments('index', {}),
parseArgs(CREATE, 'index', {}),
['FT.CREATE', 'index', 'SCHEMA']
);
});
@@ -15,7 +16,7 @@ describe('FT.CREATE', () => {
describe('TEXT', () => {
it('without options', () => {
assert.deepEqual(
CREATE.transformArguments('index', {
parseArgs(CREATE, 'index', {
field: SCHEMA_FIELD_TYPE.TEXT
}),
['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT']
@@ -24,7 +25,7 @@ describe('FT.CREATE', () => {
it('with NOSTEM', () => {
assert.deepEqual(
CREATE.transformArguments('index', {
parseArgs(CREATE, 'index', {
field: {
type: SCHEMA_FIELD_TYPE.TEXT,
NOSTEM: true
@@ -36,7 +37,7 @@ describe('FT.CREATE', () => {
it('with WEIGHT', () => {
assert.deepEqual(
CREATE.transformArguments('index', {
parseArgs(CREATE, 'index', {
field: {
type: SCHEMA_FIELD_TYPE.TEXT,
WEIGHT: 1
@@ -48,7 +49,7 @@ describe('FT.CREATE', () => {
it('with PHONETIC', () => {
assert.deepEqual(
CREATE.transformArguments('index', {
parseArgs(CREATE, 'index', {
field: {
type: SCHEMA_FIELD_TYPE.TEXT,
PHONETIC: SCHEMA_TEXT_FIELD_PHONETIC.DM_EN
@@ -60,7 +61,7 @@ describe('FT.CREATE', () => {
it('with WITHSUFFIXTRIE', () => {
assert.deepEqual(
CREATE.transformArguments('index', {
parseArgs(CREATE, 'index', {
field: {
type: SCHEMA_FIELD_TYPE.TEXT,
WITHSUFFIXTRIE: true
@@ -73,7 +74,7 @@ describe('FT.CREATE', () => {
it('NUMERIC', () => {
assert.deepEqual(
CREATE.transformArguments('index', {
parseArgs(CREATE, 'index', {
field: SCHEMA_FIELD_TYPE.NUMERIC
}),
['FT.CREATE', 'index', 'SCHEMA', 'field', 'NUMERIC']
@@ -82,7 +83,7 @@ describe('FT.CREATE', () => {
it('GEO', () => {
assert.deepEqual(
CREATE.transformArguments('index', {
parseArgs(CREATE, 'index', {
field: SCHEMA_FIELD_TYPE.GEO
}),
['FT.CREATE', 'index', 'SCHEMA', 'field', 'GEO']
@@ -93,7 +94,7 @@ describe('FT.CREATE', () => {
describe('without options', () => {
it('SCHEMA_FIELD_TYPE.TAG', () => {
assert.deepEqual(
CREATE.transformArguments('index', {
parseArgs(CREATE, 'index', {
field: SCHEMA_FIELD_TYPE.TAG
}),
['FT.CREATE', 'index', 'SCHEMA', 'field', 'TAG']
@@ -102,7 +103,7 @@ describe('FT.CREATE', () => {
it('{ type: SCHEMA_FIELD_TYPE.TAG }', () => {
assert.deepEqual(
CREATE.transformArguments('index', {
parseArgs(CREATE, 'index', {
field: {
type: SCHEMA_FIELD_TYPE.TAG
}
@@ -114,7 +115,7 @@ describe('FT.CREATE', () => {
it('with SEPARATOR', () => {
assert.deepEqual(
CREATE.transformArguments('index', {
parseArgs(CREATE, 'index', {
field: {
type: SCHEMA_FIELD_TYPE.TAG,
SEPARATOR: 'separator'
@@ -126,7 +127,7 @@ describe('FT.CREATE', () => {
it('with CASESENSITIVE', () => {
assert.deepEqual(
CREATE.transformArguments('index', {
parseArgs(CREATE, 'index', {
field: {
type: SCHEMA_FIELD_TYPE.TAG,
CASESENSITIVE: true
@@ -138,7 +139,7 @@ describe('FT.CREATE', () => {
it('with WITHSUFFIXTRIE', () => {
assert.deepEqual(
CREATE.transformArguments('index', {
parseArgs(CREATE, 'index', {
field: {
type: SCHEMA_FIELD_TYPE.TAG,
WITHSUFFIXTRIE: true
@@ -150,7 +151,7 @@ describe('FT.CREATE', () => {
it('with INDEXEMPTY', () => {
assert.deepEqual(
CREATE.transformArguments('index', {
parseArgs(CREATE, 'index', {
field: {
type: SCHEMA_FIELD_TYPE.TAG,
INDEXEMPTY: true
@@ -164,7 +165,7 @@ describe('FT.CREATE', () => {
describe('VECTOR', () => {
it('Flat algorithm', () => {
assert.deepEqual(
CREATE.transformArguments('index', {
parseArgs(CREATE, 'index', {
field: {
type: SCHEMA_FIELD_TYPE.VECTOR,
ALGORITHM: SCHEMA_VECTOR_FIELD_ALGORITHM.FLAT,
@@ -185,7 +186,7 @@ describe('FT.CREATE', () => {
it('HNSW algorithm', () => {
assert.deepEqual(
CREATE.transformArguments('index', {
parseArgs(CREATE, 'index', {
field: {
type: SCHEMA_FIELD_TYPE.VECTOR,
ALGORITHM: SCHEMA_VECTOR_FIELD_ALGORITHM.HNSW,
@@ -211,7 +212,7 @@ describe('FT.CREATE', () => {
describe('without options', () => {
it('SCHEMA_FIELD_TYPE.GEOSHAPE', () => {
assert.deepEqual(
CREATE.transformArguments('index', {
parseArgs(CREATE, 'index', {
field: SCHEMA_FIELD_TYPE.GEOSHAPE
}),
['FT.CREATE', 'index', 'SCHEMA', 'field', 'GEOSHAPE']
@@ -220,7 +221,7 @@ describe('FT.CREATE', () => {
it('{ type: SCHEMA_FIELD_TYPE.GEOSHAPE }', () => {
assert.deepEqual(
CREATE.transformArguments('index', {
parseArgs(CREATE, 'index', {
field: {
type: SCHEMA_FIELD_TYPE.GEOSHAPE
}
@@ -232,7 +233,7 @@ describe('FT.CREATE', () => {
it('with COORD_SYSTEM', () => {
assert.deepEqual(
CREATE.transformArguments('index', {
parseArgs(CREATE, 'index', {
field: {
type: SCHEMA_FIELD_TYPE.GEOSHAPE,
COORD_SYSTEM: 'SPHERICAL'
@@ -245,7 +246,7 @@ describe('FT.CREATE', () => {
it('with AS', () => {
assert.deepEqual(
CREATE.transformArguments('index', {
parseArgs(CREATE, 'index', {
field: {
type: SCHEMA_FIELD_TYPE.TEXT,
AS: 'as'
@@ -258,7 +259,7 @@ describe('FT.CREATE', () => {
describe('with SORTABLE', () => {
it('true', () => {
assert.deepEqual(
CREATE.transformArguments('index', {
parseArgs(CREATE, 'index', {
field: {
type: SCHEMA_FIELD_TYPE.TEXT,
SORTABLE: true
@@ -270,7 +271,7 @@ describe('FT.CREATE', () => {
it('UNF', () => {
assert.deepEqual(
CREATE.transformArguments('index', {
parseArgs(CREATE, 'index', {
field: {
type: SCHEMA_FIELD_TYPE.TEXT,
SORTABLE: 'UNF'
@@ -283,7 +284,7 @@ describe('FT.CREATE', () => {
it('with NOINDEX', () => {
assert.deepEqual(
CREATE.transformArguments('index', {
parseArgs(CREATE, 'index', {
field: {
type: SCHEMA_FIELD_TYPE.TEXT,
NOINDEX: true
@@ -295,7 +296,7 @@ describe('FT.CREATE', () => {
it('with INDEXMISSING', () => {
assert.deepEqual(
CREATE.transformArguments('index', {
parseArgs(CREATE, 'index', {
field: {
type: SCHEMA_FIELD_TYPE.TEXT,
INDEXMISSING: true
@@ -308,7 +309,7 @@ describe('FT.CREATE', () => {
it('with ON', () => {
assert.deepEqual(
CREATE.transformArguments('index', {}, {
parseArgs(CREATE, 'index', {}, {
ON: 'HASH'
}),
['FT.CREATE', 'index', 'ON', 'HASH', 'SCHEMA']
@@ -318,7 +319,7 @@ describe('FT.CREATE', () => {
describe('with PREFIX', () => {
it('string', () => {
assert.deepEqual(
CREATE.transformArguments('index', {}, {
parseArgs(CREATE, 'index', {}, {
PREFIX: 'prefix'
}),
['FT.CREATE', 'index', 'PREFIX', '1', 'prefix', 'SCHEMA']
@@ -327,7 +328,7 @@ describe('FT.CREATE', () => {
it('Array', () => {
assert.deepEqual(
CREATE.transformArguments('index', {}, {
parseArgs(CREATE, 'index', {}, {
PREFIX: ['1', '2']
}),
['FT.CREATE', 'index', 'PREFIX', '2', '1', '2', 'SCHEMA']
@@ -337,7 +338,7 @@ describe('FT.CREATE', () => {
it('with FILTER', () => {
assert.deepEqual(
CREATE.transformArguments('index', {}, {
parseArgs(CREATE, 'index', {}, {
FILTER: '@field != ""'
}),
['FT.CREATE', 'index', 'FILTER', '@field != ""', 'SCHEMA']
@@ -346,7 +347,7 @@ describe('FT.CREATE', () => {
it('with LANGUAGE', () => {
assert.deepEqual(
CREATE.transformArguments('index', {}, {
parseArgs(CREATE, 'index', {}, {
LANGUAGE: REDISEARCH_LANGUAGE.ARABIC
}),
['FT.CREATE', 'index', 'LANGUAGE', REDISEARCH_LANGUAGE.ARABIC, 'SCHEMA']
@@ -355,7 +356,7 @@ describe('FT.CREATE', () => {
it('with LANGUAGE_FIELD', () => {
assert.deepEqual(
CREATE.transformArguments('index', {}, {
parseArgs(CREATE, 'index', {}, {
LANGUAGE_FIELD: '@field'
}),
['FT.CREATE', 'index', 'LANGUAGE_FIELD', '@field', 'SCHEMA']
@@ -364,7 +365,7 @@ describe('FT.CREATE', () => {
it('with SCORE', () => {
assert.deepEqual(
CREATE.transformArguments('index', {}, {
parseArgs(CREATE, 'index', {}, {
SCORE: 1
}),
['FT.CREATE', 'index', 'SCORE', '1', 'SCHEMA']
@@ -373,7 +374,7 @@ describe('FT.CREATE', () => {
it('with SCORE_FIELD', () => {
assert.deepEqual(
CREATE.transformArguments('index', {}, {
parseArgs(CREATE, 'index', {}, {
SCORE_FIELD: '@field'
}),
['FT.CREATE', 'index', 'SCORE_FIELD', '@field', 'SCHEMA']
@@ -382,7 +383,7 @@ describe('FT.CREATE', () => {
it('with MAXTEXTFIELDS', () => {
assert.deepEqual(
CREATE.transformArguments('index', {}, {
parseArgs(CREATE, 'index', {}, {
MAXTEXTFIELDS: true
}),
['FT.CREATE', 'index', 'MAXTEXTFIELDS', 'SCHEMA']
@@ -391,7 +392,7 @@ describe('FT.CREATE', () => {
it('with TEMPORARY', () => {
assert.deepEqual(
CREATE.transformArguments('index', {}, {
parseArgs(CREATE, 'index', {}, {
TEMPORARY: 1
}),
['FT.CREATE', 'index', 'TEMPORARY', '1', 'SCHEMA']
@@ -400,7 +401,7 @@ describe('FT.CREATE', () => {
it('with NOOFFSETS', () => {
assert.deepEqual(
CREATE.transformArguments('index', {}, {
parseArgs(CREATE, 'index', {}, {
NOOFFSETS: true
}),
['FT.CREATE', 'index', 'NOOFFSETS', 'SCHEMA']
@@ -409,7 +410,7 @@ describe('FT.CREATE', () => {
it('with NOHL', () => {
assert.deepEqual(
CREATE.transformArguments('index', {}, {
parseArgs(CREATE, 'index', {}, {
NOHL: true
}),
['FT.CREATE', 'index', 'NOHL', 'SCHEMA']
@@ -418,7 +419,7 @@ describe('FT.CREATE', () => {
it('with NOFIELDS', () => {
assert.deepEqual(
CREATE.transformArguments('index', {}, {
parseArgs(CREATE, 'index', {}, {
NOFIELDS: true
}),
['FT.CREATE', 'index', 'NOFIELDS', 'SCHEMA']
@@ -427,7 +428,7 @@ describe('FT.CREATE', () => {
it('with NOFREQS', () => {
assert.deepEqual(
CREATE.transformArguments('index', {}, {
parseArgs(CREATE, 'index', {}, {
NOFREQS: true
}),
['FT.CREATE', 'index', 'NOFREQS', 'SCHEMA']
@@ -436,7 +437,7 @@ describe('FT.CREATE', () => {
it('with SKIPINITIALSCAN', () => {
assert.deepEqual(
CREATE.transformArguments('index', {}, {
parseArgs(CREATE, 'index', {}, {
SKIPINITIALSCAN: true
}),
['FT.CREATE', 'index', 'SKIPINITIALSCAN', 'SCHEMA']
@@ -446,7 +447,7 @@ describe('FT.CREATE', () => {
describe('with STOPWORDS', () => {
it('string', () => {
assert.deepEqual(
CREATE.transformArguments('index', {}, {
parseArgs(CREATE, 'index', {}, {
STOPWORDS: 'stopword'
}),
['FT.CREATE', 'index', 'STOPWORDS', '1', 'stopword', 'SCHEMA']
@@ -455,7 +456,7 @@ describe('FT.CREATE', () => {
it('Array', () => {
assert.deepEqual(
CREATE.transformArguments('index', {}, {
parseArgs(CREATE, 'index', {}, {
STOPWORDS: ['1', '2']
}),
['FT.CREATE', 'index', 'STOPWORDS', '2', '1', '2', 'SCHEMA']

View File

@@ -1,5 +1,6 @@
import { RedisArgument, SimpleStringReply, Command, CommandArguments } from '@redis/client/lib/RESP/types';
import { RedisVariadicArgument, pushOptionalVariadicArgument } from '@redis/client/lib/commands/generic-transformers';
import { CommandParser } from '@redis/client/lib/client/parser';
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/lib/RESP/types';
import { RedisVariadicArgument, parseOptionalVariadicArgument } from '@redis/client/lib/commands/generic-transformers';
export const SCHEMA_FIELD_TYPE = {
TEXT: 'TEXT',
@@ -102,93 +103,93 @@ export interface RediSearchSchema {
);
}
function pushCommonSchemaFieldOptions(args: CommandArguments, fieldOptions: SchemaCommonField) {
function parseCommonSchemaFieldOptions(parser: CommandParser, fieldOptions: SchemaCommonField) {
if (fieldOptions.SORTABLE) {
args.push('SORTABLE');
parser.push('SORTABLE');
if (fieldOptions.SORTABLE === 'UNF') {
args.push('UNF');
parser.push('UNF');
}
}
if (fieldOptions.NOINDEX) {
args.push('NOINDEX');
parser.push('NOINDEX');
}
}
export function pushSchema(args: CommandArguments, schema: RediSearchSchema) {
export function parseSchema(parser: CommandParser, schema: RediSearchSchema) {
for (const [field, fieldOptions] of Object.entries(schema)) {
args.push(field);
parser.push(field);
if (typeof fieldOptions === 'string') {
args.push(fieldOptions);
parser.push(fieldOptions);
continue;
}
if (fieldOptions.AS) {
args.push('AS', fieldOptions.AS);
parser.push('AS', fieldOptions.AS);
}
args.push(fieldOptions.type);
parser.push(fieldOptions.type);
if (fieldOptions.INDEXMISSING) {
args.push('INDEXMISSING');
parser.push('INDEXMISSING');
}
switch (fieldOptions.type) {
case SCHEMA_FIELD_TYPE.TEXT:
if (fieldOptions.NOSTEM) {
args.push('NOSTEM');
parser.push('NOSTEM');
}
if (fieldOptions.WEIGHT) {
args.push('WEIGHT', fieldOptions.WEIGHT.toString());
parser.push('WEIGHT', fieldOptions.WEIGHT.toString());
}
if (fieldOptions.PHONETIC) {
args.push('PHONETIC', fieldOptions.PHONETIC);
parser.push('PHONETIC', fieldOptions.PHONETIC);
}
if (fieldOptions.WITHSUFFIXTRIE) {
args.push('WITHSUFFIXTRIE');
parser.push('WITHSUFFIXTRIE');
}
if (fieldOptions.INDEXEMPTY) {
args.push('INDEXEMPTY');
parser.push('INDEXEMPTY');
}
pushCommonSchemaFieldOptions(args, fieldOptions)
parseCommonSchemaFieldOptions(parser, fieldOptions)
break;
case SCHEMA_FIELD_TYPE.NUMERIC:
case SCHEMA_FIELD_TYPE.GEO:
pushCommonSchemaFieldOptions(args, fieldOptions)
parseCommonSchemaFieldOptions(parser, fieldOptions)
break;
case SCHEMA_FIELD_TYPE.TAG:
if (fieldOptions.SEPARATOR) {
args.push('SEPARATOR', fieldOptions.SEPARATOR);
parser.push('SEPARATOR', fieldOptions.SEPARATOR);
}
if (fieldOptions.CASESENSITIVE) {
args.push('CASESENSITIVE');
parser.push('CASESENSITIVE');
}
if (fieldOptions.WITHSUFFIXTRIE) {
args.push('WITHSUFFIXTRIE');
parser.push('WITHSUFFIXTRIE');
}
if (fieldOptions.INDEXEMPTY) {
args.push('INDEXEMPTY');
parser.push('INDEXEMPTY');
}
pushCommonSchemaFieldOptions(args, fieldOptions)
parseCommonSchemaFieldOptions(parser, fieldOptions)
break;
case SCHEMA_FIELD_TYPE.VECTOR:
args.push(fieldOptions.ALGORITHM);
parser.push(fieldOptions.ALGORITHM);
const lengthIndex = args.push('') - 1;
const args: Array<RedisArgument> = [];
args.push(
'TYPE', fieldOptions.TYPE,
@@ -200,7 +201,7 @@ export function pushSchema(args: CommandArguments, schema: RediSearchSchema) {
args.push('INITIAL_CAP', fieldOptions.INITIAL_CAP.toString());
}
switch (fieldOptions.ALGORITHM) {
switch (fieldOptions.ALGORITHM) {
case SCHEMA_VECTOR_FIELD_ALGORITHM.FLAT:
if (fieldOptions.BLOCK_SIZE) {
args.push('BLOCK_SIZE', fieldOptions.BLOCK_SIZE.toString());
@@ -223,13 +224,13 @@ export function pushSchema(args: CommandArguments, schema: RediSearchSchema) {
break;
}
args[lengthIndex] = (args.length - lengthIndex - 1).toString();
parser.pushVariadicWithLength(args);
break;
case SCHEMA_FIELD_TYPE.GEOSHAPE:
if (fieldOptions.COORD_SYSTEM !== undefined) {
args.push('COORD_SYSTEM', fieldOptions.COORD_SYSTEM);
parser.push('COORD_SYSTEM', fieldOptions.COORD_SYSTEM);
}
break;
@@ -289,74 +290,72 @@ export interface CreateOptions {
}
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(index: RedisArgument, schema: RediSearchSchema, options?: CreateOptions) {
const args = ['FT.CREATE', index];
parseCommand(parser: CommandParser, index: RedisArgument, schema: RediSearchSchema, options?: CreateOptions) {
parser.push('FT.CREATE', index);
if (options?.ON) {
args.push('ON', options.ON);
parser.push('ON', options.ON);
}
pushOptionalVariadicArgument(args, 'PREFIX', options?.PREFIX);
parseOptionalVariadicArgument(parser, 'PREFIX', options?.PREFIX);
if (options?.FILTER) {
args.push('FILTER', options.FILTER);
parser.push('FILTER', options.FILTER);
}
if (options?.LANGUAGE) {
args.push('LANGUAGE', options.LANGUAGE);
parser.push('LANGUAGE', options.LANGUAGE);
}
if (options?.LANGUAGE_FIELD) {
args.push('LANGUAGE_FIELD', options.LANGUAGE_FIELD);
parser.push('LANGUAGE_FIELD', options.LANGUAGE_FIELD);
}
if (options?.SCORE) {
args.push('SCORE', options.SCORE.toString());
parser.push('SCORE', options.SCORE.toString());
}
if (options?.SCORE_FIELD) {
args.push('SCORE_FIELD', options.SCORE_FIELD);
parser.push('SCORE_FIELD', options.SCORE_FIELD);
}
// if (options?.PAYLOAD_FIELD) {
// args.push('PAYLOAD_FIELD', options.PAYLOAD_FIELD);
// parser.push('PAYLOAD_FIELD', options.PAYLOAD_FIELD);
// }
if (options?.MAXTEXTFIELDS) {
args.push('MAXTEXTFIELDS');
parser.push('MAXTEXTFIELDS');
}
if (options?.TEMPORARY) {
args.push('TEMPORARY', options.TEMPORARY.toString());
parser.push('TEMPORARY', options.TEMPORARY.toString());
}
if (options?.NOOFFSETS) {
args.push('NOOFFSETS');
parser.push('NOOFFSETS');
}
if (options?.NOHL) {
args.push('NOHL');
parser.push('NOHL');
}
if (options?.NOFIELDS) {
args.push('NOFIELDS');
parser.push('NOFIELDS');
}
if (options?.NOFREQS) {
args.push('NOFREQS');
parser.push('NOFREQS');
}
if (options?.SKIPINITIALSCAN) {
args.push('SKIPINITIALSCAN');
parser.push('SKIPINITIALSCAN');
}
pushOptionalVariadicArgument(args, 'STOPWORDS', options?.STOPWORDS);
args.push('SCHEMA');
pushSchema(args, schema);
return args;
parseOptionalVariadicArgument(parser, 'STOPWORDS', options?.STOPWORDS);
parser.push('SCHEMA');
parseSchema(parser, schema);
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -2,11 +2,12 @@ import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import CURSOR_DEL from './CURSOR_DEL';
import { SCHEMA_FIELD_TYPE } from './CREATE';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.CURSOR DEL', () => {
it('transformArguments', () => {
assert.deepEqual(
CURSOR_DEL.transformArguments('index', 0),
parseArgs(CURSOR_DEL, 'index', 0),
['FT.CURSOR', 'DEL', 'index', '0']
);
});

View File

@@ -1,10 +1,11 @@
import { SimpleStringReply, Command, RedisArgument, NumberReply, UnwrapReply } from '@redis/client/dist/lib/RESP/types';
import { CommandParser } from '@redis/client/lib/client/parser';
import { SimpleStringReply, Command, RedisArgument, NumberReply, UnwrapReply } from '@redis/client/lib/RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(index: RedisArgument, cursorId: UnwrapReply<NumberReply>) {
return ['FT.CURSOR', 'DEL', index, cursorId.toString()];
parseCommand(parser: CommandParser, index: RedisArgument, cursorId: UnwrapReply<NumberReply>) {
parser.push('FT.CURSOR', 'DEL', index, cursorId.toString());
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,19 +1,20 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import CURSOR_READ from './CURSOR_READ';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.CURSOR READ', () => {
describe('transformArguments', () => {
it('without options', () => {
assert.deepEqual(
CURSOR_READ.transformArguments('index', 0),
parseArgs(CURSOR_READ, 'index', '0'),
['FT.CURSOR', 'READ', 'index', '0']
);
});
it('with COUNT', () => {
assert.deepEqual(
CURSOR_READ.transformArguments('index', 0, {
parseArgs(CURSOR_READ, 'index', '0', {
COUNT: 1
}),
['FT.CURSOR', 'READ', 'index', '0', 'COUNT', '1']

View File

@@ -1,4 +1,5 @@
import { RedisArgument, Command, UnwrapReply, NumberReply } from '@redis/client/dist/lib/RESP/types';
import { CommandParser } from '@redis/client/lib/client/parser';
import { RedisArgument, Command, NumberReply, UnwrapReply } from '@redis/client/lib/RESP/types';
import AGGREGATE_WITHCURSOR from './AGGREGATE_WITHCURSOR';
export interface FtCursorReadOptions {
@@ -6,16 +7,14 @@ export interface FtCursorReadOptions {
}
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(index: RedisArgument, cursor: UnwrapReply<NumberReply>, options?: FtCursorReadOptions) {
const args = ['FT.CURSOR', 'READ', index, cursor.toString()];
parseCommand(parser: CommandParser, index: RedisArgument, cursor: UnwrapReply<NumberReply>, options?: FtCursorReadOptions) {
parser.push('FT.CURSOR', 'READ', index, cursor.toString());
if (options?.COUNT !== undefined) {
args.push('COUNT', options.COUNT.toString());
parser.push('COUNT', options.COUNT.toString());
}
return args;
},
transformReply: AGGREGATE_WITHCURSOR.transformReply,
unstableResp3: true

View File

@@ -1,19 +1,20 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import DICTADD from './DICTADD';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.DICTADD', () => {
describe('transformArguments', () => {
it('string', () => {
assert.deepEqual(
DICTADD.transformArguments('dictionary', 'term'),
parseArgs(DICTADD, 'dictionary', 'term'),
['FT.DICTADD', 'dictionary', 'term']
);
});
it('Array', () => {
assert.deepEqual(
DICTADD.transformArguments('dictionary', ['1', '2']),
parseArgs(DICTADD, 'dictionary', ['1', '2']),
['FT.DICTADD', 'dictionary', '1', '2']
);
});

View File

@@ -1,11 +1,13 @@
import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types';
import { pushVariadicArguments, RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
import { CommandParser } from '@redis/client/lib/client/parser';
import { RedisArgument, NumberReply, Command } from '@redis/client/lib/RESP/types';
import { RedisVariadicArgument } from '@redis/client/lib/commands/generic-transformers';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(dictionary: RedisArgument, term: RedisVariadicArgument) {
return pushVariadicArguments(['FT.DICTADD', dictionary], term);
parseCommand(parser: CommandParser, dictionary: RedisArgument, term: RedisVariadicArgument) {
parser.push('FT.DICTADD', dictionary);
parser.pushVariadic(term);
},
transformReply: undefined as unknown as () => NumberReply
} as const satisfies Command;

View File

@@ -1,19 +1,20 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import DICTDEL from './DICTDEL';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.DICTDEL', () => {
describe('transformArguments', () => {
it('string', () => {
assert.deepEqual(
DICTDEL.transformArguments('dictionary', 'term'),
parseArgs(DICTDEL, 'dictionary', 'term'),
['FT.DICTDEL', 'dictionary', 'term']
);
});
it('Array', () => {
assert.deepEqual(
DICTDEL.transformArguments('dictionary', ['1', '2']),
parseArgs(DICTDEL, 'dictionary', ['1', '2']),
['FT.DICTDEL', 'dictionary', '1', '2']
);
});

View File

@@ -1,11 +1,13 @@
import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types';
import { pushVariadicArguments, RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
import { CommandParser } from '@redis/client/lib/client/parser';
import { RedisArgument, NumberReply, Command } from '@redis/client/lib/RESP/types';
import { RedisVariadicArgument } from '@redis/client/lib/commands/generic-transformers';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(dictionary: RedisArgument, term: RedisVariadicArgument) {
return pushVariadicArguments(['FT.DICTDEL', dictionary], term);
parseCommand(parser: CommandParser, dictionary: RedisArgument, term: RedisVariadicArgument) {
parser.push('FT.DICTDEL', dictionary);
parser.pushVariadic(term);
},
transformReply: undefined as unknown as () => NumberReply
} as const satisfies Command;

View File

@@ -1,11 +1,12 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import DICTDUMP from './DICTDUMP';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.DICTDUMP', () => {
it('transformArguments', () => {
assert.deepEqual(
DICTDUMP.transformArguments('dictionary'),
parseArgs(DICTDUMP, 'dictionary'),
['FT.DICTDUMP', 'dictionary']
);
});

View File

@@ -1,10 +1,11 @@
import { RedisArgument, ArrayReply, SetReply, BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types';
import { CommandParser } from '@redis/client/lib/client/parser';
import { RedisArgument, ArrayReply, SetReply, BlobStringReply, Command } from '@redis/client/lib/RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(dictionary: RedisArgument) {
return ['FT.DICTDUMP', dictionary];
parseCommand(parser: CommandParser, dictionary: RedisArgument) {
parser.push('FT.DICTDUMP', dictionary);
},
transformReply: {
2: undefined as unknown as () => ArrayReply<BlobStringReply>,

View File

@@ -2,19 +2,20 @@ import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import DROPINDEX from './DROPINDEX';
import { SCHEMA_FIELD_TYPE } from './CREATE';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.DROPINDEX', () => {
describe('transformArguments', () => {
it('without options', () => {
assert.deepEqual(
DROPINDEX.transformArguments('index'),
parseArgs(DROPINDEX, 'index'),
['FT.DROPINDEX', 'index']
);
});
it('with DD', () => {
assert.deepEqual(
DROPINDEX.transformArguments('index', { DD: true }),
parseArgs(DROPINDEX, 'index', { DD: true }),
['FT.DROPINDEX', 'index', 'DD']
);
});

View File

@@ -1,20 +1,19 @@
import { RedisArgument, SimpleStringReply, NumberReply, Command } from '@redis/client/dist/lib/RESP/types';
import { CommandParser } from '@redis/client/lib/client/parser';
import { RedisArgument, SimpleStringReply, NumberReply, Command } from '@redis/client/lib/RESP/types';
export interface FtDropIndexOptions {
DD?: true;
}
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(index: RedisArgument, options?: FtDropIndexOptions) {
const args = ['FT.DROPINDEX', index];
parseCommand(parser: CommandParser, index: RedisArgument, options?: FtDropIndexOptions) {
parser.push('FT.DROPINDEX', index);
if (options?.DD) {
args.push('DD');
parser.push('DD');
}
return args;
},
transformReply: {
2: undefined as unknown as () => SimpleStringReply<'OK'>,

View File

@@ -1,5 +1,6 @@
import { strict as assert } from 'node:assert';
import EXPLAIN from './EXPLAIN';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
import testUtils, { GLOBAL } from '../test-utils';
import { SCHEMA_FIELD_TYPE } from './CREATE';
@@ -7,14 +8,14 @@ describe('EXPLAIN', () => {
describe('transformArguments', () => {
it('simple', () => {
assert.deepEqual(
EXPLAIN.transformArguments('index', '*'),
parseArgs(EXPLAIN, 'index', '*'),
['FT.EXPLAIN', 'index', '*']
);
});
it('with PARAMS', () => {
assert.deepEqual(
EXPLAIN.transformArguments('index', '*', {
parseArgs(EXPLAIN, 'index', '*', {
PARAMS: {
param: 'value'
}
@@ -25,7 +26,7 @@ describe('EXPLAIN', () => {
it('with DIALECT', () => {
assert.deepEqual(
EXPLAIN.transformArguments('index', '*', {
parseArgs(EXPLAIN, 'index', '*', {
DIALECT: 1
}),
['FT.EXPLAIN', 'index', '*', 'DIALECT', '1']

View File

@@ -1,5 +1,6 @@
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
import { FtSearchParams, pushParamsArgument } from './SEARCH';
import { CommandParser } from '@redis/client/lib/client/parser';
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/lib/RESP/types';
import { FtSearchParams, parseParamsArgument } from './SEARCH';
export interface FtExplainOptions {
PARAMS?: FtSearchParams;
@@ -7,22 +8,21 @@ export interface FtExplainOptions {
}
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(
parseCommand(
parser: CommandParser,
index: RedisArgument,
query: RedisArgument,
options?: FtExplainOptions
) {
const args = ['FT.EXPLAIN', index, query];
parser.push('FT.EXPLAIN', index, query);
pushParamsArgument(args, options?.PARAMS);
parseParamsArgument(parser, options?.PARAMS);
if (options?.DIALECT) {
args.push('DIALECT', options.DIALECT.toString());
parser.push('DIALECT', options.DIALECT.toString());
}
return args;
},
transformReply: undefined as unknown as () => SimpleStringReply
} as const satisfies Command;

View File

@@ -1,10 +1,11 @@
import { strict as assert } from 'node:assert';
import EXPLAINCLI from './EXPLAINCLI';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('EXPLAINCLI', () => {
it('transformArguments', () => {
assert.deepEqual(
EXPLAINCLI.transformArguments('index', '*'),
parseArgs(EXPLAINCLI, 'index', '*'),
['FT.EXPLAINCLI', 'index', '*']
);
});

View File

@@ -1,10 +1,11 @@
import { RedisArgument, ArrayReply, BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types';
import { CommandParser } from '@redis/client/lib/client/parser';
import { RedisArgument, ArrayReply, BlobStringReply, Command } from '@redis/client/lib/RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(index: RedisArgument, query: RedisArgument) {
return ['FT.EXPLAINCLI', index, query];
parseCommand(parser: CommandParser, index: RedisArgument, query: RedisArgument) {
parser.push('FT.EXPLAINCLI', index, query);
},
transformReply: undefined as unknown as () => ArrayReply<BlobStringReply>
} as const satisfies Command;

View File

@@ -2,11 +2,12 @@ import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import INFO, { InfoReply } from './INFO';
import { SCHEMA_FIELD_TYPE } from './CREATE';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('INFO', () => {
it('transformArguments', () => {
assert.deepEqual(
INFO.transformArguments('index'),
parseArgs(INFO, 'index'),
['FT.INFO', 'index']
);
});

View File

@@ -1,13 +1,14 @@
import { CommandParser } from '@redis/client/lib/client/parser';
import { RedisArgument } from "@redis/client";
import { ArrayReply, BlobStringReply, Command, DoubleReply, MapReply, NullReply, NumberReply, ReplyUnion, SimpleStringReply, TypeMapping } from "@redis/client/dist/lib/RESP/types";
import { createTransformTuplesReplyFunc, transformDoubleReply } from "@redis/client/dist/lib/commands/generic-transformers";
import { ArrayReply, BlobStringReply, Command, DoubleReply, MapReply, NullReply, NumberReply, ReplyUnion, SimpleStringReply, TypeMapping } from "@redis/client/lib/RESP/types";
import { createTransformTuplesReplyFunc, transformDoubleReply } from "@redis/client/lib/commands/generic-transformers";
import { TuplesReply } from '@redis/client/lib/RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(index: RedisArgument) {
return ['FT.INFO', index];
parseCommand(parser: CommandParser, index: RedisArgument) {
parser.push('FT.INFO', index);
},
transformReply: {
2: transformV2Reply,

View File

@@ -3,19 +3,20 @@ import testUtils, { GLOBAL } from '../test-utils';
import { FT_AGGREGATE_STEPS } from './AGGREGATE';
import PROFILE_AGGREGATE from './PROFILE_AGGREGATE';
import { SCHEMA_FIELD_TYPE } from './CREATE';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('PROFILE AGGREGATE', () => {
describe('transformArguments', () => {
it('without options', () => {
assert.deepEqual(
PROFILE_AGGREGATE.transformArguments('index', 'query'),
parseArgs(PROFILE_AGGREGATE, 'index', 'query'),
['FT.PROFILE', 'index', 'AGGREGATE', 'QUERY', 'query']
);
});
it('with options', () => {
assert.deepEqual(
PROFILE_AGGREGATE.transformArguments('index', 'query', {
parseArgs(PROFILE_AGGREGATE, 'index', 'query', {
LIMITED: true,
VERBATIM: true,
STEPS: [{

View File

@@ -1,27 +1,26 @@
// import { pushAggregatehOptions, AggregateOptions, transformReply as transformAggregateReply, AggregateRawReply } from './AGGREGATE';
// import { ProfileOptions, ProfileRawReply, ProfileReply, transformProfile } from '.';
import { Command, ReplyUnion } from "@redis/client/dist/lib/RESP/types";
import AGGREGATE, { AggregateRawReply, FtAggregateOptions, pushAggregateOptions } from "./AGGREGATE";
import { CommandParser } from '@redis/client/lib/client/parser';
import { Command, ReplyUnion } from "@redis/client/lib/RESP/types";
import AGGREGATE, { AggregateRawReply, FtAggregateOptions, parseAggregateOptions } from "./AGGREGATE";
import { ProfileOptions, ProfileRawReply, ProfileReply, transformProfile } from "./PROFILE_SEARCH";
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(
parseCommand(
parser: CommandParser,
index: string,
query: string,
options?: ProfileOptions & FtAggregateOptions
) {
const args = ['FT.PROFILE', index, 'AGGREGATE'];
parser.push('FT.PROFILE', index, 'AGGREGATE');
if (options?.LIMITED) {
args.push('LIMITED');
parser.push('LIMITED');
}
args.push('QUERY', query);
parser.push('QUERY', query);
return pushAggregateOptions(args, options)
parseAggregateOptions(parser, options)
},
transformReply: {
2: (reply: ProfileAggeregateRawReply): ProfileReply => {

View File

@@ -2,20 +2,21 @@ import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import PROFILE_SEARCH from './PROFILE_SEARCH';
import { SCHEMA_FIELD_TYPE } from './CREATE';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('PROFILE SEARCH', () => {
describe('transformArguments', () => {
it('without options', () => {
assert.deepEqual(
PROFILE_SEARCH.transformArguments('index', 'query'),
parseArgs(PROFILE_SEARCH, 'index', 'query'),
['FT.PROFILE', 'index', 'SEARCH', 'QUERY', 'query']
);
});
it('with options', () => {
assert.deepEqual(
PROFILE_SEARCH.transformArguments('index', 'query', {
parseArgs(PROFILE_SEARCH, 'index', 'query', {
LIMITED: true,
VERBATIM: true,
INKEYS: 'key'

View File

@@ -1,10 +1,7 @@
// import { SearchOptions, SearchRawReply, transformReply as transformSearchReply } from './SEARCH';
// import { pushSearchOptions, ProfileOptions, ProfileRawReply, ProfileReply, transformProfile } from '.';
// import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { Command, RedisArgument, ReplyUnion } from "@redis/client/dist/lib/RESP/types";
import SEARCH, { FtSearchOptions, SearchRawReply, SearchReply, pushSearchOptions } from "./SEARCH";
import { CommandParser } from '@redis/client/lib/client/parser';
import { Command, RedisArgument, ReplyUnion } from "@redis/client/lib/RESP/types";
import { AggregateReply } from "./AGGREGATE";
import SEARCH, { FtSearchOptions, SearchRawReply, SearchReply, parseSearchOptions } from "./SEARCH";
export type ProfileRawReply<T> = [
results: T,
@@ -27,22 +24,23 @@ export interface ProfileOptions {
}
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(
parseCommand(
parser: CommandParser,
index: RedisArgument,
query: RedisArgument,
options?: ProfileOptions & FtSearchOptions
) {
let args: Array<RedisArgument> = ['FT.PROFILE', index, 'SEARCH'];
parser.push('FT.PROFILE', index, 'SEARCH');
if (options?.LIMITED) {
args.push('LIMITED');
parser.push('LIMITED');
}
args.push('QUERY', query);
parser.push('QUERY', query);
return pushSearchOptions(args, options);
parseSearchOptions(parser, options);
},
transformReply: {
2: (reply: ProfileSearchRawReply, withoutDocuments: boolean): ProfileReply => {

View File

@@ -1,19 +1,20 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import SEARCH from './SEARCH';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.SEARCH', () => {
describe('transformArguments', () => {
it('without options', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query'),
parseArgs(SEARCH, 'index', 'query'),
['FT.SEARCH', 'index', 'query']
);
});
it('with VERBATIM', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
VERBATIM: true
}),
['FT.SEARCH', 'index', 'query', 'VERBATIM']
@@ -22,7 +23,7 @@ describe('FT.SEARCH', () => {
it('with NOSTOPWORDS', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
NOSTOPWORDS: true
}),
['FT.SEARCH', 'index', 'query', 'NOSTOPWORDS']
@@ -31,7 +32,7 @@ describe('FT.SEARCH', () => {
it('with INKEYS', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
INKEYS: 'key'
}),
['FT.SEARCH', 'index', 'query', 'INKEYS', '1', 'key']
@@ -40,7 +41,7 @@ describe('FT.SEARCH', () => {
it('with INFIELDS', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
INFIELDS: 'field'
}),
['FT.SEARCH', 'index', 'query', 'INFIELDS', '1', 'field']
@@ -49,7 +50,7 @@ describe('FT.SEARCH', () => {
it('with RETURN', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
RETURN: 'return'
}),
['FT.SEARCH', 'index', 'query', 'RETURN', '1', 'return']
@@ -59,7 +60,7 @@ describe('FT.SEARCH', () => {
describe('with SUMMARIZE', () => {
it('true', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
SUMMARIZE: true
}),
['FT.SEARCH', 'index', 'query', 'SUMMARIZE']
@@ -69,7 +70,7 @@ describe('FT.SEARCH', () => {
describe('with FIELDS', () => {
it('string', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
SUMMARIZE: {
FIELDS: '@field'
}
@@ -80,7 +81,7 @@ describe('FT.SEARCH', () => {
it('Array', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
SUMMARIZE: {
FIELDS: ['@1', '@2']
}
@@ -92,7 +93,7 @@ describe('FT.SEARCH', () => {
it('with FRAGS', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
SUMMARIZE: {
FRAGS: 1
}
@@ -103,7 +104,7 @@ describe('FT.SEARCH', () => {
it('with LEN', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
SUMMARIZE: {
LEN: 1
}
@@ -114,7 +115,7 @@ describe('FT.SEARCH', () => {
it('with SEPARATOR', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
SUMMARIZE: {
SEPARATOR: 'separator'
}
@@ -127,7 +128,7 @@ describe('FT.SEARCH', () => {
describe('with HIGHLIGHT', () => {
it('true', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
HIGHLIGHT: true
}),
['FT.SEARCH', 'index', 'query', 'HIGHLIGHT']
@@ -137,7 +138,7 @@ describe('FT.SEARCH', () => {
describe('with FIELDS', () => {
it('string', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
HIGHLIGHT: {
FIELDS: ['@field']
}
@@ -148,7 +149,7 @@ describe('FT.SEARCH', () => {
it('Array', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
HIGHLIGHT: {
FIELDS: ['@1', '@2']
}
@@ -160,7 +161,7 @@ describe('FT.SEARCH', () => {
it('with TAGS', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
HIGHLIGHT: {
TAGS: {
open: 'open',
@@ -175,7 +176,7 @@ describe('FT.SEARCH', () => {
it('with SLOP', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
SLOP: 1
}),
['FT.SEARCH', 'index', 'query', 'SLOP', '1']
@@ -184,7 +185,7 @@ describe('FT.SEARCH', () => {
it('with TIMEOUT', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
TIMEOUT: 1
}),
['FT.SEARCH', 'index', 'query', 'TIMEOUT', '1']
@@ -193,7 +194,7 @@ describe('FT.SEARCH', () => {
it('with INORDER', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
INORDER: true
}),
['FT.SEARCH', 'index', 'query', 'INORDER']
@@ -202,7 +203,7 @@ describe('FT.SEARCH', () => {
it('with LANGUAGE', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
LANGUAGE: 'Arabic'
}),
['FT.SEARCH', 'index', 'query', 'LANGUAGE', 'Arabic']
@@ -211,7 +212,7 @@ describe('FT.SEARCH', () => {
it('with EXPANDER', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
EXPANDER: 'expender'
}),
['FT.SEARCH', 'index', 'query', 'EXPANDER', 'expender']
@@ -220,7 +221,7 @@ describe('FT.SEARCH', () => {
it('with SCORER', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
SCORER: 'scorer'
}),
['FT.SEARCH', 'index', 'query', 'SCORER', 'scorer']
@@ -229,7 +230,7 @@ describe('FT.SEARCH', () => {
it('with SORTBY', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
SORTBY: '@by'
}),
['FT.SEARCH', 'index', 'query', 'SORTBY', '@by']
@@ -238,7 +239,7 @@ describe('FT.SEARCH', () => {
it('with LIMIT', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
LIMIT: {
from: 0,
size: 1
@@ -250,7 +251,7 @@ describe('FT.SEARCH', () => {
it('with PARAMS', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
PARAMS: {
string: 'string',
buffer: Buffer.from('buffer'),
@@ -263,7 +264,7 @@ describe('FT.SEARCH', () => {
it('with DIALECT', () => {
assert.deepEqual(
SEARCH.transformArguments('index', 'query', {
parseArgs(SEARCH, 'index', 'query', {
DIALECT: 1
}),
['FT.SEARCH', 'index', 'query', 'DIALECT', '1']

View File

@@ -1,12 +1,15 @@
import { RedisArgument, Command, ReplyUnion } from '@redis/client/dist/lib/RESP/types';
import { RedisVariadicArgument, pushOptionalVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
import { CommandParser } from '@redis/client/lib/client/parser';
import { RedisArgument, Command, ReplyUnion } from '@redis/client/lib/RESP/types';
import { RedisVariadicArgument, parseOptionalVariadicArgument } from '@redis/client/lib/commands/generic-transformers';
import { RediSearchProperty, RediSearchLanguage } from './CREATE';
export type FtSearchParams = Record<string, RedisArgument | number>;
export function pushParamsArgument(args: Array<RedisArgument>, params?: FtSearchParams) {
export function parseParamsArgument(parser: CommandParser, params?: FtSearchParams) {
if (params) {
const length = args.push('PARAMS', '');
parser.push('PARAMS');
const args: Array<RedisArgument> = [];
for (const key in params) {
if (!Object.hasOwn(params, key)) continue;
@@ -17,7 +20,7 @@ export function pushParamsArgument(args: Array<RedisArgument>, params?: FtSearch
);
}
args[length - 1] = (args.length - length).toString();
parser.pushVariadicWithLength(args);
}
}
@@ -58,109 +61,107 @@ export interface FtSearchOptions {
DIALECT?: number;
}
export function pushSearchOptions(args: Array<RedisArgument>, options?: FtSearchOptions) {
export function parseSearchOptions(parser: CommandParser, options?: FtSearchOptions) {
if (options?.VERBATIM) {
args.push('VERBATIM');
parser.push('VERBATIM');
}
if (options?.NOSTOPWORDS) {
args.push('NOSTOPWORDS');
parser.push('NOSTOPWORDS');
}
pushOptionalVariadicArgument(args, 'INKEYS', options?.INKEYS);
pushOptionalVariadicArgument(args, 'INFIELDS', options?.INFIELDS);
pushOptionalVariadicArgument(args, 'RETURN', options?.RETURN);
parseOptionalVariadicArgument(parser, 'INKEYS', options?.INKEYS);
parseOptionalVariadicArgument(parser, 'INFIELDS', options?.INFIELDS);
parseOptionalVariadicArgument(parser, 'RETURN', options?.RETURN);
if (options?.SUMMARIZE) {
args.push('SUMMARIZE');
parser.push('SUMMARIZE');
if (typeof options.SUMMARIZE === 'object') {
pushOptionalVariadicArgument(args, 'FIELDS', options.SUMMARIZE.FIELDS);
parseOptionalVariadicArgument(parser, 'FIELDS', options.SUMMARIZE.FIELDS);
if (options.SUMMARIZE.FRAGS !== undefined) {
args.push('FRAGS', options.SUMMARIZE.FRAGS.toString());
parser.push('FRAGS', options.SUMMARIZE.FRAGS.toString());
}
if (options.SUMMARIZE.LEN !== undefined) {
args.push('LEN', options.SUMMARIZE.LEN.toString());
parser.push('LEN', options.SUMMARIZE.LEN.toString());
}
if (options.SUMMARIZE.SEPARATOR !== undefined) {
args.push('SEPARATOR', options.SUMMARIZE.SEPARATOR);
parser.push('SEPARATOR', options.SUMMARIZE.SEPARATOR);
}
}
}
if (options?.HIGHLIGHT) {
args.push('HIGHLIGHT');
parser.push('HIGHLIGHT');
if (typeof options.HIGHLIGHT === 'object') {
pushOptionalVariadicArgument(args, 'FIELDS', options.HIGHLIGHT.FIELDS);
parseOptionalVariadicArgument(parser, 'FIELDS', options.HIGHLIGHT.FIELDS);
if (options.HIGHLIGHT.TAGS) {
args.push('TAGS', options.HIGHLIGHT.TAGS.open, options.HIGHLIGHT.TAGS.close);
parser.push('TAGS', options.HIGHLIGHT.TAGS.open, options.HIGHLIGHT.TAGS.close);
}
}
}
if (options?.SLOP !== undefined) {
args.push('SLOP', options.SLOP.toString());
parser.push('SLOP', options.SLOP.toString());
}
if (options?.TIMEOUT !== undefined) {
args.push('TIMEOUT', options.TIMEOUT.toString());
parser.push('TIMEOUT', options.TIMEOUT.toString());
}
if (options?.INORDER) {
args.push('INORDER');
parser.push('INORDER');
}
if (options?.LANGUAGE) {
args.push('LANGUAGE', options.LANGUAGE);
parser.push('LANGUAGE', options.LANGUAGE);
}
if (options?.EXPANDER) {
args.push('EXPANDER', options.EXPANDER);
parser.push('EXPANDER', options.EXPANDER);
}
if (options?.SCORER) {
args.push('SCORER', options.SCORER);
parser.push('SCORER', options.SCORER);
}
if (options?.SORTBY) {
args.push('SORTBY');
parser.push('SORTBY');
if (typeof options.SORTBY === 'string' || options.SORTBY instanceof Buffer) {
args.push(options.SORTBY);
parser.push(options.SORTBY);
} else {
args.push(options.SORTBY.BY);
parser.push(options.SORTBY.BY);
if (options.SORTBY.DIRECTION) {
args.push(options.SORTBY.DIRECTION);
parser.push(options.SORTBY.DIRECTION);
}
}
}
if (options?.LIMIT) {
args.push('LIMIT', options.LIMIT.from.toString(), options.LIMIT.size.toString());
parser.push('LIMIT', options.LIMIT.from.toString(), options.LIMIT.size.toString());
}
pushParamsArgument(args, options?.PARAMS);
parseParamsArgument(parser, options?.PARAMS);
if (options?.DIALECT !== undefined) {
args.push('DIALECT', options.DIALECT.toString());
parser.push('DIALECT', options.DIALECT.toString());
}
return args;
}
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(index: RedisArgument, query: RedisArgument, options?: FtSearchOptions) {
const args = ['FT.SEARCH', index, query];
parseCommand(parser: CommandParser, index: RedisArgument, query: RedisArgument, options?: FtSearchOptions) {
parser.push('FT.SEARCH', index, query);
return pushSearchOptions(args, options);
parseSearchOptions(parser, options);
},
transformReply: {
2: (reply: SearchRawReply): SearchReply => {

View File

@@ -1,12 +1,13 @@
import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils';
import SEARCH_NOCONTENT from './SEARCH_NOCONTENT';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.SEARCH NOCONTENT', () => {
describe('transformArguments', () => {
it('without options', () => {
assert.deepEqual(
SEARCH_NOCONTENT.transformArguments('index', 'query'),
parseArgs(SEARCH_NOCONTENT, 'index', 'query'),
['FT.SEARCH', 'index', 'query', 'NOCONTENT']
);
});

View File

@@ -1,13 +1,12 @@
import { Command, ReplyUnion } from '@redis/client/dist/lib/RESP/types';
import { Command, ReplyUnion } from '@redis/client/lib/RESP/types';
import SEARCH, { SearchRawReply } from './SEARCH';
export default {
FIRST_KEY_INDEX: SEARCH.FIRST_KEY_INDEX,
NOT_KEYED_COMMAND: SEARCH.NOT_KEYED_COMMAND,
IS_READ_ONLY: SEARCH.IS_READ_ONLY,
transformArguments(...args: Parameters<typeof SEARCH.transformArguments>) {
const redisArgs = SEARCH.transformArguments(...args);
redisArgs.push('NOCONTENT');
return redisArgs;
parseCommand(...args: Parameters<typeof SEARCH.parseCommand>) {
SEARCH.parseCommand(...args);
args[0].push('NOCONTENT');
},
transformReply: {
2: (reply: SearchRawReply): SearchNoContentReply => {

View File

@@ -1,19 +1,20 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import SPELLCHECK from './SPELLCHECK';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.SPELLCHECK', () => {
describe('transformArguments', () => {
it('without options', () => {
assert.deepEqual(
SPELLCHECK.transformArguments('index', 'query'),
parseArgs(SPELLCHECK, 'index', 'query'),
['FT.SPELLCHECK', 'index', 'query']
);
});
it('with DISTANCE', () => {
assert.deepEqual(
SPELLCHECK.transformArguments('index', 'query', {
parseArgs(SPELLCHECK, 'index', 'query', {
DISTANCE: 2
}),
['FT.SPELLCHECK', 'index', 'query', 'DISTANCE', '2']
@@ -23,7 +24,7 @@ describe('FT.SPELLCHECK', () => {
describe('with TERMS', () => {
it('single', () => {
assert.deepEqual(
SPELLCHECK.transformArguments('index', 'query', {
parseArgs(SPELLCHECK, 'index', 'query', {
TERMS: {
mode: 'INCLUDE',
dictionary: 'dictionary'
@@ -35,7 +36,7 @@ describe('FT.SPELLCHECK', () => {
it('multiple', () => {
assert.deepEqual(
SPELLCHECK.transformArguments('index', 'query', {
parseArgs(SPELLCHECK, 'index', 'query', {
TERMS: [{
mode: 'INCLUDE',
dictionary: 'include'
@@ -51,7 +52,7 @@ describe('FT.SPELLCHECK', () => {
it('with DIALECT', () => {
assert.deepEqual(
SPELLCHECK.transformArguments('index', 'query', {
parseArgs(SPELLCHECK, 'index', 'query', {
DIALECT: 1
}),
['FT.SPELLCHECK', 'index', 'query', 'DIALECT', '1']

View File

@@ -1,4 +1,5 @@
import { RedisArgument, CommandArguments, Command, ReplyUnion } from '@redis/client/dist/lib/RESP/types';
import { CommandParser } from '@redis/client/lib/client/parser';
import { RedisArgument, Command, ReplyUnion } from '@redis/client/lib/RESP/types';
export interface Terms {
mode: 'INCLUDE' | 'EXCLUDE';
@@ -12,30 +13,28 @@ export interface FtSpellCheckOptions {
}
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(index: RedisArgument, query: RedisArgument, options?: FtSpellCheckOptions) {
const args = ['FT.SPELLCHECK', index, query];
parseCommand(parser: CommandParser, index: RedisArgument, query: RedisArgument, options?: FtSpellCheckOptions) {
parser.push('FT.SPELLCHECK', index, query);
if (options?.DISTANCE) {
args.push('DISTANCE', options.DISTANCE.toString());
parser.push('DISTANCE', options.DISTANCE.toString());
}
if (options?.TERMS) {
if (Array.isArray(options.TERMS)) {
for (const term of options.TERMS) {
pushTerms(args, term);
parseTerms(parser, term);
}
} else {
pushTerms(args, options.TERMS);
parseTerms(parser, options.TERMS);
}
}
if (options?.DIALECT) {
args.push('DIALECT', options.DIALECT.toString());
parser.push('DIALECT', options.DIALECT.toString());
}
return args;
},
transformReply: {
2: (rawReply: SpellCheckRawReply): SpellCheckReply => {
@@ -52,6 +51,10 @@ export default {
unstableResp3: true
} as const satisfies Command;
function parseTerms(parser: CommandParser, { mode, dictionary }: Terms) {
parser.push('TERMS', mode, dictionary);
}
type SpellCheckRawReply = Array<[
_: string,
term: string,
@@ -65,7 +68,3 @@ type SpellCheckReply = Array<{
suggestion: string
}>
}>;
function pushTerms(args: CommandArguments, { mode, dictionary }: Terms) {
args.push('TERMS', mode, dictionary);
}

View File

@@ -1,26 +1,27 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import SUGADD from './SUGADD';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.SUGADD', () => {
describe('transformArguments', () => {
it('without options', () => {
assert.deepEqual(
SUGADD.transformArguments('key', 'string', 1),
parseArgs(SUGADD, 'key', 'string', 1),
['FT.SUGADD', 'key', 'string', '1']
);
});
it('with INCR', () => {
assert.deepEqual(
SUGADD.transformArguments('key', 'string', 1, { INCR: true }),
parseArgs(SUGADD, 'key', 'string', 1, { INCR: true }),
['FT.SUGADD', 'key', 'string', '1', 'INCR']
);
});
it('with PAYLOAD', () => {
assert.deepEqual(
SUGADD.transformArguments('key', 'string', 1, { PAYLOAD: 'payload' }),
parseArgs(SUGADD, 'key', 'string', 1, { PAYLOAD: 'payload' }),
['FT.SUGADD', 'key', 'string', '1', 'PAYLOAD', 'payload']
);
});

View File

@@ -1,4 +1,5 @@
import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types';
import { CommandParser } from '@redis/client/lib/client/parser';
import { RedisArgument, NumberReply, Command } from '@redis/client/lib/RESP/types';
export interface FtSugAddOptions {
INCR?: boolean;
@@ -6,20 +7,19 @@ export interface FtSugAddOptions {
}
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument, string: RedisArgument, score: number, options?: FtSugAddOptions) {
const args = ['FT.SUGADD', key, string, score.toString()];
parseCommand(parser: CommandParser, key: RedisArgument, string: RedisArgument, score: number, options?: FtSugAddOptions) {
parser.push('FT.SUGADD');
parser.pushKey(key);
parser.push(string, score.toString());
if (options?.INCR) {
args.push('INCR');
parser.push('INCR');
}
if (options?.PAYLOAD) {
args.push('PAYLOAD', options.PAYLOAD);
parser.push('PAYLOAD', options.PAYLOAD);
}
return args;
},
transformReply: undefined as unknown as () => NumberReply
} as const satisfies Command;

View File

@@ -1,11 +1,12 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import SUGDEL from './SUGDEL';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.SUGDEL', () => {
it('transformArguments', () => {
assert.deepEqual(
SUGDEL.transformArguments('key', 'string'),
parseArgs(SUGDEL, 'key', 'string'),
['FT.SUGDEL', 'key', 'string']
);
});

View File

@@ -1,10 +1,12 @@
import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types';
import { CommandParser } from '@redis/client/lib/client/parser';
import { RedisArgument, NumberReply, Command } from '@redis/client/lib/RESP/types';
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument, string: RedisArgument) {
return ['FT.SUGDEL', key, string];
parseCommand(parser: CommandParser, key: RedisArgument, string: RedisArgument) {
parser.push('FT.SUGDEL');
parser.pushKey(key);
parser.push(string);
},
transformReply: undefined as unknown as () => NumberReply<0 | 1>
} as const satisfies Command;

View File

@@ -1,26 +1,27 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import SUGGET from './SUGGET';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.SUGGET', () => {
describe('transformArguments', () => {
it('without options', () => {
assert.deepEqual(
SUGGET.transformArguments('key', 'prefix'),
parseArgs(SUGGET, 'key', 'prefix'),
['FT.SUGGET', 'key', 'prefix']
);
});
it('with FUZZY', () => {
assert.deepEqual(
SUGGET.transformArguments('key', 'prefix', { FUZZY: true }),
parseArgs(SUGGET, 'key', 'prefix', { FUZZY: true }),
['FT.SUGGET', 'key', 'prefix', 'FUZZY']
);
});
it('with MAX', () => {
assert.deepEqual(
SUGGET.transformArguments('key', 'prefix', { MAX: 10 }),
parseArgs(SUGGET, 'key', 'prefix', { MAX: 10 }),
['FT.SUGGET', 'key', 'prefix', 'MAX', '10']
);
});

View File

@@ -1,4 +1,5 @@
import { NullReply, ArrayReply, BlobStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types';
import { CommandParser } from '@redis/client/lib/client/parser';
import { NullReply, ArrayReply, BlobStringReply, Command, RedisArgument } from '@redis/client/lib/RESP/types';
export interface FtSugGetOptions {
FUZZY?: boolean;
@@ -6,20 +7,19 @@ export interface FtSugGetOptions {
}
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument, prefix: RedisArgument, options?: FtSugGetOptions) {
const args = ['FT.SUGGET', key, prefix];
parseCommand(parser: CommandParser, key: RedisArgument, prefix: RedisArgument, options?: FtSugGetOptions) {
parser.push('FT.SUGGET');
parser.pushKey(key);
parser.push(prefix);
if (options?.FUZZY) {
args.push('FUZZY');
parser.push('FUZZY');
}
if (options?.MAX !== undefined) {
args.push('MAX', options.MAX.toString());
parser.push('MAX', options.MAX.toString());
}
return args;
},
transformReply: undefined as unknown as () => NullReply | ArrayReply<BlobStringReply>
} as const satisfies Command;

View File

@@ -1,11 +1,12 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import SUGGET_WITHPAYLOADS from './SUGGET_WITHPAYLOADS';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.SUGGET WITHPAYLOADS', () => {
it('transformArguments', () => {
assert.deepEqual(
SUGGET_WITHPAYLOADS.transformArguments('key', 'prefix'),
parseArgs(SUGGET_WITHPAYLOADS, 'key', 'prefix'),
['FT.SUGGET', 'key', 'prefix', 'WITHPAYLOADS']
);
});

View File

@@ -1,14 +1,12 @@
import { NullReply, ArrayReply, BlobStringReply, UnwrapReply, Command } from '@redis/client/dist/lib/RESP/types';
import { isNullReply } from '@redis/client/dist/lib/commands/generic-transformers';
import { NullReply, ArrayReply, BlobStringReply, UnwrapReply, Command } from '@redis/client/lib/RESP/types';
import { isNullReply } from '@redis/client/lib/commands/generic-transformers';
import SUGGET from './SUGGET';
export default {
FIRST_KEY_INDEX: SUGGET.FIRST_KEY_INDEX,
IS_READ_ONLY: SUGGET.IS_READ_ONLY,
transformArguments(...args: Parameters<typeof SUGGET.transformArguments>) {
const transformedArguments = SUGGET.transformArguments(...args);
transformedArguments.push('WITHPAYLOADS');
return transformedArguments;
parseCommand(...args: Parameters<typeof SUGGET.parseCommand>) {
SUGGET.parseCommand(...args);
args[0].push('WITHPAYLOADS');
},
transformReply(reply: NullReply | UnwrapReply<ArrayReply<BlobStringReply>>) {
if (isNullReply(reply)) return null;

View File

@@ -1,11 +1,12 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import SUGGET_WITHSCORES from './SUGGET_WITHSCORES';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.SUGGET WITHSCORES', () => {
it('transformArguments', () => {
assert.deepEqual(
SUGGET_WITHSCORES.transformArguments('key', 'prefix'),
parseArgs(SUGGET_WITHSCORES, 'key', 'prefix'),
['FT.SUGGET', 'key', 'prefix', 'WITHSCORES']
);
});

View File

@@ -1,5 +1,5 @@
import { NullReply, ArrayReply, BlobStringReply, DoubleReply, UnwrapReply, Command, TypeMapping } from '@redis/client/dist/lib/RESP/types';
import { isNullReply, transformDoubleReply } from '@redis/client/dist/lib/commands/generic-transformers';
import { NullReply, ArrayReply, BlobStringReply, DoubleReply, UnwrapReply, Command, TypeMapping } from '@redis/client/lib/RESP/types';
import { isNullReply, transformDoubleReply } from '@redis/client/lib/commands/generic-transformers';
import SUGGET from './SUGGET';
type SuggestScore = {
@@ -8,12 +8,10 @@ type SuggestScore = {
}
export default {
FIRST_KEY_INDEX: SUGGET.FIRST_KEY_INDEX,
IS_READ_ONLY: SUGGET.IS_READ_ONLY,
transformArguments(...args: Parameters<typeof SUGGET.transformArguments>) {
const transformedArguments = SUGGET.transformArguments(...args);
transformedArguments.push('WITHSCORES');
return transformedArguments;
parseCommand(...args: Parameters<typeof SUGGET.parseCommand>) {
SUGGET.parseCommand(...args);
args[0].push('WITHSCORES');
},
transformReply: {
2: (reply: NullReply | UnwrapReply<ArrayReply<BlobStringReply>>, preserve?: any, typeMapping?: TypeMapping) => {

View File

@@ -1,11 +1,12 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import SUGGET_WITHSCORES_WITHPAYLOADS from './SUGGET_WITHSCORES_WITHPAYLOADS';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.SUGGET WITHSCORES WITHPAYLOADS', () => {
it('transformArguments', () => {
assert.deepEqual(
SUGGET_WITHSCORES_WITHPAYLOADS.transformArguments('key', 'prefix'),
parseArgs(SUGGET_WITHSCORES_WITHPAYLOADS, 'key', 'prefix'),
['FT.SUGGET', 'key', 'prefix', 'WITHSCORES', 'WITHPAYLOADS']
);
});

View File

@@ -1,5 +1,5 @@
import { NullReply, ArrayReply, BlobStringReply, DoubleReply, UnwrapReply, Command, TypeMapping } from '@redis/client/dist/lib/RESP/types';
import { isNullReply, transformDoubleReply } from '@redis/client/dist/lib/commands/generic-transformers';
import { NullReply, ArrayReply, BlobStringReply, DoubleReply, UnwrapReply, Command, TypeMapping } from '@redis/client/lib/RESP/types';
import { isNullReply, transformDoubleReply } from '@redis/client/lib/commands/generic-transformers';
import SUGGET from './SUGGET';
type SuggestScoreWithPayload = {
@@ -9,15 +9,13 @@ type SuggestScoreWithPayload = {
}
export default {
FIRST_KEY_INDEX: SUGGET.FIRST_KEY_INDEX,
IS_READ_ONLY: SUGGET.IS_READ_ONLY,
transformArguments(...args: Parameters<typeof SUGGET.transformArguments>) {
const transformedArguments = SUGGET.transformArguments(...args);
transformedArguments.push(
parseCommand(...args: Parameters<typeof SUGGET.parseCommand>) {
SUGGET.parseCommand(...args);
args[0].push(
'WITHSCORES',
'WITHPAYLOADS'
);
return transformedArguments;
},
transformReply: {
2: (reply: NullReply | UnwrapReply<ArrayReply<BlobStringReply>>, preserve?: any, typeMapping?: TypeMapping) => {

View File

@@ -1,11 +1,12 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import SUGLEN from './SUGLEN';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.SUGLEN', () => {
it('transformArguments', () => {
assert.deepEqual(
SUGLEN.transformArguments('key'),
parseArgs(SUGLEN, 'key'),
['FT.SUGLEN', 'key']
);
});

View File

@@ -1,10 +1,10 @@
import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types';
import { CommandParser } from '@redis/client/lib/client/parser';
import { RedisArgument, NumberReply, Command } from '@redis/client/lib/RESP/types';
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument) {
return ['FT.SUGLEN', key];
parseCommand(parser: CommandParser, key: RedisArgument) {
parser.push('FT.SUGLEN', key);
},
transformReply: undefined as unknown as () => NumberReply
} as const satisfies Command;

View File

@@ -2,11 +2,12 @@ import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import SYNDUMP from './SYNDUMP';
import { SCHEMA_FIELD_TYPE } from './CREATE';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.SYNDUMP', () => {
it('transformArguments', () => {
assert.deepEqual(
SYNDUMP.transformArguments('index'),
parseArgs(SYNDUMP, 'index'),
['FT.SYNDUMP', 'index']
);
});

View File

@@ -1,10 +1,11 @@
import { RedisArgument, MapReply, BlobStringReply, ArrayReply, UnwrapReply, Command } from '@redis/client/dist/lib/RESP/types';
import { CommandParser } from '@redis/client/lib/client/parser';
import { RedisArgument, MapReply, BlobStringReply, ArrayReply, UnwrapReply, Command } from '@redis/client/lib/RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(index: RedisArgument) {
return ['FT.SYNDUMP', index];
parseCommand(parser: CommandParser, index: RedisArgument) {
parser.push('FT.SYNDUMP', index);
},
transformReply: {
2: (reply: UnwrapReply<ArrayReply<BlobStringReply | ArrayReply<BlobStringReply>>>) => {

View File

@@ -2,26 +2,27 @@ import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import SYNUPDATE from './SYNUPDATE';
import { SCHEMA_FIELD_TYPE } from './CREATE';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.SYNUPDATE', () => {
describe('transformArguments', () => {
it('single term', () => {
assert.deepEqual(
SYNUPDATE.transformArguments('index', 'groupId', 'term'),
parseArgs(SYNUPDATE, 'index', 'groupId', 'term'),
['FT.SYNUPDATE', 'index', 'groupId', 'term']
);
});
it('multiple terms', () => {
assert.deepEqual(
SYNUPDATE.transformArguments('index', 'groupId', ['1', '2']),
parseArgs(SYNUPDATE, 'index', 'groupId', ['1', '2']),
['FT.SYNUPDATE', 'index', 'groupId', '1', '2']
);
});
it('with SKIPINITIALSCAN', () => {
assert.deepEqual(
SYNUPDATE.transformArguments('index', 'groupId', 'term', {
parseArgs(SYNUPDATE, 'index', 'groupId', 'term', {
SKIPINITIALSCAN: true
}),
['FT.SYNUPDATE', 'index', 'groupId', 'SKIPINITIALSCAN', 'term']

View File

@@ -1,26 +1,28 @@
import { SimpleStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types';
import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers';
import { CommandParser } from '@redis/client/lib/client/parser';
import { SimpleStringReply, Command, RedisArgument } from '@redis/client/lib/RESP/types';
import { RedisVariadicArgument } from '@redis/client/lib/commands/generic-transformers';
export interface FtSynUpdateOptions {
SKIPINITIALSCAN?: boolean;
}
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(
parseCommand(
parser: CommandParser,
index: RedisArgument,
groupId: RedisArgument,
terms: RedisVariadicArgument,
options?: FtSynUpdateOptions
) {
const args = ['FT.SYNUPDATE', index, groupId];
parser.push('FT.SYNUPDATE', index, groupId);
if (options?.SKIPINITIALSCAN) {
args.push('SKIPINITIALSCAN');
parser.push('SKIPINITIALSCAN');
}
return pushVariadicArguments(args, terms);
parser.pushVariadic(terms);
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -2,11 +2,12 @@ import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import TAGVALS from './TAGVALS';
import { SCHEMA_FIELD_TYPE } from './CREATE';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('FT.TAGVALS', () => {
it('transformArguments', () => {
assert.deepEqual(
TAGVALS.transformArguments('index', '@field'),
parseArgs(TAGVALS, 'index', '@field'),
['FT.TAGVALS', 'index', '@field']
);
});

View File

@@ -1,10 +1,11 @@
import { RedisArgument, ArrayReply, SetReply, BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types';
import { CommandParser } from '@redis/client/lib/client/parser';
import { RedisArgument, ArrayReply, SetReply, BlobStringReply, Command } from '@redis/client/lib/RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments(index: RedisArgument, fieldName: RedisArgument) {
return ['FT.TAGVALS', index, fieldName];
parseCommand(parser: CommandParser, index: RedisArgument, fieldName: RedisArgument) {
parser.push('FT.TAGVALS', index, fieldName);
},
transformReply: {
2: undefined as unknown as () => ArrayReply<BlobStringReply>,

View File

@@ -1,11 +1,12 @@
import { strict as assert } from 'node:assert';
import testUtils, { GLOBAL } from '../test-utils';
import _LIST from './_LIST';
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
describe('_LIST', () => {
it('transformArguments', () => {
assert.deepEqual(
_LIST.transformArguments(),
parseArgs(_LIST),
['FT._LIST']
);
});

View File

@@ -1,10 +1,11 @@
import { ArrayReply, SetReply, BlobStringReply, Command } from '@redis/client/dist/lib/RESP/types';
import { CommandParser } from '@redis/client/lib/client/parser';
import { ArrayReply, SetReply, BlobStringReply, Command } from '@redis/client/lib/RESP/types';
export default {
FIRST_KEY_INDEX: undefined,
NOT_KEYED_COMMAND: true,
IS_READ_ONLY: true,
transformArguments() {
return ['FT._LIST'];
parseCommand(parser: CommandParser) {
parser.push('FT._LIST');
},
transformReply: {
2: undefined as unknown as () => ArrayReply<BlobStringReply>,