You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-01 16:46:54 +03:00
As per the docs, unstableResp3 commands should throw when client is created with { RESP: 3, unstableResp3: false|undefined } fixes #2989
129 lines
3.8 KiB
TypeScript
129 lines
3.8 KiB
TypeScript
import { Command, CommanderConfig, RedisArgument, RedisCommands, RedisFunction, RedisFunctions, RedisModules, RedisScript, RedisScripts, RespVersions, TransformReply } from './RESP/types';
|
|
|
|
interface AttachConfigOptions<
|
|
M extends RedisModules,
|
|
F extends RedisFunctions,
|
|
S extends RedisScripts,
|
|
RESP extends RespVersions
|
|
> {
|
|
BaseClass: new (...args: any) => any;
|
|
commands: RedisCommands;
|
|
createCommand(command: Command, resp: RespVersions): (...args: any) => any;
|
|
createModuleCommand(command: Command, resp: RespVersions): (...args: any) => any;
|
|
createFunctionCommand(name: string, fn: RedisFunction, resp: RespVersions): (...args: any) => any;
|
|
createScriptCommand(script: RedisScript, resp: RespVersions): (...args: any) => any;
|
|
config?: CommanderConfig<M, F, S, RESP>;
|
|
}
|
|
|
|
/* FIXME: better error message / link */
|
|
function throwResp3SearchModuleUnstableError() {
|
|
throw new Error('Some RESP3 results for Redis Query Engine responses may change. Refer to the readme for guidance');
|
|
}
|
|
|
|
export function attachConfig<
|
|
M extends RedisModules,
|
|
F extends RedisFunctions,
|
|
S extends RedisScripts,
|
|
RESP extends RespVersions
|
|
>({
|
|
BaseClass,
|
|
commands,
|
|
createCommand,
|
|
createModuleCommand,
|
|
createFunctionCommand,
|
|
createScriptCommand,
|
|
config
|
|
}: AttachConfigOptions<M, F, S, RESP>) {
|
|
const RESP = config?.RESP ?? 2,
|
|
Class: any = class extends BaseClass {};
|
|
|
|
for (const [name, command] of Object.entries(commands)) {
|
|
if (config?.RESP == 3 && command.unstableResp3 && !config.unstableResp3) {
|
|
Class.prototype[name] = throwResp3SearchModuleUnstableError;
|
|
} else {
|
|
Class.prototype[name] = createCommand(command, RESP);
|
|
}
|
|
}
|
|
|
|
if (config?.modules) {
|
|
for (const [moduleName, module] of Object.entries(config.modules)) {
|
|
const fns = Object.create(null);
|
|
for (const [name, command] of Object.entries(module)) {
|
|
if (config.RESP == 3 && command.unstableResp3 && !config.unstableResp3) {
|
|
fns[name] = throwResp3SearchModuleUnstableError;
|
|
} else {
|
|
fns[name] = createModuleCommand(command, RESP);
|
|
}
|
|
}
|
|
|
|
attachNamespace(Class.prototype, moduleName, fns);
|
|
}
|
|
}
|
|
|
|
if (config?.functions) {
|
|
for (const [library, commands] of Object.entries(config.functions)) {
|
|
const fns = Object.create(null);
|
|
for (const [name, command] of Object.entries(commands)) {
|
|
fns[name] = createFunctionCommand(name, command, RESP);
|
|
}
|
|
|
|
attachNamespace(Class.prototype, library, fns);
|
|
}
|
|
}
|
|
|
|
if (config?.scripts) {
|
|
for (const [name, script] of Object.entries(config.scripts)) {
|
|
Class.prototype[name] = createScriptCommand(script, RESP);
|
|
}
|
|
}
|
|
|
|
return Class;
|
|
}
|
|
|
|
function attachNamespace(prototype: any, name: PropertyKey, fns: any) {
|
|
Object.defineProperty(prototype, name, {
|
|
get() {
|
|
const value = Object.create(fns);
|
|
value._self = this;
|
|
Object.defineProperty(this, name, { value });
|
|
return value;
|
|
}
|
|
});
|
|
}
|
|
|
|
export function getTransformReply(command: Command, resp: RespVersions): TransformReply | undefined {
|
|
switch (typeof command.transformReply) {
|
|
case 'function':
|
|
return command.transformReply;
|
|
|
|
case 'object':
|
|
return command.transformReply[resp];
|
|
}
|
|
}
|
|
|
|
export function functionArgumentsPrefix(name: string, fn: RedisFunction) {
|
|
const prefix: Array<RedisArgument> = [
|
|
fn.IS_READ_ONLY ? 'FCALL_RO' : 'FCALL',
|
|
name
|
|
];
|
|
|
|
if (fn.NUMBER_OF_KEYS !== undefined) {
|
|
prefix.push(fn.NUMBER_OF_KEYS.toString());
|
|
}
|
|
|
|
return prefix;
|
|
}
|
|
|
|
export function scriptArgumentsPrefix(script: RedisScript) {
|
|
const prefix: Array<string | Buffer> = [
|
|
script.IS_READ_ONLY ? 'EVALSHA_RO' : 'EVALSHA',
|
|
script.SHA1
|
|
];
|
|
|
|
if (script.NUMBER_OF_KEYS !== undefined) {
|
|
prefix.push(script.NUMBER_OF_KEYS.toString());
|
|
}
|
|
|
|
return prefix;
|
|
}
|