Skip to main content
Module

x/redis/redis.ts

πŸ¦• Redis client for Deno πŸ•
Very Popular
Go to Latest
File
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824
type Reader = Deno.Reader;type Writer = Deno.Writer;type Closer = Deno.Closer;import { BufReader, BufWriter } from "./vendor/https/deno.land/std/io/bufio.ts";import { yellow } from "./vendor/https/deno.land/std/fmt/colors.ts";import { ConnectionClosedError } from "./errors.ts";import { psubscribe, RedisSubscription, subscribe } from "./pubsub.ts";import { RedisRawReply, sendCommand, BulkResult } from "./io.ts";import { createRedisPipeline, RedisPipeline } from "./pipeline.ts";import { deferred, Deferred } from "./vendor/https/deno.land/std/util/async.ts";export type Redis = { // Connection auth(password: string): Promise<BulkResult>; echo(message: string): Promise<BulkResult>; ping(message?: string): Promise<string>; quit(): Promise<string>; select(index: number): Promise<string>; swapdb(index: number, index2: number): Promise<string>; // Keys del(...keys: string[]): Promise<number>; dump(key: string): Promise<string>; exists(...keys: string[]): Promise<number>; expire(key: string, seconds: number): Promise<number>; expireat(key: string, timestamp: string): Promise<number>; keys(pattern: string): Promise<string[]>; migrate( host: string, port: number | string, key: string, destination_db: string, timeout: number, opts?: { copy?: boolean; replace?: boolean; keys?: string[]; } ): Promise<string>; move(key: string, db: string): Promise<number>; object_refcount(key: string): Promise<number>; object_encoding(key: string): Promise<number>; object_ideltime(key: string): Promise<number>; object_freq(key: string): Promise<BulkResult>; object_help(): Promise<BulkResult>; persist(key: string): Promise<number>; pexpire(key: string, milliseconds: number): Promise<number>; pexpireat(key: string, milliseconds_timestamp: number): Promise<number>; pttl(key: string): Promise<number>; randomkey(): Promise<string>; rename(key: string, newkey: string): Promise<string>; renamenx(key: string, newkey: string): Promise<number>; restore( key: string, ttl: number, serialized_value: string, replace?: boolean ): Promise<string>; sort( key: string, opts?: { by?: string; offset?: number; count?: number; patterns?: string[]; order: "ASC" | "DESC"; alpha?: boolean; destination?: string; } ): Promise<string[] | number>; touch(...keys: string[]): Promise<number>; ttl(key: string): Promise<number>; type(key: string): Promise<string>; unlink(...keys: string[]): Promise<number>; wait(numreplicas: number, timeout: number): Promise<number>; // String append(key: string, value: string): Promise<number>; bitcount(key: string): Promise<number>; bitcount(key: string, start: number, end: number): Promise<number>; bitfield(): Promise<string[]>; bitop( operation: "AND" | "OR" | "XOR" | "NOT", destkey: string, ...keys: string[] ): Promise<number>; bitpos( key: string, bit: number, start?: number, end?: number ): Promise<number>; decr(key: string): Promise<number>; decrby(key: string, decrement: number): Promise<number>; incr(key: string): Promise<number>; incrby(key: string, increment: number): Promise<number>; incrbyfloat(key: string, increment: number): Promise<string>; mget(...keys: string[]): Promise<string[]>; mset(key: string, value: string): Promise<string>; mset(...key_values: string[]): Promise<string>; msetnx(key: string, value: string): Promise<number>; msetnx(...key_values: string[]): Promise<number>; psetex(key: string, milliseconds: number, value: string): Promise<string>; set( key: string, value: string, opts?: { ex?: number; px?: number; mode?: "NX" | "XX"; } ): Promise<BulkResult>; setbit(key: string, offset: number, value: string): Promise<number>; setex(key: string, seconds: number, value: string): Promise<string>; setnx(key: string, value: string): Promise<number>; setrange(key: string, offset: number, value: string): Promise<number>; strlen(key: string): Promise<number>; get(key: string): Promise<BulkResult>; getbit(key: string, offset: number): Promise<number>; getrange(key: string, start: number, end: number): Promise<string>; getset(key: string, value: string): Promise<string>; // Geo geoadd( key: string, longitude: number, latitude: number, member: string ): Promise<number>; geoadd( key: string, ...longitude_latitude_member: [number | number | string][] ): Promise<number>; geohash(key: string, ...members: string[]): Promise<string[]>; geopos(key: string, ...members: string[]): Promise<string[]>; geodist( key: string, member1: string, member2: string, unit?: "m" | "km" | "ft" | "mi" ): Promise<string>; georadius( key: string, longitude: number, latitude: number, radius: number, unit: "m" | "km" | "ft" | "mi", opts?: { withCoord?: boolean; withDist?: boolean; withHash?: boolean; count?: number; sort?: "ASC" | "DESC"; store?: string; storeDist?: string; } ): Promise<string[]>; georadiusbymember( key: string, member: string, radius: number, unit: "m" | "km" | "ft" | "mi", opts?: { withCoord?: boolean; withDist?: boolean; withHash?: boolean; count?: number; sort?: "ASC" | "DESC"; store?: string; storeDist?: string; } ): Promise<string[]>; // Hash hdel(key: string, ...fields: string[]): Promise<number>; hexists(key: string, field: string): Promise<number>; hget(key: string, field: string): Promise<string>; hgetall(key: string): Promise<string[]>; hincrby(key: string, field: string, increment: number): Promise<number>; hincrbyfloat(key: string, field: string, increment: number): Promise<string>; hkeys(key: string): Promise<string[]>; hlen(key: string): Promise<number>; hmget(key: string, ...fields: string[]): Promise<string[]>; hmset(key: string, field: string, value: string): Promise<string>; hmset(key: string, ...field_values: string[]): Promise<string>; hset(key: string, field: string, value: string): Promise<number>; hsetnx(key: string, field: string, value: string): Promise<number>; hstrlen(key: string, field: string): Promise<number>; hvals(key: string): Promise<string[]>; // List blpop(key: string | string[], timeout: number): Promise<string[]>; brpop(key: string | string[], timeout: number): Promise<string[]>; brpoplpush( source: string, destination: string, timeout: number ): Promise<string>; lindex(key: string, index: number): Promise<string>; linsert( key: string, loc: "BEFORE" | "AFTER", pivot: string, value: string ): Promise<number>; llen(key: string): Promise<number>; lpop(key: string): Promise<string>; lpush(key: string, ...values: string[]): Promise<number>; lpushx(key: string, value: string): Promise<number>; lrange(key: string, start: number, stop: number): Promise<string[]>; lrem(key: string, count: number, value: string): Promise<number>; lset(key: string, index: number, value: string): Promise<string>; ltrim(key: string, start: number, stop: number): Promise<string>; rpop(key: string): Promise<string>; rpoplpush(source: string, destination: string): Promise<string>; rpush(key: string, ...values: string[]): Promise<number>; rpushx(key: string, value: string): Promise<number>; // HypeprLogLog pfadd(key: string, ...elements: string[]): Promise<number>; pfcount(...keys: string[]): Promise<number>; pfmerge(destkey: string, ...sourcekeys: string[]): Promise<string>; // PubSub publish(channel: string, message: string): Promise<number>; psubscribe(...patterns: string[]): Promise<RedisSubscription>; subscribe(...channels: string[]): Promise<RedisSubscription>; pubsub_channels(pattern: string): Promise<string[]>; pubsub_numsubs(...channels: string[]): Promise<string[]>; pubsub_numpat(): Promise<number>; // Cluster readonly(): Promise<string>; readwrite(): Promise<string>; // Set sadd(key: string, ...members: string[]): Promise<number>; scard(key: string): Promise<number>; sdiff(...keys: string[]): Promise<string[]>; sdiffstore(destination: string, ...keys: string[]): Promise<number>; sinter(...keys: string[]): Promise<string[]>; sinterstore(destination: string, ...keys: string[]): Promise<number>; sismember(key: string, member: string): Promise<number>; smembers(key: string): Promise<string[]>; smove(source: string, destination: string, member: string): Promise<number>; spop(key: string): Promise<string>; spop(key: string, count: number): Promise<string[]>; srandmember(key: string, count?: number): Promise<string>; srem(key: string, ...members: string[]): Promise<number>; sunion(...keys: string[]): Promise<string[]>; sunionstore(destination: string, ...keys: string[]): Promise<number>; // SortedSet bzpopmin(key: string | string[], timeout: number): Promise<string[]>; bzpopmax(key: string | string[], timeout: number): Promise<string[]>; zadd( key: string, score: number, member: string, opts?: { nxx?: "NX" | "XX"; ch?: boolean; incr?: boolean; } ): Promise<number>; zadd( key: string, score_members: (number | string)[], opts?: { nxx?: "NX" | "XX"; ch?: boolean; incr?: boolean; } ): Promise<number>; zcard(key: string): Promise<number>; zcount(key: string, min: number, max: number): Promise<number>; zincrby(key: string, increment: number, member: string): Promise<string>; zinterstore( destination: string, numkeys: number, keys: string | string[], weights?: number | number[], aggregate?: "SUM" | "MIN" | "MAX" ): Promise<number>; zlexcount(key: string, min: number, max: number): Promise<number>; zpopmax(key: string, count?: number): Promise<string[]>; zpopmin(key: string, count?: number): Promise<string[]>; zrange( key: string, start: number, stop: number, opts?: { withScore?: boolean; } ): Promise<string[]>; zrangebylex( key: string, min: number, max: number, opts?: { offset?: number; count?: number; } ): Promise<string[]>; zrevrangebylex( key: string, max: number, min: number, opts?: { offset?: number; count?: number; } ): Promise<string[]>; zrangebyscore( key: string, min: number, max: number, opts?: { withScore?: boolean; offset?: number; count?: number; } ): Promise<string[]>; zrank(key: string, member: string): Promise<number | undefined>; zrem(key: string, ...members: string[]): Promise<number>; zremrangebylex(key: string, min: number, max: number): Promise<number>; zremrangebyrank(key: string, start: number, stop: number): Promise<number>; zremrangebyscore(key: string, min: number, max: number): Promise<number>; zrevrange( key: string, start: number, stop: number, opts?: { withScore?: boolean; } ): Promise<string[]>; zrevrangebyscore( key: string, max: number, min: number, ops?: { withScore?: boolean; offset?: number; count?: number; } ): Promise<string[]>; zrevrank(key: string, member: string): Promise<number | undefined>; zscore(key: string, member: string): Promise<string>; zunionstore( destination: string, keys: string[], opts?: { weights?: number[]; aggregate?: "SUM" | "MIN" | "MAX"; } ): Promise<number>; // Cluster // cluster // // Server bgrewriteaof(): Promise<BulkResult>; bgsave(): Promise<BulkResult>; // client // command(): Promise<string[]>; command_count(): Promise<number>; command_getkeys(): Promise<string[]>; command_info(...command_names: string[]): Promise<string[]>; config_get(parameter: string): Promise<string[]>; config_rewrite(): Promise<BulkResult>; config_set(parameter: string, value: string): Promise<BulkResult>; config_resetstat(): Promise<BulkResult>; dbsize(): Promise<number>; debug_object(key: string): Promise<BulkResult>; debug_segfault(): Promise<BulkResult>; flushall(async?: boolean): Promise<BulkResult>; flushdb(async?: boolean): Promise<BulkResult>; info(section?: string): Promise<string>; lastsave(): Promise<number>; memory_doctor(): Promise<string>; memory_help(): Promise<string[]>; memory_malloc_stats(): Promise<string>; memory_purge(): Promise<string>; memory_stats(): Promise<string[]>; memory_usage( key: string, opts?: { samples?: number; } ): Promise<number>; monitor(): void; role(): Promise<string[]>; save(): Promise<string>; shutdown(arg: "NOSAVE" | "SAVE"): Promise<string>; slaveof(host: string, port: string | number): Promise<string>; replicaof(host: string, port: string | number): Promise<string>; slowlog(subcommand: string, ...argument: string[]): Promise<RedisRawReply>; sync(): void; time(): Promise<string[]>; // Scripting eval(script: string, key: string, arg: string): Promise<RedisRawReply>; eval(script: string, keys: string[], args: string[]): Promise<RedisRawReply>; evalsha(sha1: string, key: string, arg: string): Promise<RedisRawReply>; evalsha(sha1: string, keys: string[], args: string[]): Promise<RedisRawReply>; script_debug(arg: "YES" | "SYNC" | "NO"): Promise<string>; script_exists(...sha1s: string[]): Promise<string[]>; script_flush(): Promise<string>; script_kill(): Promise<string>; script_load(script: string): Promise<string>; // multi multi(): Promise<string>; exec(): Promise<any[]>; discard(): Promise<BulkResult>; watch(...keys: string[]): Promise<string>; unwatch(): Promise<string>; // pipeline tx(): RedisPipeline; pipeline(): RedisPipeline; // scan scan( cursor: number, opts?: { pattern?: string; count?: number; } ): Promise<string[]>; hscan( key: string, cursor: number, opts?: { pattern?: string; count?: number; } ): Promise<string[]>; sscan( key: string, cursor: number, opts?: { pattern?: string; count?: number; } ): Promise<string[]>; zscan( key: string, cursor: number, opts?: { pattern?: string; } ): Promise<string[]>;
readonly isClosed: boolean; close(): void;};
export interface CommandExecutor { execRawReply( command: string, ...args: (string | number)[] ): Promise<RedisRawReply>;}
export function muxExecutor(r: BufReader, w: BufWriter): CommandExecutor { let queue: { command: string; args: (string | number)[]; d: Deferred<RedisRawReply>; }[] = [];
function dequeue(): void { const [e] = queue; if (!e) return; sendCommand(w, r, e.command, ...e.args) .then(v => e.d.resolve(v)) .catch(err => e.d.reject(err)) .finally(() => { queue.shift(); dequeue(); }); }
return { async execRawReply( command: string, ...args: (string | number)[] ): Promise<RedisRawReply> { const d = deferred<RedisRawReply>(); queue.push({ command, args, d }); if (queue.length === 1) { dequeue(); } return d; } };}
class RedisImpl implements Redis { _isClosed = false; get isClosed() { return this._isClosed; }
private executor: CommandExecutor; constructor( private closer: Closer, private writer: BufWriter, private reader: BufReader, executor?: CommandExecutor ) { this.executor = executor || muxExecutor(reader, writer); }
async execRawReply( command: string, ...args: (string | number)[] ): Promise<RedisRawReply> { if (this.isClosed) throw new ConnectionClosedError(); return sendCommand(this.writer, this.reader, command, ...args); }
async execStatusReply( command: string, ...args: (string | number)[] ): Promise<string> { const [_, reply] = await this.executor.execRawReply(command, ...args); return reply as string; }
async execIntegerReply( command: string, ...args: (string | number)[] ): Promise<number> { const [_, reply] = await this.executor.execRawReply(command, ...args); return reply as number; }
async execBulkReply( command: string, ...args: (string | number)[] ): Promise<BulkResult> { const [_, reply] = await this.executor.execRawReply(command, ...args); // Note: `reply != null` won't work when `strict` is false #50 if (typeof reply !== "string" && typeof reply !== "undefined") { throw new Error(); } return reply; }
async execArrayReply( command: string, ...args: (string | number)[] ): Promise<any[]> { const [_, reply] = await this.executor.execRawReply(command, ...args); return reply as any[]; }
append(key: string, value: string | number) { return this.execIntegerReply("APPEND", key, value); }
auth(password: string) { return this.execBulkReply("AUTH", password); }
bgrewriteaof() { return this.execBulkReply("BGREWRITEAOF"); }
bgsave() { return this.execBulkReply("BGSAVE"); }
bitcount(key: string, start?: number, end?: number) { if (start != null && end != null) return this.execIntegerReply("BITCOUNT", key, start, end); else if (start != null) return this.execIntegerReply("BITCOUNT", key, start); else return this.execIntegerReply("BITCOUNT", key); }
bitfield() { return this.execArrayReply("BITFIELD"); }
bitop(operation: string, destkey: string, ...keys: string[]) { return this.execIntegerReply("BITOP", operation, destkey, ...keys); }
bitpos(key: string, bit: number, start?: number, end?: number) { if (start != null && end != null) { return this.execIntegerReply("BITPOS", key, bit, start, end); } else if (start != null) { return this.execIntegerReply("BITPOS", key, bit, start); } else { return this.execIntegerReply("BITPOS", key, bit); } }
blpop(keys: string[], timeout: number) { if (typeof keys === "string") { return this.execArrayReply("BLPOP", keys, timeout); } else { return this.execArrayReply("BLPOP", ...keys, timeout); } }
brpop(keys: string[], timeout: number) { if (typeof keys === "string") { return this.execArrayReply("BRPOP", keys, timeout); } else { return this.execArrayReply("BRPOP", ...keys, timeout); } }
brpoplpush(source: string, destination: string, timeout: number) { return this.execStatusReply("BRPOPLPUSH", source, destination, timeout); }
bzpopmin(keys: string[], timeout: number) { if (typeof keys === "string") { return this.execArrayReply("BZPOPMIN", keys, timeout); } else { return this.execArrayReply("BZPOPMIN", ...keys, timeout); } }
bzpopmax(keys: string[], timeout: number) { if (typeof keys === "string") { return this.execArrayReply("BZPOPMAX", keys, timeout); } else { return this.execArrayReply("BZPOPMAX", ...keys, timeout); } }
command() { return this.execArrayReply("COMMAND"); }
command_count() { return this.execIntegerReply("COMMAND", "COUNT"); }
command_getkeys() { return this.execArrayReply("COMMAND", "GETKEYS"); }
command_info(...command_names: string[]) { return this.execArrayReply("COMMAND", "INFO", ...command_names); }
config_get(parameter: string) { return this.execArrayReply("CONFIG", "GET", parameter); }
config_rewrite() { return this.execBulkReply("CONFIG", "REWRITE"); }
config_set(parameter: string, value: string | number) { return this.execBulkReply("CONFIG", "SET", parameter, value); }
config_resetstat() { return this.execBulkReply("CONFIG", "RESETSTAT"); }
dbsize() { return this.execIntegerReply("DBSIZE"); }
debug_object(key: string) { return this.execBulkReply("DEBUG", "OBJECT", key); }
debug_segfault() { return this.execBulkReply("DEBUG", "SEGFAULT"); }
decr(key: string) { return this.execIntegerReply("DECR", key); }
decrby(key: string, decrement: number) { return this.execIntegerReply("DECRBY", key, decrement); }
del(key: string, ...keys: string[]) { return this.execIntegerReply("DEL", key, ...keys); }
discard() { return this.execBulkReply("DISCARD"); }
dump(key: string) { return this.execStatusReply("DUMP", key); }
echo(message: string) { return this.execStatusReply("ECHO", message); }
eval(script: string, keys: string | string[], arg: string | string[]) { return this.doEval("EVAL", script, keys, arg); }
evalsha(sha1: string, keys: string | string[], args: string | string[]) { return this.doEval("EVALSHA", sha1, keys, args); }
private doEval( cmd: string, script: string, keys: string | string[], args: string | string[] ) { const _args = [script]; if (typeof keys === "string") { _args.push(keys); } else { _args.push(...keys); } if (typeof args === "string") { _args.push(args); } else { _args.push(...args); } return this.execRawReply(cmd, ..._args); }
exec() { return this.execArrayReply("EXEC"); }
exists(...keys: string[]) { return this.execIntegerReply("EXISTS", ...keys); }
expire(key: string, seconds: number) { return this.execIntegerReply("EXPIRE", key, seconds); }
expireat(key: string, timestamp: string) { return this.execIntegerReply("EXPIREAT", key, timestamp); }
flushall(async: boolean) { const args = async ? ["ASYNC"] : []; return this.execBulkReply("FLUSHALL", ...args); }
flushdb(async: boolean) { const args = async ? ["ASYNC"] : []; return this.execBulkReply("FLUSHDB", ...args); }
geoadd(key: string, ...args: any) { const _args = [key]; if (Array.isArray([args[0]])) { for (const triple of args) { _args.push(...triple); } } else { _args.push(...args); } return this.execIntegerReply("GEOADD", key, ..._args); }
geohash(key: string, ...members: string[]) { return this.execArrayReply("GEOHASH", key, ...members); }
geopos(key: string, ...members: string[]) { return this.execArrayReply("GEOPOS", key, ...members); }
geodist(key: string, member1: string, member2: string, unit?: string) { if (unit) return this.execStatusReply("GEODIST", key, member1, member2, unit); else return this.execStatusReply("GEODIST", key, member1, member2); }
georadius( key: string, longitude: number, latitude: number, radius: number, unit: string, opts?: { withCoord?: boolean; withDist?: boolean; withHash?: boolean; count?: number; sort?: "ASC" | "DESC"; store?: string; storeDist?: string; } ) { const args = this.pushGeoRadiusOpts( [key, longitude, latitude, radius, unit], opts ); return this.execArrayReply("GEORADIUS", ...args); }
georadiusbymember( key: string, member: string, radius: number, unit: string, opts?: { withCoord?: boolean; withDist?: boolean; withHash?: boolean; count?: number; sort?: "ASC" | "DESC"; store?: string; storeDist?: string; } ) { const args = this.pushGeoRadiusOpts([key, member, radius, unit], opts); return this.execArrayReply("GEORADIUSBYMEMBER", ...args); }
private pushGeoRadiusOpts( args: (string | number)[], opts: | { withCoord?: boolean; withDist?: boolean; withHash?: boolean; count?: number; sort?: "ASC" | "DESC"; store?: string; storeDist?: string; } | undefined ) { if (!opts) return args; if (opts.withCoord) { args.push("WITHCOORD"); } if (opts.withDist) { args.push("WITHDIST"); } if (opts.withHash) { args.push("WITHHASH"); } if (typeof opts.count === "number") { args.push(opts.count); } if (opts.sort === "ASC" || opts.sort === "DESC") { args.push(opts.sort); } if (typeof opts.store === "string") { args.push(opts.store); } if (typeof opts.storeDist === "string") { args.push(opts.storeDist); } return args; }
get(key: string) { return this.execBulkReply("GET", key); }
getbit(key: string, offset: number) { return this.execIntegerReply("GETBIT", key, offset); }
getrange(key: string, start: number, end: number) { return this.execStatusReply("GETRANGE", key, start, end); }
getset(key: string, value: string) { return this.execStatusReply("GETSET", key, value); }
hdel(key: string, field: string, ...fields: string[]) { return this.execIntegerReply("HDEL", key, field, ...fields); }
hexists(key: string, field: string) { return this.execIntegerReply("HEXISTS", key, field); }
hget(key: string, field: string) { return this.execStatusReply("HGET", key, field); }
hgetall(key: string) { return this.execArrayReply("HGETALL", key); }
hincrby(key: string, field: string, increment: number) { return this.execIntegerReply("HINCRBY", key, field, increment); }
hincrbyfloat(key: string, field: string, increment: number) { return this.execStatusReply("HINCRBYFLOAT", key, field, increment); }
hkeys(key: string) { return this.execArrayReply("HKEYS", key); }
hlen(key: string) { return this.execIntegerReply("HLEN", key); }
hmget(key: string, ...fields: string[]) { return this.execArrayReply("HMGET", key, ...fields); }
hmset(key: string, ...field_values: string[]) { return this.execStatusReply("HMSET", key, ...field_values); }
hset(key: string, field: string, value: string) { return this.execIntegerReply("HSET", key, field, value); }
hsetnx(key: string, field: string, value: string) { return this.execIntegerReply("HSETNX", key, field, value); }
hstrlen(key: string, field: string) { return this.execIntegerReply("HSTRLEN", key, field); }
hvals(key: string) { return this.execArrayReply("HVALS", key); }
incr(key: string) { return this.execIntegerReply("INCR", key); }
incrby(key: string, increment: number) { return this.execIntegerReply("INCRBY", key, increment); }
incrbyfloat(key: string, increment: number) { return this.execStatusReply("INCRBYFLOAT", key, increment); }
info(section?: string) { if (section) { return this.execStatusReply("INFO", section); } else { return this.execStatusReply("INFO"); } }
keys(pattern: string) { return this.execArrayReply("KEYS", pattern); }
lastsave() { return this.execIntegerReply("LASTSAVE"); }
lindex(key: string, index: number) { return this.execStatusReply("LINDEX", key, index); }
linsert(key: string, arg: "BEFORE" | "AFTER", pivot: string, value: string) { return this.execIntegerReply("LINSERT", key, arg); }
llen(key: string) { return this.execIntegerReply("LLEN", key); }
lpop(key: string) { return this.execStatusReply("LPOP", key); }
lpush(key: string, ...values: (string | number)[]) { return this.execIntegerReply("LPUSH", key, ...values); }
lpushx(key: string, value: string | number) { return this.execIntegerReply("LPUSHX", key, value); }
lrange(key: string, start: number, stop: number) { return this.execArrayReply("LRANGE", key, start, stop); }
lrem(key: string, count: number, value: string | number) { return this.execIntegerReply("LREM", key, count, value); }
lset(key: string, index: number, value: string | number) { return this.execStatusReply("LSET", key, index, value); }
ltrim(key: string, start: number, stop: number) { return this.execStatusReply("LTRIM", key, start, stop); }
memory_doctor() { return this.execStatusReply("MEMORY", "DOCTOR"); }
memory_help() { return this.execArrayReply("MEMORY", "HELP"); }
memory_malloc_stats() { return this.execStatusReply("MEMORY", "MALLOC", "STATS"); }
memory_purge() { return this.execStatusReply("MEMORY", "PURGE"); }
memory_stats() { return this.execArrayReply("MEMORY", "STATS"); }
memory_usage( key: string, opts?: { samples?: number; } ) { const args: (number | string)[] = [key]; if (opts && typeof opts.samples === "number") { args.push("SAMPLES", opts.samples); } return this.execIntegerReply("MEMORY", "USAGE", ...args); }
mget(...keys: string[]) { return this.execArrayReply("MGET", ...keys); }
migrate( host: string, port: number | string, key: string, destination_db: string, timeout: number, opts?: { copy?: boolean; replace?: boolean; keys?: string[]; } ) { const args = [host, port, key, destination_db, timeout]; if (opts) { if (opts.copy) { args.push("COPY"); } if (opts.replace) { args.push("REPLACE"); } if (opts.keys) { args.push("KEYS", ...opts.keys); } } return this.execStatusReply("MIGRATE", ...args); }
monitor() { throw new Error("not supported yet"); }
move(key: string, db: string) { return this.execIntegerReply("MOVE", key, db); }
mset(...key_values: string[]) { return this.execStatusReply("MSET", ...key_values); }
msetnx(...key_values: string[]) { return this.execIntegerReply("MSETNX", ...key_values); }
multi() { return this.execStatusReply("MULTI"); }
object_encoding(key: string) { return this.execIntegerReply("OBJECT", "ENCODING", key); }
object_freq(key: string) { return this.execBulkReply("OBJECT", "FREQ", key); }
object_help() { return this.execBulkReply("OBJECT", "HELP"); }
object_ideltime(key: string) { return this.execIntegerReply("OBJECT", "IDLETIME", key); }
object_refcount(key: string) { return this.execIntegerReply("OBJECT", "REFCOUNT", key); }
persist(key: string) { return this.execIntegerReply("PERSIST", key); }
pexpire(key: string, milliseconds: number) { return this.execIntegerReply("PEXPIRE", key, milliseconds); }
pexpireat(key: string, milliseconds_timestamp: number) { return this.execIntegerReply("PEXPIREAT", key, milliseconds_timestamp); }
pfadd(key: string, element: string, ...elements: string[]) { return this.execIntegerReply("PFADD", key, element, ...elements); }
pfcount(key: string, ...keys: string[]) { return this.execIntegerReply("PFCOUNT", key, ...keys); }
pfmerge(destkey: string, ...sourcekeys: string[]) { return this.execStatusReply("PFMERGE", destkey, ...sourcekeys); }
ping(message?: string) { if (message) return this.execStatusReply("PING", message); else return this.execStatusReply("PING"); }
psetex(key: string, milliseconds: number, value: string) { return this.execStatusReply("PSETEX", key, milliseconds, value); }
// PubSub
publish(channel: string, message: string) { return this.execIntegerReply("PUBLISH", channel, message); }
subscribe(...channels: string[]) { return subscribe(this.writer, this.reader, ...channels); }
psubscribe(...patterns: string[]) { return psubscribe(this.writer, this.reader, ...patterns); }
pubsub_channels(pattern: string) { return this.execArrayReply("PUBSUB", "CHANNELS", pattern); }
pubsub_numpat() { return this.execIntegerReply("PUBSUB", "NUMPAT"); }
pubsub_numsubs(...channels: string[]) { return this.execArrayReply("PUBSUB", "NUMSUBS", ...channels); }
pttl(key: string) { return this.execIntegerReply("PTTL", key); }
quit() { try { return this.execStatusReply("QUIT"); } finally { this._isClosed = true; } }
randomkey() { return this.execStatusReply("RANDOMKEY"); }
readonly() { return this.execStatusReply("READONLY"); }
readwrite() { return this.execStatusReply("READWRITE"); }
rename(key: string, newkey: string) { return this.execStatusReply("RENAME", key, newkey); }
renamenx(key: string, newkey: string) { return this.execIntegerReply("RENAMENX", key, newkey); }
restore( key: string, ttl: number, serialized_value: string, REPLACE?: boolean ) { const args = [key, ttl, serialized_value]; if (REPLACE) { args.push("REPLACE"); } return this.execStatusReply("RESTORE", ...args); }
role() { return this.execArrayReply("ROLE"); }
rpop(key: string) { return this.execStatusReply("RPOP", key); }
rpoplpush(source: string, destination: string) { return this.execStatusReply("RPOPLPUSH", source, destination); }
rpush(key: string, ...values: (string | number)[]) { return this.execIntegerReply("RPUSH", key, ...values); }
rpushx(key: string, value: string) { return this.execIntegerReply("RPUSHX", key, value); }
sadd(key: string, member: string, ...members: string[]) { return this.execIntegerReply("SADD", key, member, ...members); }
save() { return this.execStatusReply("SAVE"); }
scard(key: string) { return this.execIntegerReply("SCARD", key); }
script_debug(arg: "YES" | "SYNC" | "NO") { return this.execStatusReply("SCRIPT", "DEBUG", arg); }
script_exists(...sha1s: string[]) { return this.execArrayReply("SCRIPT", "EXISTS", ...sha1s); }
script_flush() { return this.execStatusReply("SCRIPT", "FLUSH"); }
script_kill() { return this.execStatusReply("SCRIPT", "KILL"); }
script_load(script: string) { return this.execStatusReply("SCRIPT", "LOAD", script); }
sdiff(...keys: string[]) { return this.execArrayReply("SDIFF", ...keys); }
sdiffstore(destination: string, key: string, ...keys: string[]) { return this.execIntegerReply("SDIFFSTORE", destination, key, ...keys); }
select(index: number) { return this.execStatusReply("SELECT", index); }
set( key: string, value: string, opts?: { ex?: number; px?: number; mode?: "NX" | "XX"; } ) { const args: (number | string)[] = [key, value]; if (opts) { if (opts.ex) { args.push("EX", opts.ex); } else if (opts.px) { args.push("PX", opts.px); } if (opts.mode) { args.push(opts.mode); } } return this.execBulkReply("SET", ...args); }
setbit(key: string, offset: number, value: string) { return this.execIntegerReply("SETBIT", key, offset, value); }
setex(key: string, seconds: number, value: string) { return this.execStatusReply("SETEX", key, seconds, value); }
setnx(key: string, value: string) { return this.execIntegerReply("SETNX", key, value); }
setrange(key: string, offset: number, value: string) { return this.execIntegerReply("SETRANGE", key, offset, value); }
shutdown(arg: string) { return this.execStatusReply("SHUTDOWN", arg); }
sinter(key: string, ...keys: string[]) { return this.execArrayReply("SINTER", key, ...keys); }
sinterstore(destination: string, key: string, ...keys: string[]) { return this.execIntegerReply("SINTERSTORE", destination, key, ...keys); }
sismember(key: string, member: string) { return this.execIntegerReply("SISMEMBER", key, member); }
slaveof(host: string, port: string | number) { return this.execStatusReply("SLAVEOF", host, port); }
replicaof(host: string, port: string | number) { return this.execStatusReply("REPLICAOF", host, port); }
slowlog(subcommand: string, ...argument: string[]) { return this.execRawReply("SLOWLOG", subcommand, ...argument); }
smembers(key: string) { return this.execArrayReply("SMEMBERS", key); }
smove(source: string, destination: string, member: string) { return this.execIntegerReply("SMOVE", source, destination, member); }
sort( key: string, opts?: { by?: string; offset?: number; count?: number; patterns?: string[]; order: "ASC" | "DESC"; alpha?: boolean; destination?: string; } ) { const args: (number | string)[] = [key]; if (opts) { if (opts.by) { args.push("BY", opts.by); } if (opts.offset !== void 0 && opts.count !== void 0) { args.push("LIMIT", opts.offset, opts.count); } if (opts.patterns) { for (const pat of opts.patterns) { args.push("GET", pat); } } if (opts.alpha) { args.push("ALPHA"); } if (opts.order) { args.push(opts.order); } if (opts.destination) { args.push("STORE", opts.destination); } } if (opts && opts.destination) { return this.execIntegerReply("SORT", ...args); } else { return this.execArrayReply("SORT", ...args); } }
spop(key: string): Promise<string>; spop(key: string, count: number): Promise<string[]>; spop(...args: (string | number)[]): Promise<string | string[]> { return this.execStatusReply("SPOP", ...args); }
srandmember(key: string, count?: number) { if (count != null) return this.execStatusReply("SRANDMEMBER", key, count); else return this.execStatusReply("SRANDMEMBER", key); }
srem(key: string, ...members: string[]) { return this.execIntegerReply("SREM", key, ...members); }
strlen(key: string) { return this.execIntegerReply("STRLEN", key); }
sunion(...keys: string[]) { return this.execArrayReply("SUNION", ...keys); }
sunionstore(destination: string, ...keys: string[]) { return this.execIntegerReply("SUNIONSTORE", destination, ...keys); }
swapdb(index: number, index2: number) { return this.execStatusReply("SWAPDB", index, index2); }
sync() { throw new Error("not implemented"); }
time() { return this.execArrayReply("TIME"); }
touch(...keys: string[]) { return this.execIntegerReply("TOUCH", ...keys); }
ttl(key: string) { return this.execIntegerReply("TTL", key); }
type(key: string) { return this.execStatusReply("TYPE", key); }
unlink(...keys: string[]) { return this.execIntegerReply("UNLINK", ...keys); }
unwatch() { return this.execStatusReply("UNWATCH"); }
wait(numreplicas: number, timeout: number) { return this.execIntegerReply("WAIT", numreplicas, timeout); }
watch(key: string, ...keys: string[]) { return this.execStatusReply("WATCH", key, ...keys); }
zadd(key: string, scoreOrArr: any, memberOrOpts: any, opts?: any) { const args: (string | number)[] = [key]; let _opts = opts; if (typeof scoreOrArr === "number") { args.push(scoreOrArr); args.push(memberOrOpts); } else { args.push(...scoreOrArr); _opts = memberOrOpts; } if (_opts) { if (_opts.nxx) { args.push(_opts.nxx); } if (_opts.ch) { args.push("CH"); } if (_opts.incr) { args.push("INCR"); } } return this.execIntegerReply("ZADD", ...args); }
zcard(key: string) { return this.execIntegerReply("ZCARD", key); }
zcount(key: string, min: number, max: number) { return this.execIntegerReply("ZCOUNT", key, min, max); }
zincrby(key: string, increment: number, member: string) { return this.execStatusReply("ZINCRBY", key, increment, member); }
zinterstore( destination: string, numkeys: number, keys: string[], weights?: number | number[], aggregate?: string ) { const args = this.pushZInterStoreArgs( [destination, numkeys], keys, weights, aggregate ); return this.execIntegerReply("ZINTERSTORE", ...args); }
zunionstore( destination: string, keys: string[], opts?: { weights?: number[]; aggregate?: "SUM" | "MIN" | "MAX"; } ): Promise<number> { const args: (string | number)[] = [destination, keys.length, ...keys]; if (opts) { if (opts.weights) { args.push("WEIGHTS", ...opts.weights); } if (opts.aggregate) { args.push("AGGREGATE", opts.aggregate); } } return this.execIntegerReply("ZUNIONSTORE", ...args); }
private pushZInterStoreArgs( args: (number | string)[], keys: string | string[], weights?: number | number[], aggregate?: string ) { if (typeof keys === "string") { args.push(keys); } else { args.push(...keys); } if (weights) { args.push("WEIGHTS"); if (typeof weights === "number") { args.push(weights); } else { args.push(...weights); } } if (aggregate) { args.push("AGGREGATE"); args.push(aggregate); } return args; }
zlexcount(key: string, min: number, max: number) { return this.execIntegerReply("ZLEXCOUNT", key, min, max); }
zpopmax(key: string, count?: number) { if (count != null) return this.execArrayReply("ZPOPMAX", key, count); else return this.execArrayReply("ZPOPMAX", key); }
zpopmin(key: string, count?: number) { if (count != null) return this.execArrayReply("ZPOPMIN", key, count); else return this.execArrayReply("ZPOPMIN", key); }
zrange( key: string, start: number, stop: number, opts?: { withScore?: boolean; } ) { const args = this.pushZrangeOpts([key, start, stop], opts); return this.execArrayReply("ZRANGE", ...args); }
zrangebylex( key: string, min: number, max: number, opts?: { withScore?: boolean; count?: number; } ) { const args = this.pushZrangeOpts([key, min, max], opts); return this.execArrayReply("ZRANGEBYLEX", ...args); }
zrevrangebylex( key: string, max: number, min: number, opts?: { withScore?: boolean; count?: number; } ) { const args = this.pushZrangeOpts([key, min, max], opts); return this.execArrayReply("ZREVRANGEBYLEX", ...args); }
zrangebyscore( key: string, min: number, max: number, opts?: { withScore?: boolean; count?: number; } ) { const args = this.pushZrangeOpts([key, min, max], opts); return this.execArrayReply("ZRANGEBYSCORE", ...args); }
private pushZrangeOpts( args: (number | string)[], opts?: { withScore?: boolean; offset?: number; count?: number; } ) { if (opts) { if (opts.withScore) { args.push("WITHSCORES"); } if (opts.offset !== void 0 && opts.count !== void 0) { args.push("LIMIT", opts.offset, opts.count); } } return args; }
zrank(key: string, member: string) { return this.execIntegerReply("ZRANK", key, member); }
zrem(key: string, ...members: string[]) { return this.execIntegerReply("ZREM", key, ...members); }
zremrangebylex(key: string, min: number, max: number) { return this.execIntegerReply("ZREMRANGEBYLEX", key, min, max); }
zremrangebyrank(key: string, start: number, stop: number) { return this.execIntegerReply("ZREMRANGEBYRANK", key, start, stop); }
zremrangebyscore(key: string, min: number, max: number) { return this.execIntegerReply("ZREMRANGEBYSCORE", key, min, max); }
zrevrange( key: string, start: number, stop: number, opts?: { withScore?: boolean; } ) { const args = this.pushZrangeOpts([key, start, stop], opts); return this.execArrayReply("ZREVRANGE", ...args); }
zrevrangebyscore( key: string, max: number, min: number, opts?: { withScore?: boolean; offset?: number; count?: number; } ) { const args = this.pushZrangeOpts([key, max, min], opts); return this.execArrayReply("ZREVRANGEBYSCORE", ...args); }
zrevrank(key: string, member: string) { return this.execIntegerReply("ZREVRANK", key, member); }
zscore(key: string, member: string) { return this.execStatusReply("ZSCORE", key, member); }
scan( cursor: number, opts?: { pattern?: string; count?: number; } ) { const arg = this.pushScanOpts([cursor], opts); return this.execArrayReply("SCAN", ...arg); }
sscan( key: string, cursor: number, opts?: { pattern?: string; count?: number; } ) { const arg = this.pushScanOpts([key, cursor], opts); return this.execArrayReply("SSCAN", ...arg); }
hscan( key: string, cursor: number, opts?: { pattern?: string; count?: number; } ) { const arg = this.pushScanOpts([key, cursor], opts); return this.execArrayReply("HSCAN", ...arg); }
zscan( key: string, cursor: number, opts?: { pattern?: string; } ) { const arg = this.pushScanOpts([key, cursor], opts); return this.execArrayReply("ZSCAN", ...arg); }
private pushScanOpts( arg: (number | string)[], opts?: { pattern?: string; count?: number; } ) { if (opts) { if (opts.pattern) { arg.push("MATCH", opts.pattern); } if (opts.count !== void 0) { arg.push("COUNT", opts.count); } } return arg; }
// pipeline tx() { return createRedisPipeline(this.writer, this.reader, { tx: true }); }
pipeline() { return createRedisPipeline(this.writer, this.reader); }
// Stream
close() { this.closer.close(); }}
export type RedisConnectOptions = { hostname: string; port?: number | string; tls?: boolean; db?: number;};
function prasePortLike(port: string | number | undefined): number { if (typeof port === "string") { return parseInt(port); } else if (typeof port === "number") { return port; } else if (port === undefined) { return 6379; } else { throw new Error("port is invalid: typeof=" + typeof port); }}
/** * Connect to Redis server * @param opts redis server's url http/https url with port number * Examples: * const conn = connect({hostname: "127.0.0.1", port: 6379})// -> tcp, 127.0.0.1:6379 * const conn = connect({hostname: "redis.proxy", port: 443, tls: true}) // -> TLS, redis.proxy:443 */export async function connect({ hostname, port, tls, db}: RedisConnectOptions): Promise<Redis> { const dialOpts: Deno.ConnectOptions = { hostname, port: prasePortLike(port) }; if (!Number.isSafeInteger(dialOpts.port)) { throw new Error("deno-redis: opts.port is invalid"); } const conn: Deno.Conn = tls ? await Deno.connectTLS(dialOpts) : await Deno.connect(dialOpts); const client = await create(conn, conn, conn); if (db) { await client.select(db); } return client;}
export function create( closer: Closer, writer: Writer, reader: Reader, executor?: CommandExecutor) { return new RedisImpl( closer, new BufWriter(writer), new BufReader(reader), executor );}