From 2b6e99a2b2c9dc40cd517da22b40e43e236b88df Mon Sep 17 00:00:00 2001 From: Shaya Potter Date: Sun, 2 Jun 2024 15:29:05 +0300 Subject: [PATCH] bring all modules / all commands into v5 update unstableResp3Module flag to only commands that have unstable api add ability to tag commands to ignore user type mapping (as transformReply will convert it to a non typed map type) update bloom info commands to work with new non typed map ability fill in search/time-series commands and tag with unstableResp3Modules flag as appropriate --- packages/bloom/lib/commands/bloom/INFO.ts | 65 +++++- .../lib/commands/count-min-sketch/INFO.ts | 51 ++++- packages/bloom/lib/commands/cuckoo/INFO.ts | 126 ++++++---- packages/bloom/lib/commands/t-digest/INFO.ts | 141 ++++++++---- packages/bloom/lib/commands/top-k/INFO.ts | 59 ++++- packages/client/lib/RESP/decoder.ts | 2 +- packages/client/lib/RESP/types.ts | 13 ++ packages/client/lib/client/commands-queue.ts | 4 +- packages/client/lib/client/index.ts | 72 ++++-- packages/client/lib/client/legacy-mode.ts | 2 +- packages/client/lib/client/multi-command.ts | 10 +- packages/client/lib/client/pool.ts | 56 ++++- packages/client/lib/cluster/index.ts | 146 +++++++----- packages/client/lib/cluster/multi-command.ts | 33 +-- packages/client/lib/multi-command.ts | 8 +- .../client/lib/sentinel/multi-commands.ts | 7 +- packages/client/lib/sentinel/utils.ts | 90 +++++--- packages/json/lib/commands/TYPE.ts | 6 +- packages/search/lib/commands/AGGREGATE.ts | 9 +- packages/search/lib/commands/ALIASADD.ts | 3 +- packages/search/lib/commands/ALIASDEL.ts | 3 +- packages/search/lib/commands/ALIASUPDATE.ts | 3 +- packages/search/lib/commands/ALTER.ts | 3 +- packages/search/lib/commands/CONFIG_GET.ts | 3 +- packages/search/lib/commands/CONFIG_SET.ts | 3 +- packages/search/lib/commands/CREATE.ts | 3 +- packages/search/lib/commands/CURSOR_DEL.ts | 3 +- packages/search/lib/commands/DICTADD.ts | 3 +- packages/search/lib/commands/DICTDEL.ts | 3 +- packages/search/lib/commands/DICTDUMP.ts | 3 +- packages/search/lib/commands/DROPINDEX.ts | 3 +- packages/search/lib/commands/EXPLAIN.ts | 3 +- packages/search/lib/commands/EXPLAINCLI.ts | 3 +- .../search/lib/commands/PROFILE_SEARCH.ts | 216 +++++++++--------- packages/search/lib/commands/SUGADD.ts | 1 - packages/search/lib/commands/SUGDEL.ts | 3 +- packages/search/lib/commands/SUGGET.ts | 3 +- .../lib/commands/SUGGET_WITHPAYLOADS.ts | 3 +- .../SUGGET_WITHSCORES_WITHPAYLOADS.ts | 3 +- packages/search/lib/commands/SYNDUMP.ts | 3 +- packages/search/lib/commands/SYNUPDATE.ts | 3 +- packages/search/lib/commands/TAGVALS.ts | 3 +- packages/search/lib/commands/_LIST.ts | 3 +- packages/time-series/lib/commands/INFO.ts | 162 ++++++------- .../time-series/lib/commands/INFO_DEBUG.ts | 107 ++++----- packages/time-series/lib/commands/MGET.ts | 40 +++- .../lib/commands/MGET_WITHLABELS.ts | 23 +- packages/time-series/lib/commands/MRANGE.ts | 33 ++- .../lib/commands/MRANGE_WITHLABELS.ts | 29 ++- .../time-series/lib/commands/MREVRANGE.ts | 3 +- .../lib/commands/MREVRANGE_WITHLABELS.ts | 3 +- packages/time-series/lib/commands/RANGE.ts | 6 +- packages/time-series/lib/commands/index.ts | 49 +++- 53 files changed, 1070 insertions(+), 568 deletions(-) diff --git a/packages/bloom/lib/commands/bloom/INFO.ts b/packages/bloom/lib/commands/bloom/INFO.ts index d5055b1c03f..32227cb9862 100644 --- a/packages/bloom/lib/commands/bloom/INFO.ts +++ b/packages/bloom/lib/commands/bloom/INFO.ts @@ -1,4 +1,20 @@ -import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, Command, UnwrapReply, NullReply, BlobStringReply, NumberReply, TuplesToMapReply, Resp2Reply } from '@redis/client/dist/lib/RESP/types'; + +export type BfInfoReplyMap = TuplesToMapReply<[ + [BlobStringReply<'Capacity'>, NumberReply], + [BlobStringReply<'Size'>, NumberReply], + [BlobStringReply<'Number of filters'>, NumberReply], + [BlobStringReply<'Number of items inserted'>, NumberReply], + [BlobStringReply<'Expansion rate'>, NullReply | NumberReply] +]>; + +export interface BfInfoReply { + capacity?: NumberReply; + size?: NumberReply; + numberOfFilters?: NumberReply; + numberOfInsertedItems?: NumberReply; + expansionRate?: NullReply | NumberReply; +} export default { FIRST_KEY_INDEX: 1, @@ -6,6 +22,49 @@ export default { transformArguments(key: RedisArgument) { return ['BF.INFO', key]; }, - // TODO - transformReply: undefined as unknown as () => any + transformReply: { + 2: (reply: UnwrapReply>): BfInfoReply => { + return { + capacity: reply[1], + size: reply[3], + numberOfFilters: reply[5], + numberOfInsertedItems: reply[7], + expansionRate: reply[9] + } + }, + 3: (reply: UnwrapReply) => { + if (reply instanceof Map) { + throw new Error("BF.INFO shouldn't return a map type in resp3 anymore"); +/* + return { + capacity: reply.get("Capacity" as unknown as BlobStringReply<'Capacity'>), + size: reply.get("Size" as unknown as BlobStringReply<"Size">), + numberOfFilters: reply.get("Number of filters" as unknown as BlobStringReply<"Number of filters">), + numberOfInsertedItems: reply.get('Number of items inserted' as unknown as BlobStringReply<'Number of items inserted'>), + expansionRate: reply.get('Expansion rate' as unknown as BlobStringReply<'Expansion rate'>), + } +*/ + } else if (reply instanceof Array) { + throw new Error("BF.INFO shouldn't return a array type in resp3 anymore"); +/* + return { + capacity: reply[1], + size: reply[3], + numberOfFilters: reply[5], + numberOfInsertedItems: reply[7], + expansionRate: reply[9] + } +*/ + } else { + return { + capacity: reply["Capacity"], + size: reply["Size"], + numberOfFilters: reply["Number of filters"], + numberOfInsertedItems: reply["Number of items inserted"], + expansionRate: reply["Expansion rate"] + } + } + }, + }, + ignoreTypeMapping: true } as const satisfies Command; diff --git a/packages/bloom/lib/commands/count-min-sketch/INFO.ts b/packages/bloom/lib/commands/count-min-sketch/INFO.ts index 8ded9b6cd60..0de0921ada6 100644 --- a/packages/bloom/lib/commands/count-min-sketch/INFO.ts +++ b/packages/bloom/lib/commands/count-min-sketch/INFO.ts @@ -1,10 +1,16 @@ import { RedisArgument, TuplesToMapReply, BlobStringReply, NumberReply, UnwrapReply, Resp2Reply, Command } from '@redis/client/dist/lib/RESP/types'; -export type BfInfoReply = TuplesToMapReply<[ +export type CmsInfoReplyMap = TuplesToMapReply<[ [BlobStringReply<'width'>, NumberReply], [BlobStringReply<'depth'>, NumberReply], [BlobStringReply<'count'>, NumberReply] ]>; + +export interface CmsInfoReply { + width?: NumberReply; + depth?: NumberReply; + count?: NumberReply; +} export default { FIRST_KEY_INDEX: 1, @@ -13,11 +19,40 @@ export default { return ['CMS.INFO', key]; }, transformReply: { - 2: (reply: UnwrapReply>) => ({ - width: reply[1], - depth: reply[3], - count: reply[5] - }), - 3: undefined as unknown as () => BfInfoReply - } + 2: (reply: UnwrapReply>): CmsInfoReply => { + return { + width: reply[1], + depth: reply[3], + count: reply[5] + } + }, + 3: (reply: UnwrapReply): CmsInfoReply => { + if (reply instanceof Map) { + throw new Error("BF.INFO shouldn't return a nap type in resp3 anymore"); +/* + return { + width: reply.get("width" as unknown as BlobStringReply<'width'>), + depth: reply.get("depth" as unknown as BlobStringReply<"depth">), + count: reply.get("count" as unknown as BlobStringReply<"count">) + } +*/ + } else if (reply instanceof Array) { + throw new Error("BF.INFO shouldn't return a array type in resp3 anymore"); +/* + return { + width: reply[1], + depth: reply[3], + count: reply[5] + } +*/ + } else { + return { + width: reply['width'], + depth: reply['depth'], + count: reply['count'] + } + } + } + }, + ignoreTypeMapping: true } as const satisfies Command; diff --git a/packages/bloom/lib/commands/cuckoo/INFO.ts b/packages/bloom/lib/commands/cuckoo/INFO.ts index f7a789712d8..f1d45e602a5 100644 --- a/packages/bloom/lib/commands/cuckoo/INFO.ts +++ b/packages/bloom/lib/commands/cuckoo/INFO.ts @@ -1,4 +1,26 @@ -import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, Command, NumberReply, BlobStringReply, TuplesToMapReply, UnwrapReply, Resp2Reply } from '@redis/client/dist/lib/RESP/types'; + +export type CfInfoReplyMap = TuplesToMapReply<[ + [BlobStringReply<'Size'>, NumberReply], + [BlobStringReply<'Number of buckets'>, NumberReply], + [BlobStringReply<'Number of filters'>, NumberReply], + [BlobStringReply<'Number of items inserted'>, NumberReply], + [BlobStringReply<'Number of items deleted'>, NumberReply], + [BlobStringReply<'Bucket size'>, NumberReply], + [BlobStringReply<'Expansion rate'>, NumberReply], + [BlobStringReply<'Max iterations'>, NumberReply] +]>; + +export interface CfInfoReply { + size: NumberReply; + numberOfBuckets: NumberReply; + numberOfFilters: NumberReply; + numberOfInsertedItems: NumberReply; + numberOfDeletedItems: NumberReply; + bucketSize: NumberReply; + expansionRate: NumberReply; + maxIteration: NumberReply; +} export default { FIRST_KEY_INDEX: 1, @@ -6,48 +28,62 @@ export default { transformArguments(key: RedisArgument) { return ['CF.INFO', key]; }, - // TODO - // export type InfoRawReply = [ - // _: string, - // size: number, - // _: string, - // numberOfBuckets: number, - // _: string, - // numberOfFilters: number, - // _: string, - // numberOfInsertedItems: number, - // _: string, - // numberOfDeletedItems: number, - // _: string, - // bucketSize: number, - // _: string, - // expansionRate: number, - // _: string, - // maxIteration: number - // ]; - - // export interface InfoReply { - // size: number; - // numberOfBuckets: number; - // numberOfFilters: number; - // numberOfInsertedItems: number; - // numberOfDeletedItems: number; - // bucketSize: number; - // expansionRate: number; - // maxIteration: number; - // } - - // export function transformReply(reply: InfoRawReply): InfoReply { - // return { - // size: reply[1], - // numberOfBuckets: reply[3], - // numberOfFilters: reply[5], - // numberOfInsertedItems: reply[7], - // numberOfDeletedItems: reply[9], - // bucketSize: reply[11], - // expansionRate: reply[13], - // maxIteration: reply[15] - // }; - // } - transformReply: undefined as unknown as () => any + + transformReply: { + 2: (reply: UnwrapReply>): CfInfoReply => { + return { + size: reply[1], + numberOfBuckets: reply[3], + numberOfFilters: reply[5], + numberOfInsertedItems: reply[7], + numberOfDeletedItems: reply[9], + bucketSize: reply[11], + expansionRate: reply[13], + maxIteration: reply[15] + } + }, + 3: (reply: UnwrapReply): CfInfoReply => { + if (reply instanceof Map) { + throw new Error("BF.INFO shouldn't return a map type in resp3 anymore"); +/* + return { + size: reply.get("Size" as unknown as BlobStringReply<"Size">)!, + numberOfBuckets: reply.get('Number of buckets' as unknown as BlobStringReply<'Number of buckets'>)!, + numberOfFilters: reply.get('Number of filters' as unknown as BlobStringReply<"Number of filters">)!, + numberOfInsertedItems: reply.get('Number of items inserted' as unknown as BlobStringReply<'Number of items inserted'>)!, + numberOfDeletedItems: reply.get('Number of items deleted' as unknown as BlobStringReply<'Number of items deleted'>)!, + bucketSize: reply.get('Bucket size' as unknown as BlobStringReply<'Bucket size'>)!, + expansionRate: reply.get('Expansion rate' as unknown as BlobStringReply<'Expansion rate'>)!, + maxIteration: reply.get('Max iterations' as unknown as BlobStringReply<'Max iterations'>)! + } +*/ + } else if (reply instanceof Array) { + throw new Error("BF.INFO shouldn't return a array type in resp3 anymore"); +/* + return { + size: reply[1], + numberOfBuckets: reply[3], + numberOfFilters: reply[5], + numberOfInsertedItems: reply[7], + numberOfDeletedItems: reply[9], + bucketSize: reply[11], + expansionRate: reply[13], + maxIteration: reply[15] + } +*/ + } else { + return { + size: reply['Size'], + numberOfBuckets: reply['Number of buckets'], + numberOfFilters: reply['Number of filters'], + numberOfInsertedItems: reply['Number of items inserted'], + numberOfDeletedItems: reply['Number of items deleted'], + bucketSize: reply['Bucket size'], + expansionRate: reply['Expansion rate'], + maxIteration: reply['Max iterations'] + } + } + } + }, + ignoreTypeMapping: true } as const satisfies Command; diff --git a/packages/bloom/lib/commands/t-digest/INFO.ts b/packages/bloom/lib/commands/t-digest/INFO.ts index 5286f9742bf..369f53e4e0c 100644 --- a/packages/bloom/lib/commands/t-digest/INFO.ts +++ b/packages/bloom/lib/commands/t-digest/INFO.ts @@ -1,4 +1,42 @@ -import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, Command, BlobStringReply, NumberReply, TuplesToMapReply, UnwrapReply, Resp2Reply } from '@redis/client/dist/lib/RESP/types'; + +export type TdInfoReplyMap = TuplesToMapReply<[ + [BlobStringReply<'Compression'>, NumberReply], + [BlobStringReply<'Capacity'>, NumberReply], + [BlobStringReply<'Merged nodes'>, NumberReply], + [BlobStringReply<'Unmerged nodes'>, NumberReply], + [BlobStringReply<'Merged weight'>, NumberReply], + [BlobStringReply<'Unmerged weight'>, NumberReply], + [BlobStringReply<'Observations'>, NumberReply], + [BlobStringReply<'Total compressions'>, NumberReply], + [BlobStringReply<'Memory usage'>, NumberReply] +]>; + +export interface TdInfoReply { + compression?: NumberReply; + capacity?: NumberReply; + mergedNodes?: NumberReply; + unmergedNodes?: NumberReply; + mergedWeight?: NumberReply; + unmergedWeight?: NumberReply; + observations?: NumberReply, + totalCompression?: NumberReply; + memoryUsage?: NumberReply +} + +/* +const keyMap = { + 'Compression': { member: 'compression', index: 1 }, + 'Capacity': { member: 'capacity', index: 3 }, + 'Merged nodes': { member: 'mergedNodes', index: 5 }, + 'Unmerged nodes': { member: 'unmergedNodes', index: 7 }, + 'Merged weight': { member: 'mergedWeight', index: 9 }, + 'Unmerged weight': { member: 'unmergedWeight', index: 11 }, + 'Observations': { member: 'observations', index: 13 }, + 'Total compressions': { member: 'totalCompression': index: 15 }, + 'Memory usage': { member: 'memoryUsage', index: 17 } +} +*/ export default { FIRST_KEY_INDEX: 1, @@ -6,44 +44,65 @@ export default { transformArguments(key: RedisArgument) { return ['TDIGEST.INFO', key]; }, - // TODO - // type InfoRawReply = [ - // 'Compression', - // number, - // 'Capacity', - // number, - // 'Merged nodes', - // number, - // 'Unmerged nodes', - // number, - // 'Merged weight', - // string, - // 'Unmerged weight', - // string, - // 'Total compressions', - // number - // ]; - - // interface InfoReply { - // comperssion: number; - // capacity: number; - // mergedNodes: number; - // unmergedNodes: number; - // mergedWeight: number; - // unmergedWeight: number; - // totalCompression: number; - // } - - // export function transformReply(reply: InfoRawReply): InfoReply { - // return { - // comperssion: reply[1], - // capacity: reply[3], - // mergedNodes: reply[5], - // unmergedNodes: reply[7], - // mergedWeight: Number(reply[9]), - // unmergedWeight: Number(reply[11]), - // totalCompression: reply[13] - // }; - // } - transformReply: undefined as unknown as () => any + transformReply: { + 2: (reply: UnwrapReply>): TdInfoReply => { + return { + compression: reply[1], + capacity: reply[3], + mergedNodes: reply[5], + unmergedNodes: reply[7], + mergedWeight: reply[9], + unmergedWeight: reply[11], + observations: reply[13], + totalCompression: reply[15], + memoryUsage: reply[17] + }; + }, + 3: (reply: UnwrapReply): TdInfoReply => { + if (reply instanceof Map) { + throw new Error("BF.INFO shouldn't return a map type in resp3 anymore"); +/* + return { + compression: reply.get('Compression' as unknown as BlobStringReply), + capacity: reply.get('Capacity' as unknown as BlobStringReply), + mergedNodes: reply.get('Merged nodes' as unknown as BlobStringReply), + unmergedNodes: reply.get('Unmerged nodes' as unknown as BlobStringReply), + mergedWeight: reply.get('Merged weight' as unknown as BlobStringReply), + unmergedWeight: reply.get('Unmerged weight' as unknown as BlobStringReply), + observations: reply.get('Observations' as unknown as BlobStringReply), + totalCompression: reply.get('Total compressions' as unknown as BlobStringReply), + memoryUsage: reply.get('Memory usage' as unknown as BlobStringReply) + }; +*/ + } else if (reply instanceof Array) { + throw new Error("BF.INFO shouldn't return a array type in resp3 anymore"); +/* + return { + compression: reply[1], + capacity: reply[3], + mergedNodes: reply[5], + unmergedNodes: reply[7], + mergedWeight: reply[9], + unmergedWeight: reply[11], + observations: reply[13], + totalCompression: reply[15], + memoryUsage: reply[17] + }; +*/ + } else { + return { + compression: reply['Compression'], + capacity: reply['Capacity'], + mergedNodes: reply['Merged nodes'], + unmergedNodes: reply['Unmerged nodes'], + mergedWeight: reply['Merged weight'], + unmergedWeight: reply['Unmerged weight'], + observations: reply['Observations'], + totalCompression: reply['Total compressions'], + memoryUsage: reply['Memory usage'] + }; + } + } + }, + ignoreTypeMapping: true } as const satisfies Command; diff --git a/packages/bloom/lib/commands/top-k/INFO.ts b/packages/bloom/lib/commands/top-k/INFO.ts index 6d943b7a02b..d67e9902692 100644 --- a/packages/bloom/lib/commands/top-k/INFO.ts +++ b/packages/bloom/lib/commands/top-k/INFO.ts @@ -1,11 +1,18 @@ import { RedisArgument, TuplesToMapReply, BlobStringReply, NumberReply, DoubleReply, UnwrapReply, Resp2Reply, Command } from '@redis/client/dist/lib/RESP/types'; -export type TopKInfoReply = TuplesToMapReply<[ +export type TopKInfoReplyMap = TuplesToMapReply<[ [BlobStringReply<'k'>, NumberReply], [BlobStringReply<'width'>, NumberReply], [BlobStringReply<'depth'>, NumberReply], [BlobStringReply<'decay'>, DoubleReply] ]>; + +export type TkInfoReply = { + k: NumberReply, + width: NumberReply, + depth: NumberReply, + decay: number, +} export default { FIRST_KEY_INDEX: 1, @@ -14,12 +21,44 @@ export default { return ['TOPK.INFO', key]; }, transformReply: { - 2: (reply: UnwrapReply>) => ({ - k: reply[1], - width: reply[3], - depth: reply[5], - decay: Number(reply[7]) - }), - 3: undefined as unknown as () => TopKInfoReply - } -} as const satisfies Command; + 2: (reply: UnwrapReply>): TkInfoReply => { + return { + k: reply[1], + width: reply[3], + depth: reply[5], + decay: Number(reply[7]) + } + }, + 3: (reply: UnwrapReply): TkInfoReply => { + if (reply instanceof Map) { + throw new Error("BF.INFO shouldn't return a map type in resp3 anymore"); +/* + return { + k: reply.get('k' as unknown as BlobStringReply<'k'>) as NumberReply, + width: reply.get('width' as unknown as BlobStringReply<'width'>) as NumberReply, + depth: reply.get('depth' as unknown as BlobStringReply<'depth'>) as NumberReply, + decay: Number(reply.get('decay' as unknown as BlobStringReply<'decay'>) as DoubleReply) + }; +*/ + } else if (reply instanceof Array) { + throw new Error("BF.INFO shouldn't return a array type in resp3 anymore"); +/* + return { + k: reply[1], + width: reply[3], + depth: reply[5], + decay: Number(reply[7]) + }; +*/ + } else { + return { + k: reply['k'], + width: reply['width'], + depth: reply['depth'], + decay: Number(reply['decay']) + }; + } + } + }, + ignoreTypeMapping: true +} as const satisfies Command diff --git a/packages/client/lib/RESP/decoder.ts b/packages/client/lib/RESP/decoder.ts index 2485ea23b37..2ece84ef28e 100644 --- a/packages/client/lib/RESP/decoder.ts +++ b/packages/client/lib/RESP/decoder.ts @@ -35,7 +35,7 @@ const ASCII = { } as const; export const PUSH_TYPE_MAPPING = { - [RESP_TYPES.BLOB_STRING]: Buffer + [RESP_TYPES.SIMPLE_STRING]: Buffer }; // this was written with performance in mind, so it's not very readable... sorry :( diff --git a/packages/client/lib/RESP/types.ts b/packages/client/lib/RESP/types.ts index f807cf4b32a..349e11db9c5 100644 --- a/packages/client/lib/RESP/types.ts +++ b/packages/client/lib/RESP/types.ts @@ -140,6 +140,18 @@ export interface TuplesToMapReply extends RespType< Map | FlattenTuples > {} +type SimpleMapKeyValue = [key: SimpleStringReply, value: unknown]; + +type SimpleMapTuples = Array; + +export interface SimpleTuplesToMapReply extends RespType< + RESP_TYPES['MAP'], + { + [P in T[number] as P[0] extends SimpleStringReply ? S : never]: P[1]; + }, + Map | FlattenTuples +> {} + type FlattenTuples = ( T extends [] ? [] : T extends [MapKeyValue] ? T[0] : @@ -276,6 +288,7 @@ export type Command = { TRANSFORM_LEGACY_REPLY?: boolean; transformReply: TransformReply | Record; unstableResp3Module?: boolean; + ignoreTypeMapping?: boolean; }; export type RedisCommands = Record; diff --git a/packages/client/lib/client/commands-queue.ts b/packages/client/lib/client/commands-queue.ts index a4029779fc8..0d6ee3259e4 100644 --- a/packages/client/lib/client/commands-queue.ts +++ b/packages/client/lib/client/commands-queue.ts @@ -183,9 +183,9 @@ export default class RedisCommandsQueue { if (this.#onPush(reply)) return; if (PONG.equals(reply[0] as Buffer)) { - const { resolve, typeMapping } = this.#waitingForReply.shift()!, + const { resolve } = this.#waitingForReply.shift()!, buffer = ((reply[1] as Buffer).length === 0 ? reply[0] : reply[1]) as Buffer; - resolve(typeMapping?.[RESP_TYPES.SIMPLE_STRING] === Buffer ? buffer : buffer.toString()); + resolve(buffer.toString()); return; } } diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 42e1927c212..b7d5ab79f28 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -152,8 +152,17 @@ export default class RedisClient< static #createCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); return async function (this: ProxyClient, ...args: Array) { - const redisArgs = command.transformArguments(...args), - reply = await this.sendCommand(redisArgs, this._commandOptions); + const redisArgs = command.transformArguments(...args); + + let commandOptions: typeof this._commandOptions; + if (this._commandOptions) { + commandOptions = {...this._commandOptions}; + if (command.ignoreTypeMapping) { + commandOptions.typeMapping = undefined + } + } + + const reply = await this.sendCommand(redisArgs, commandOptions); return transformReply ? transformReply(reply, redisArgs.preserve) : reply; @@ -163,8 +172,17 @@ export default class RedisClient< static #createModuleCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); return async function (this: NamespaceProxyClient, ...args: Array) { - const redisArgs = command.transformArguments(...args), - reply = await this._self.sendCommand(redisArgs, this._self._commandOptions); + const redisArgs = command.transformArguments(...args); + + let commandOptions: typeof this._self._commandOptions; + if (this._self._commandOptions) { + commandOptions = {...this._self._commandOptions}; + if (command.ignoreTypeMapping) { + commandOptions.typeMapping = undefined + } + } + + const reply = await this._self.sendCommand(redisArgs, commandOptions); return transformReply ? transformReply(reply, redisArgs.preserve) : reply; @@ -175,10 +193,19 @@ export default class RedisClient< const prefix = functionArgumentsPrefix(name, fn), transformReply = getTransformReply(fn, resp); return async function (this: NamespaceProxyClient, ...args: Array) { - const fnArgs = fn.transformArguments(...args), - reply = await this._self.sendCommand( + const fnArgs = fn.transformArguments(...args); + + let commandOptions: typeof this._self._commandOptions; + if (this._self._commandOptions) { + commandOptions = {...this._self._commandOptions}; + if (fn.ignoreTypeMapping) { + commandOptions.typeMapping = undefined + } + } + + const reply = await this._self.sendCommand( prefix.concat(fnArgs), - this._self._commandOptions + commandOptions ); return transformReply ? transformReply(reply, fnArgs.preserve) : @@ -190,9 +217,18 @@ export default class RedisClient< const prefix = scriptArgumentsPrefix(script), transformReply = getTransformReply(script, resp); return async function (this: ProxyClient, ...args: Array) { - const scriptArgs = script.transformArguments(...args), - redisArgs = prefix.concat(scriptArgs), - reply = await this.executeScript(script, redisArgs, this._commandOptions); + const scriptArgs = script.transformArguments(...args); + const redisArgs = prefix.concat(scriptArgs) + + let commandOptions: typeof this._commandOptions; + if (this._commandOptions) { + commandOptions = {...this._commandOptions}; + if (script.ignoreTypeMapping) { + commandOptions.typeMapping = undefined + } + } + + const reply = await this.executeScript(script, redisArgs, commandOptions); return transformReply ? transformReply(reply, scriptArgs.preserve) : reply; @@ -792,9 +828,9 @@ export default class RedisClient< const chainId = Symbol('Pipeline Chain'), promise = Promise.all( - commands.map(({ args }) => this._self.#queue.addCommand(args, { + commands.map(({ args, ignoreTypeMapping }) => this._self.#queue.addCommand(args, { chainId, - typeMapping: this._commandOptions?.typeMapping + typeMapping: !ignoreTypeMapping ? this._commandOptions?.typeMapping : undefined })) ); this._self.#scheduleWrite(); @@ -831,17 +867,17 @@ export default class RedisClient< throw new WatchError('Client reconnected after WATCH'); } - const typeMapping = this._commandOptions?.typeMapping, - chainId = Symbol('MULTI Chain'), - promises = [ + const typeMapping = this._commandOptions?.typeMapping; + const chainId = Symbol('MULTI Chain'); + const promises = [ this._self.#queue.addCommand(['MULTI'], { chainId }), ]; - for (const { args } of commands) { + for (const { args, ignoreTypeMapping } of commands) { promises.push( this._self.#queue.addCommand(args, { - chainId, - typeMapping + chainId: chainId, + typeMapping: !ignoreTypeMapping ? typeMapping : undefined }) ); } diff --git a/packages/client/lib/client/legacy-mode.ts b/packages/client/lib/client/legacy-mode.ts index 03e7cf4efe1..6673c1c07fa 100644 --- a/packages/client/lib/client/legacy-mode.ts +++ b/packages/client/lib/client/legacy-mode.ts @@ -126,7 +126,7 @@ class LegacyMultiCommand { return function (this: LegacyMultiCommand, ...args: LegacyArguments) { const redisArgs = [name]; RedisLegacyClient.pushArguments(redisArgs, args); - this.#multi.addCommand(redisArgs, transformReply); + this.#multi.addCommand(redisArgs, undefined, transformReply); return this; }; } diff --git a/packages/client/lib/client/multi-command.ts b/packages/client/lib/client/multi-command.ts index ef65144d56b..fcd233797f4 100644 --- a/packages/client/lib/client/multi-command.ts +++ b/packages/client/lib/client/multi-command.ts @@ -91,6 +91,7 @@ export default class RedisClientMultiCommand { return function (this: RedisClientMultiCommand, ...args: Array) { return this.addCommand( command.transformArguments(...args), + command.ignoreTypeMapping, transformReply ); }; @@ -101,6 +102,7 @@ export default class RedisClientMultiCommand { return function (this: { _self: RedisClientMultiCommand }, ...args: Array) { return this._self.addCommand( command.transformArguments(...args), + command.ignoreTypeMapping, transformReply ); }; @@ -115,6 +117,7 @@ export default class RedisClientMultiCommand { redisArgs.preserve = fnArgs.preserve; return this._self.addCommand( redisArgs, + fn.ignoreTypeMapping, transformReply ); }; @@ -126,6 +129,7 @@ export default class RedisClientMultiCommand { this.#multi.addScript( script, script.transformArguments(...args), + script.ignoreTypeMapping, transformReply ); return this; @@ -161,14 +165,14 @@ export default class RedisClientMultiCommand { SELECT(db: number, transformReply?: TransformReply): this { this.#selectedDB = db; - this.#multi.addCommand(['SELECT', db.toString()], transformReply); + this.#multi.addCommand(['SELECT', db.toString()], undefined, transformReply); return this; } select = this.SELECT; - addCommand(args: CommandArguments, transformReply?: TransformReply) { - this.#multi.addCommand(args, transformReply); + addCommand(args: CommandArguments, ignoreTypeMapping?: boolean, transformReply?: TransformReply) { + this.#multi.addCommand(args, ignoreTypeMapping, transformReply); return this; } diff --git a/packages/client/lib/client/pool.ts b/packages/client/lib/client/pool.ts index bc65ae1b3fc..1abd4c8edcf 100644 --- a/packages/client/lib/client/pool.ts +++ b/packages/client/lib/client/pool.ts @@ -65,8 +65,17 @@ export class RedisClientPool< static #createCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); return async function (this: ProxyPool, ...args: Array) { - const redisArgs = command.transformArguments(...args), - reply = await this.sendCommand(redisArgs, this._commandOptions); + const redisArgs = command.transformArguments(...args); + + let commandOptions: typeof this._commandOptions; + if (this._commandOptions) { + commandOptions = {...this._commandOptions}; + if (command.ignoreTypeMapping) { + commandOptions.typeMapping = undefined + } + } + + const reply = await this.sendCommand(redisArgs, commandOptions); return transformReply ? transformReply(reply, redisArgs.preserve) : reply; @@ -76,8 +85,17 @@ export class RedisClientPool< static #createModuleCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); return async function (this: NamespaceProxyPool, ...args: Array) { - const redisArgs = command.transformArguments(...args), - reply = await this._self.sendCommand(redisArgs, this._self._commandOptions); + const redisArgs = command.transformArguments(...args); + + let commandOptions: typeof this._self._commandOptions; + if (this._self._commandOptions) { + commandOptions = {...this._self._commandOptions}; + if (command.ignoreTypeMapping) { + commandOptions.typeMapping = undefined + } + } + + const reply = await this._self.sendCommand(redisArgs, commandOptions); return transformReply ? transformReply(reply, redisArgs.preserve) : reply; @@ -88,10 +106,19 @@ export class RedisClientPool< const prefix = functionArgumentsPrefix(name, fn), transformReply = getTransformReply(fn, resp); return async function (this: NamespaceProxyPool, ...args: Array) { - const fnArgs = fn.transformArguments(...args), - reply = await this._self.sendCommand( + const fnArgs = fn.transformArguments(...args); + + let commandOptions: typeof this._self._commandOptions; + if (this._self._commandOptions) { + commandOptions = {...this._self._commandOptions}; + if (fn.ignoreTypeMapping) { + commandOptions.typeMapping = undefined + } + } + + const reply = await this._self.sendCommand( prefix.concat(fnArgs), - this._self._commandOptions + commandOptions ); return transformReply ? transformReply(reply, fnArgs.preserve) : @@ -103,9 +130,18 @@ export class RedisClientPool< const prefix = scriptArgumentsPrefix(script), transformReply = getTransformReply(script, resp); return async function (this: ProxyPool, ...args: Array) { - const scriptArgs = script.transformArguments(...args), - redisArgs = prefix.concat(scriptArgs), - reply = await this.executeScript(script, redisArgs, this._commandOptions); + const scriptArgs = script.transformArguments(...args); + const redisArgs = prefix.concat(scriptArgs); + + let commandOptions: typeof this._commandOptions; + if (this._commandOptions) { + commandOptions = {...this._commandOptions}; + if (script.ignoreTypeMapping) { + commandOptions.typeMapping = undefined + } + } + + const reply = await this.executeScript(script, redisArgs, commandOptions); return transformReply ? transformReply(reply, scriptArgs.preserve) : reply; diff --git a/packages/client/lib/cluster/index.ts b/packages/client/lib/cluster/index.ts index 6718747bc91..20f55fe58c8 100644 --- a/packages/client/lib/cluster/index.ts +++ b/packages/client/lib/cluster/index.ts @@ -174,19 +174,28 @@ export default class RedisCluster< static #createCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); return async function (this: ProxyCluster, ...args: Array) { - const redisArgs = command.transformArguments(...args), - firstKey = RedisCluster.extractFirstKey( - command, - args, - redisArgs - ), - reply = await this.sendCommand( - firstKey, - command.IS_READ_ONLY, - redisArgs, - this._commandOptions, - // command.POLICIES - ); + const redisArgs = command.transformArguments(...args); + const firstKey = RedisCluster.extractFirstKey( + command, + args, + redisArgs + ); + + let commandOptions: typeof this._commandOptions; + if (this._commandOptions) { + commandOptions = {...this._commandOptions}; + if (command.ignoreTypeMapping) { + commandOptions.typeMapping = undefined + } + } + + const reply = await this.sendCommand( + firstKey, + command.IS_READ_ONLY, + redisArgs, + commandOptions, + // command.POLICIES + ); return transformReply ? transformReply(reply, redisArgs.preserve) : @@ -197,19 +206,28 @@ export default class RedisCluster< static #createModuleCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); return async function (this: NamespaceProxyCluster, ...args: Array) { - const redisArgs = command.transformArguments(...args), - firstKey = RedisCluster.extractFirstKey( - command, - args, - redisArgs - ), - reply = await this._self.sendCommand( - firstKey, - command.IS_READ_ONLY, - redisArgs, - this._self._commandOptions, - // command.POLICIES - ); + const redisArgs = command.transformArguments(...args); + const firstKey = RedisCluster.extractFirstKey( + command, + args, + redisArgs + ); + + let commandOptions: typeof this._self._commandOptions; + if (this._self._commandOptions) { + commandOptions = {...this._self._commandOptions}; + if (command.ignoreTypeMapping) { + commandOptions.typeMapping = undefined + } + } + + const reply = await this._self.sendCommand( + firstKey, + command.IS_READ_ONLY, + redisArgs, + commandOptions, + // command.POLICIES + ); return transformReply ? transformReply(reply, redisArgs.preserve) : @@ -221,20 +239,29 @@ export default class RedisCluster< const prefix = functionArgumentsPrefix(name, fn), transformReply = getTransformReply(fn, resp); return async function (this: NamespaceProxyCluster, ...args: Array) { - const fnArgs = fn.transformArguments(...args), - firstKey = RedisCluster.extractFirstKey( - fn, - args, - fnArgs - ), - redisArgs = prefix.concat(fnArgs), - reply = await this._self.sendCommand( - firstKey, - fn.IS_READ_ONLY, - redisArgs, - this._self._commandOptions, - // fn.POLICIES - ); + const fnArgs = fn.transformArguments(...args); + const firstKey = RedisCluster.extractFirstKey( + fn, + args, + fnArgs + ); + const redisArgs = prefix.concat(fnArgs); + + let commandOptions: typeof this._self._commandOptions; + if (this._self._commandOptions) { + commandOptions = {...this._self._commandOptions}; + if (fn.ignoreTypeMapping) { + commandOptions.typeMapping = undefined + } + } + + const reply = await this._self.sendCommand( + firstKey, + fn.IS_READ_ONLY, + redisArgs, + commandOptions, + // fn.POLICIES + ); return transformReply ? transformReply(reply, fnArgs.preserve) : @@ -246,21 +273,30 @@ export default class RedisCluster< const prefix = scriptArgumentsPrefix(script), transformReply = getTransformReply(script, resp); return async function (this: ProxyCluster, ...args: Array) { - const scriptArgs = script.transformArguments(...args), - firstKey = RedisCluster.extractFirstKey( - script, - args, - scriptArgs - ), - redisArgs = prefix.concat(scriptArgs), - reply = await this.executeScript( - script, - firstKey, - script.IS_READ_ONLY, - redisArgs, - this._commandOptions, - // script.POLICIES - ); + const scriptArgs = script.transformArguments(...args); + const firstKey = RedisCluster.extractFirstKey( + script, + args, + scriptArgs + ); + const redisArgs = prefix.concat(scriptArgs); + + let commandOptions: typeof this._commandOptions; + if (this._commandOptions) { + commandOptions = {...this._commandOptions}; + if (script.ignoreTypeMapping) { + commandOptions.typeMapping = undefined + } + } + + const reply = await this.executeScript( + script, + firstKey, + script.IS_READ_ONLY, + redisArgs, + commandOptions, + // script.POLICIES + ); return transformReply ? transformReply(reply, scriptArgs.preserve) : diff --git a/packages/client/lib/cluster/multi-command.ts b/packages/client/lib/cluster/multi-command.ts index 225d1624653..d01ab87490a 100644 --- a/packages/client/lib/cluster/multi-command.ts +++ b/packages/client/lib/cluster/multi-command.ts @@ -94,16 +94,17 @@ export default class RedisClusterMultiCommand { static #createCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); return function (this: RedisClusterMultiCommand, ...args: Array) { - const redisArgs = command.transformArguments(...args), - firstKey = RedisCluster.extractFirstKey( - command, - args, - redisArgs - ); + const redisArgs = command.transformArguments(...args); + const firstKey = RedisCluster.extractFirstKey( + command, + args, + redisArgs + ); return this.addCommand( firstKey, command.IS_READ_ONLY, redisArgs, + command.ignoreTypeMapping, transformReply ); }; @@ -122,6 +123,7 @@ export default class RedisClusterMultiCommand { firstKey, command.IS_READ_ONLY, redisArgs, + command.ignoreTypeMapping, transformReply ); }; @@ -131,18 +133,19 @@ export default class RedisClusterMultiCommand { const prefix = functionArgumentsPrefix(name, fn), transformReply = getTransformReply(fn, resp); return function (this: { _self: RedisClusterMultiCommand }, ...args: Array) { - const fnArgs = fn.transformArguments(...args), - redisArgs: CommandArguments = prefix.concat(fnArgs), - firstKey = RedisCluster.extractFirstKey( - fn, - args, - fnArgs - ); + const fnArgs = fn.transformArguments(...args); + const redisArgs: CommandArguments = prefix.concat(fnArgs); + const firstKey = RedisCluster.extractFirstKey( + fn, + args, + fnArgs + ); redisArgs.preserve = fnArgs.preserve; return this._self.addCommand( firstKey, fn.IS_READ_ONLY, redisArgs, + fn.ignoreTypeMapping, transformReply ); }; @@ -163,6 +166,7 @@ export default class RedisClusterMultiCommand { this.#multi.addScript( script, scriptArgs, + script.ignoreTypeMapping, transformReply ); return this; @@ -214,10 +218,11 @@ export default class RedisClusterMultiCommand { firstKey: RedisArgument | undefined, isReadonly: boolean | undefined, args: CommandArguments, + ignoreTypeMapping?: boolean, transformReply?: TransformReply ) { this.#setState(firstKey, isReadonly); - this.#multi.addCommand(args, transformReply); + this.#multi.addCommand(args, ignoreTypeMapping, transformReply); return this; } diff --git a/packages/client/lib/multi-command.ts b/packages/client/lib/multi-command.ts index 019a0203284..7641d7910e2 100644 --- a/packages/client/lib/multi-command.ts +++ b/packages/client/lib/multi-command.ts @@ -12,6 +12,7 @@ export type MultiReplyType = T extends MULTI_REPL export interface RedisMultiQueuedCommand { args: CommandArguments; + ignoreTypeMapping?: boolean; transformReply?: TransformReply; } @@ -20,14 +21,15 @@ export default class RedisMultiCommand { readonly scriptsInUse = new Set(); - addCommand(args: CommandArguments, transformReply?: TransformReply) { + addCommand(args: CommandArguments, ignoreTypeMapping?: boolean, transformReply?: TransformReply) { this.queue.push({ args, + ignoreTypeMapping, transformReply }); } - addScript(script: RedisScript, args: CommandArguments, transformReply?: TransformReply) { + addScript(script: RedisScript, args: CommandArguments, ignoreTypeMapping?: boolean, transformReply?: TransformReply) { const redisArgs: CommandArguments = []; redisArgs.preserve = args.preserve; if (this.scriptsInUse.has(script.SHA1)) { @@ -43,7 +45,7 @@ export default class RedisMultiCommand { redisArgs.push(...args); - this.addCommand(redisArgs, transformReply); + this.addCommand(redisArgs, ignoreTypeMapping, transformReply); } transformReplies(rawReplies: Array): Array { diff --git a/packages/client/lib/sentinel/multi-commands.ts b/packages/client/lib/sentinel/multi-commands.ts index 21b5e15fd92..96fa3209495 100644 --- a/packages/client/lib/sentinel/multi-commands.ts +++ b/packages/client/lib/sentinel/multi-commands.ts @@ -92,6 +92,7 @@ export default class RedisSentinelMultiCommand { return this.addCommand( command.IS_READ_ONLY, redisArgs, + command.ignoreTypeMapping, transformReply ); }; @@ -107,6 +108,7 @@ export default class RedisSentinelMultiCommand { return this._self.addCommand( command.IS_READ_ONLY, redisArgs, + command.ignoreTypeMapping, transformReply ); }; @@ -122,6 +124,7 @@ export default class RedisSentinelMultiCommand { return this._self.addCommand( fn.IS_READ_ONLY, redisArgs, + fn.ignoreTypeMapping, transformReply ); }; @@ -137,6 +140,7 @@ export default class RedisSentinelMultiCommand { this._multi.addScript( script, scriptArgs, + script.ignoreTypeMapping, transformReply ); return this; @@ -179,10 +183,11 @@ export default class RedisSentinelMultiCommand { addCommand( isReadonly: boolean | undefined, args: CommandArguments, + ignoreTypeMapping?: boolean, transformReply?: TransformReply ) { this._setState(isReadonly); - this._multi.addCommand(args, transformReply); + this._multi.addCommand(args, ignoreTypeMapping, transformReply); return this; } diff --git a/packages/client/lib/sentinel/utils.ts b/packages/client/lib/sentinel/utils.ts index 4ae829183a2..84af98bd79e 100644 --- a/packages/client/lib/sentinel/utils.ts +++ b/packages/client/lib/sentinel/utils.ts @@ -38,12 +38,21 @@ export function clientSocketToNode(socket: RedisSocketOptions): RedisNode { export function createCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); return async function (this: T, ...args: Array) { - const redisArgs = command.transformArguments(...args), - reply = await this._self.sendCommand( - command.IS_READ_ONLY, - redisArgs, - this._self.commandOptions - ); + const redisArgs = command.transformArguments(...args); + + let commandOptions: typeof this._self.commandOptions; + if (this._self.commandOptions) { + commandOptions = {...this._self.commandOptions}; + if (command.ignoreTypeMapping) { + commandOptions.typeMapping = undefined + } + } + + const reply = await this._self.sendCommand( + command.IS_READ_ONLY, + redisArgs, + commandOptions + ); return transformReply ? transformReply(reply, redisArgs.preserve) : @@ -55,13 +64,22 @@ export function createFunctionCommand) { - const fnArgs = fn.transformArguments(...args), - redisArgs = prefix.concat(fnArgs), - reply = await this._self._self.sendCommand( - fn.IS_READ_ONLY, - redisArgs, - this._self._self.commandOptions - ); + const fnArgs = fn.transformArguments(...args); + const redisArgs = prefix.concat(fnArgs); + + let commandOptions: typeof this._self._self.commandOptions; + if (this._self._self.commandOptions) { + commandOptions = {...this._self._self.commandOptions}; + if (fn.ignoreTypeMapping) { + commandOptions.typeMapping = undefined + } + } + + const reply = await this._self._self.sendCommand( + fn.IS_READ_ONLY, + redisArgs, + commandOptions + ); return transformReply ? transformReply(reply, fnArgs.preserve) : @@ -72,12 +90,21 @@ export function createFunctionCommand(command: Command, resp: RespVersions) { const transformReply = getTransformReply(command, resp); return async function (this: T, ...args: Array) { - const redisArgs = command.transformArguments(...args), - reply = await this._self._self.sendCommand( - command.IS_READ_ONLY, - redisArgs, - this._self._self.commandOptions - ); + const redisArgs = command.transformArguments(...args); + + let commandOptions: typeof this._self._self.commandOptions; + if (this._self._self.commandOptions) { + commandOptions = {...this._self._self.commandOptions}; + if (command.ignoreTypeMapping) { + commandOptions.typeMapping = undefined + } + } + + const reply = await this._self._self.sendCommand( + command.IS_READ_ONLY, + redisArgs, + commandOptions + ); return transformReply ? transformReply(reply, redisArgs.preserve) : @@ -89,14 +116,23 @@ export function createScriptCommand) { - const scriptArgs = script.transformArguments(...args), - redisArgs = prefix.concat(scriptArgs), - reply = await this._self.executeScript( - script, - script.IS_READ_ONLY, - redisArgs, - this._self.commandOptions - ); + const scriptArgs = script.transformArguments(...args); + const redisArgs = prefix.concat(scriptArgs); + + let commandOptions: typeof this._self.commandOptions; + if (this._self.commandOptions) { + commandOptions = {...this._self.commandOptions}; + if (script.ignoreTypeMapping) { + commandOptions.typeMapping = undefined + } + } + + const reply = await this._self.executeScript( + script, + script.IS_READ_ONLY, + redisArgs, + commandOptions + ); return transformReply ? transformReply(reply, scriptArgs.preserve) : diff --git a/packages/json/lib/commands/TYPE.ts b/packages/json/lib/commands/TYPE.ts index 68c5d850ebf..07f22ba9818 100644 --- a/packages/json/lib/commands/TYPE.ts +++ b/packages/json/lib/commands/TYPE.ts @@ -18,8 +18,8 @@ export default { }, transformReply: { 2: undefined as unknown as () => NullReply | BlobStringReply | ArrayReply, - // TODO: ?!??! - 3: undefined as unknown as () => any - } + 3: undefined as unknown as () => ArrayReply> + }, + unstableResp3Module: true } as const satisfies Command; diff --git a/packages/search/lib/commands/AGGREGATE.ts b/packages/search/lib/commands/AGGREGATE.ts index 970186d6225..4e8d356bac8 100644 --- a/packages/search/lib/commands/AGGREGATE.ts +++ b/packages/search/lib/commands/AGGREGATE.ts @@ -1,4 +1,4 @@ -import { ArrayReply, BlobStringReply, Command, RedisArgument, ReplyUnion, UnwrapReply } from '@redis/client/dist/lib/RESP/types'; +import { ArrayReply, BlobStringReply, Command, NumberReply, RedisArgument, ReplyUnion, UnwrapReply } from '@redis/client/dist/lib/RESP/types'; import { RediSearchProperty } from './CREATE'; import { FtSearchParams, pushParamsArgument } from './SEARCH'; import { pushVariadicArgument, transformTuplesReply } from '@redis/client/dist/lib/commands/generic-transformers'; @@ -126,7 +126,7 @@ export interface FtAggregateOptions { } export type AggregateRawReply = [ - total: number, + total: UnwrapReply, ...results: UnwrapReply>> ]; @@ -153,12 +153,13 @@ export default { } return { - total: rawReply[0], + total: Number(rawReply[0]), results }; }, 3: undefined as unknown as () => ReplyUnion - } + }, + unstableResp3Module: true } as const satisfies Command; export function pushAggregateOptions(args: Array, options?: FtAggregateOptions) { diff --git a/packages/search/lib/commands/ALIASADD.ts b/packages/search/lib/commands/ALIASADD.ts index 470bd39a2d6..648e1fef97e 100644 --- a/packages/search/lib/commands/ALIASADD.ts +++ b/packages/search/lib/commands/ALIASADD.ts @@ -6,6 +6,5 @@ export default { transformArguments(alias: RedisArgument, index: RedisArgument) { return ['FT.ALIASADD', alias, index]; }, - transformReply: undefined as unknown as () => SimpleStringReply<'OK'>, - unstableResp3Module: true + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> } as const satisfies Command; diff --git a/packages/search/lib/commands/ALIASDEL.ts b/packages/search/lib/commands/ALIASDEL.ts index 643225bc4b8..40cc45a19de 100644 --- a/packages/search/lib/commands/ALIASDEL.ts +++ b/packages/search/lib/commands/ALIASDEL.ts @@ -6,6 +6,5 @@ export default { transformArguments(alias: RedisArgument) { return ['FT.ALIASDEL', alias]; }, - transformReply: undefined as unknown as () => SimpleStringReply<'OK'>, - unstableResp3Module: true, + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> } as const satisfies Command; diff --git a/packages/search/lib/commands/ALIASUPDATE.ts b/packages/search/lib/commands/ALIASUPDATE.ts index b74eb10e844..e2b72cfe649 100644 --- a/packages/search/lib/commands/ALIASUPDATE.ts +++ b/packages/search/lib/commands/ALIASUPDATE.ts @@ -6,6 +6,5 @@ export default { transformArguments(alias: RedisArgument, index: RedisArgument) { return ['FT.ALIASUPDATE', alias, index]; }, - transformReply: undefined as unknown as () => SimpleStringReply<'OK'>, - unstableResp3Module: true + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> } as const satisfies Command; diff --git a/packages/search/lib/commands/ALTER.ts b/packages/search/lib/commands/ALTER.ts index 0dd8c2a476e..d5587b2397c 100644 --- a/packages/search/lib/commands/ALTER.ts +++ b/packages/search/lib/commands/ALTER.ts @@ -9,6 +9,5 @@ export default { pushSchema(args, schema); return args; }, - transformReply: undefined as unknown as () => SimpleStringReply<'OK'>, - unstableResp3Module: true + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> } as const satisfies Command; diff --git a/packages/search/lib/commands/CONFIG_GET.ts b/packages/search/lib/commands/CONFIG_GET.ts index 4d95118dc24..f96461e8694 100644 --- a/packages/search/lib/commands/CONFIG_GET.ts +++ b/packages/search/lib/commands/CONFIG_GET.ts @@ -14,6 +14,5 @@ export default { } return transformedReply; - }, - unstableResp3Module: true + } } as const satisfies Command; diff --git a/packages/search/lib/commands/CONFIG_SET.ts b/packages/search/lib/commands/CONFIG_SET.ts index 13659301712..ac001bf68a6 100644 --- a/packages/search/lib/commands/CONFIG_SET.ts +++ b/packages/search/lib/commands/CONFIG_SET.ts @@ -10,6 +10,5 @@ export default { transformArguments(property: FtConfigProperties, value: RedisArgument) { return ['FT.CONFIG', 'SET', property, value]; }, - transformReply: undefined as unknown as () => SimpleStringReply<'OK'>, - unstableResp3Module: true + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> } as const satisfies Command; diff --git a/packages/search/lib/commands/CREATE.ts b/packages/search/lib/commands/CREATE.ts index 1ccb797da93..f6b66085f2d 100644 --- a/packages/search/lib/commands/CREATE.ts +++ b/packages/search/lib/commands/CREATE.ts @@ -347,6 +347,5 @@ export default { return args; }, - transformReply: undefined as unknown as () => SimpleStringReply<'OK'>, - unstableResp3Module: true + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> } as const satisfies Command; diff --git a/packages/search/lib/commands/CURSOR_DEL.ts b/packages/search/lib/commands/CURSOR_DEL.ts index 96638b442d0..b0f87669661 100644 --- a/packages/search/lib/commands/CURSOR_DEL.ts +++ b/packages/search/lib/commands/CURSOR_DEL.ts @@ -6,6 +6,5 @@ export default { transformArguments(index: RedisArgument, cursorId: number) { return ['FT.CURSOR', 'DEL', index, cursorId.toString()]; }, - transformReply: undefined as unknown as () => SimpleStringReply<'OK'>, - unstableResp3Module: true + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> } as const satisfies Command; diff --git a/packages/search/lib/commands/DICTADD.ts b/packages/search/lib/commands/DICTADD.ts index 78cdc0a2831..f633d58b1f3 100644 --- a/packages/search/lib/commands/DICTADD.ts +++ b/packages/search/lib/commands/DICTADD.ts @@ -7,6 +7,5 @@ export default { transformArguments(dictionary: RedisArgument, term: RedisVariadicArgument) { return pushVariadicArguments(['FT.DICTADD', dictionary], term); }, - transformReply: undefined as unknown as () => NumberReply, - unstableResp3Module: true + transformReply: undefined as unknown as () => NumberReply } as const satisfies Command; diff --git a/packages/search/lib/commands/DICTDEL.ts b/packages/search/lib/commands/DICTDEL.ts index e8f3fb633f8..087211751ee 100644 --- a/packages/search/lib/commands/DICTDEL.ts +++ b/packages/search/lib/commands/DICTDEL.ts @@ -7,6 +7,5 @@ export default { transformArguments(dictionary: RedisArgument, term: RedisVariadicArgument) { return pushVariadicArguments(['FT.DICTDEL', dictionary], term); }, - transformReply: undefined as unknown as () => NumberReply, - unstableResp3Module: true + transformReply: undefined as unknown as () => NumberReply } as const satisfies Command; diff --git a/packages/search/lib/commands/DICTDUMP.ts b/packages/search/lib/commands/DICTDUMP.ts index 87dce6025d5..f542403cc57 100644 --- a/packages/search/lib/commands/DICTDUMP.ts +++ b/packages/search/lib/commands/DICTDUMP.ts @@ -9,6 +9,5 @@ export default { transformReply: { 2: undefined as unknown as () => ArrayReply, 3: undefined as unknown as () => SetReply - }, - unstableResp3Module: true + } } as const satisfies Command; diff --git a/packages/search/lib/commands/DROPINDEX.ts b/packages/search/lib/commands/DROPINDEX.ts index 59a2dfd2df0..64fe9711e7f 100644 --- a/packages/search/lib/commands/DROPINDEX.ts +++ b/packages/search/lib/commands/DROPINDEX.ts @@ -19,6 +19,5 @@ export default { transformReply: { 2: undefined as unknown as () => SimpleStringReply<'OK'>, 3: undefined as unknown as () => NumberReply - }, - unstableResp3Module: true + } } as const satisfies Command; diff --git a/packages/search/lib/commands/EXPLAIN.ts b/packages/search/lib/commands/EXPLAIN.ts index 3266395c845..0ad84feb68d 100644 --- a/packages/search/lib/commands/EXPLAIN.ts +++ b/packages/search/lib/commands/EXPLAIN.ts @@ -24,6 +24,5 @@ export default { return args; }, - transformReply: undefined as unknown as () => SimpleStringReply, - unstableResp3Module: true + transformReply: undefined as unknown as () => SimpleStringReply } as const satisfies Command; diff --git a/packages/search/lib/commands/EXPLAINCLI.ts b/packages/search/lib/commands/EXPLAINCLI.ts index 5b22237aac0..e16866991b9 100644 --- a/packages/search/lib/commands/EXPLAINCLI.ts +++ b/packages/search/lib/commands/EXPLAINCLI.ts @@ -6,6 +6,5 @@ export default { transformArguments(index: RedisArgument, query: RedisArgument) { return ['FT.EXPLAINCLI', index, query]; }, - transformReply: undefined as unknown as () => ArrayReply, - unstableResp3Module: true + transformReply: undefined as unknown as () => ArrayReply } as const satisfies Command; diff --git a/packages/search/lib/commands/PROFILE_SEARCH.ts b/packages/search/lib/commands/PROFILE_SEARCH.ts index 45fbbcdae9d..75545ad1697 100644 --- a/packages/search/lib/commands/PROFILE_SEARCH.ts +++ b/packages/search/lib/commands/PROFILE_SEARCH.ts @@ -7,144 +7,144 @@ import SEARCH, { FtSearchOptions, SearchRawReply, SearchReply, pushSearchOptions import { AggregateReply } from "./AGGREGATE"; export type ProfileRawReply = [ - results: T, - profile: [ - _: string, - TotalProfileTime: string, - _: string, - ParsingTime: string, - _: string, - PipelineCreationTime: string, - _: string, - IteratorsProfile: Array - ] + results: T, + profile: [ + _: string, + TotalProfileTime: string, + _: string, + ParsingTime: string, + _: string, + PipelineCreationTime: string, + _: string, + IteratorsProfile: Array + ] ]; type ProfileSearchRawReply = ProfileRawReply; export interface ProfileOptions { - LIMITED?: true; + LIMITED?: true; } export default { - FIRST_KEY_INDEX: undefined, - IS_READ_ONLY: true, - transformArguments( - index: RedisArgument, - query: RedisArgument, - options?: ProfileOptions & FtSearchOptions - ) { - let args: Array = ['FT.PROFILE', index, 'SEARCH']; - - if (options?.LIMITED) { - args.push('LIMITED'); - } + FIRST_KEY_INDEX: undefined, + IS_READ_ONLY: true, + transformArguments( + index: RedisArgument, + query: RedisArgument, + options?: ProfileOptions & FtSearchOptions + ) { + let args: Array = ['FT.PROFILE', index, 'SEARCH']; + + if (options?.LIMITED) { + args.push('LIMITED'); + } - args.push('QUERY', query); + args.push('QUERY', query); - return pushSearchOptions(args, options); - }, - transformReply: { - 2: (reply: ProfileSearchRawReply, withoutDocuments: boolean): ProfileReply => { - return { - results: SEARCH.transformReply[2](reply[0]), - profile: transformProfile(reply[1]) - } - }, - 3: undefined as unknown as () => ReplyUnion + return pushSearchOptions(args, options); + }, + transformReply: { + 2: (reply: ProfileSearchRawReply, withoutDocuments: boolean): ProfileReply => { + return { + results: SEARCH.transformReply[2](reply[0]), + profile: transformProfile(reply[1]) + } }, - unstableResp3Module: true - } as const satisfies Command; - - export interface ProfileReply { - results: SearchReply | AggregateReply; - profile: ProfileData; + 3: undefined as unknown as () => ReplyUnion + }, + unstableResp3Module: true +} as const satisfies Command; + +export interface ProfileReply { + results: SearchReply | AggregateReply; + profile: ProfileData; } - interface ChildIterator { - type?: string, - counter?: number, - term?: string, - size?: number, - time?: string, - childIterators?: Array +interface ChildIterator { + type?: string, + counter?: number, + term?: string, + size?: number, + time?: string, + childIterators?: Array } interface IteratorsProfile { - type?: string, - counter?: number, - queryType?: string, - time?: string, - childIterators?: Array + type?: string, + counter?: number, + queryType?: string, + time?: string, + childIterators?: Array } interface ProfileData { - totalProfileTime: string, - parsingTime: string, - pipelineCreationTime: string, - iteratorsProfile: IteratorsProfile + totalProfileTime: string, + parsingTime: string, + pipelineCreationTime: string, + iteratorsProfile: IteratorsProfile } export function transformProfile(reply: Array): ProfileData{ - return { - totalProfileTime: reply[0][1], - parsingTime: reply[1][1], - pipelineCreationTime: reply[2][1], - iteratorsProfile: transformIterators(reply[3][1]) - }; + return { + totalProfileTime: reply[0][1], + parsingTime: reply[1][1], + pipelineCreationTime: reply[2][1], + iteratorsProfile: transformIterators(reply[3][1]) + }; } function transformIterators(IteratorsProfile: Array): IteratorsProfile { - var res: IteratorsProfile = {}; - for (let i = 0; i < IteratorsProfile.length; i += 2) { - const value = IteratorsProfile[i+1]; - switch (IteratorsProfile[i]) { - case 'Type': - res.type = value; - break; - case 'Counter': - res.counter = value; - break; - case 'Time': - res.time = value; - break; - case 'Query type': - res.queryType = value; - break; - case 'Child iterators': - res.childIterators = value.map(transformChildIterators); - break; - } + var res: IteratorsProfile = {}; + for (let i = 0; i < IteratorsProfile.length; i += 2) { + const value = IteratorsProfile[i+1]; + switch (IteratorsProfile[i]) { + case 'Type': + res.type = value; + break; + case 'Counter': + res.counter = value; + break; + case 'Time': + res.time = value; + break; + case 'Query type': + res.queryType = value; + break; + case 'Child iterators': + res.childIterators = value.map(transformChildIterators); + break; } + } - return res; + return res; } function transformChildIterators(IteratorsProfile: Array): ChildIterator { - var res: ChildIterator = {}; - for (let i = 1; i < IteratorsProfile.length; i += 2) { - const value = IteratorsProfile[i+1]; - switch (IteratorsProfile[i]) { - case 'Type': - res.type = value; - break; - case 'Counter': - res.counter = value; - break; - case 'Time': - res.time = value; - break; - case 'Size': - res.size = value; - break; - case 'Term': - res.term = value; - break; - case 'Child iterators': - res.childIterators = value.map(transformChildIterators); - break; - } + var res: ChildIterator = {}; + for (let i = 1; i < IteratorsProfile.length; i += 2) { + const value = IteratorsProfile[i+1]; + switch (IteratorsProfile[i]) { + case 'Type': + res.type = value; + break; + case 'Counter': + res.counter = value; + break; + case 'Time': + res.time = value; + break; + case 'Size': + res.size = value; + break; + case 'Term': + res.term = value; + break; + case 'Child iterators': + res.childIterators = value.map(transformChildIterators); + break; } + } - return res; + return res; } \ No newline at end of file diff --git a/packages/search/lib/commands/SUGADD.ts b/packages/search/lib/commands/SUGADD.ts index a3d579a3712..e821b35f74f 100644 --- a/packages/search/lib/commands/SUGADD.ts +++ b/packages/search/lib/commands/SUGADD.ts @@ -22,5 +22,4 @@ export default { return args; }, transformReply: undefined as unknown as () => NumberReply, - unstableResp3Module: true } as const satisfies Command; diff --git a/packages/search/lib/commands/SUGDEL.ts b/packages/search/lib/commands/SUGDEL.ts index 525623d26ef..ed9a8aef24f 100644 --- a/packages/search/lib/commands/SUGDEL.ts +++ b/packages/search/lib/commands/SUGDEL.ts @@ -6,6 +6,5 @@ export default { transformArguments(key: RedisArgument, string: RedisArgument) { return ['FT.SUGDEL', key, string]; }, - transformReply: undefined as unknown as () => NumberReply<0 | 1>, - unstableResp3Module: true + transformReply: undefined as unknown as () => NumberReply<0 | 1> } as const satisfies Command; diff --git a/packages/search/lib/commands/SUGGET.ts b/packages/search/lib/commands/SUGGET.ts index becff45bdaa..9359920fcb2 100644 --- a/packages/search/lib/commands/SUGGET.ts +++ b/packages/search/lib/commands/SUGGET.ts @@ -21,6 +21,5 @@ export default { return args; }, - transformReply: undefined as unknown as () => NullReply | ArrayReply, - unstableResp3Module: true + transformReply: undefined as unknown as () => NullReply | ArrayReply } as const satisfies Command; diff --git a/packages/search/lib/commands/SUGGET_WITHPAYLOADS.ts b/packages/search/lib/commands/SUGGET_WITHPAYLOADS.ts index d0f8993df55..d8b097f3dbc 100644 --- a/packages/search/lib/commands/SUGGET_WITHPAYLOADS.ts +++ b/packages/search/lib/commands/SUGGET_WITHPAYLOADS.ts @@ -27,6 +27,5 @@ export default { } return transformedReply; - }, - unstableResp3Module: true + } } as const satisfies Command; diff --git a/packages/search/lib/commands/SUGGET_WITHSCORES_WITHPAYLOADS.ts b/packages/search/lib/commands/SUGGET_WITHSCORES_WITHPAYLOADS.ts index 982ae44d667..91d1ad2ecce 100644 --- a/packages/search/lib/commands/SUGGET_WITHSCORES_WITHPAYLOADS.ts +++ b/packages/search/lib/commands/SUGGET_WITHSCORES_WITHPAYLOADS.ts @@ -54,6 +54,5 @@ export default { return transformedReply; } - }, - unstableResp3Module: true + } } as const satisfies Command; diff --git a/packages/search/lib/commands/SYNDUMP.ts b/packages/search/lib/commands/SYNDUMP.ts index 59f0058b3c2..2fe7540fda5 100644 --- a/packages/search/lib/commands/SYNDUMP.ts +++ b/packages/search/lib/commands/SYNDUMP.ts @@ -18,6 +18,5 @@ export default { return result; }, 3: undefined as unknown as () => MapReply> - }, - unstableResp3Module: true + } } as const satisfies Command; diff --git a/packages/search/lib/commands/SYNUPDATE.ts b/packages/search/lib/commands/SYNUPDATE.ts index 414bc0c8d0e..926d8e58e1c 100644 --- a/packages/search/lib/commands/SYNUPDATE.ts +++ b/packages/search/lib/commands/SYNUPDATE.ts @@ -22,6 +22,5 @@ export default { return pushVariadicArguments(args, terms); }, - transformReply: undefined as unknown as () => SimpleStringReply<'OK'>, - unstableResp3Module: true + transformReply: undefined as unknown as () => SimpleStringReply<'OK'> } as const satisfies Command; diff --git a/packages/search/lib/commands/TAGVALS.ts b/packages/search/lib/commands/TAGVALS.ts index 092836161c7..8a6e73c97b8 100644 --- a/packages/search/lib/commands/TAGVALS.ts +++ b/packages/search/lib/commands/TAGVALS.ts @@ -9,6 +9,5 @@ export default { transformReply: { 2: undefined as unknown as () => ArrayReply, 3: undefined as unknown as () => SetReply - }, - unstableResp3Module: true + } } as const satisfies Command; diff --git a/packages/search/lib/commands/_LIST.ts b/packages/search/lib/commands/_LIST.ts index 31c4f4e22d5..efb6c31acce 100644 --- a/packages/search/lib/commands/_LIST.ts +++ b/packages/search/lib/commands/_LIST.ts @@ -9,6 +9,5 @@ export default { transformReply: { 2: undefined as unknown as () => ArrayReply, 3: undefined as unknown as () => SetReply - }, - unstableResp3Module: true, + } } as const satisfies Command; diff --git a/packages/time-series/lib/commands/INFO.ts b/packages/time-series/lib/commands/INFO.ts index 851d96d5713..393d3d2ef6f 100644 --- a/packages/time-series/lib/commands/INFO.ts +++ b/packages/time-series/lib/commands/INFO.ts @@ -1,82 +1,86 @@ -// import { TimeSeriesAggregationType, TimeSeriesDuplicatePolicies } from '.'; +import { BlobStringReply, Command, NumberReply, SimpleStringReply } from "@redis/client/dist/lib/RESP/types"; +import { TimeSeriesDuplicatePolicies } from "."; +import { TimeSeriesAggregationType } from "./CREATERULE"; -// export const FIRST_KEY_INDEX = 1; +export type InfoRawReply = [ + 'totalSamples', + NumberReply, + 'memoryUsage', + NumberReply, + 'firstTimestamp', + NumberReply, + 'lastTimestamp', + NumberReply, + 'retentionTime', + NumberReply, + 'chunkCount', + NumberReply, + 'chunkSize', + NumberReply, + 'chunkType', + SimpleStringReply, + 'duplicatePolicy', + TimeSeriesDuplicatePolicies | null, + 'labels', + Array<[name: BlobStringReply, value: BlobStringReply]>, + 'sourceKey', + BlobStringReply | null, + 'rules', + Array<[key: BlobStringReply, timeBucket: NumberReply, aggregationType: TimeSeriesAggregationType]> +]; -// export const IS_READ_ONLY = true; +export interface InfoReply { + totalSamples: NumberReply; + memoryUsage: NumberReply; + firstTimestamp: NumberReply; + lastTimestamp: NumberReply; + retentionTime: NumberReply; + chunkCount: NumberReply; + chunkSize: NumberReply; + chunkType: SimpleStringReply; + duplicatePolicy: TimeSeriesDuplicatePolicies | null; + labels: Array<{ + name: BlobStringReply; + value: BlobStringReply; + }>; + sourceKey: BlobStringReply | null; + rules: Array<{ + key: BlobStringReply; + timeBucket: NumberReply; + aggregationType: TimeSeriesAggregationType + }>; +} -// export function transformArguments(key: string): Array { -// return ['TS.INFO', key]; -// } - -// export type InfoRawReply = [ -// 'totalSamples', -// number, -// 'memoryUsage', -// number, -// 'firstTimestamp', -// number, -// 'lastTimestamp', -// number, -// 'retentionTime', -// number, -// 'chunkCount', -// number, -// 'chunkSize', -// number, -// 'chunkType', -// string, -// 'duplicatePolicy', -// TimeSeriesDuplicatePolicies | null, -// 'labels', -// Array<[name: string, value: string]>, -// 'sourceKey', -// string | null, -// 'rules', -// Array<[key: string, timeBucket: number, aggregationType: TimeSeriesAggregationType]> -// ]; - -// export interface InfoReply { -// totalSamples: number; -// memoryUsage: number; -// firstTimestamp: number; -// lastTimestamp: number; -// retentionTime: number; -// chunkCount: number; -// chunkSize: number; -// chunkType: string; -// duplicatePolicy: TimeSeriesDuplicatePolicies | null; -// labels: Array<{ -// name: string; -// value: string; -// }>; -// sourceKey: string | null; -// rules: Array<{ -// key: string; -// timeBucket: number; -// aggregationType: TimeSeriesAggregationType -// }>; -// } - -// export function transformReply(reply: InfoRawReply): InfoReply { -// return { -// totalSamples: reply[1], -// memoryUsage: reply[3], -// firstTimestamp: reply[5], -// lastTimestamp: reply[7], -// retentionTime: reply[9], -// chunkCount: reply[11], -// chunkSize: reply[13], -// chunkType: reply[15], -// duplicatePolicy: reply[17], -// labels: reply[19].map(([name, value]) => ({ -// name, -// value -// })), -// sourceKey: reply[21], -// rules: reply[23].map(([key, timeBucket, aggregationType]) => ({ -// key, -// timeBucket, -// aggregationType -// })) -// }; -// } +export default { + FIRST_KEY_INDEX: 1, + IS_READ_ONLY: true, + transformArguments(key: string) { + return ['TS.INFO', key]; + }, + transformReply: { + 2: (reply: InfoRawReply): InfoReply => { + return { + totalSamples: reply[1], + memoryUsage: reply[3], + firstTimestamp: reply[5], + lastTimestamp: reply[7], + retentionTime: reply[9], + chunkCount: reply[11], + chunkSize: reply[13], + chunkType: reply[15], + duplicatePolicy: reply[17], + labels: reply[19].map(([name, value]) => ({ + name, + value + })), + sourceKey: reply[21], + rules: reply[23].map(([key, timeBucket, aggregationType]) => ({ + key, + timeBucket, + aggregationType + })) + }; + }, + 3: undefined as unknown as () => InfoReply + } + } as const satisfies Command; \ No newline at end of file diff --git a/packages/time-series/lib/commands/INFO_DEBUG.ts b/packages/time-series/lib/commands/INFO_DEBUG.ts index f781593b1e6..5fa162029f5 100644 --- a/packages/time-series/lib/commands/INFO_DEBUG.ts +++ b/packages/time-series/lib/commands/INFO_DEBUG.ts @@ -1,57 +1,58 @@ -// import { -// transformArguments as transformInfoArguments, -// InfoRawReply, -// InfoReply, -// transformReply as transformInfoReply -// } from './INFO'; +import { BlobStringReply, Command, NumberReply, SimpleStringReply } from "@redis/client/dist/lib/RESP/types"; +import INFO, { InfoRawReply, InfoReply } from "./INFO"; -// export { IS_READ_ONLY, FIRST_KEY_INDEX } from './INFO'; +type InfoDebugRawReply = [ + ...InfoRawReply, + 'keySelfName', + BlobStringReply, + 'chunks', + Array<[ + 'startTimestamp', + NumberReply, + 'endTimestamp', + NumberReply, + 'samples', + NumberReply, + 'size', + NumberReply, + 'bytesPerSample', + SimpleStringReply + ]> +]; -// export function transformArguments(key: string): Array { -// const args = transformInfoArguments(key); -// args.push('DEBUG'); -// return args; -// } +interface InfoDebugReply extends InfoReply { + keySelfName: BlobStringReply, + chunks: Array<{ + startTimestamp: NumberReply; + endTimestamp: NumberReply; + samples: NumberReply; + size: NumberReply; + bytesPerSample: SimpleStringReply; + }>; +} -// type InfoDebugRawReply = [ -// ...InfoRawReply, -// 'keySelfName', -// string, -// 'chunks', -// Array<[ -// 'startTimestamp', -// number, -// 'endTimestamp', -// number, -// 'samples', -// number, -// 'size', -// number, -// 'bytesPerSample', -// string -// ]> -// ]; -// interface InfoDebugReply extends InfoReply { -// keySelfName: string; -// chunks: Array<{ -// startTimestamp: number; -// endTimestamp: number; -// samples: number; -// size: number; -// bytesPerSample: string; -// }>; -// } - -// export function transformReply(rawReply: InfoDebugRawReply): InfoDebugReply { -// const reply = transformInfoReply(rawReply as unknown as InfoRawReply); -// (reply as InfoDebugReply).keySelfName = rawReply[25]; -// (reply as InfoDebugReply).chunks = rawReply[27].map(chunk => ({ -// startTimestamp: chunk[1], -// endTimestamp: chunk[3], -// samples: chunk[5], -// size: chunk[7], -// bytesPerSample: chunk[9] -// })); -// return reply as InfoDebugReply; -// } +export default { + FIRST_KEY_INDEX: INFO.FIRST_KEY_INDEX, + IS_READ_ONLY: INFO.IS_READ_ONLY, + transformArguments(key: string) { + const args = INFO.transformArguments(key); + args.push('DEBUG'); + return args; + }, + transformReply: { + 2: (rawReply: InfoDebugRawReply): InfoDebugReply => { + const reply = INFO.transformReply[2](rawReply as unknown as InfoRawReply); + (reply as InfoDebugReply).keySelfName = rawReply[25]; + (reply as InfoDebugReply).chunks = rawReply[27].map(chunk => ({ + startTimestamp: chunk[1], + endTimestamp: chunk[3], + samples: chunk[5], + size: chunk[7], + bytesPerSample: chunk[9] + })); + return reply as InfoDebugReply; + }, + 3: undefined as unknown as () => InfoDebugReply + } + } as const satisfies Command; \ No newline at end of file diff --git a/packages/time-series/lib/commands/MGET.ts b/packages/time-series/lib/commands/MGET.ts index 861c23b1e42..23c376de3c2 100644 --- a/packages/time-series/lib/commands/MGET.ts +++ b/packages/time-series/lib/commands/MGET.ts @@ -1,5 +1,6 @@ import { CommandArguments, Command } from '@redis/client/dist/lib/RESP/types'; import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; +import { RawLabels, SampleRawReply2, SampleRawReply3, SampleReply2, SampleReply3, transformSampleReply } from '.'; export interface TsMGetOptions { LATEST?: boolean; @@ -18,6 +19,28 @@ export function pushFilterArgument(args: CommandArguments, filter: RedisVariadic return pushVariadicArguments(args, filter); } +export type MGetRawReply2 = Array<[ + key: string, + labels: RawLabels, + sample: SampleRawReply2 +]>; + +export type MGetRawReply3 = Array<[ + key: string, + labels: RawLabels, + sample: SampleRawReply3 +]>; + +export interface MGetReply2 { + key: string, + sample: SampleReply2 +} + +export interface MGetReply3 { + key: string, + sample: SampleReply3 +} + export default { FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, @@ -25,7 +48,18 @@ export default { const args = pushLatestArgument(['TS.MGET'], options?.LATEST); return pushFilterArgument(args, filter); }, - // TODO - // transformSampleReply - transformReply: undefined as unknown as () => any + transformReply: { + 2: (reply: MGetRawReply2): Array => { + return reply.map(([key, _, sample]) => ({ + key, + sample: transformSampleReply[2](sample) + })); + }, + 3: (reply: MGetRawReply3): Array => { + return reply.map(([key, _, sample]) => ({ + key, + sample: transformSampleReply[3](sample) + })); + }, + } } as const satisfies Command; diff --git a/packages/time-series/lib/commands/MGET_WITHLABELS.ts b/packages/time-series/lib/commands/MGET_WITHLABELS.ts index 273e71729b1..fe6ad2a94c5 100644 --- a/packages/time-series/lib/commands/MGET_WITHLABELS.ts +++ b/packages/time-series/lib/commands/MGET_WITHLABELS.ts @@ -1,12 +1,16 @@ -import { Command } from '@redis/client/dist/lib/RESP/types'; +import { Command, ReplyUnion } from '@redis/client/dist/lib/RESP/types'; import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; -import { TsMGetOptions, pushLatestArgument, pushFilterArgument } from './MGET'; -import { pushWithLabelsArgument } from '.'; +import { TsMGetOptions, pushLatestArgument, pushFilterArgument, MGetReply2, MGetRawReply2 } from './MGET'; +import { Labels, pushWithLabelsArgument, transformLablesReply, transformSampleReply } from '.'; export interface TsMGetWithLabelsOptions extends TsMGetOptions { SELECTED_LABELS?: RedisVariadicArgument; } +export interface MGetWithLabelsReply2 extends MGetReply2 { + labels: Labels; +}; + export default { FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, @@ -15,6 +19,15 @@ export default { args = pushWithLabelsArgument(args, options?.SELECTED_LABELS); return pushFilterArgument(args, filter); }, - // TODO - transformReply: undefined as unknown as () => any + transformReply: { + 2: (reply: MGetRawReply2): Array => { + return reply.map(([key, labels, sample]) => ({ + key, + labels: transformLablesReply(labels), + sample: transformSampleReply[2](sample) + })); + }, + 3: undefined as unknown as () => ReplyUnion + }, + unstableResp3Module: true } as const satisfies Command; diff --git a/packages/time-series/lib/commands/MRANGE.ts b/packages/time-series/lib/commands/MRANGE.ts index a3a3db8ab83..c33d68316fa 100644 --- a/packages/time-series/lib/commands/MRANGE.ts +++ b/packages/time-series/lib/commands/MRANGE.ts @@ -1,6 +1,6 @@ -import { RedisArgument, Command, CommandArguments } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, Command, CommandArguments, ReplyUnion } from '@redis/client/dist/lib/RESP/types'; import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; -import { Timestamp } from '.'; +import { RawLabels, SampleRawReply2, SampleReply2, Timestamp, transformSampleReply } from '.'; import { TsRangeOptions, pushRangeArguments } from './RANGE'; import { pushFilterArgument } from './MGET'; @@ -58,10 +58,35 @@ export function transformMRangeArguments( return pushGroupByArgument(args, options?.GROUPBY); } +export type MRangeRawReply2 = Array<[ + key: string, + labels: RawLabels, + samples: Array +]>; + +export interface MRangeReplyItem2 { + key: string; + samples: Array; +} + export default { FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments: transformMRangeArguments.bind(undefined, 'TS.MRANGE'), - // TODO - transformReply: undefined as unknown as () => any + transformReply: { + 2: (reply: MRangeRawReply2): Array => { + const args = []; + + for (const [key, _, sample] of reply) { + args.push({ + key, + samples: sample.map(transformSampleReply[2]) + }); + } + + return args; + }, + 3: undefined as unknown as () => ReplyUnion + }, + unstableResp3Module: true } as const satisfies Command; diff --git a/packages/time-series/lib/commands/MRANGE_WITHLABELS.ts b/packages/time-series/lib/commands/MRANGE_WITHLABELS.ts index 9336626ab4d..98286f32b25 100644 --- a/packages/time-series/lib/commands/MRANGE_WITHLABELS.ts +++ b/packages/time-series/lib/commands/MRANGE_WITHLABELS.ts @@ -1,7 +1,7 @@ -import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types'; +import { RedisArgument, Command, ReplyUnion } from '@redis/client/dist/lib/RESP/types'; import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; -import { TsMRangeOptions, pushGroupByArgument } from './MRANGE'; -import { Timestamp, pushWithLabelsArgument } from '.'; +import { MRangeRawReply2, MRangeReplyItem2, TsMRangeOptions, pushGroupByArgument } from './MRANGE'; +import { Labels, Timestamp, pushWithLabelsArgument, transformLablesReply, transformSampleReply } from '.'; import { pushFilterArgument } from './MGET'; import { pushRangeArguments } from './RANGE'; @@ -22,10 +22,29 @@ export function transformMRangeWithLabelsArguments( return pushGroupByArgument(args, options?.GROUPBY); } +export interface MRangeWithLabelsReplyItem2 extends MRangeReplyItem2 { + labels: Labels; +} + export default { FIRST_KEY_INDEX: undefined, IS_READ_ONLY: true, transformArguments: transformMRangeWithLabelsArguments.bind(undefined, 'TS.MRANGE'), - // TODO - transformReply: undefined as unknown as () => any + transformReply: { + 2: (reply: MRangeRawReply2): Array => { + const args = []; + + for (const [key, labels, samples] of reply) { + args.push({ + key, + labels: transformLablesReply(labels), + samples: samples.map(transformSampleReply[2]) + }); + } + + return args; + }, + 3: undefined as unknown as () => ReplyUnion + }, + unstableResp3Module: true } as const satisfies Command; diff --git a/packages/time-series/lib/commands/MREVRANGE.ts b/packages/time-series/lib/commands/MREVRANGE.ts index c64c37118e2..1798aa94401 100644 --- a/packages/time-series/lib/commands/MREVRANGE.ts +++ b/packages/time-series/lib/commands/MREVRANGE.ts @@ -5,5 +5,6 @@ export default { FIRST_KEY_INDEX: MRANGE.FIRST_KEY_INDEX, IS_READ_ONLY: MRANGE.IS_READ_ONLY, transformArguments: transformMRangeArguments.bind(undefined, 'TS.MREVRANGE'), - transformReply: MRANGE.transformReply + transformReply: MRANGE.transformReply, + unstableResp3Module: MRANGE.unstableResp3Module } as const satisfies Command; diff --git a/packages/time-series/lib/commands/MREVRANGE_WITHLABELS.ts b/packages/time-series/lib/commands/MREVRANGE_WITHLABELS.ts index 6187ec621bb..f16f57a4cbd 100644 --- a/packages/time-series/lib/commands/MREVRANGE_WITHLABELS.ts +++ b/packages/time-series/lib/commands/MREVRANGE_WITHLABELS.ts @@ -5,5 +5,6 @@ export default { FIRST_KEY_INDEX: MRANGE_WITHLABELS.FIRST_KEY_INDEX, IS_READ_ONLY: MRANGE_WITHLABELS.IS_READ_ONLY, transformArguments: transformMRangeWithLabelsArguments.bind(undefined, 'TS.MREVRANGE'), - transformReply: MRANGE_WITHLABELS.transformReply + transformReply: MRANGE_WITHLABELS.transformReply, + unstableResp3Module: MRANGE_WITHLABELS.unstableResp3Module } as const satisfies Command; diff --git a/packages/time-series/lib/commands/RANGE.ts b/packages/time-series/lib/commands/RANGE.ts index 5f6635b3b3d..b939090853c 100644 --- a/packages/time-series/lib/commands/RANGE.ts +++ b/packages/time-series/lib/commands/RANGE.ts @@ -1,5 +1,5 @@ import { CommandArguments, RedisArgument, ArrayReply, UnwrapReply, Command } from '@redis/client/dist/lib/RESP/types'; -import { Timestamp, transformTimestampArgument, SampleRawReply, transformSampleReply } from '.'; +import { Timestamp, transformTimestampArgument, transformSampleReply, SampleRawReply2, SampleRawReply3 } from '.'; import { TimeSeriesAggregationType } from './CREATERULE'; export const TIME_SERIES_BUCKET_TIMESTAMP = { @@ -108,10 +108,10 @@ export default { IS_READ_ONLY: true, transformArguments: transformRangeArguments.bind(undefined, 'TS.RANGE'), transformReply: { - 2(reply: UnwrapReply>) { + 2(reply: UnwrapReply>) { return reply.map(sample => transformSampleReply['2'](sample)); }, - 3(reply: UnwrapReply>) { + 3(reply: UnwrapReply>) { return reply.map(sample => transformSampleReply['3'](sample)); } } diff --git a/packages/time-series/lib/commands/index.ts b/packages/time-series/lib/commands/index.ts index e9137a15a00..eb9f4cb90a9 100644 --- a/packages/time-series/lib/commands/index.ts +++ b/packages/time-series/lib/commands/index.ts @@ -1,4 +1,4 @@ -import type { BlobStringReply, CommandArguments, DoubleReply, NumberReply, RedisArgument, RedisCommands, TuplesReply, UnwrapReply } from '@redis/client/dist/lib/RESP/types'; +import type { BlobStringReply, CommandArguments, DoubleReply, NumberReply, RedisArgument, RedisCommands } from '@redis/client/dist/lib/RESP/types'; import ADD from './ADD'; import ALTER from './ALTER'; import CREATE from './CREATE'; @@ -121,6 +121,8 @@ export function transformTimestampArgument(timestamp: Timestamp): string { ).toString(); } +export type RawLabels = Array<[label: string, value: string]>; + export type Labels = { [label: string]: string; }; @@ -137,28 +139,51 @@ export function pushLabelsArgument(args: Array, labels?: Labels) return args; } -export type SampleRawReply = { - 2: TuplesReply<[timestamp: NumberReply, value: BlobStringReply]>; - 3: TuplesReply<[timestamp: NumberReply, value: DoubleReply]>; +export interface SampleRawReply2 { + timestamp: NumberReply; + value: BlobStringReply; }; +export interface SampleRawReply3 { + timestamp: NumberReply + value: DoubleReply +} + +export interface SampleReply2 { + timestamp: NumberReply; + value: number; +} + +export interface SampleReply3 { + timestamp: NumberReply; + value: DoubleReply; +} + export const transformSampleReply = { - 2(reply: SampleRawReply[2]) { - const [timestamp, value] = reply as unknown as UnwrapReply; + 2(reply: SampleRawReply2): SampleReply2 { return { - timestamp, - value: Number(value) + timestamp: reply.timestamp, + value: Number(reply.value) }; }, - 3(reply: SampleRawReply[3]) { - const [timestamp, value] = reply as unknown as UnwrapReply; + 3(reply: SampleRawReply3): SampleReply3 { return { - timestamp, - value + timestamp: reply.timestamp, + value: reply.value }; } }; +export function transformLablesReply(reply: RawLabels): Labels { + const labels: Labels = {}; + + for (const [key, value] of reply) { + labels[key] = value; + } + + return labels +} + export function pushWithLabelsArgument(args: CommandArguments, selectedLabels?: RedisVariadicArgument) { if (!selectedLabels) { args.push('WITHLABELS');