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