export type RedisCallback = (error: Error | null, result: T) => void; /** * A minimal subset of the callback interface that is implemented by several Redis * clients. */ export interface CompatibleCallbackRedisClient { get(key: string, callback?: RedisCallback): unknown; set(key: string, value: string, callback?: RedisCallback): unknown; set( key: string, value: string, expiryMode: 'PX', time: number, callback?: RedisCallback ): unknown; del(key: string, callback?: RedisCallback): unknown; on?(event: 'error', callback?: (error: Error) => unknown): unknown; sadd(key: string, member: string, callback?: RedisCallback): unknown; srem(key: string, member: string, callback?: RedisCallback): unknown; smembers(key: string, callback?: RedisCallback): unknown; sismember(key: string, member: string, callback?: RedisCallback): unknown; } /** * A minimal subset of the Promise interface that is implemented by several Redis clients. */ export interface CompatiblePromiseRedisClient { get(key: string): PromiseLike; set(key: string, value: string): PromiseLike; set(key: string, value: string, expiryMode: 'PX', time: number): PromiseLike; del(key: string): PromiseLike; on?(event: 'error', callback: (error: Error) => unknown): unknown; sadd(key: string, member: string): PromiseLike; srem(key: string, member: string): PromiseLike; smembers(key: string): PromiseLike; sismember(key: string, member: string): PromiseLike; } /** * A minimal subset of the Promise interface that is implemented by the “modern” * node-redis version 4. */ export interface CompatibleNodeRedisV4Client { get(key: string): Promise; GET(key: string): Promise; set(key: string, value: string, options?: { PX: number }): Promise; SET(key: string, value: string, options?: { PX: number }): Promise; del(key: string): Promise; DEL(key: string): Promise; on?(event: 'error', callback: (error: Error) => unknown): unknown; SADD(key: string, member: string): Promise; SREM(key: string, member: string): Promise; SMEMBERS(key: string): Promise; SISMEMBER(key: string, member: string): Promise; } export type CompatibleRedisClient = | CompatibleCallbackRedisClient | CompatiblePromiseRedisClient | CompatibleNodeRedisV4Client; function isPromiseClient( client: CompatibleRedisClient ): client is CompatiblePromiseRedisClient { const result = client.get('hello'); if (typeof (result as PromiseLike)?.then === 'function') { (result as PromiseLike).then( // Handle fulfilled and rejected callbacks (prevent unhandled Promise rejection) () => { // Nothing }, error => { console.error(error); } ); return true; } return false; } export function isCompatiblePromiseRedisClient( client: CompatibleRedisClient ): client is CompatiblePromiseRedisClient { // It must have lowercase methods for (const method of ['get', 'set', 'del', 'sadd', 'srem', 'smembers']) { if (!(method in client)) { return false; } } return isPromiseClient(client); } export function isCompatibleNodeRedisV4Client( client: CompatibleRedisClient ): client is CompatibleNodeRedisV4Client { // It must have uppercase methods for (const method of [ 'GET', 'get', 'SET', 'set', 'DEL', 'del', 'SADD', 'SREM', 'SMEMBERS', 'SISMEMBER' ]) { if (!(method in client)) { return false; } } return isPromiseClient(client); }