You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-19 07:02:06 +03:00
enhance the way commanders (client/multi/cluster) get extended with modules and scripts
This commit is contained in:
88
lib/commander.ts
Normal file
88
lib/commander.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
|
||||
import COMMANDS, { RedisCommand, RedisModules, TransformArgumentsReply } from './commands';
|
||||
import { RedisLuaScript, RedisLuaScripts } from './lua-script';
|
||||
import { CommandOptions, isCommandOptions } from './command-options';
|
||||
|
||||
type Instantiable<T = any> = new(...args: Array<any>) => T;
|
||||
|
||||
type CommandExecutor<T extends Instantiable = Instantiable> = (this: InstanceType<T>, command: RedisCommand, args: Array<unknown>) => unknown;
|
||||
|
||||
export function extendWithDefaultCommands<T extends Instantiable>(BaseClass: T, executor: CommandExecutor<T>): void {
|
||||
for (const [name, command] of Object.entries(COMMANDS)) {
|
||||
BaseClass.prototype[name] = function (...args: Array<unknown>): unknown {
|
||||
return executor.call(this, command, args);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
interface ExtendWithModulesAndScriptsConfig<
|
||||
T extends Instantiable,
|
||||
M extends RedisModules,
|
||||
S extends RedisLuaScripts
|
||||
> {
|
||||
BaseClass: T;
|
||||
modules: M | undefined;
|
||||
modulesCommandsExecutor: CommandExecutor<T>;
|
||||
scripts: S | undefined;
|
||||
scriptsExecutor(this: InstanceType<T>, script: RedisLuaScript, args: Array<unknown>): unknown;
|
||||
}
|
||||
|
||||
export function extendWithModulesAndScripts<
|
||||
T extends Instantiable,
|
||||
M extends RedisModules,
|
||||
S extends RedisLuaScripts,
|
||||
>(config: ExtendWithModulesAndScriptsConfig<T, M, S>): T {
|
||||
let Commander: T | undefined,
|
||||
modulesBaseObject: Record<string, any>;
|
||||
|
||||
if (config.modules) {
|
||||
modulesBaseObject = Object.create(null);
|
||||
Commander = class extends config.BaseClass {
|
||||
constructor(...args: Array<any>) {
|
||||
super(...args);
|
||||
modulesBaseObject.self = this;
|
||||
}
|
||||
};
|
||||
|
||||
for (const [moduleName, module] of Object.entries(config.modules)) {
|
||||
Commander.prototype[moduleName] = Object.create(modulesBaseObject);
|
||||
|
||||
for (const [commandName, command] of Object.entries(module)) {
|
||||
Commander.prototype[moduleName][commandName] = function (...args: Array<unknown>): unknown {
|
||||
return config.modulesCommandsExecutor.call(this.self, command, args);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config.scripts) {
|
||||
Commander ??= class extends config.BaseClass {};
|
||||
|
||||
for (const [name, script] of Object.entries(config.scripts)) {
|
||||
Commander.prototype[name] = function (...args: Array<unknown>): unknown {
|
||||
return config.scriptsExecutor.call(this, script, args);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return (Commander ?? config.BaseClass) as any;
|
||||
}
|
||||
|
||||
export function transformCommandArguments<T = unknown>(
|
||||
command: RedisCommand,
|
||||
args: Array<unknown>
|
||||
): {
|
||||
args: TransformArgumentsReply;
|
||||
options: CommandOptions<T> | undefined;
|
||||
} {
|
||||
let options;
|
||||
if (isCommandOptions<T>(args[0])) {
|
||||
options = args[0];
|
||||
args = args.slice(1);
|
||||
}
|
||||
|
||||
return {
|
||||
args: command.transformArguments(...args),
|
||||
options
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user