diff --git a/command.ts b/command.ts index 2a4fd77f..a886312c 100644 --- a/command.ts +++ b/command.ts @@ -5,6 +5,7 @@ import type { ConditionalArray, Integer, Raw, + RedisValue, SimpleString, } from "./protocol/mod.ts"; import type { RedisPipeline } from "./pipeline.ts"; @@ -216,9 +217,9 @@ export interface RedisCommands { // Connection auth(password: string): Promise; auth(username: string, password: string): Promise; - echo(message: string): Promise; + echo(message: RedisValue): Promise; ping(): Promise; - ping(message: string): Promise; + ping(message: RedisValue): Promise; quit(): Promise; select(index: number): Promise; @@ -275,7 +276,7 @@ export interface RedisCommands { wait(numreplicas: number, timeout: number): Promise; // String - append(key: string, value: string): Promise; + append(key: string, value: RedisValue): Promise; bitcount(key: string): Promise; bitcount(key: string, start: number, end: number): Promise; bitfield( @@ -302,36 +303,36 @@ export interface RedisCommands { get(key: string): Promise; getbit(key: string, offset: number): Promise; getrange(key: string, start: number, end: number): Promise; - getset(key: string, value: string): Promise; + getset(key: string, value: RedisValue): Promise; incr(key: string): Promise; incrby(key: string, increment: number): Promise; incrbyfloat(key: string, increment: number): Promise; mget(...keys: string[]): Promise; - mset(key: string, value: string): Promise; - mset(...key_values: [string, string][]): Promise; - mset(key_values: Record): Promise; - msetnx(key: string, value: string): Promise; - msetnx(...key_values: [string, string][]): Promise; - msetnx(key_values: Record): Promise; + mset(key: string, value: RedisValue): Promise; + mset(...key_values: [string, RedisValue][]): Promise; + mset(key_values: Record): Promise; + msetnx(key: string, value: RedisValue): Promise; + msetnx(...key_values: [string, RedisValue][]): Promise; + msetnx(key_values: Record): Promise; psetex( key: string, milliseconds: number, - value: string, + value: RedisValue, ): Promise; set( key: string, - value: string, + value: RedisValue, opts?: SetOpts, ): Promise; set( key: string, - value: string, + value: RedisValue, opts?: SetWithModeOpts, ): Promise; - setbit(key: string, offset: number, value: string): Promise; - setex(key: string, seconds: number, value: string): Promise; - setnx(key: string, value: string): Promise; - setrange(key: string, offset: number, value: string): Promise; + setbit(key: string, offset: number, value: RedisValue): Promise; + setex(key: string, seconds: number, value: RedisValue): Promise; + setnx(key: string, value: RedisValue): Promise; + setrange(key: string, offset: number, value: RedisValue): Promise; stralgo( algorithm: StralgoAlgorithm, target: StralgoTarget, @@ -402,20 +403,20 @@ export interface RedisCommands { /** * @deprecated since 4.0.0, use hset */ - hmset(key: string, field: string, value: string): Promise; + hmset(key: string, field: string, value: RedisValue): Promise; /** * @deprecated since 4.0.0, use hset */ hmset( key: string, - ...field_values: [string, string][] + ...field_values: [string, RedisValue][] ): Promise; /** * @deprecated since 4.0.0, use hset */ hmset( key: string, - field_values: Record, + field_values: Record, ): Promise; hscan( key: string, @@ -427,20 +428,20 @@ export interface RedisCommands { * @description Sets `field` in the hash to `value`. * @see https://redis.io/commands/hset */ - hset(key: string, field: string, value: string): Promise; + hset(key: string, field: string, value: RedisValue): Promise; /** * @description Sets the field-value pairs specified by `fieldValues` to the hash stored at `key`. * NOTE: Variadic form for `HSET` is supported only in Redis v4.0.0 or higher. */ - hset(key: string, ...fieldValues: [string, string][]): Promise; + hset(key: string, ...fieldValues: [string, RedisValue][]): Promise; /** * @description Sets the field-value pairs specified by `fieldValues` to the hash stored at `key`. * NOTE: Variadic form for `HSET` is supported only in Redis v4.0.0 or higher. */ - hset(key: string, fieldValues: Record): Promise; - hsetnx(key: string, field: string, value: string): Promise; + hset(key: string, fieldValues: Record): Promise; + hsetnx(key: string, field: string, value: RedisValue): Promise; hstrlen(key: string, field: string): Promise; hvals(key: string): Promise; @@ -463,7 +464,7 @@ export interface RedisCommands { key: string, loc: LInsertLocation, pivot: string, - value: string, + value: RedisValue, ): Promise; llen(key: string): Promise; lpop(key: string): Promise; @@ -474,7 +475,7 @@ export interface RedisCommands { */ lpos( key: string, - element: string, + element: RedisValue, opts?: LPosOpts, ): Promise; @@ -486,20 +487,20 @@ export interface RedisCommands { */ lpos( key: string, - element: string, + element: RedisValue, opts: LPosWithCountOpts, ): Promise; - lpush(key: string, ...elements: string[]): Promise; - lpushx(key: string, ...elements: string[]): Promise; + lpush(key: string, ...elements: RedisValue[]): Promise; + lpushx(key: string, ...elements: RedisValue[]): Promise; lrange(key: string, start: number, stop: number): Promise; - lrem(key: string, count: number, element: string): Promise; - lset(key: string, index: number, element: string): Promise; + lrem(key: string, count: number, element: RedisValue): Promise; + lset(key: string, index: number, element: RedisValue): Promise; ltrim(key: string, start: number, stop: number): Promise; rpop(key: string): Promise; rpoplpush(source: string, destination: string): Promise; - rpush(key: string, ...elements: string[]): Promise; - rpushx(key: string, ...elements: string[]): Promise; + rpush(key: string, ...elements: RedisValue[]): Promise; + rpushx(key: string, ...elements: RedisValue[]): Promise; // HyperLogLog pfadd(key: string, ...elements: string[]): Promise; @@ -513,26 +514,30 @@ export interface RedisCommands { pubsubChannels(pattern?: string): Promise; pubsubNumsub(...channels: string[]): Promise<(BulkString | Integer)[]>; pubsubNumpat(): Promise; - publish(channel: string, message: string): Promise; + publish(channel: string, message: RedisValue): Promise; subscribe( ...channels: string[] ): Promise>; // Set - sadd(key: string, ...members: string[]): Promise; + sadd(key: string, ...members: RedisValue[]): Promise; scard(key: string): Promise; sdiff(...keys: string[]): Promise; sdiffstore(destination: string, ...keys: string[]): Promise; sinter(...keys: string[]): Promise; sinterstore(destination: string, ...keys: string[]): Promise; - sismember(key: string, member: string): Promise; + sismember(key: string, member: RedisValue): Promise; smembers(key: string): Promise; - smove(source: string, destination: string, member: string): Promise; + smove( + source: string, + destination: string, + member: RedisValue, + ): Promise; spop(key: string): Promise; spop(key: string, count: number): Promise; srandmember(key: string): Promise; srandmember(key: string, count: number): Promise; - srem(key: string, ...members: string[]): Promise; + srem(key: string, ...members: RedisValue[]): Promise; sscan( key: string, cursor: number, @@ -900,28 +905,32 @@ XRANGE somestream - + zadd( key: string, score: number, - member: string, + member: RedisValue, opts?: ZAddOpts, ): Promise; zadd( key: string, - score_members: [number, string][], + score_members: [number, RedisValue][], opts?: ZAddOpts, ): Promise; zadd( key: string, - member_scores: Record, + member_scores: Record, opts?: ZAddOpts, ): Promise; zaddIncr( key: string, score: number, - member: string, + member: RedisValue, opts?: ZAddOpts, ): Promise; zcard(key: string): Promise; zcount(key: string, min: number, max: number): Promise; - zincrby(key: string, increment: number, member: string): Promise; + zincrby( + key: string, + increment: number, + member: RedisValue, + ): Promise; zinterstore( destination: string, keys: string[], @@ -958,8 +967,8 @@ XRANGE somestream - + max: number | string, opts?: ZRangeByScoreOpts, ): Promise; - zrank(key: string, member: string): Promise; - zrem(key: string, ...members: string[]): Promise; + zrank(key: string, member: RedisValue): Promise; + zrem(key: string, ...members: RedisValue[]): Promise; zremrangebylex(key: string, min: string, max: string): Promise; zremrangebyrank(key: string, start: number, stop: number): Promise; zremrangebyscore( @@ -985,13 +994,13 @@ XRANGE somestream - + min: number | string, opts?: ZRangeByScoreOpts, ): Promise; - zrevrank(key: string, member: string): Promise; + zrevrank(key: string, member: RedisValue): Promise; zscan( key: string, cursor: number, opts?: ZScanOpts, ): Promise<[BulkString, BulkString[]]>; - zscore(key: string, member: string): Promise; + zscore(key: string, member: RedisValue): Promise; zunionstore( destination: string, keys: string[], @@ -1178,8 +1187,8 @@ XRANGE somestream - + time(): Promise<[BulkString, BulkString]>; // Scripting - eval(script: string, keys: string[], args: string[]): Promise; - evalsha(sha1: string, keys: string[], args: string[]): Promise; + eval(script: string, keys: string[], args: RedisValue[]): Promise; + evalsha(sha1: string, keys: string[], args: RedisValue[]): Promise; scriptDebug(mode: ScriptDebugMode): Promise; scriptExists(...sha1s: string[]): Promise; scriptFlush(): Promise; diff --git a/executor.ts b/executor.ts index 282f4fac..b13f7615 100644 --- a/executor.ts +++ b/executor.ts @@ -2,7 +2,7 @@ import type { Connection } from "./connection.ts"; import { EOFError } from "./errors.ts"; import { Deferred, deferred } from "./vendor/https/deno.land/std/async/mod.ts"; import { sendCommand } from "./protocol/mod.ts"; -import type { RedisReply } from "./protocol/mod.ts"; +import type { RedisReply, RedisValue } from "./protocol/mod.ts"; export abstract class CommandExecutor { connection: Connection; @@ -13,20 +13,20 @@ export abstract class CommandExecutor { abstract exec( command: string, - ...args: (string | number)[] + ...args: RedisValue[] ): Promise; } export class MuxExecutor extends CommandExecutor { private queue: { command: string; - args: (string | number)[]; + args: RedisValue[]; d: Deferred; }[] = []; exec( command: string, - ...args: (string | number)[] + ...args: RedisValue[] ): Promise { const d = deferred(); this.queue.push({ command, args, d }); diff --git a/mod.ts b/mod.ts index 72d6ecc2..030fbc0a 100644 --- a/mod.ts +++ b/mod.ts @@ -70,6 +70,7 @@ export type { Raw, RedisReply, RedisReplyOrError, + RedisValue, Reply, SimpleString, SimpleStringReply, diff --git a/pipeline.ts b/pipeline.ts index c9ec59e1..a1d39146 100644 --- a/pipeline.ts +++ b/pipeline.ts @@ -4,6 +4,7 @@ import { createSimpleStringReply, RedisReply, RedisReplyOrError, + RedisValue, sendCommands, } from "./protocol/mod.ts"; import { Redis, RedisImpl } from "./redis.ts"; @@ -28,12 +29,12 @@ export function createRedisPipeline( export class PipelineExecutor extends CommandExecutor { private commands: { command: string; - args: (number | string)[]; + args: RedisValue[]; }[] = []; private queue: { commands: { command: string; - args: (number | string)[]; + args: RedisValue[]; }[]; d: Deferred; }[] = []; @@ -44,7 +45,7 @@ export class PipelineExecutor extends CommandExecutor { exec( command: string, - ...args: (string | number)[] + ...args: RedisValue[] ): Promise { this.commands.push({ command, args }); return Promise.resolve(createSimpleStringReply("OK")); diff --git a/protocol/command.ts b/protocol/command.ts index 62634521..c24c24e1 100644 --- a/protocol/command.ts +++ b/protocol/command.ts @@ -5,34 +5,44 @@ import { import { readReply } from "./reply.ts"; import { ErrorReplyError } from "../errors.ts"; import { encoder } from "./_util.ts"; -import type { RedisReply, RedisReplyOrError } from "./types.ts"; +import type { RedisReply, RedisReplyOrError, RedisValue } from "./types.ts"; -export function createRequest( +const CRLF = encoder.encode("\r\n"); +const ArrayCode = encoder.encode("*"); +const BulkCode = encoder.encode("$"); + +async function writeRequest( + writer: BufWriter, command: string, - args: (string | number)[], -): string { + args: RedisValue[], +) { const _args = args.filter((v) => v !== void 0 && v !== null); - let msg = ""; - msg += `*${1 + _args.length}\r\n`; - msg += `$${command.length}\r\n`; - msg += `${command}\r\n`; + await writer.write(ArrayCode); + await writer.write(encoder.encode(String(1 + _args.length))); + await writer.write(CRLF); + await writer.write(BulkCode); + await writer.write(encoder.encode(String(command.length))); + await writer.write(CRLF); + await writer.write(encoder.encode(command)); + await writer.write(CRLF); for (const arg of _args) { - const val = String(arg); - const bytesLen = encoder.encode(val).byteLength; - msg += `$${bytesLen}\r\n`; - msg += `${val}\r\n`; + const bytes = arg instanceof Uint8Array ? arg : encoder.encode(String(arg)); + const bytesLen = bytes.byteLength; + await writer.write(BulkCode); + await writer.write(encoder.encode(String(bytesLen))); + await writer.write(CRLF); + await writer.write(bytes); + await writer.write(CRLF); } - return msg; } export async function sendCommand( writer: BufWriter, reader: BufReader, command: string, - ...args: (number | string)[] + ...args: RedisValue[] ): Promise { - const msg = createRequest(command, args); - await writer.write(encoder.encode(msg)); + await writeRequest(writer, command, args); await writer.flush(); return readReply(reader); } @@ -42,11 +52,12 @@ export async function sendCommands( reader: BufReader, commands: { command: string; - args: (number | string)[]; + args: RedisValue[]; }[], ): Promise { - const msg = commands.map((c) => createRequest(c.command, c.args)).join(""); - await writer.write(encoder.encode(msg)); + for (const { command, args } of commands) { + await writeRequest(writer, command, args); + } await writer.flush(); const ret: RedisReplyOrError[] = []; for (let i = 0; i < commands.length; i++) { diff --git a/protocol/mod.ts b/protocol/mod.ts index bec4fdf1..537dd20c 100644 --- a/protocol/mod.ts +++ b/protocol/mod.ts @@ -10,6 +10,7 @@ export type { Raw, RedisReply, RedisReplyOrError, + RedisValue, Reply, SimpleString, SimpleStringReply, @@ -26,4 +27,4 @@ export { unwrapReply, } from "./reply.ts"; -export { createRequest, sendCommand, sendCommands } from "./command.ts"; +export { sendCommand, sendCommands } from "./command.ts"; diff --git a/protocol/types.ts b/protocol/types.ts index f4c2d137..835f3468 100644 --- a/protocol/types.ts +++ b/protocol/types.ts @@ -4,6 +4,8 @@ import { ErrorReplyError } from "../errors.ts"; * @see https://redis.io/topics/protocol */ +export type RedisValue = string | number | Uint8Array; + /** * @description Represents the type of the value returned by `SimpleStringReply#value()`. */ diff --git a/redis.ts b/redis.ts index aefcb472..a0e47121 100644 --- a/redis.ts +++ b/redis.ts @@ -54,6 +54,7 @@ import type { Integer, IntegerReply, Raw, + RedisValue, SimpleString, SimpleStringReply, } from "./protocol/mod.ts"; @@ -123,7 +124,7 @@ export class RedisImpl implements Redis { this.connection.close(); } - async execReply(command: string, ...args: (string | number)[]): Promise { + async execReply(command: string, ...args: RedisValue[]): Promise { const reply = await this.executor.exec( command, ...args, @@ -133,7 +134,7 @@ export class RedisImpl implements Redis { async execStatusReply( command: string, - ...args: (string | number)[] + ...args: RedisValue[] ): Promise { const reply = await this.executor.exec(command, ...args); return reply.value() as SimpleString; @@ -141,7 +142,7 @@ export class RedisImpl implements Redis { async execIntegerReply( command: string, - ...args: (string | number)[] + ...args: RedisValue[] ): Promise { const reply = await this.executor.exec(command, ...args); return reply.value() as Integer; @@ -149,7 +150,7 @@ export class RedisImpl implements Redis { async execBulkReply( command: string, - ...args: (string | number)[] + ...args: RedisValue[] ): Promise { const reply = await this.executor.exec(command, ...args); return reply.value() as T; @@ -157,7 +158,7 @@ export class RedisImpl implements Redis { async execArrayReply( command: string, - ...args: (string | number)[] + ...args: RedisValue[] ): Promise { const reply = await this.executor.exec(command, ...args); return reply.value() as T[]; @@ -165,7 +166,7 @@ export class RedisImpl implements Redis { async execIntegerOrNilReply( command: string, - ...args: (string | number)[] + ...args: RedisValue[] ): Promise { const reply = await this.executor.exec(command, ...args); return reply.value() as Integer | BulkNil; @@ -173,7 +174,7 @@ export class RedisImpl implements Redis { async execStatusOrNilReply( command: string, - ...args: (string | number)[] + ...args: RedisValue[] ): Promise { const reply = await this.executor.exec(command, ...args); return reply.value() as SimpleString | BulkNil; @@ -242,11 +243,11 @@ export class RedisImpl implements Redis { return this.execBulkReply("ACL", "WHOAMI"); } - append(key: string, value: string | number) { + append(key: string, value: RedisValue) { return this.execIntegerReply("APPEND", key, value); } - auth(param1: string, param2?: string) { + auth(param1: RedisValue, param2?: RedisValue) { if (param2 !== undefined) { return this.execStatusReply("AUTH", param1, param2); } @@ -619,7 +620,7 @@ export class RedisImpl implements Redis { return this.execBulkReply("DUMP", key); } - echo(message: string) { + echo(message: RedisValue) { return this.execBulkReply("ECHO", message); } @@ -776,7 +777,7 @@ export class RedisImpl implements Redis { return this.execBulkReply("GETRANGE", key, start, end); } - getset(key: string, value: string) { + getset(key: string, value: RedisValue) { return this.execBulkReply("GETSET", key, value); } @@ -823,12 +824,12 @@ export class RedisImpl implements Redis { // deno-lint-ignore no-explicit-any hmset(key: string, ...params: any[]) { - const args = [key]; + const args = [key] as RedisValue[]; if (Array.isArray(params[0])) { args.push(...params.flatMap((e) => e)); } else if (typeof params[0] === "object") { for (const [field, value] of Object.entries(params[0])) { - args.push(field, value as string); + args.push(field, value as RedisValue); } } else { args.push(...params); @@ -838,12 +839,12 @@ export class RedisImpl implements Redis { // deno-lint-ignore no-explicit-any hset(key: string, ...params: any[]) { - const args = [key]; + const args = [key] as RedisValue[]; if (Array.isArray(params[0])) { args.push(...params.flatMap((e) => e)); } else if (typeof params[0] === "object") { for (const [field, value] of Object.entries(params[0])) { - args.push(field, value as string); + args.push(field, value as RedisValue); } } else { args.push(...params); @@ -851,7 +852,7 @@ export class RedisImpl implements Redis { return this.execIntegerReply("HSET", ...args); } - hsetnx(key: string, field: string, value: string) { + hsetnx(key: string, field: string, value: RedisValue) { return this.execIntegerReply("HSETNX", key, field, value); } @@ -894,7 +895,7 @@ export class RedisImpl implements Redis { return this.execBulkReply("LINDEX", key, index); } - linsert(key: string, loc: LInsertLocation, pivot: string, value: string) { + linsert(key: string, loc: LInsertLocation, pivot: string, value: RedisValue) { return this.execIntegerReply("LINSERT", key, loc, pivot, value); } @@ -908,19 +909,19 @@ export class RedisImpl implements Redis { lpos( key: string, - element: string, + element: RedisValue, opts?: LPosOpts, ): Promise; lpos( key: string, - element: string, + element: RedisValue, opts: LPosWithCountOpts, ): Promise; lpos( key: string, - element: string, + element: RedisValue, opts?: LPosOpts | LPosWithCountOpts, ): Promise { const args = [element]; @@ -941,11 +942,11 @@ export class RedisImpl implements Redis { : this.execArrayReply("LPOS", key, ...args); } - lpush(key: string, ...elements: (string | number)[]) { + lpush(key: string, ...elements: RedisValue[]) { return this.execIntegerReply("LPUSH", key, ...elements); } - lpushx(key: string, ...elements: (string | number)[]) { + lpushx(key: string, ...elements: RedisValue[]) { return this.execIntegerReply("LPUSHX", key, ...elements); } @@ -1043,12 +1044,12 @@ export class RedisImpl implements Redis { // deno-lint-ignore no-explicit-any mset(...params: any[]) { - const args: string[] = []; + const args: RedisValue[] = []; if (Array.isArray(params[0])) { args.push(...params.flatMap((e) => e)); } else if (typeof params[0] === "object") { for (const [key, value] of Object.entries(params[0])) { - args.push(key, value as string); + args.push(key, value as RedisValue); } } else { args.push(...params); @@ -1058,12 +1059,12 @@ export class RedisImpl implements Redis { // deno-lint-ignore no-explicit-any msetnx(...params: any[]) { - const args: string[] = []; + const args: RedisValue[] = []; if (Array.isArray(params[0])) { args.push(...params.flatMap((e) => e)); } else if (typeof params[0] === "object") { for (const [key, value] of Object.entries(params[0])) { - args.push(key, value as string); + args.push(key, value as RedisValue); } } else { args.push(...params); @@ -1119,14 +1120,14 @@ export class RedisImpl implements Redis { return this.execStatusReply("PFMERGE", destkey, ...sourcekeys); } - ping(message?: string) { + ping(message?: RedisValue) { if (message) { return this.execBulkReply("PING", message); } return this.execStatusReply("PING"); } - psetex(key: string, milliseconds: number, value: string) { + psetex(key: string, milliseconds: number, value: RedisValue) { return this.execStatusReply("PSETEX", key, milliseconds, value); } @@ -1231,11 +1232,11 @@ export class RedisImpl implements Redis { return this.execBulkReply("RPOPLPUSH", source, destination); } - rpush(key: string, ...elements: (string | number)[]) { + rpush(key: string, ...elements: RedisValue[]) { return this.execIntegerReply("RPUSH", key, ...elements); } - rpushx(key: string, ...elements: (string | number)[]) { + rpushx(key: string, ...elements: RedisValue[]) { return this.execIntegerReply("RPUSHX", key, ...elements); } @@ -1285,20 +1286,20 @@ export class RedisImpl implements Redis { set( key: string, - value: string, + value: RedisValue, opts?: SetOpts, ): Promise; set( key: string, - value: string, + value: RedisValue, opts?: SetWithModeOpts, ): Promise; set( key: string, - value: string, + value: RedisValue, opts?: SetOpts | SetWithModeOpts, ) { - const args: (number | string)[] = [key, value]; + const args: RedisValue[] = [key, value]; if (opts?.ex !== undefined) { args.push("EX", opts.ex); } else if (opts?.px !== undefined) { @@ -1314,19 +1315,19 @@ export class RedisImpl implements Redis { return this.execStatusReply("SET", ...args); } - setbit(key: string, offset: number, value: string) { + setbit(key: string, offset: number, value: RedisValue) { return this.execIntegerReply("SETBIT", key, offset, value); } - setex(key: string, seconds: number, value: string) { + setex(key: string, seconds: number, value: RedisValue) { return this.execStatusReply("SETEX", key, seconds, value); } - setnx(key: string, value: string) { + setnx(key: string, value: RedisValue) { return this.execIntegerReply("SETNX", key, value); } - setrange(key: string, offset: number, value: string) { + setrange(key: string, offset: number, value: RedisValue) { return this.execIntegerReply("SETRANGE", key, offset, value); } @@ -1525,7 +1526,7 @@ export class RedisImpl implements Redis { fieldValues: XAddFieldValues, maxlen: XMaxlen | undefined = undefined, ) { - const args: (string | number)[] = [key]; + const args: RedisValue[] = [key]; if (maxlen) { args.push("MAXLEN"); diff --git a/stream.ts b/stream.ts index a1c6ac59..aac1ab5e 100644 --- a/stream.ts +++ b/stream.ts @@ -1,4 +1,4 @@ -import type { ConditionalArray, Raw } from "./protocol/mod.ts"; +import type { ConditionalArray, Raw, RedisValue } from "./protocol/mod.ts"; export interface XId { unixMs: number; @@ -66,8 +66,8 @@ export type XIdNeg = XIdInput | "-"; export type XIdCreateGroup = XIdInput | "$"; export type XAddFieldValues = - | Record - | Map; + | Record + | Map; export interface XReadOpts { count?: number; diff --git a/tests/executor_test.ts b/tests/executor_test.ts new file mode 100644 index 00000000..2a7a9475 --- /dev/null +++ b/tests/executor_test.ts @@ -0,0 +1,50 @@ +import { BulkReply, ErrorReplyError, parseURL } from "../mod.ts"; +import { + assert, + assertEquals, + assertThrowsAsync, +} from "../vendor/https/deno.land/std/testing/asserts.ts"; +import { newClient, startRedis, stopRedis, TestSuite } from "./test_util.ts"; + +const suite = new TestSuite("executor"); +const server = await startRedis({ port: 7017 }); +const opts = { hostname: "127.0.0.1", port: 7017 }; +const client = await newClient(opts); + +suite.afterAll(() => { + stopRedis(server); + client.close(); +}); + +suite.test("simple, string, and integer replies", async () => { + // simple string + { + const reply = await client.executor.exec("SET", "key", "a"); + assertEquals(reply.type, "simple string"); + assertEquals(reply.value(), "OK"); + } + + // bulk string + { + const reply = await client.executor.exec("GET", "key"); + assertEquals(reply.type, "bulk string"); + assertEquals(reply.value(), "a"); + } + + // integer + { + const reply = await client.executor.exec("EXISTS", "key"); + assertEquals(reply.type, "integer"); + assertEquals(reply.value(), 1); + } +}); + +suite.test("get the raw data as Uint8Array", async () => { + const encoder = new TextEncoder(); + await client.set("key", encoder.encode("hello")); + const reply = await client.executor.exec("GET", "key"); + assertEquals(reply.type, "bulk string"); + assertEquals((reply as BulkReply).buffer(), encoder.encode("hello")); +}); + +suite.runTests(); diff --git a/tests/general_test.ts b/tests/general_test.ts index 9dbb46f9..1ac138f1 100644 --- a/tests/general_test.ts +++ b/tests/general_test.ts @@ -91,29 +91,6 @@ suite.test("exists", async () => { }); }); -suite.test("execRawReply", async () => { - // simple string - { - const reply = await client.executor.exec("SET", "key", "a"); - assertEquals(reply.type, "simple string"); - assertEquals(reply.value(), "OK"); - } - - // bulk string - { - const reply = await client.executor.exec("GET", "key"); - assertEquals(reply.type, "bulk string"); - assertEquals(reply.value(), "a"); - } - - // integer - { - const reply = await client.executor.exec("EXISTS", "key"); - assertEquals(reply.type, "integer"); - assertEquals(reply.value(), 1); - } -}); - suite.test("eval", async () => { const raw = await client.eval( "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}", diff --git a/tests/string_test.ts b/tests/string_test.ts index 7ed2d643..fdd9763d 100644 --- a/tests/string_test.ts +++ b/tests/string_test.ts @@ -167,6 +167,13 @@ suite.test("set", async () => { assertEquals(fuga, "fuga你好こんにちは"); }); +suite.test("set Number", async () => { + const s = await client.set("key", 123); + assertEquals(s, "OK"); + const v = await client.get("key"); + assertEquals(v, "123"); +}); + suite.test("setbit", async () => { await client.set("key", "2"); // 00110010 assertEquals(