diff --git a/md/Redis-todo.md b/md/Redis-todo.md index ab10ed249e..9a61439b52 100644 --- a/md/Redis-todo.md +++ b/md/Redis-todo.md @@ -10,3 +10,4 @@ `Number` -> `Boolean`: - `HSETNX` (deprecated) +- `SCRIPT EXISTS` diff --git a/md/v4-to-v5.md b/md/v4-to-v5.md index c04b54a373..218141b463 100644 --- a/md/v4-to-v5.md +++ b/md/v4-to-v5.md @@ -68,6 +68,7 @@ Some command arguments/replies have changed to align more closely to data types - `RENAMENX`: `boolean` -> `number` [^boolean-to-number] - `HSCAN`: `tuples` has been renamed to `entries` - `PFADD`: `boolean` -> `number` [^boolean-to-number] +- `SCRIPT EXISTS`: `Array` -> `Array` [^boolean-to-number] [^enum-to-constants]: TODO diff --git a/packages/client/lib/client/multi-command.ts b/packages/client/lib/client/multi-command.ts index d1842e8e61..b52190c10a 100644 --- a/packages/client/lib/client/multi-command.ts +++ b/packages/client/lib/client/multi-command.ts @@ -1,6 +1,6 @@ import COMMANDS from '../commands'; import RedisMultiCommand, { RedisMultiQueuedCommand } from '../multi-command'; -import { ReplyWithFlags, CommandReply, Command, CommandArguments, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TransformReply, RedisScript, RedisFunction, Flags } from '../RESP/types'; +import { ReplyWithFlags, CommandReply, Command, CommandArguments, CommanderConfig, RedisFunctions, RedisModules, RedisScripts, RespVersions, TransformReply, RedisScript, RedisFunction, Flags, ReplyUnion } from '../RESP/types'; import { attachConfig, functionArgumentsPrefix, getTransformReply } from '../commander'; type CommandSignature< @@ -83,6 +83,11 @@ export type RedisClientMultiCommandType< WithScripts ); +type ReplyType< + REPLIES, + T = 'generic' +> = T extends 'typed' ? REPLIES : Array; + export type RedisClientMultiExecutor = ( queue: Array, selectedDB?: number, @@ -216,8 +221,8 @@ export default class RedisClientMultiCommand extends RedisMultiCom select = this.SELECT; - async exec(execAsPipeline = false): Promise { - if (execAsPipeline) return this.execAsPipeline(); + async exec(execAsPipeline = false) { + if (execAsPipeline) return this.execAsPipeline(); return this.handleExecReplies( await this.#executor( @@ -225,19 +230,19 @@ export default class RedisClientMultiCommand extends RedisMultiCom this.#selectedDB, RedisMultiCommand.generateChainId() ) - ) as REPLIES; + ) as ReplyType; } EXEC = this.exec; - async execAsPipeline(): Promise { - if (this.queue.length === 0) return [] as REPLIES; + async execAsPipeline() { + if (this.queue.length === 0) return [] as ReplyType; return this.transformReplies( await this.#executor( this.queue, this.#selectedDB ) - ) as REPLIES; + ) as ReplyType; } } diff --git a/packages/client/lib/commands/FUNCTION_STATS.ts b/packages/client/lib/commands/FUNCTION_STATS.ts index eacbcc19ad..6175d7775e 100644 --- a/packages/client/lib/commands/FUNCTION_STATS.ts +++ b/packages/client/lib/commands/FUNCTION_STATS.ts @@ -1,87 +1,87 @@ -// import { RedisCommandArguments } from '.'; +// // import { RedisCommandArguments } from '.'; -// export function transformArguments(): RedisCommandArguments { +// // export function transformArguments(): RedisCommandArguments { +// // return ['FUNCTION', 'STATS']; +// // } + +// // type FunctionStatsRawReply = [ +// // 'running_script', +// // null | [ +// // 'name', +// // string, +// // 'command', +// // string, +// // 'duration_ms', +// // number +// // ], +// // 'engines', +// // Array // "flat tuples" (there is no way to type that) +// // // ...[string, [ +// // // 'libraries_count', +// // // number, +// // // 'functions_count', +// // // number +// // // ]] +// // ]; + +// // interface FunctionStatsReply { +// // runningScript: null | { +// // name: string; +// // command: string; +// // durationMs: number; +// // }; +// // engines: Record; +// // } + +// // export function transformReply(reply: FunctionStatsRawReply): FunctionStatsReply { +// // const engines = Object.create(null); +// // for (let i = 0; i < reply[3].length; i++) { +// // engines[reply[3][i]] = { +// // librariesCount: reply[3][++i][1], +// // functionsCount: reply[3][i][3] +// // }; +// // } + +// // return { +// // runningScript: reply[1] === null ? null : { +// // name: reply[1][1], +// // command: reply[1][3], +// // durationMs: reply[1][5] +// // }, +// // engines +// // }; +// // } + + +// // #!LUA name=math \n redis.register_function{ function_name = "square", callback = function(keys, args) return args[1] * args[1] end, flags = { "no-writes" } } + +// import { Command, TuplesToMapReply, BlobStringReply, NullReply, NumberReply, MapReply } from '../RESP/types'; + +// type FunctionStatsReply = TuplesToMapReply<[ +// [BlobStringReply<'running_script'>, NullReply | TuplesToMapReply<[ +// [BlobStringReply<'name'>, BlobStringReply], +// [BlobStringReply<'command'>, BlobStringReply], +// [BlobStringReply<'duration_ms'>, NumberReply] +// ]>], +// [BlobStringReply<'engines'>, MapReply, NumberReply], +// [BlobStringReply<'functions_count'>, NumberReply] +// ]>>] +// ]>; + +// export default { +// IS_READ_ONLY: true, +// FIRST_KEY_INDEX: undefined, +// transformArguments() { // return ['FUNCTION', 'STATS']; -// } +// }, +// transformReply: { +// 2: (reply) => { -// type FunctionStatsRawReply = [ -// 'running_script', -// null | [ -// 'name', -// string, -// 'command', -// string, -// 'duration_ms', -// number -// ], -// 'engines', -// Array // "flat tuples" (there is no way to type that) -// // ...[string, [ -// // 'libraries_count', -// // number, -// // 'functions_count', -// // number -// // ]] -// ]; - -// interface FunctionStatsReply { -// runningScript: null | { -// name: string; -// command: string; -// durationMs: number; -// }; -// engines: Record; -// } - -// export function transformReply(reply: FunctionStatsRawReply): FunctionStatsReply { -// const engines = Object.create(null); -// for (let i = 0; i < reply[3].length; i++) { -// engines[reply[3][i]] = { -// librariesCount: reply[3][++i][1], -// functionsCount: reply[3][i][3] -// }; -// } - -// return { -// runningScript: reply[1] === null ? null : { -// name: reply[1][1], -// command: reply[1][3], -// durationMs: reply[1][5] -// }, -// engines -// }; -// } - - -// #!LUA name=math \n redis.register_function{ function_name = "square", callback = function(keys, args) return args[1] * args[1] end, flags = { "no-writes" } } - -import { Command, TuplesToMapReply, BlobStringReply, NullReply, NumberReply, MapReply } from '../RESP/types'; - -type FunctionStatsReply = TuplesToMapReply<[ - [BlobStringReply<'running_script'>, NullReply | TuplesToMapReply<[ - [BlobStringReply<'name'>, BlobStringReply], - [BlobStringReply<'command'>, BlobStringReply], - [BlobStringReply<'duration_ms'>, NumberReply] - ]>], - [BlobStringReply<'engines'>, MapReply, NumberReply], - [BlobStringReply<'functions_count'>, NumberReply] - ]>>] -]>; - -export default { - IS_READ_ONLY: true, - FIRST_KEY_INDEX: undefined, - transformArguments() { - return ['FUNCTION', 'STATS']; - }, - transformReply: { - 2: (reply) => { - - }, - 3: undefined as unknown as () => - } -} as const satisfies Command; +// }, +// 3: undefined as unknown as () => +// } +// } as const satisfies Command; diff --git a/packages/client/lib/commands/RESTORE-ASKING.ts b/packages/client/lib/commands/RESTORE-ASKING.ts index d53d8541cd..f9cb75ab3c 100644 --- a/packages/client/lib/commands/RESTORE-ASKING.ts +++ b/packages/client/lib/commands/RESTORE-ASKING.ts @@ -1,5 +1,10 @@ -export function transformArguments(): Array { - return ['RESTORE-ASKING']; -} +import { SimpleStringReply, Command } from '../RESP/types'; -export declare function transformReply(): string; +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments() { + return ['RESTORE-ASKING']; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SAVE.ts b/packages/client/lib/commands/SAVE.ts index 3d75c29df9..53cb248696 100644 --- a/packages/client/lib/commands/SAVE.ts +++ b/packages/client/lib/commands/SAVE.ts @@ -1,7 +1,10 @@ -import { RedisCommandArgument } from '.'; +import { SimpleStringReply, Command } from '../RESP/types'; -export function transformArguments(): Array { +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments() { return ['SAVE']; -} - -export declare function transformReply(): RedisCommandArgument; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SCRIPT_DEBUG.ts b/packages/client/lib/commands/SCRIPT_DEBUG.ts index e9e1e909d5..8c0021382d 100644 --- a/packages/client/lib/commands/SCRIPT_DEBUG.ts +++ b/packages/client/lib/commands/SCRIPT_DEBUG.ts @@ -1,5 +1,10 @@ -export function transformArguments(mode: 'YES' | 'SYNC' | 'NO'): Array { - return ['SCRIPT', 'DEBUG', mode]; -} +import { SimpleStringReply, Command } from '../RESP/types'; -export declare function transformReply(): string; +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments(mode: 'YES' | 'SYNC' | 'NO') { + return ['SCRIPT', 'DEBUG', mode]; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SCRIPT_EXISTS.ts b/packages/client/lib/commands/SCRIPT_EXISTS.ts index 72123806e8..4233f7dc22 100644 --- a/packages/client/lib/commands/SCRIPT_EXISTS.ts +++ b/packages/client/lib/commands/SCRIPT_EXISTS.ts @@ -1,8 +1,11 @@ -import { RedisCommandArguments } from '.'; +import { RedisArgument, ArrayReply, NumberReply, Command } from '../RESP/types'; import { pushVariadicArguments } from './generic-transformers'; -export function transformArguments(sha1: string | Array): RedisCommandArguments { +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments(sha1: RedisArgument | Array) { return pushVariadicArguments(['SCRIPT', 'EXISTS'], sha1); -} - -export { transformBooleanArrayReply as transformReply } from './generic-transformers'; + }, + transformReply: undefined as unknown as () => ArrayReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SCRIPT_FLUSH.ts b/packages/client/lib/commands/SCRIPT_FLUSH.ts index 2c220e9e3d..a6bfe7648c 100644 --- a/packages/client/lib/commands/SCRIPT_FLUSH.ts +++ b/packages/client/lib/commands/SCRIPT_FLUSH.ts @@ -1,11 +1,16 @@ -export function transformArguments(mode?: 'ASYNC' | 'SYNC'): Array { +import { SimpleStringReply, Command } from '../RESP/types'; + +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments(mode?: 'ASYNC' | 'SYNC') { const args = ['SCRIPT', 'FLUSH']; if (mode) { - args.push(mode); + args.push(mode); } return args; -} - -export declare function transformReply(): string; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SCRIPT_KILL.ts b/packages/client/lib/commands/SCRIPT_KILL.ts index c0a53da868..96aa119b01 100644 --- a/packages/client/lib/commands/SCRIPT_KILL.ts +++ b/packages/client/lib/commands/SCRIPT_KILL.ts @@ -1,5 +1,10 @@ -export function transformArguments(): Array { - return ['SCRIPT', 'KILL']; -} +import { SimpleStringReply, Command } from '../RESP/types'; -export declare function transformReply(): string; +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments() { + return ['SCRIPT', 'KILL']; + }, + transformReply: undefined as unknown as () => SimpleStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SCRIPT_LOAD.ts b/packages/client/lib/commands/SCRIPT_LOAD.ts index 7cb28c1ec7..758a6835ac 100644 --- a/packages/client/lib/commands/SCRIPT_LOAD.ts +++ b/packages/client/lib/commands/SCRIPT_LOAD.ts @@ -1,5 +1,10 @@ -export function transformArguments(script: string): Array { - return ['SCRIPT', 'LOAD', script]; -} +import { BlobStringReply, Command, RedisArgument } from '../RESP/types'; -export declare function transformReply(): string; +export default { + IS_READ_ONLY: true, + FIRST_KEY_INDEX: undefined, + transformArguments(script: RedisArgument) { + return ['SCRIPT', 'LOAD', script]; + }, + transformReply: undefined as unknown as () => BlobStringReply +} as const satisfies Command; diff --git a/packages/client/lib/commands/SET.ts b/packages/client/lib/commands/SET.ts index 3def49d604..f0b1efd4f0 100644 --- a/packages/client/lib/commands/SET.ts +++ b/packages/client/lib/commands/SET.ts @@ -1,6 +1,6 @@ import { RedisArgument, SimpleStringReply, BlobStringReply, NullReply, Command } from '../RESP/types'; -interface SetOptions { +export interface SetOptions { expiration?: { type: 'EX' | 'PX' | 'EXAT' | 'PXAT'; value: number; diff --git a/packages/client/lib/commands/SETBIT.ts b/packages/client/lib/commands/SETBIT.ts index 94f463330a..20c69155b0 100644 --- a/packages/client/lib/commands/SETBIT.ts +++ b/packages/client/lib/commands/SETBIT.ts @@ -1,14 +1,15 @@ -import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { RedisArgument, NumberReply, Command } from '../RESP/types'; import { BitValue } from './generic-transformers'; -export const FIRST_KEY_INDEX = 1; - -export function transformArguments( - key: RedisCommandArgument, +export default { + IS_READ_ONLY: false, + FIRST_KEY_INDEX: 1, + transformArguments( + key: RedisArgument, offset: number, value: BitValue -): RedisCommandArguments { + ) { return ['SETBIT', key, offset.toString(), value.toString()]; -} - -export declare function transformReply(): BitValue; + }, + transformReply: undefined as unknown as () => NumberReply +} as const satisfies Command;