1
0
mirror of https://github.com/redis/node-redis.git synced 2025-08-04 15:02:09 +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,64 +1,82 @@
import { RedisCommandArgument, RedisCommandArguments } from '.';
import { StreamMessageReply, transformTuplesReply } from './generic-transformers';
import { RedisArgument, TuplesToMapReply, BlobStringReply, NumberReply, NullReply, TuplesReply, ArrayReply, UnwrapReply, Command } from '../RESP/types';
import { isNullReply, transformTuplesReply } from './generic-transformers';
export const FIRST_KEY_INDEX = 2;
export type XInfoStreamReply = TuplesToMapReply<[
[BlobStringReply<'length'>, NumberReply],
[BlobStringReply<'radix-tree-keys'>, NumberReply],
[BlobStringReply<'radix-tree-nodes'>, NumberReply],
[BlobStringReply<'last-generated-id'>, BlobStringReply],
/** added in 7.2 */
[BlobStringReply<'max-deleted-entry-id'>, BlobStringReply],
/** added in 7.2 */
[BlobStringReply<'entries-added'>, NumberReply],
/** added in 7.2 */
[BlobStringReply<'recorded-first-entry-id'>, BlobStringReply],
[BlobStringReply<'groups'>, NumberReply],
[BlobStringReply<'first-entry'>, ReturnType<typeof transformEntry>],
[BlobStringReply<'last-entry'>, ReturnType<typeof transformEntry>]
]>;
export const IS_READ_ONLY = true;
export function transformArguments(key: RedisCommandArgument): RedisCommandArguments {
export default {
FIRST_KEY_INDEX: 2,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument) {
return ['XINFO', 'STREAM', key];
}
},
transformReply: {
// TODO: is there a "type safe" way to do it?
2(reply: any) {
const parsedReply: Partial<XInfoStreamReply['DEFAULT']> = {};
interface XInfoStreamReply {
length: number;
radixTreeKeys: number;
radixTreeNodes: number;
groups: number;
lastGeneratedId: RedisCommandArgument;
firstEntry: StreamMessageReply | null;
lastEntry: StreamMessageReply | null;
}
for (let i = 0; i < reply.length; i += 2) {
switch (reply[i]) {
case 'first-entry':
case 'last-entry':
parsedReply[reply[i] as ('first-entry' | 'last-entry')] = transformEntry(reply[i + 1]) as any;
break;
export function transformReply(rawReply: Array<any>): XInfoStreamReply {
const parsedReply: Partial<XInfoStreamReply> = {};
for (let i = 0; i < rawReply.length; i+= 2) {
switch (rawReply[i]) {
case 'length':
parsedReply.length = rawReply[i + 1];
break;
case 'radix-tree-keys':
parsedReply.radixTreeKeys = rawReply[i + 1];
break;
case 'radix-tree-nodes':
parsedReply.radixTreeNodes = rawReply[i + 1];
break;
case 'groups':
parsedReply.groups = rawReply[i + 1];
break;
case 'last-generated-id':
parsedReply.lastGeneratedId = rawReply[i + 1];
break;
case 'first-entry':
parsedReply.firstEntry = rawReply[i + 1] ? {
id: rawReply[i + 1][0],
message: transformTuplesReply(rawReply[i + 1][1])
} : null;
break;
case 'last-entry':
parsedReply.lastEntry = rawReply[i + 1] ? {
id: rawReply[i + 1][0],
message: transformTuplesReply(rawReply[i + 1][1])
} : null;
break;
default:
parsedReply[reply[i] as keyof typeof parsedReply] = reply[i + 1];
break;
}
}
}
return parsedReply as XInfoStreamReply;
return parsedReply as XInfoStreamReply['DEFAULT'];
},
3(reply: any) {
if (reply instanceof Map) {
reply.set(
'first-entry',
transformEntry(reply.get('first-entry'))
);
reply.set(
'last-entry',
transformEntry(reply.get('last-entry'))
);
} else if (reply instanceof Array) {
reply[17] = transformEntry(reply[17]);
reply[19] = transformEntry(reply[19]);
} else {
reply['first-entry'] = transformEntry(reply['first-entry']);
reply['last-entry'] = transformEntry(reply['last-entry']);
}
return reply as XInfoStreamReply;
}
}
} as const satisfies Command;
type RawEntry = TuplesReply<[
id: BlobStringReply,
message: ArrayReply<BlobStringReply>
]> | NullReply;
function transformEntry(entry: RawEntry) {
if (isNullReply(entry)) return entry;
const [id, message] = entry as unknown as UnwrapReply<typeof entry>;
return {
id,
message: transformTuplesReply(message)
};
}