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

V5 bringing RESP3, Sentinel and TypeMapping to node-redis

RESP3 Support
   - Some commands responses in RESP3 aren't stable yet and therefore return an "untyped" ReplyUnion.
 
Sentinel

TypeMapping

Correctly types Multi commands

Note: some API changes to be further documented in v4-to-v5.md
This commit is contained in:
Shaya Potter
2024-10-15 17:46:52 +03:00
committed by GitHub
parent 2fc79bdfb3
commit b2d35c5286
1174 changed files with 45931 additions and 36274 deletions

View File

@@ -1,29 +1,152 @@
import { SearchOptions, SearchRawReply, transformReply as transformSearchReply } from './SEARCH';
import { pushSearchOptions, ProfileOptions, ProfileRawReply, ProfileReply, transformProfile } from '.';
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
// import { SearchOptions, SearchRawReply, transformReply as transformSearchReply } from './SEARCH';
// import { pushSearchOptions, ProfileOptions, ProfileRawReply, ProfileReply, transformProfile } from '.';
// import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
export const IS_READ_ONLY = true;
import { Command, RedisArgument, ReplyUnion } from "@redis/client/dist/lib/RESP/types";
import SEARCH, { FtSearchOptions, SearchRawReply, SearchReply, pushSearchOptions } from "./SEARCH";
import { AggregateReply } from "./AGGREGATE";
export function transformArguments(
index: string,
query: string,
options?: ProfileOptions & SearchOptions
): RedisCommandArguments {
let args: RedisCommandArguments = ['FT.PROFILE', index, 'SEARCH'];
if (options?.LIMITED) {
args.push('LIMITED');
}
args.push('QUERY', query);
return pushSearchOptions(args, options);
}
export type ProfileRawReply<T> = [
results: T,
profile: [
_: string,
TotalProfileTime: string,
_: string,
ParsingTime: string,
_: string,
PipelineCreationTime: string,
_: string,
IteratorsProfile: Array<any>
]
];
type ProfileSearchRawReply = ProfileRawReply<SearchRawReply>;
export function transformReply(reply: ProfileSearchRawReply, withoutDocuments: boolean): ProfileReply {
return {
results: transformSearchReply(reply[0], withoutDocuments),
profile: transformProfile(reply[1])
};
export interface ProfileOptions {
LIMITED?: true;
}
export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true,
transformArguments(
index: RedisArgument,
query: RedisArgument,
options?: ProfileOptions & FtSearchOptions
) {
let args: Array<RedisArgument> = ['FT.PROFILE', index, 'SEARCH'];
if (options?.LIMITED) {
args.push('LIMITED');
}
args.push('QUERY', query);
return pushSearchOptions(args, options);
},
transformReply: {
2: (reply: ProfileSearchRawReply, withoutDocuments: boolean): ProfileReply => {
return {
results: SEARCH.transformReply[2](reply[0]),
profile: transformProfile(reply[1])
}
},
3: undefined as unknown as () => ReplyUnion
},
unstableResp3: true
} as const satisfies Command;
export interface ProfileReply {
results: SearchReply | AggregateReply;
profile: ProfileData;
}
interface ChildIterator {
type?: string,
counter?: number,
term?: string,
size?: number,
time?: string,
childIterators?: Array<ChildIterator>
}
interface IteratorsProfile {
type?: string,
counter?: number,
queryType?: string,
time?: string,
childIterators?: Array<ChildIterator>
}
interface ProfileData {
totalProfileTime: string,
parsingTime: string,
pipelineCreationTime: string,
warning: string,
iteratorsProfile: IteratorsProfile
}
export function transformProfile(reply: Array<any>): ProfileData{
return {
totalProfileTime: reply[0][1],
parsingTime: reply[1][1],
pipelineCreationTime: reply[2][1],
warning: reply[3][1] ? reply[3][1] : 'None',
iteratorsProfile: transformIterators(reply[4][1])
};
}
function transformIterators(IteratorsProfile: Array<any>): IteratorsProfile {
var res: IteratorsProfile = {};
for (let i = 0; i < IteratorsProfile.length; i += 2) {
const value = IteratorsProfile[i+1];
switch (IteratorsProfile[i]) {
case 'Type':
res.type = value;
break;
case 'Counter':
res.counter = value;
break;
case 'Time':
res.time = value;
break;
case 'Query type':
res.queryType = value;
break;
case 'Child iterators':
res.childIterators = value.map(transformChildIterators);
break;
}
}
return res;
}
function transformChildIterators(IteratorsProfile: Array<any>): ChildIterator {
var res: ChildIterator = {};
for (let i = 1; i < IteratorsProfile.length; i += 2) {
const value = IteratorsProfile[i+1];
switch (IteratorsProfile[i]) {
case 'Type':
res.type = value;
break;
case 'Counter':
res.counter = value;
break;
case 'Time':
res.time = value;
break;
case 'Size':
res.size = value;
break;
case 'Term':
res.term = value;
break;
case 'Child iterators':
res.childIterators = value.map(transformChildIterators);
break;
}
}
return res;
}