You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-09 00:22:08 +03:00
* update workflows & README
* add .deepsource.toml
* fix client.quit, add error events on cluster, fix some "deepsource.io" warnings
* Release 4.0.0-rc.1
* add cluster.duplicate, add some tests
* fix #1650 - add support for Buffer in some commands, add GET_BUFFER command
* fix GET and GET_BUFFER return type
* update FAQ
* Update invalid code example in README.md (#1654)
* Update invalid code example in README.md
* Update README.md
Co-authored-by: Leibale Eidelman <leibale1998@gmail.com>
* fix #1652
* ref #1653 - better types
* better types
* fix 54124793ad
* Update GEOSEARCHSTORE.spec.ts
* fix #1660 - add support for client.HSET('key', 'field', 'value')
* upgrade dependencies, update README
* fix #1659 - add support for db-number in client options url
* fix README, remove unused import, downgrade typedoc & typedoc-plugin-markdown
* update client-configurations.md
* fix README
* add CLUSTER_SLOTS, add some tests
* fix "createClient with url" test with redis 5
* remove unused imports
* Release 4.0.0-rc.2
* add missing semicolon
* replace empty "transformReply" functions with typescript "declare"
* fix EVAL & EVALSHA, add some tests, npm update
* fix #1665 - add ZRANGEBYLEX, ZRANGEBYSCORE, ZRANGEBYSCORE_WITHSCORES
* new issue templates
* add all COMMAND commands
* run COMMAND & COMMAND INFO tests only on redis >6
* Create SECURITY.md
* fix #1671 - add support for all client configurations in cluster
* ref #1671 - add support for defaults
* remove some commands from cluster, npm update, clean code,
* lock benny version
* fix #1674 - remove `isolationPoolOptions` when creating isolated connection
* increase test coverage
* update .npmignore
* Release 4.0.0-rc.3
Co-authored-by: Richard Samuelsson <noobtoothfairy@gmail.com>
116 lines
3.7 KiB
TypeScript
116 lines
3.7 KiB
TypeScript
|
|
import { CommandOptions, isCommandOptions } from './command-options';
|
|
import { RedisCommand, RedisCommandArguments, RedisCommandRawReply, RedisCommandReply, RedisCommands, RedisModules, RedisScript, RedisScripts } from './commands';
|
|
|
|
type Instantiable<T = any> = new(...args: Array<any>) => T;
|
|
|
|
interface ExtendWithCommandsConfig<T extends Instantiable> {
|
|
BaseClass: T;
|
|
commands: RedisCommands;
|
|
executor(command: RedisCommand, args: Array<unknown>): unknown;
|
|
}
|
|
|
|
export function extendWithCommands<T extends Instantiable>({ BaseClass, commands, executor }: ExtendWithCommandsConfig<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> {
|
|
BaseClass: T;
|
|
modules?: RedisModules;
|
|
modulesCommandsExecutor(this: InstanceType<T>, command: RedisCommand, args: Array<unknown>): unknown;
|
|
scripts?: RedisScripts;
|
|
scriptsExecutor(this: InstanceType<T>, script: RedisScript, args: Array<unknown>): unknown;
|
|
}
|
|
|
|
export function extendWithModulesAndScripts<T extends Instantiable>(config: ExtendWithModulesAndScriptsConfig<T>): T {
|
|
let Commander: T | undefined;
|
|
|
|
if (config.modules) {
|
|
Commander = class extends config.BaseClass {
|
|
constructor(...args: Array<any>) {
|
|
super(...args);
|
|
|
|
for (const module of Object.keys(config.modules!)) {
|
|
this[module] = new this[module](this);
|
|
}
|
|
}
|
|
};
|
|
|
|
for (const [moduleName, module] of Object.entries(config.modules)) {
|
|
Commander.prototype[moduleName] = class {
|
|
readonly self: T;
|
|
|
|
constructor(self: InstanceType<T>) {
|
|
this.self = self;
|
|
}
|
|
};
|
|
|
|
for (const [commandName, command] of Object.entries(module)) {
|
|
Commander.prototype[moduleName].prototype[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: RedisCommandArguments;
|
|
options: CommandOptions<T> | undefined;
|
|
} {
|
|
let options;
|
|
if (isCommandOptions<T>(args[0])) {
|
|
options = args[0];
|
|
args = args.slice(1);
|
|
}
|
|
|
|
return {
|
|
args: command.transformArguments(...args),
|
|
options
|
|
};
|
|
}
|
|
|
|
const DELIMITER = '\r\n';
|
|
|
|
export function* encodeCommand(args: RedisCommandArguments): IterableIterator<string | Buffer> {
|
|
yield `*${args.length}${DELIMITER}`;
|
|
|
|
for (const arg of args) {
|
|
const byteLength = typeof arg === 'string' ? Buffer.byteLength(arg): arg.length;
|
|
yield `$${byteLength.toString()}${DELIMITER}`;
|
|
yield arg;
|
|
yield DELIMITER;
|
|
}
|
|
}
|
|
|
|
export function transformCommandReply(
|
|
command: RedisCommand,
|
|
rawReply: RedisCommandRawReply,
|
|
preserved: unknown
|
|
): RedisCommandReply<typeof command> {
|
|
if (!command.transformReply) {
|
|
return rawReply;
|
|
}
|
|
|
|
return command.transformReply(rawReply, preserved);
|
|
}
|