You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-06 02:15:48 +03:00
convert "resp types" to interfaces to allow circular references
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { BlobError, SimpleError } from '../errors';
|
||||
import { RedisScriptConfig, SHA1 } from '../lua-script';
|
||||
import { RESP_TYPES } from './decoder';
|
||||
import { VerbatimString } from './verbatim-string';
|
||||
@@ -6,120 +7,138 @@ export type RESP_TYPES = typeof RESP_TYPES;
|
||||
|
||||
export type RespTypes = RESP_TYPES[keyof RESP_TYPES];
|
||||
|
||||
export type RespType<
|
||||
// using interface(s) to allow circular references
|
||||
// type X = BlobStringReply | ArrayReply<X>;
|
||||
|
||||
export interface RespType<
|
||||
RESP_TYPE extends RespTypes,
|
||||
DEFAULT,
|
||||
TYPES = never,
|
||||
FLAG_TYPES = DEFAULT | TYPES
|
||||
> = (DEFAULT | TYPES) & {
|
||||
TYPE_MAPPING = DEFAULT | TYPES
|
||||
> {
|
||||
RESP_TYPE: RESP_TYPE;
|
||||
DEFAULT: DEFAULT;
|
||||
TYPES: TYPES;
|
||||
FLAG: Flag<FLAG_TYPES>;
|
||||
};
|
||||
TYPE_MAPPING: MappedType<TYPE_MAPPING>;
|
||||
}
|
||||
|
||||
export type NullReply = RespType<
|
||||
export interface NullReply extends RespType<
|
||||
RESP_TYPES['NULL'],
|
||||
null
|
||||
>;
|
||||
export type BooleanReply<
|
||||
> {}
|
||||
|
||||
export interface BooleanReply<
|
||||
T extends boolean = boolean
|
||||
> = RespType<
|
||||
> extends RespType<
|
||||
RESP_TYPES['BOOLEAN'],
|
||||
T
|
||||
>;
|
||||
export type NumberReply<
|
||||
> {}
|
||||
|
||||
export interface NumberReply<
|
||||
T extends number = number
|
||||
> = RespType<
|
||||
> extends RespType<
|
||||
RESP_TYPES['NUMBER'],
|
||||
T,
|
||||
`${T}`,
|
||||
number | string
|
||||
>;
|
||||
export type BigNumberReply<
|
||||
> {}
|
||||
|
||||
export interface BigNumberReply<
|
||||
T extends bigint = bigint
|
||||
> = RespType<
|
||||
> extends RespType<
|
||||
RESP_TYPES['BIG_NUMBER'],
|
||||
T,
|
||||
number | `${T}`,
|
||||
bigint | number | string
|
||||
>;
|
||||
export type DoubleReply<
|
||||
> {}
|
||||
|
||||
export interface DoubleReply<
|
||||
T extends number = number
|
||||
> = RespType<
|
||||
> extends RespType<
|
||||
RESP_TYPES['DOUBLE'],
|
||||
T,
|
||||
`${T}`,
|
||||
number | string
|
||||
>;
|
||||
export type SimpleStringReply<
|
||||
> {}
|
||||
|
||||
export interface SimpleStringReply<
|
||||
T extends string = string
|
||||
> = RespType<
|
||||
> extends RespType<
|
||||
RESP_TYPES['SIMPLE_STRING'],
|
||||
T,
|
||||
Buffer,
|
||||
string | Buffer
|
||||
>;
|
||||
export type BlobStringReply<
|
||||
> {}
|
||||
|
||||
export interface BlobStringReply<
|
||||
T extends string = string
|
||||
> = RespType<
|
||||
> extends RespType<
|
||||
RESP_TYPES['BLOB_STRING'],
|
||||
T,
|
||||
Buffer,
|
||||
string | Buffer
|
||||
>;
|
||||
export type VerbatimStringReply<
|
||||
> {}
|
||||
|
||||
export interface VerbatimStringReply<
|
||||
T extends string = string
|
||||
> = RespType<
|
||||
> extends RespType<
|
||||
RESP_TYPES['VERBATIM_STRING'],
|
||||
T,
|
||||
Buffer | VerbatimString,
|
||||
string | Buffer | VerbatimString
|
||||
>;
|
||||
export type SimpleErrorReply = RespType<
|
||||
> {}
|
||||
|
||||
export interface SimpleErrorReply extends RespType<
|
||||
RESP_TYPES['SIMPLE_ERROR'],
|
||||
SimpleError,
|
||||
Buffer
|
||||
>;
|
||||
export type BlobErrorReply = RespType<
|
||||
> {}
|
||||
|
||||
export interface BlobErrorReply extends RespType<
|
||||
RESP_TYPES['BLOB_ERROR'],
|
||||
BlobError,
|
||||
Buffer
|
||||
>;
|
||||
export type ArrayReply<T> = RespType<
|
||||
> {}
|
||||
|
||||
export interface ArrayReply<T> extends RespType<
|
||||
RESP_TYPES['ARRAY'],
|
||||
Array<T>,
|
||||
never,
|
||||
Array<any>
|
||||
>;
|
||||
export type TuplesReply<T extends [...Array<unknown>]> = RespType<
|
||||
> {}
|
||||
|
||||
export interface TuplesReply<T extends [...Array<unknown>]> extends RespType<
|
||||
RESP_TYPES['ARRAY'],
|
||||
T,
|
||||
never,
|
||||
Array<any>
|
||||
>;
|
||||
export type SetReply<T> = RespType<
|
||||
> {}
|
||||
|
||||
export interface SetReply<T> extends RespType<
|
||||
RESP_TYPES['SET'],
|
||||
Array<T>,
|
||||
Set<T>,
|
||||
Array<any> | Set<any>
|
||||
>;
|
||||
export type MapReply<K, V> = RespType<
|
||||
> {}
|
||||
|
||||
export interface MapReply<K, V> extends RespType<
|
||||
RESP_TYPES['MAP'],
|
||||
{ [key: string]: V },
|
||||
Map<K, V> | Array<K | V>,
|
||||
Map<any, any> | Array<any>
|
||||
>;
|
||||
> {}
|
||||
|
||||
type MapKeyValue = [key: BlobStringReply, value: unknown];
|
||||
|
||||
type MapTuples = Array<MapKeyValue>;
|
||||
|
||||
export type TuplesToMapReply<T extends MapTuples> = RespType<
|
||||
export interface TuplesToMapReply<T extends MapTuples> extends RespType<
|
||||
RESP_TYPES['MAP'],
|
||||
{
|
||||
[P in T[number] as P[0] extends BlobStringReply<infer S> ? S : never]: P[1];
|
||||
},
|
||||
Map<T[number][0], T[number][1]> | FlattenTuples<T>
|
||||
>;
|
||||
> {}
|
||||
|
||||
type FlattenTuples<T> = (
|
||||
T extends [] ? [] :
|
||||
@@ -131,31 +150,28 @@ type FlattenTuples<T> = (
|
||||
never
|
||||
);
|
||||
|
||||
export type ReplyUnion = NullReply | BooleanReply | NumberReply | BigNumberReply | DoubleReply | SimpleStringReply | BlobStringReply | VerbatimStringReply | SimpleErrorReply | BlobErrorReply |
|
||||
// cannot reuse ArrayReply, SetReply and MapReply because of circular reference
|
||||
RespType<
|
||||
RESP_TYPES['ARRAY'],
|
||||
Array<ReplyUnion>
|
||||
> |
|
||||
RespType<
|
||||
RESP_TYPES['SET'],
|
||||
Array<ReplyUnion>,
|
||||
Set<ReplyUnion>
|
||||
> |
|
||||
RespType<
|
||||
RESP_TYPES['MAP'],
|
||||
{ [key: string]: ReplyUnion },
|
||||
Map<ReplyUnion, ReplyUnion> | Array<ReplyUnion | ReplyUnion>
|
||||
>;
|
||||
export type ReplyUnion = (
|
||||
NullReply |
|
||||
BooleanReply |
|
||||
NumberReply |
|
||||
BigNumberReply |
|
||||
DoubleReply |
|
||||
SimpleStringReply |
|
||||
BlobStringReply |
|
||||
VerbatimStringReply |
|
||||
SimpleErrorReply |
|
||||
BlobErrorReply |
|
||||
ArrayReply<ReplyUnion> |
|
||||
SetReply<ReplyUnion> |
|
||||
MapReply<ReplyUnion, ReplyUnion>
|
||||
);
|
||||
|
||||
export type Reply = ReplyWithTypeMapping<ReplyUnion, {}>;
|
||||
export type MappedType<T> = ((...args: any) => T) | (new (...args: any) => T);
|
||||
|
||||
export type Flag<T> = ((...args: any) => T) | (new (...args: any) => T);
|
||||
|
||||
type RespTypeUnion<T> = T extends RespType<RespTypes, unknown, unknown, infer FLAG_TYPES> ? FLAG_TYPES : never;
|
||||
type InferTypeMapping<T> = T extends RespType<RespTypes, unknown, unknown, infer FLAG_TYPES> ? FLAG_TYPES : never;
|
||||
|
||||
export type TypeMapping = {
|
||||
[P in RespTypes]?: Flag<RespTypeUnion<Extract<ReplyUnion, RespType<P, any, any, any>>>>;
|
||||
[P in RespTypes]?: MappedType<InferTypeMapping<Extract<ReplyUnion, RespType<P, any, any, any>>>>;
|
||||
};
|
||||
|
||||
type MapKey<
|
||||
@@ -167,13 +183,15 @@ type MapKey<
|
||||
[RESP_TYPES.BLOB_STRING]: StringConstructor;
|
||||
}>;
|
||||
|
||||
export type UnwrapReply<REPLY extends RespType<any, any, any, any>> = REPLY['DEFAULT' | 'TYPES'];
|
||||
|
||||
export type ReplyWithTypeMapping<
|
||||
REPLY,
|
||||
TYPE_MAPPING extends TypeMapping
|
||||
> = (
|
||||
// if REPLY is a type, extract the coresponding type from TYPE_MAPPING or use the default type
|
||||
REPLY extends RespType<infer RESP_TYPE, infer DEFAULT, infer TYPES, unknown> ?
|
||||
TYPE_MAPPING[RESP_TYPE] extends Flag<infer T> ?
|
||||
TYPE_MAPPING[RESP_TYPE] extends MappedType<infer T> ?
|
||||
ReplyWithTypeMapping<Extract<DEFAULT | TYPES, T>, TYPE_MAPPING> :
|
||||
ReplyWithTypeMapping<DEFAULT, TYPE_MAPPING>
|
||||
: (
|
||||
@@ -193,6 +211,11 @@ export type ReplyWithTypeMapping<
|
||||
)
|
||||
);
|
||||
|
||||
type a = ReplyWithTypeMapping<
|
||||
ArrayReply<TuplesReply<[BlobStringReply | NullReply]>>,
|
||||
{}
|
||||
>;
|
||||
|
||||
export type TransformReply = (this: void, reply: any, preserve?: any) => any; // TODO;
|
||||
|
||||
export type RedisArgument = string | Buffer;
|
||||
@@ -323,7 +346,7 @@ export type CommandReply<
|
||||
// if transformReply[RESP] is a function, use its return type
|
||||
COMMAND['transformReply'] extends Record<RESP, (...args: any) => infer T> ? T :
|
||||
// otherwise use the generic reply type
|
||||
Reply
|
||||
ReplyUnion
|
||||
);
|
||||
|
||||
export type CommandSignature<
|
||||
|
@@ -425,7 +425,6 @@ export default class RedisClient<
|
||||
} catch (err) {
|
||||
this._queue.decoder.reset();
|
||||
this.emit('error', err);
|
||||
|
||||
}
|
||||
})
|
||||
.on('error', err => {
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, Resp2Reply, Command } from '../RESP/types';
|
||||
import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types';
|
||||
|
||||
type AclUser = TuplesToMapReply<[
|
||||
[BlobStringReply<'flags'>, ArrayReply<BlobStringReply>],
|
||||
@@ -23,17 +23,20 @@ export default {
|
||||
return ['ACL', 'GETUSER', username];
|
||||
},
|
||||
transformReply: {
|
||||
2: (reply: Resp2Reply<AclUser>) => ({
|
||||
2: (reply: UnwrapReply<Resp2Reply<AclUser>>) => ({
|
||||
flags: reply[1],
|
||||
passwords: reply[3],
|
||||
commands: reply[5],
|
||||
keys: reply[7],
|
||||
channels: reply[9],
|
||||
selectors: reply[11]?.map(selector => ({
|
||||
commands: selector[1],
|
||||
keys: selector[3],
|
||||
channels: selector[5]
|
||||
}))
|
||||
selectors: (reply[11] as unknown as UnwrapReply<typeof reply[11]>)?.map(selector => {
|
||||
const inferred = selector as unknown as UnwrapReply<typeof selector>;
|
||||
return {
|
||||
commands: inferred[1],
|
||||
keys: inferred[3],
|
||||
channels: inferred[5]
|
||||
};
|
||||
})
|
||||
}),
|
||||
3: undefined as unknown as () => AclUser
|
||||
}
|
||||
|
@@ -1,5 +1,4 @@
|
||||
import { DoubleReply, Resp2Reply } from '../RESP/types';
|
||||
import { ArrayReply, BlobStringReply, Command, NumberReply, TuplesToMapReply } from '../RESP/types';
|
||||
import { ArrayReply, TuplesToMapReply, BlobStringReply, NumberReply, DoubleReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types';
|
||||
|
||||
export type AclLogReply = ArrayReply<TuplesToMapReply<[
|
||||
[BlobStringReply<'count'>, NumberReply],
|
||||
@@ -30,18 +29,23 @@ export default {
|
||||
return args;
|
||||
},
|
||||
transformReply: {
|
||||
2: (reply: Resp2Reply<AclLogReply>) => reply.map(item => ({
|
||||
count: item[1],
|
||||
reason: item[3],
|
||||
context: item[5],
|
||||
object: item[7],
|
||||
username: item[9],
|
||||
'age-seconds': Number(item[11]),
|
||||
'client-info': item[13],
|
||||
'entry-id': item[15],
|
||||
'timestamp-created': item[17],
|
||||
'timestamp-last-updated': item[19]
|
||||
})),
|
||||
2: (reply: UnwrapReply<Resp2Reply<AclLogReply>>) => {
|
||||
return reply.map(item => {
|
||||
const inferred = item as unknown as UnwrapReply<typeof item>;
|
||||
return {
|
||||
count: inferred[1],
|
||||
reason: inferred[3],
|
||||
context: inferred[5],
|
||||
object: inferred[7],
|
||||
username: inferred[9],
|
||||
'age-seconds': Number(inferred[11]),
|
||||
'client-info': inferred[13],
|
||||
'entry-id': inferred[15],
|
||||
'timestamp-created': inferred[17],
|
||||
'timestamp-last-updated': inferred[19]
|
||||
};
|
||||
})
|
||||
},
|
||||
3: undefined as unknown as () => AclLogReply
|
||||
}
|
||||
} as const satisfies Command;
|
||||
|
@@ -34,6 +34,12 @@ describe('BITFIELD', () => {
|
||||
});
|
||||
|
||||
testUtils.testAll('bitField', async client => {
|
||||
const a = client.bitField('key', [{
|
||||
operation: 'GET',
|
||||
encoding: 'i8',
|
||||
offset: 0
|
||||
}]);
|
||||
|
||||
assert.deepEqual(
|
||||
await client.bitField('key', [{
|
||||
operation: 'GET',
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { BlobStringReply, NullReply, Command } from '../RESP/types';
|
||||
import { UnwrapReply, NullReply, TuplesReply, BlobStringReply, Command } from '../RESP/types';
|
||||
import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers';
|
||||
|
||||
export default {
|
||||
@@ -12,7 +12,7 @@ export default {
|
||||
args.push(timeout.toString());
|
||||
return args;
|
||||
},
|
||||
transformReply(reply: NullReply | [BlobStringReply, BlobStringReply]) {
|
||||
transformReply(reply: UnwrapReply<NullReply | TuplesReply<[BlobStringReply, BlobStringReply]>>) {
|
||||
if (reply === null) return null;
|
||||
|
||||
return {
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { RedisArgument, Command, NullReply, TuplesReply, BlobStringReply, DoubleReply } from '../RESP/types';
|
||||
import { RedisArgument, NullReply, TuplesReply, BlobStringReply, DoubleReply, UnwrapReply, Command } from '../RESP/types';
|
||||
import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers';
|
||||
|
||||
export function transformBZPopArguments(
|
||||
@@ -20,14 +20,14 @@ export default {
|
||||
return transformBZPopArguments('BZPOPMAX', ...args);
|
||||
},
|
||||
transformReply: {
|
||||
2: (reply: NullReply | TuplesReply<[BlobStringReply, BlobStringReply, BlobStringReply]>) => {
|
||||
2(reply: UnwrapReply<NullReply | TuplesReply<[BlobStringReply, BlobStringReply, BlobStringReply]>>) {
|
||||
return reply === null ? null : {
|
||||
key: reply[0],
|
||||
value: reply[1],
|
||||
score: Number(reply[2])
|
||||
};
|
||||
},
|
||||
3: (reply: NullReply | TuplesReply<[BlobStringReply, BlobStringReply, DoubleReply]>) => {
|
||||
3(reply: UnwrapReply<NullReply | TuplesReply<[BlobStringReply, BlobStringReply, DoubleReply]>>) {
|
||||
return reply === null ? null : {
|
||||
key: reply[0],
|
||||
value: reply[1],
|
||||
|
@@ -1,50 +1,50 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { transformArguments, transformReply } from './CLIENT_INFO';
|
||||
import CLIENT_INFO from './CLIENT_INFO';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
|
||||
describe('CLIENT INFO', () => {
|
||||
testUtils.isVersionGreaterThanHook([6, 2]);
|
||||
testUtils.isVersionGreaterThanHook([6, 2]);
|
||||
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['CLIENT', 'INFO']
|
||||
);
|
||||
});
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
CLIENT_INFO.transformArguments(),
|
||||
['CLIENT', 'INFO']
|
||||
);
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.clientInfo', async client => {
|
||||
const reply = await client.clientInfo();
|
||||
assert.equal(typeof reply.id, 'number');
|
||||
assert.equal(typeof reply.addr, 'string');
|
||||
assert.equal(typeof reply.laddr, 'string');
|
||||
assert.equal(typeof reply.fd, 'number');
|
||||
assert.equal(typeof reply.name, 'string');
|
||||
assert.equal(typeof reply.age, 'number');
|
||||
assert.equal(typeof reply.idle, 'number');
|
||||
assert.equal(typeof reply.flags, 'string');
|
||||
assert.equal(typeof reply.db, 'number');
|
||||
assert.equal(typeof reply.sub, 'number');
|
||||
assert.equal(typeof reply.psub, 'number');
|
||||
assert.equal(typeof reply.multi, 'number');
|
||||
assert.equal(typeof reply.qbuf, 'number');
|
||||
assert.equal(typeof reply.qbufFree, 'number');
|
||||
assert.equal(typeof reply.argvMem, 'number');
|
||||
assert.equal(typeof reply.obl, 'number');
|
||||
assert.equal(typeof reply.oll, 'number');
|
||||
assert.equal(typeof reply.omem, 'number');
|
||||
assert.equal(typeof reply.totMem, 'number');
|
||||
assert.equal(typeof reply.events, 'string');
|
||||
assert.equal(typeof reply.cmd, 'string');
|
||||
assert.equal(typeof reply.user, 'string');
|
||||
assert.equal(typeof reply.redir, 'number');
|
||||
testUtils.testWithClient('client.clientInfo', async client => {
|
||||
const reply = await client.clientInfo();
|
||||
assert.equal(typeof reply.id, 'number');
|
||||
assert.equal(typeof reply.addr, 'string');
|
||||
assert.equal(typeof reply.laddr, 'string');
|
||||
assert.equal(typeof reply.fd, 'number');
|
||||
assert.equal(typeof reply.name, 'string');
|
||||
assert.equal(typeof reply.age, 'number');
|
||||
assert.equal(typeof reply.idle, 'number');
|
||||
assert.equal(typeof reply.flags, 'string');
|
||||
assert.equal(typeof reply.db, 'number');
|
||||
assert.equal(typeof reply.sub, 'number');
|
||||
assert.equal(typeof reply.psub, 'number');
|
||||
assert.equal(typeof reply.multi, 'number');
|
||||
assert.equal(typeof reply.qbuf, 'number');
|
||||
assert.equal(typeof reply.qbufFree, 'number');
|
||||
assert.equal(typeof reply.argvMem, 'number');
|
||||
assert.equal(typeof reply.obl, 'number');
|
||||
assert.equal(typeof reply.oll, 'number');
|
||||
assert.equal(typeof reply.omem, 'number');
|
||||
assert.equal(typeof reply.totMem, 'number');
|
||||
assert.equal(typeof reply.events, 'string');
|
||||
assert.equal(typeof reply.cmd, 'string');
|
||||
assert.equal(typeof reply.user, 'string');
|
||||
assert.equal(typeof reply.redir, 'number');
|
||||
|
||||
if (testUtils.isVersionGreaterThan([7, 0])) {
|
||||
assert.equal(typeof reply.multiMem, 'number');
|
||||
assert.equal(typeof reply.resp, 'number');
|
||||
}
|
||||
if (testUtils.isVersionGreaterThan([7, 0])) {
|
||||
assert.equal(typeof reply.multiMem, 'number');
|
||||
assert.equal(typeof reply.resp, 'number');
|
||||
|
||||
if (testUtils.isVersionGreaterThan([7, 0, 3])) {
|
||||
assert.equal(typeof reply.ssub, 'number');
|
||||
}
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
if (testUtils.isVersionGreaterThan([7, 0, 3])) {
|
||||
assert.equal(typeof reply.ssub, 'number');
|
||||
}
|
||||
}
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
||||
|
@@ -1,78 +1,77 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { transformArguments, transformReply } from './CLIENT_LIST';
|
||||
import CLIENT_LIST from './CLIENT_LIST';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
|
||||
describe('CLIENT LIST', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('simple', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['CLIENT', 'LIST']
|
||||
);
|
||||
});
|
||||
|
||||
it('with TYPE', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments({
|
||||
TYPE: 'NORMAL'
|
||||
}),
|
||||
['CLIENT', 'LIST', 'TYPE', 'NORMAL']
|
||||
);
|
||||
});
|
||||
|
||||
it('with ID', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments({
|
||||
ID: ['1', '2']
|
||||
}),
|
||||
['CLIENT', 'LIST', 'ID', '1', '2']
|
||||
);
|
||||
});
|
||||
describe('transformArguments', () => {
|
||||
it('simple', () => {
|
||||
assert.deepEqual(
|
||||
CLIENT_LIST.transformArguments(),
|
||||
['CLIENT', 'LIST']
|
||||
);
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.clientList', async client => {
|
||||
const reply = await client.clientList();
|
||||
assert.ok(Array.isArray(reply));
|
||||
it('with TYPE', () => {
|
||||
assert.deepEqual(
|
||||
CLIENT_LIST.transformArguments({
|
||||
TYPE: 'NORMAL'
|
||||
}),
|
||||
['CLIENT', 'LIST', 'TYPE', 'NORMAL']
|
||||
);
|
||||
});
|
||||
|
||||
for (const item of reply) {
|
||||
assert.equal(typeof item.id, 'number');
|
||||
assert.equal(typeof item.addr, 'string');
|
||||
assert.equal(typeof item.fd, 'number');
|
||||
assert.equal(typeof item.name, 'string');
|
||||
assert.equal(typeof item.age, 'number');
|
||||
assert.equal(typeof item.idle, 'number');
|
||||
assert.equal(typeof item.flags, 'string');
|
||||
assert.equal(typeof item.db, 'number');
|
||||
assert.equal(typeof item.sub, 'number');
|
||||
assert.equal(typeof item.psub, 'number');
|
||||
assert.equal(typeof item.multi, 'number');
|
||||
assert.equal(typeof item.qbuf, 'number');
|
||||
assert.equal(typeof item.qbufFree, 'number');
|
||||
assert.equal(typeof item.obl, 'number');
|
||||
assert.equal(typeof item.oll, 'number');
|
||||
assert.equal(typeof item.omem, 'number');
|
||||
assert.equal(typeof item.events, 'string');
|
||||
assert.equal(typeof item.cmd, 'string');
|
||||
it('with ID', () => {
|
||||
assert.deepEqual(
|
||||
CLIENT_LIST.transformArguments({
|
||||
ID: ['1', '2']
|
||||
}),
|
||||
['CLIENT', 'LIST', 'ID', '1', '2']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
if (testUtils.isVersionGreaterThan([6, 0])) {
|
||||
assert.equal(typeof item.argvMem, 'number');
|
||||
assert.equal(typeof item.totMem, 'number');
|
||||
assert.equal(typeof item.user, 'string');
|
||||
}
|
||||
testUtils.testWithClient('client.clientList', async client => {
|
||||
const reply = await client.clientList();
|
||||
assert.ok(Array.isArray(reply));
|
||||
for (const item of reply) {
|
||||
assert.equal(typeof item.id, 'number');
|
||||
assert.equal(typeof item.addr, 'string');
|
||||
assert.equal(typeof item.fd, 'number');
|
||||
assert.equal(typeof item.name, 'string');
|
||||
assert.equal(typeof item.age, 'number');
|
||||
assert.equal(typeof item.idle, 'number');
|
||||
assert.equal(typeof item.flags, 'string');
|
||||
assert.equal(typeof item.db, 'number');
|
||||
assert.equal(typeof item.sub, 'number');
|
||||
assert.equal(typeof item.psub, 'number');
|
||||
assert.equal(typeof item.multi, 'number');
|
||||
assert.equal(typeof item.qbuf, 'number');
|
||||
assert.equal(typeof item.qbufFree, 'number');
|
||||
assert.equal(typeof item.obl, 'number');
|
||||
assert.equal(typeof item.oll, 'number');
|
||||
assert.equal(typeof item.omem, 'number');
|
||||
assert.equal(typeof item.events, 'string');
|
||||
assert.equal(typeof item.cmd, 'string');
|
||||
|
||||
if (testUtils.isVersionGreaterThan([6, 2])) {
|
||||
assert.equal(typeof item.redir, 'number');
|
||||
assert.equal(typeof item.laddr, 'string');
|
||||
}
|
||||
if (testUtils.isVersionGreaterThan([6, 0])) {
|
||||
assert.equal(typeof item.argvMem, 'number');
|
||||
assert.equal(typeof item.totMem, 'number');
|
||||
assert.equal(typeof item.user, 'string');
|
||||
|
||||
if (testUtils.isVersionGreaterThan([7, 0])) {
|
||||
assert.equal(typeof item.multiMem, 'number');
|
||||
assert.equal(typeof item.resp, 'number');
|
||||
}
|
||||
if (testUtils.isVersionGreaterThan([6, 2])) {
|
||||
assert.equal(typeof item.redir, 'number');
|
||||
assert.equal(typeof item.laddr, 'string');
|
||||
|
||||
if (testUtils.isVersionGreaterThan([7, 0])) {
|
||||
assert.equal(typeof item.multiMem, 'number');
|
||||
assert.equal(typeof item.resp, 'number');
|
||||
|
||||
if (testUtils.isVersionGreaterThan([7, 0, 3])) {
|
||||
assert.equal(typeof item.ssub, 'number');
|
||||
assert.equal(typeof item.ssub, 'number');
|
||||
}
|
||||
}
|
||||
}
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
}
|
||||
}
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
||||
|
@@ -36,7 +36,7 @@ export default {
|
||||
length = split.length - 1,
|
||||
reply: Array<ClientInfoReply> = [];
|
||||
for (let i = 0; i < length; i++) {
|
||||
reply.push(CLIENT_INFO.transformReply(split[i] as VerbatimStringReply));
|
||||
reply.push(CLIENT_INFO.transformReply(split[i] as unknown as VerbatimStringReply));
|
||||
}
|
||||
|
||||
return reply;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { TuplesToMapReply, BlobStringReply, SetReply, NumberReply, ArrayReply, Resp2Reply, Command } from '../RESP/types';
|
||||
import { TuplesToMapReply, BlobStringReply, SetReply, NumberReply, ArrayReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types';
|
||||
|
||||
type TrackingInfo = TuplesToMapReply<[
|
||||
[BlobStringReply<'flags'>, SetReply<BlobStringReply>],
|
||||
@@ -13,7 +13,7 @@ export default {
|
||||
return ['CLIENT', 'TRACKINGINFO'];
|
||||
},
|
||||
transformReply: {
|
||||
2: (reply: Resp2Reply<TrackingInfo>) => ({
|
||||
2: (reply: UnwrapReply<Resp2Reply<TrackingInfo>>) => ({
|
||||
flags: reply[1],
|
||||
redirect: reply[3],
|
||||
prefixes: reply[5]
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { ArrayReply, TuplesToMapReply, BlobStringReply, NumberReply, Resp2Reply, Command } from '../RESP/types';
|
||||
import { ArrayReply, TuplesToMapReply, BlobStringReply, NumberReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types';
|
||||
|
||||
type ClusterLinksReply = ArrayReply<TuplesToMapReply<[
|
||||
[BlobStringReply<'direction'>, BlobStringReply],
|
||||
@@ -16,14 +16,17 @@ export default {
|
||||
return ['CLUSTER', 'LINKS'];
|
||||
},
|
||||
transformReply: {
|
||||
2: (reply: Resp2Reply<ClusterLinksReply>) => reply.map(link => ({
|
||||
direction: link[1],
|
||||
node: link[3],
|
||||
'create-time': link[5],
|
||||
events: link[7],
|
||||
'send-buffer-allocated': link[9],
|
||||
'send-buffer-used': link[11]
|
||||
})),
|
||||
2: (reply: UnwrapReply<Resp2Reply<ClusterLinksReply>>) => reply.map(link => {
|
||||
const unwrapped = link as unknown as UnwrapReply<typeof link>;
|
||||
return {
|
||||
direction: unwrapped[1],
|
||||
node: unwrapped[3],
|
||||
'create-time': unwrapped[5],
|
||||
events: unwrapped[7],
|
||||
'send-buffer-allocated': unwrapped[9],
|
||||
'send-buffer-used': unwrapped[11]
|
||||
};
|
||||
}),
|
||||
3: undefined as unknown as () => ClusterLinksReply
|
||||
}
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import { NumberReply, ArrayReply, BlobStringReply, Command } from '../RESP/types';
|
||||
import { TuplesReply, BlobStringReply, NumberReply, ArrayReply, UnwrapReply, Command } from '../RESP/types';
|
||||
|
||||
type RawNode = [
|
||||
type RawNode = TuplesReply<[
|
||||
host: BlobStringReply,
|
||||
port: NumberReply,
|
||||
id: BlobStringReply
|
||||
];
|
||||
]>;
|
||||
|
||||
type ClusterSlotsRawReply = ArrayReply<[
|
||||
from: NumberReply,
|
||||
@@ -21,7 +21,7 @@ export default {
|
||||
transformArguments() {
|
||||
return ['CLUSTER', 'SLOTS'];
|
||||
},
|
||||
transformReply(reply: ClusterSlotsRawReply) {
|
||||
transformReply(reply: UnwrapReply<ClusterSlotsRawReply>) {
|
||||
return reply.map(([from, to, master, ...replicas]) => ({
|
||||
from,
|
||||
to,
|
||||
@@ -31,7 +31,8 @@ export default {
|
||||
}
|
||||
} as const satisfies Command;
|
||||
|
||||
function transformNode([host, port, id ]: RawNode) {
|
||||
function transformNode(node: RawNode) {
|
||||
const [host, port, id] = node as unknown as UnwrapReply<typeof node>;
|
||||
return {
|
||||
host,
|
||||
port,
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { RedisArgument, ArrayReply, TuplesReply, BlobStringReply, SetReply, Command } from '../RESP/types';
|
||||
import { RedisArgument, ArrayReply, TuplesReply, BlobStringReply, SetReply, UnwrapReply, Command } from '../RESP/types';
|
||||
|
||||
export type CommandGetKeysAndFlagsRawReply = ArrayReply<TuplesReply<[
|
||||
key: BlobStringReply,
|
||||
@@ -11,10 +11,13 @@ export default {
|
||||
transformArguments(args: Array<RedisArgument>) {
|
||||
return ['COMMAND', 'GETKEYSANDFLAGS', ...args];
|
||||
},
|
||||
transformReply(reply: CommandGetKeysAndFlagsRawReply) {
|
||||
return reply.map(([key, flags]) => ({
|
||||
key,
|
||||
flags
|
||||
}));
|
||||
transformReply(reply: UnwrapReply<CommandGetKeysAndFlagsRawReply>) {
|
||||
return reply.map(entry => {
|
||||
const [key, flags] = entry as unknown as UnwrapReply<typeof entry>;
|
||||
return {
|
||||
key,
|
||||
flags
|
||||
};
|
||||
});
|
||||
}
|
||||
} as const satisfies Command;
|
||||
|
@@ -25,19 +25,21 @@ describe('FUNCTION LIST', () => {
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.functionList', async client => {
|
||||
await loadMathFunction(client);
|
||||
const [, reply] = await Promise.all([
|
||||
loadMathFunction(client),
|
||||
client.functionList()
|
||||
]);
|
||||
|
||||
assert.deepEqual(
|
||||
await client.functionList(),
|
||||
[{
|
||||
library_name: MATH_FUNCTION.name,
|
||||
engine: MATH_FUNCTION.engine,
|
||||
functions: [{
|
||||
name: MATH_FUNCTION.library.square.NAME,
|
||||
description: null,
|
||||
flags: ['no-writes']
|
||||
}]
|
||||
reply[0].library_name;
|
||||
|
||||
assert.deepEqual(reply, [{
|
||||
library_name: MATH_FUNCTION.name,
|
||||
engine: MATH_FUNCTION.engine,
|
||||
functions: [{
|
||||
name: MATH_FUNCTION.library.square.NAME,
|
||||
description: null,
|
||||
flags: ['no-writes']
|
||||
}]
|
||||
);
|
||||
}]);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
||||
|
@@ -1,18 +1,18 @@
|
||||
import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, NullReply, SetReply, Resp2Reply, CommandArguments, Command } from '../RESP/types';
|
||||
import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, NullReply, SetReply, UnwrapReply, Resp2Reply, CommandArguments, Command, ReplyWithTypeMapping } from '../RESP/types';
|
||||
|
||||
export interface FunctionListOptions {
|
||||
LIBRARYNAME?: RedisArgument;
|
||||
}
|
||||
|
||||
export type FunctionListReplyItem = [
|
||||
[BlobStringReply<'library_name'>, BlobStringReply],
|
||||
[BlobStringReply<'library_name'>, BlobStringReply | NullReply],
|
||||
[BlobStringReply<'engine'>, BlobStringReply],
|
||||
[BlobStringReply<'functions'>, ArrayReply<TuplesToMapReply<[
|
||||
[BlobStringReply<'name'>, BlobStringReply],
|
||||
[BlobStringReply<'description'>, BlobStringReply | NullReply],
|
||||
[BlobStringReply<'flags'>, SetReply<BlobStringReply>],
|
||||
]>>]
|
||||
]
|
||||
];
|
||||
|
||||
export type FunctionListReply = ArrayReply<TuplesToMapReply<FunctionListReplyItem>>;
|
||||
|
||||
@@ -29,16 +29,22 @@ export default {
|
||||
return args;
|
||||
},
|
||||
transformReply: {
|
||||
2: (reply: Resp2Reply<FunctionListReply>) => {
|
||||
return reply.map(library => ({
|
||||
library_name: library[1],
|
||||
engine: library[3],
|
||||
functions: library[5].map(fn => ({
|
||||
name: fn[1],
|
||||
description: fn[3],
|
||||
flags: fn[5]
|
||||
}))
|
||||
}));
|
||||
2: (reply: UnwrapReply<Resp2Reply<FunctionListReply>>) => {
|
||||
return reply.map(library => {
|
||||
const unwrapped = library as unknown as UnwrapReply<typeof library>;
|
||||
return {
|
||||
library_name: unwrapped[1],
|
||||
engine: unwrapped[3],
|
||||
functions: (unwrapped[5] as unknown as UnwrapReply<typeof unwrapped[5]>).map(fn => {
|
||||
const unwrapped = fn as unknown as UnwrapReply<typeof fn>;
|
||||
return {
|
||||
name: unwrapped[1],
|
||||
description: unwrapped[3],
|
||||
flags: unwrapped[5]
|
||||
};
|
||||
})
|
||||
};
|
||||
});
|
||||
},
|
||||
3: undefined as unknown as () => FunctionListReply
|
||||
}
|
||||
|
@@ -25,20 +25,24 @@ describe('FUNCTION LIST WITHCODE', () => {
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.functionListWithCode', async client => {
|
||||
await loadMathFunction(client);
|
||||
const [, reply] = await Promise.all([
|
||||
loadMathFunction(client),
|
||||
client.functionListWithCode()
|
||||
]);
|
||||
|
||||
assert.deepEqual(
|
||||
await client.functionListWithCode(),
|
||||
[{
|
||||
library_name: MATH_FUNCTION.name,
|
||||
engine: MATH_FUNCTION.engine,
|
||||
functions: [{
|
||||
name: MATH_FUNCTION.library.square.NAME,
|
||||
description: null,
|
||||
flags: ['no-writes']
|
||||
}],
|
||||
library_code: MATH_FUNCTION.code
|
||||
}]
|
||||
);
|
||||
const a = reply[0];
|
||||
|
||||
const b = a.functions[0].description;
|
||||
|
||||
assert.deepEqual(reply, [{
|
||||
library_name: MATH_FUNCTION.name,
|
||||
engine: MATH_FUNCTION.engine,
|
||||
functions: [{
|
||||
name: MATH_FUNCTION.library.square.NAME,
|
||||
description: null,
|
||||
flags: ['no-writes']
|
||||
}],
|
||||
library_code: MATH_FUNCTION.code
|
||||
}]);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { TuplesToMapReply, BlobStringReply, ArrayReply, Command, Resp2Reply } from '../RESP/types';
|
||||
import { TuplesToMapReply, BlobStringReply, ArrayReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types';
|
||||
import FUNCTION_LIST, { FunctionListReplyItem } from './FUNCTION_LIST';
|
||||
|
||||
export type FunctionListWithCodeReply = ArrayReply<TuplesToMapReply<[
|
||||
@@ -15,17 +15,23 @@ export default {
|
||||
return redisArgs;
|
||||
},
|
||||
transformReply: {
|
||||
2: (reply: Resp2Reply<FunctionListWithCodeReply>) => {
|
||||
return reply.map((library: any) => ({
|
||||
library_name: library[1],
|
||||
engine: library[3],
|
||||
functions: library[5].map((fn: any) => ({
|
||||
name: fn[1],
|
||||
description: fn[3],
|
||||
flags: fn[5]
|
||||
})),
|
||||
library_code: library[7]
|
||||
})) as unknown as number;
|
||||
2: (reply: UnwrapReply<Resp2Reply<FunctionListWithCodeReply>>) => {
|
||||
return reply.map(library => {
|
||||
const unwrapped = library as unknown as UnwrapReply<typeof library>;
|
||||
return {
|
||||
library_name: unwrapped[1],
|
||||
engine: unwrapped[3],
|
||||
functions: (unwrapped[5] as unknown as UnwrapReply<typeof unwrapped[5]>).map(fn => {
|
||||
const unwrapped = fn as unknown as UnwrapReply<typeof fn>;
|
||||
return {
|
||||
name: unwrapped[1],
|
||||
description: unwrapped[3],
|
||||
flags: unwrapped[5]
|
||||
};
|
||||
}),
|
||||
library_code: unwrapped[7]
|
||||
};
|
||||
});
|
||||
},
|
||||
3: undefined as unknown as () => FunctionListWithCodeReply
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { ArrayReply, BlobStringReply, NullReply, Command, RedisArgument } from '../RESP/types';
|
||||
import { RedisArgument, ArrayReply, TuplesReply, BlobStringReply, NullReply, UnwrapReply, Command } from '../RESP/types';
|
||||
import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers';
|
||||
|
||||
export default {
|
||||
@@ -10,10 +10,13 @@ export default {
|
||||
) {
|
||||
return pushVariadicArguments(['GEOPOS', key], member);
|
||||
},
|
||||
transformReply(reply: ArrayReply<[BlobStringReply, BlobStringReply] | NullReply>) {
|
||||
return reply.map(item => item === null ? null : {
|
||||
longitude: item[0],
|
||||
latitude: item[1]
|
||||
transformReply(reply: UnwrapReply<ArrayReply<TuplesReply<[BlobStringReply, BlobStringReply]> | NullReply>>) {
|
||||
return reply.map(item => {
|
||||
const unwrapped = item as unknown as UnwrapReply<typeof item>;
|
||||
return unwrapped === null ? null : {
|
||||
longitude: unwrapped[0],
|
||||
latitude: unwrapped[1]
|
||||
};
|
||||
});
|
||||
}
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { ArrayReply, BlobStringReply, NumberReply, DoubleReply, Command, RedisArgument } from '../RESP/types';
|
||||
import { RedisArgument, ArrayReply, TuplesReply, BlobStringReply, NumberReply, DoubleReply, UnwrapReply, Command } from '../RESP/types';
|
||||
import GEOSEARCH, { GeoSearchBy, GeoSearchFrom, GeoSearchOptions } from './GEOSEARCH';
|
||||
|
||||
export const GEO_REPLY_WITH = {
|
||||
@@ -35,7 +35,7 @@ export default {
|
||||
return args;
|
||||
},
|
||||
transformReply(
|
||||
reply: ArrayReply<[BlobStringReply, ...Array<any>]>,
|
||||
reply: UnwrapReply<ArrayReply<TuplesReply<[BlobStringReply, ...Array<any>]>>>,
|
||||
replyWith: Array<GeoReplyWith>
|
||||
) {
|
||||
const replyWithSet = new Set(replyWith);
|
||||
@@ -45,20 +45,22 @@ export default {
|
||||
coordinatesIndex = replyWithSet.has(GEO_REPLY_WITH.COORDINATES) && ++index;
|
||||
|
||||
return reply.map(raw => {
|
||||
const unwrapped = raw as unknown as UnwrapReply<typeof raw>;
|
||||
|
||||
const item: GeoReplyWithMember = {
|
||||
member: raw[0]
|
||||
member: unwrapped[0]
|
||||
};
|
||||
|
||||
if (distanceIndex) {
|
||||
item.distance = raw[distanceIndex];
|
||||
item.distance = unwrapped[distanceIndex];
|
||||
}
|
||||
|
||||
if (hashIndex) {
|
||||
item.hash = raw[hashIndex];
|
||||
item.hash = unwrapped[hashIndex];
|
||||
}
|
||||
|
||||
if (coordinatesIndex) {
|
||||
const [longitude, latitude] = raw[coordinatesIndex];
|
||||
const [longitude, latitude] = unwrapped[coordinatesIndex];
|
||||
item.coordinates = {
|
||||
longitude,
|
||||
latitude
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { RedisArgument, ArrayReply, BlobStringReply, Command, NumberReply, Resp2Reply, RespVersions, TuplesToMapReply } from '../RESP/types';
|
||||
import { RedisArgument, RespVersions, TuplesToMapReply, BlobStringReply, NumberReply, ArrayReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types';
|
||||
|
||||
export interface HelloOptions {
|
||||
protover?: RespVersions;
|
||||
@@ -45,7 +45,7 @@ export default {
|
||||
return args;
|
||||
},
|
||||
transformReply: {
|
||||
2: (reply: Resp2Reply<HelloReply>) => ({
|
||||
2: (reply: UnwrapReply<Resp2Reply<HelloReply>>) => ({
|
||||
server: reply[1],
|
||||
version: reply[3],
|
||||
proto: reply[5],
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types';
|
||||
import { RedisArgument, ArrayReply, TuplesReply, BlobStringReply, UnwrapReply, Command } from '../RESP/types';
|
||||
|
||||
export type HRandFieldCountWithValuesReply = Array<{
|
||||
field: BlobStringReply;
|
||||
@@ -12,7 +12,7 @@ export default {
|
||||
return ['HRANDFIELD', key, count.toString(), 'WITHVALUES'];
|
||||
},
|
||||
transformReply: {
|
||||
2: (rawReply: ArrayReply<BlobStringReply>) => {
|
||||
2: (rawReply: UnwrapReply<ArrayReply<BlobStringReply>>) => {
|
||||
const reply: HRandFieldCountWithValuesReply = [];
|
||||
|
||||
let i = 0;
|
||||
@@ -25,11 +25,14 @@ export default {
|
||||
|
||||
return reply;
|
||||
},
|
||||
3: (reply: ArrayReply<[BlobStringReply, BlobStringReply]>) => {
|
||||
return reply.map(([field, value]) => ({
|
||||
field,
|
||||
value
|
||||
})) satisfies HRandFieldCountWithValuesReply;
|
||||
3: (reply: UnwrapReply<ArrayReply<TuplesReply<[BlobStringReply, BlobStringReply]>>>) => {
|
||||
return reply.map(entry => {
|
||||
const [field, value] = entry as unknown as UnwrapReply<typeof entry>;
|
||||
return {
|
||||
field,
|
||||
value
|
||||
};
|
||||
}) satisfies HRandFieldCountWithValuesReply;
|
||||
}
|
||||
}
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, NumberReply, Resp2Reply, Command, TuplesReply } from '../RESP/types';
|
||||
import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, NumberReply, UnwrapReply, Resp2Reply, Command, TuplesReply } from '../RESP/types';
|
||||
import LCS from './LCS';
|
||||
|
||||
export interface LcsIdxOptions {
|
||||
@@ -41,7 +41,7 @@ export default {
|
||||
return args;
|
||||
},
|
||||
transformReply: {
|
||||
2: (reply: Resp2Reply<LcsIdxReply>) => ({
|
||||
2: (reply: UnwrapReply<Resp2Reply<LcsIdxReply>>) => ({
|
||||
matches: reply[1],
|
||||
len: reply[3]
|
||||
}),
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, NumberReply, Resp2Reply, Command, TuplesReply } from '../RESP/types';
|
||||
import { RedisArgument, TuplesToMapReply, BlobStringReply, ArrayReply, TuplesReply, NumberReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types';
|
||||
import LCS_IDX, { LcsIdxOptions, LcsIdxRange } from './LCS_IDX';
|
||||
|
||||
export type LcsIdxWithMatchLenMatches = ArrayReply<
|
||||
@@ -27,7 +27,7 @@ export default {
|
||||
return args;
|
||||
},
|
||||
transformReply: {
|
||||
2: (reply: Resp2Reply<LcsIdxWithMatchLenReply>) => ({
|
||||
2: (reply: UnwrapReply<Resp2Reply<LcsIdxWithMatchLenReply>>) => ({
|
||||
matches: reply[1],
|
||||
len: reply[3]
|
||||
}),
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { TuplesToMapReply, BlobStringReply, NumberReply, DoubleReply, Command, Resp2Reply } from '../RESP/types';
|
||||
import { TuplesToMapReply, BlobStringReply, NumberReply, DoubleReply, ArrayReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types';
|
||||
|
||||
export type MemoryStatsReply = TuplesToMapReply<[
|
||||
[BlobStringReply<'peak.allocated'>, NumberReply],
|
||||
@@ -39,13 +39,12 @@ export default {
|
||||
return ['MEMORY', 'STATS'];
|
||||
},
|
||||
transformReply: {
|
||||
2: (rawReply: Array<BlobStringReply | NumberReply>) => {
|
||||
const reply: Partial<Resp2Reply<MemoryStatsReply['DEFAULT']>> = {};
|
||||
2: (rawReply: UnwrapReply<ArrayReply<BlobStringReply | NumberReply>>) => {
|
||||
const reply: any = {};
|
||||
|
||||
let i = 0;
|
||||
while (i < rawReply.length) {
|
||||
const key = rawReply[i++] as keyof MemoryStatsReply['DEFAULT'];
|
||||
reply[key] = rawReply[i++] as any;
|
||||
reply[rawReply[i++] as any] = rawReply[i++];
|
||||
}
|
||||
|
||||
return reply as MemoryStatsReply['DEFAULT'];
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { ArrayReply, BlobStringReply, NumberReply, Command, Resp2Reply, TuplesToMapReply } from '../RESP/types';
|
||||
import { ArrayReply, TuplesToMapReply, BlobStringReply, NumberReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types';
|
||||
|
||||
export type ModuleListReply = ArrayReply<TuplesToMapReply<[
|
||||
[BlobStringReply<'name'>, BlobStringReply],
|
||||
@@ -12,11 +12,14 @@ export default {
|
||||
return ['MODULE', 'LIST'];
|
||||
},
|
||||
transformReply: {
|
||||
2: (reply: Resp2Reply<ModuleListReply>) => {
|
||||
return reply.map(module => ({
|
||||
name: module[1],
|
||||
ver: module[3]
|
||||
}));
|
||||
2: (reply: UnwrapReply<Resp2Reply<ModuleListReply>>) => {
|
||||
return reply.map(module => {
|
||||
const unwrapped = module as unknown as UnwrapReply<typeof module>;
|
||||
return {
|
||||
name: unwrapped[1],
|
||||
ver: unwrapped[3]
|
||||
};
|
||||
});
|
||||
},
|
||||
3: undefined as unknown as () => ModuleListReply
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { ArrayReply, BlobStringReply, NumberReply, Command } from '../RESP/types';
|
||||
import { ArrayReply, BlobStringReply, NumberReply, UnwrapReply, Command } from '../RESP/types';
|
||||
import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers';
|
||||
|
||||
export default {
|
||||
@@ -11,7 +11,7 @@ export default {
|
||||
|
||||
return args;
|
||||
},
|
||||
transformReply(rawReply: ArrayReply<BlobStringReply | NumberReply>) {
|
||||
transformReply(rawReply: UnwrapReply<ArrayReply<BlobStringReply | NumberReply>>) {
|
||||
const reply = Object.create(null);
|
||||
let i = 0;
|
||||
while (i < rawReply.length) {
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import { ArrayReply, BlobStringReply, Command, NumberReply } from '../RESP/types';
|
||||
import { BlobStringReply, NumberReply, ArrayReply, TuplesReply, UnwrapReply, Command } from '../RESP/types';
|
||||
|
||||
type MasterRole = [
|
||||
role: BlobStringReply<'master'>,
|
||||
replicationOffest: NumberReply,
|
||||
replicas: ArrayReply<[host: BlobStringReply, port: BlobStringReply, replicationOffest: BlobStringReply]>
|
||||
replicas: ArrayReply<TuplesReply<[host: BlobStringReply, port: BlobStringReply, replicationOffest: BlobStringReply]>>
|
||||
];
|
||||
|
||||
type SlaveRole = [
|
||||
@@ -19,7 +19,7 @@ type SentinelRole = [
|
||||
masterNames: ArrayReply<BlobStringReply>
|
||||
];
|
||||
|
||||
type Role = MasterRole | SlaveRole | SentinelRole;
|
||||
type Role = TuplesReply<MasterRole | SlaveRole | SentinelRole>;
|
||||
|
||||
export default {
|
||||
FIRST_KEY_INDEX: undefined,
|
||||
@@ -27,18 +27,21 @@ export default {
|
||||
transformArguments() {
|
||||
return ['ROLE'];
|
||||
},
|
||||
transformReply(reply: Role) {
|
||||
switch (reply[0] as Role[0]['DEFAULT']) {
|
||||
transformReply(reply: UnwrapReply<Role>) {
|
||||
switch (reply[0] as unknown as UnwrapReply<typeof reply[0]>) {
|
||||
case 'master': {
|
||||
const [role, replicationOffest, replicas] = reply as MasterRole;
|
||||
return {
|
||||
role,
|
||||
replicationOffest,
|
||||
replicas: replicas.map(([host, port, replicationOffest]) => ({
|
||||
host,
|
||||
port: Number(port),
|
||||
replicationOffest: Number(replicationOffest)
|
||||
})),
|
||||
replicas: (replicas as unknown as UnwrapReply<typeof replicas>).map(replica => {
|
||||
const [host, port, replicationOffest] = replica as unknown as UnwrapReply<typeof replica>;
|
||||
return {
|
||||
host,
|
||||
port: Number(port),
|
||||
replicationOffest: Number(replicationOffest)
|
||||
};
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { RedisArgument, TuplesReply, BlobStringReply, ArrayReply, Command } from '../RESP/types';
|
||||
import { RedisArgument, TuplesReply, BlobStringReply, ArrayReply, UnwrapReply, Command } from '../RESP/types';
|
||||
import { StreamMessagesRawReply, transformStreamMessagesReply } from './generic-transformers';
|
||||
|
||||
export interface XAutoClaimOptions {
|
||||
@@ -37,7 +37,7 @@ export default {
|
||||
|
||||
return args;
|
||||
},
|
||||
transformReply(reply: XAutoClaimRawReply) {
|
||||
transformReply(reply: UnwrapReply<XAutoClaimRawReply>) {
|
||||
return {
|
||||
nextId: reply[0],
|
||||
messages: transformStreamMessagesReply(reply[1]),
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { TuplesReply, BlobStringReply, ArrayReply, Command } from '../RESP/types';
|
||||
import { TuplesReply, BlobStringReply, ArrayReply, UnwrapReply, Command } from '../RESP/types';
|
||||
import XAUTOCLAIM from './XAUTOCLAIM';
|
||||
|
||||
type XAutoClaimJustIdRawReply = TuplesReply<[
|
||||
@@ -15,7 +15,7 @@ export default {
|
||||
redisArgs.push('JUSTID');
|
||||
return redisArgs;
|
||||
},
|
||||
transformReply(reply: XAutoClaimJustIdRawReply) {
|
||||
transformReply(reply: UnwrapReply<XAutoClaimJustIdRawReply>) {
|
||||
return {
|
||||
nextId: reply[0],
|
||||
messages: reply[1],
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { RedisArgument, ArrayReply, TuplesToMapReply, BlobStringReply, NumberReply, Resp2Reply, Command } from '../RESP/types';
|
||||
import { RedisArgument, ArrayReply, TuplesToMapReply, BlobStringReply, NumberReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types';
|
||||
|
||||
export type XInfoConsumersReply = ArrayReply<TuplesToMapReply<[
|
||||
[BlobStringReply<'name'>, BlobStringReply],
|
||||
@@ -18,13 +18,16 @@ export default {
|
||||
return ['XINFO', 'CONSUMERS', key, group];
|
||||
},
|
||||
transformReply: {
|
||||
2: (reply: Resp2Reply<XInfoConsumersReply>) => {
|
||||
return reply.map(consumer => ({
|
||||
name: consumer[1],
|
||||
pending: consumer[3],
|
||||
idle: consumer[5],
|
||||
inactive: consumer[7]
|
||||
}));
|
||||
2: (reply: UnwrapReply<Resp2Reply<XInfoConsumersReply>>) => {
|
||||
return reply.map(consumer => {
|
||||
const unwrapped = consumer as unknown as UnwrapReply<typeof consumer>;
|
||||
return {
|
||||
name: unwrapped[1],
|
||||
pending: unwrapped[3],
|
||||
idle: unwrapped[5],
|
||||
inactive: unwrapped[7]
|
||||
};
|
||||
});
|
||||
},
|
||||
3: undefined as unknown as () => XInfoConsumersReply
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { RedisArgument, ArrayReply, TuplesToMapReply, BlobStringReply, NumberReply, Resp2Reply, Command, NullReply } from '../RESP/types';
|
||||
import { RedisArgument, ArrayReply, TuplesToMapReply, BlobStringReply, NumberReply, NullReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types';
|
||||
|
||||
export type XInfoGroupsReply = ArrayReply<TuplesToMapReply<[
|
||||
[BlobStringReply<'name'>, BlobStringReply],
|
||||
@@ -18,15 +18,18 @@ export default {
|
||||
return ['XINFO', 'GROUPS', key];
|
||||
},
|
||||
transformReply: {
|
||||
2: (reply: Resp2Reply<XInfoGroupsReply>) => {
|
||||
return reply.map(group => ({
|
||||
name: group[1],
|
||||
consumers: group[3],
|
||||
pending: group[5],
|
||||
'last-delivered-id': group[7],
|
||||
'entries-read': group[9],
|
||||
lag: group[11]
|
||||
}));
|
||||
2: (reply: UnwrapReply<Resp2Reply<XInfoGroupsReply>>) => {
|
||||
return reply.map(group => {
|
||||
const unwrapped = group as unknown as UnwrapReply<typeof group>;
|
||||
return {
|
||||
name: unwrapped[1],
|
||||
consumers: unwrapped[3],
|
||||
pending: unwrapped[5],
|
||||
'last-delivered-id': unwrapped[7],
|
||||
'entries-read': unwrapped[9],
|
||||
lag: unwrapped[11]
|
||||
};
|
||||
});
|
||||
},
|
||||
3: undefined as unknown as () => XInfoGroupsReply
|
||||
}
|
||||
|
@@ -67,5 +67,5 @@ export default {
|
||||
} as const satisfies Command;
|
||||
|
||||
function transformEntry(entry: StreamMessageRawReply | NullReply) {
|
||||
return entry === null ? null : transformStreamMessageReply(entry);
|
||||
return entry === null ? null : transformStreamMessageReply(entry as StreamMessageRawReply);
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { RedisArgument, BlobStringReply, NullReply, TuplesReply, NumberReply, Command, ArrayReply } from '../RESP/types';
|
||||
import { RedisArgument, BlobStringReply, NullReply, ArrayReply, TuplesReply, NumberReply, UnwrapReply, Command } from '../RESP/types';
|
||||
|
||||
type XPendingRawReply = TuplesReply<[
|
||||
pending: NumberReply,
|
||||
@@ -16,15 +16,19 @@ export default {
|
||||
transformArguments(key: RedisArgument, group: RedisArgument) {
|
||||
return ['XPENDING', key, group];
|
||||
},
|
||||
transformReply(reply: XPendingRawReply) {
|
||||
transformReply(reply: UnwrapReply<XPendingRawReply>) {
|
||||
const consumers = reply[3] as unknown as UnwrapReply<typeof reply[3]>;
|
||||
return {
|
||||
pending: reply[0],
|
||||
firstId: reply[1],
|
||||
lastId: reply[2],
|
||||
consumers: reply[3] === null ? null : reply[3].map(([name, deliveriesCounter]) => ({
|
||||
name,
|
||||
deliveriesCounter: Number(deliveriesCounter)
|
||||
}))
|
||||
consumers: consumers === null ? null : consumers.map(consumer => {
|
||||
const [name, deliveriesCounter] = consumer as unknown as UnwrapReply<typeof consumer>;
|
||||
return {
|
||||
name,
|
||||
deliveriesCounter: Number(deliveriesCounter)
|
||||
};
|
||||
})
|
||||
}
|
||||
}
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { RedisArgument, ArrayReply, TuplesReply, BlobStringReply, NumberReply, Command } from '../RESP/types';
|
||||
import { RedisArgument, ArrayReply, TuplesReply, BlobStringReply, NumberReply, UnwrapReply, Command } from '../RESP/types';
|
||||
|
||||
export interface XPendingRangeOptions {
|
||||
IDLE?: number;
|
||||
@@ -41,12 +41,15 @@ export default {
|
||||
|
||||
return args;
|
||||
},
|
||||
transformReply(reply: XPendingRangeRawReply) {
|
||||
return reply.map(pending => ({
|
||||
id: pending[0],
|
||||
consumer: pending[1],
|
||||
millisecondsSinceLastDelivery: pending[2],
|
||||
deliveriesCounter: pending[3]
|
||||
}));
|
||||
transformReply(reply: UnwrapReply<XPendingRangeRawReply>) {
|
||||
return reply.map(pending => {
|
||||
const unwrapped = pending as unknown as UnwrapReply<typeof pending>;
|
||||
return {
|
||||
id: unwrapped[0],
|
||||
consumer: unwrapped[1],
|
||||
millisecondsSinceLastDelivery: unwrapped[2],
|
||||
deliveriesCounter: unwrapped[3]
|
||||
};
|
||||
});
|
||||
}
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { NullReply, TuplesReply, BlobStringReply, DoubleReply, ArrayReply, Resp2Reply, Command, RedisArgument } from '../RESP/types';
|
||||
import { pushVariadicArgument, RedisVariadicArgument, SortedSetSide, transformSortedSetReply } from './generic-transformers';
|
||||
import { RedisArgument, NullReply, TuplesReply, BlobStringReply, DoubleReply, ArrayReply, UnwrapReply, Resp2Reply, Command } from '../RESP/types';
|
||||
import { pushVariadicArgument, RedisVariadicArgument, SortedSetSide, transformSortedSetReply, transformDoubleReply } from './generic-transformers';
|
||||
|
||||
export interface ZMPopOptions {
|
||||
COUNT?: number;
|
||||
@@ -39,20 +39,23 @@ export default {
|
||||
return transformZMPopArguments(['ZMPOP'], ...args);
|
||||
},
|
||||
transformReply: {
|
||||
2: (reply: Resp2Reply<ZMPopRawReply>) => {
|
||||
2(reply: UnwrapReply<Resp2Reply<ZMPopRawReply>>) {
|
||||
return reply === null ? null : {
|
||||
key: reply[0],
|
||||
members: reply[1].map(([value, score]) => ({
|
||||
value,
|
||||
score: Number(score)
|
||||
}))
|
||||
members: (reply[1] as unknown as UnwrapReply<typeof reply[1]>).map(member => {
|
||||
const [value, score] = member as unknown as UnwrapReply<typeof member>;
|
||||
return {
|
||||
value,
|
||||
score: transformDoubleReply[2](score)
|
||||
};
|
||||
})
|
||||
};
|
||||
},
|
||||
3: (reply: ZMPopRawReply) => {
|
||||
3(reply: UnwrapReply<ZMPopRawReply>) {
|
||||
return reply === null ? null : {
|
||||
key: reply[0],
|
||||
members: transformSortedSetReply[3](reply[1])
|
||||
};
|
||||
},
|
||||
}
|
||||
}
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { RedisArgument, ArrayReply, NullReply, BlobStringReply, DoubleReply, Command } from '../RESP/types';
|
||||
import { RedisArgument, ArrayReply, NullReply, BlobStringReply, DoubleReply, UnwrapReply, Command } from '../RESP/types';
|
||||
import { pushVariadicArguments, RedisVariadicArgument, transformNullableDoubleReply } from './generic-transformers';
|
||||
|
||||
export default {
|
||||
@@ -11,7 +11,7 @@ export default {
|
||||
return pushVariadicArguments(['ZMSCORE', key], member);
|
||||
},
|
||||
transformReply: {
|
||||
2: (reply: ArrayReply<NullReply | BlobStringReply>) => {
|
||||
2: (reply: UnwrapReply<ArrayReply<NullReply | BlobStringReply>>) => {
|
||||
return reply.map(transformNullableDoubleReply[2]);
|
||||
},
|
||||
3: undefined as unknown as () => ArrayReply<NullReply | DoubleReply>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { RedisArgument, TuplesReply, BlobStringReply, DoubleReply, Command } from '../RESP/types';
|
||||
import { RedisArgument, TuplesReply, BlobStringReply, DoubleReply, UnwrapReply, Command } from '../RESP/types';
|
||||
|
||||
export default {
|
||||
FIRST_KEY_INDEX: 1,
|
||||
@@ -7,7 +7,7 @@ export default {
|
||||
return ['ZPOPMAX', key];
|
||||
},
|
||||
transformReply: {
|
||||
2: (reply: TuplesReply<[]> | TuplesReply<[BlobStringReply, BlobStringReply]>) => {
|
||||
2: (reply: UnwrapReply<TuplesReply<[] | [BlobStringReply, BlobStringReply]>>) => {
|
||||
if (reply.length === 0) return null;
|
||||
|
||||
return {
|
||||
@@ -15,7 +15,7 @@ export default {
|
||||
score: Number(reply[1])
|
||||
};
|
||||
},
|
||||
3: (reply: TuplesReply<[]> | TuplesReply<[BlobStringReply, DoubleReply]>) => {
|
||||
3: (reply: UnwrapReply<TuplesReply<[] | [BlobStringReply, DoubleReply]>>) => {
|
||||
if (reply.length === 0) return null;
|
||||
|
||||
return {
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { NullReply, TuplesReply, NumberReply, BlobStringReply, DoubleReply, Command } from '../RESP/types';
|
||||
import { NullReply, TuplesReply, NumberReply, BlobStringReply, DoubleReply, UnwrapReply, Command } from '../RESP/types';
|
||||
import ZRANK from './ZRANK';
|
||||
|
||||
export default {
|
||||
@@ -10,7 +10,7 @@ export default {
|
||||
return redisArgs;
|
||||
},
|
||||
transformReply: {
|
||||
2: (reply: NullReply | TuplesReply<[NumberReply, BlobStringReply]>) => {
|
||||
2: (reply: UnwrapReply<NullReply | TuplesReply<[NumberReply, BlobStringReply]>>) => {
|
||||
if (reply === null) return null;
|
||||
|
||||
return {
|
||||
@@ -18,7 +18,7 @@ export default {
|
||||
score: Number(reply[1])
|
||||
};
|
||||
},
|
||||
3: (reply: NullReply | TuplesReply<[BlobStringReply, DoubleReply]>) => {
|
||||
3: (reply: UnwrapReply<NullReply | TuplesReply<[BlobStringReply, DoubleReply]>>) => {
|
||||
if (reply === null) return null;
|
||||
|
||||
return {
|
||||
|
@@ -1,12 +1,14 @@
|
||||
import { ArrayReply, BlobStringReply, BooleanReply, CommandArguments, DoubleReply, NullReply, NumberReply, RedisArgument, TuplesReply } from '../RESP/types';
|
||||
import { UnwrapReply, ArrayReply, BlobStringReply, BooleanReply, CommandArguments, DoubleReply, MapReply, NullReply, NumberReply, RedisArgument, TuplesReply } from '../RESP/types';
|
||||
|
||||
export const transformBooleanReply = {
|
||||
2: (reply: NumberReply<0 | 1>) => reply === 1,
|
||||
2: (reply: NumberReply<0 | 1>) => reply as unknown as UnwrapReply<typeof reply> === 1,
|
||||
3: undefined as unknown as () => BooleanReply
|
||||
};
|
||||
|
||||
export const transformBooleanArrayReply = {
|
||||
2: (reply: ArrayReply<NumberReply<0 | 1>>) => reply.map(transformBooleanReply[2]),
|
||||
2: (reply: ArrayReply<NumberReply<0 | 1>>) => {
|
||||
return (reply as unknown as UnwrapReply<typeof reply>).map(transformBooleanReply[2]);
|
||||
},
|
||||
3: undefined as unknown as () => ArrayReply<BooleanReply>
|
||||
};
|
||||
|
||||
@@ -60,7 +62,7 @@ export const transformNullableDoubleReply = {
|
||||
2: (reply: BlobStringReply | NullReply) => {
|
||||
if (reply === null) return null;
|
||||
|
||||
return transformDoubleReply[2](reply);
|
||||
return transformDoubleReply[2](reply as BlobStringReply);
|
||||
},
|
||||
3: undefined as unknown as () => DoubleReply | NullReply
|
||||
};
|
||||
@@ -68,10 +70,11 @@ export const transformNullableDoubleReply = {
|
||||
export function transformTuplesReply(
|
||||
reply: ArrayReply<BlobStringReply>
|
||||
): Record<string, BlobStringReply> {
|
||||
const message = Object.create(null);
|
||||
const inferred = reply as unknown as UnwrapReply<typeof reply>,
|
||||
message = Object.create(null);
|
||||
|
||||
for (let i = 0; i < reply.length; i += 2) {
|
||||
message[reply[i].toString()] = reply[i + 1];
|
||||
for (let i = 0; i < inferred.length; i += 2) {
|
||||
message[inferred[i].toString()] = inferred[i + 1];
|
||||
}
|
||||
|
||||
return message;
|
||||
@@ -82,7 +85,8 @@ export type StreamMessageRawReply = TuplesReply<[
|
||||
message: ArrayReply<BlobStringReply>
|
||||
]>;
|
||||
|
||||
export function transformStreamMessageReply([id, message]: StreamMessageRawReply) {
|
||||
export function transformStreamMessageReply(reply: StreamMessageRawReply) {
|
||||
const [id, message] = reply as unknown as UnwrapReply<typeof reply>;
|
||||
return {
|
||||
id,
|
||||
message: transformTuplesReply(message)
|
||||
@@ -92,13 +96,11 @@ export function transformStreamMessageReply([id, message]: StreamMessageRawReply
|
||||
export type StreamMessagesRawReply = ArrayReply<StreamMessageRawReply>;
|
||||
|
||||
export function transformStreamMessagesReply(reply: StreamMessagesRawReply) {
|
||||
return reply.map(transformStreamMessageReply);
|
||||
return (reply as unknown as UnwrapReply<typeof reply>)
|
||||
.map(message => transformStreamMessageReply(message));
|
||||
}
|
||||
|
||||
// export type StreamsMessagesReply = Array<{
|
||||
// name: RedisArgument;
|
||||
// messages: StreamMessagesReply;
|
||||
// }> | null;
|
||||
// export type StreamsMessagesReply = MapReply<BlobStringReply, StreamMessagesRawReply>;
|
||||
|
||||
// export function transformStreamsMessagesReply(reply: Array<any> | null): StreamsMessagesReply | null {
|
||||
// if (reply === null) return null;
|
||||
@@ -118,21 +120,25 @@ export type SortedSetSide = 'MIN' | 'MAX';
|
||||
|
||||
export const transformSortedSetReply = {
|
||||
2: (reply: ArrayReply<BlobStringReply>) => {
|
||||
const members = [];
|
||||
for (let i = 0; i < reply.length; i += 2) {
|
||||
const inferred = reply as unknown as UnwrapReply<typeof reply>,
|
||||
members = [];
|
||||
for (let i = 0; i < inferred.length; i += 2) {
|
||||
members.push({
|
||||
value: reply[i],
|
||||
score: transformDoubleReply[2](reply[i + 1])
|
||||
value: inferred[i],
|
||||
score: transformDoubleReply[2](inferred[i + 1])
|
||||
});
|
||||
}
|
||||
|
||||
return members;
|
||||
},
|
||||
3: (reply: ArrayReply<TuplesReply<[BlobStringReply, DoubleReply]>>) => {
|
||||
return reply.map(([value, score]) => ({
|
||||
value,
|
||||
score
|
||||
}));
|
||||
return (reply as unknown as UnwrapReply<typeof reply>).map(member => {
|
||||
const [value, score] = member as unknown as UnwrapReply<typeof member>;
|
||||
return {
|
||||
value,
|
||||
score
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,67 +1,67 @@
|
||||
export class AbortError extends Error {
|
||||
constructor() {
|
||||
super('The command was aborted');
|
||||
}
|
||||
constructor() {
|
||||
super('The command was aborted');
|
||||
}
|
||||
}
|
||||
|
||||
export class WatchError extends Error {
|
||||
constructor() {
|
||||
super('One (or more) of the watched keys has been changed');
|
||||
}
|
||||
constructor() {
|
||||
super('One (or more) of the watched keys has been changed');
|
||||
}
|
||||
}
|
||||
|
||||
export class ConnectionTimeoutError extends Error {
|
||||
constructor() {
|
||||
super('Connection timeout');
|
||||
}
|
||||
constructor() {
|
||||
super('Connection timeout');
|
||||
}
|
||||
}
|
||||
|
||||
export class ClientClosedError extends Error {
|
||||
constructor() {
|
||||
super('The client is closed');
|
||||
}
|
||||
constructor() {
|
||||
super('The client is closed');
|
||||
}
|
||||
}
|
||||
|
||||
export class ClientOfflineError extends Error {
|
||||
constructor() {
|
||||
super('The client is offline');
|
||||
}
|
||||
constructor() {
|
||||
super('The client is offline');
|
||||
}
|
||||
}
|
||||
|
||||
export class DisconnectsClientError extends Error {
|
||||
constructor() {
|
||||
super('Disconnects client');
|
||||
}
|
||||
constructor() {
|
||||
super('Disconnects client');
|
||||
}
|
||||
}
|
||||
|
||||
export class SocketClosedUnexpectedlyError extends Error {
|
||||
constructor() {
|
||||
super('Socket closed unexpectedly');
|
||||
}
|
||||
constructor() {
|
||||
super('Socket closed unexpectedly');
|
||||
}
|
||||
}
|
||||
|
||||
export class RootNodesUnavailableError extends Error {
|
||||
constructor() {
|
||||
super('All the root nodes are unavailable');
|
||||
}
|
||||
constructor() {
|
||||
super('All the root nodes are unavailable');
|
||||
}
|
||||
}
|
||||
|
||||
export class ReconnectStrategyError extends Error {
|
||||
originalError: Error;
|
||||
socketError: unknown;
|
||||
originalError: Error;
|
||||
socketError: unknown;
|
||||
|
||||
constructor(originalError: Error, socketError: unknown) {
|
||||
super(originalError.message);
|
||||
this.originalError = originalError;
|
||||
this.socketError = socketError;
|
||||
}
|
||||
constructor(originalError: Error, socketError: unknown) {
|
||||
super(originalError.message);
|
||||
this.originalError = originalError;
|
||||
this.socketError = socketError;
|
||||
}
|
||||
}
|
||||
|
||||
export class ErrorReply extends Error {
|
||||
constructor(message: string) {
|
||||
super(message);
|
||||
this.stack = undefined;
|
||||
}
|
||||
constructor(message: string) {
|
||||
super(message);
|
||||
this.stack = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export class SimpleError extends ErrorReply {}
|
||||
|
Reference in New Issue
Block a user