UNPKG

@upstash/redis

Version:

An HTTP/REST based Redis client built on top of Upstash REST API.

1,971 lines (1,814 loc) • 137 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // platforms/nodejs.ts var nodejs_exports = {}; __export(nodejs_exports, { Redis: () => Redis2, errors: () => error_exports }); module.exports = __toCommonJS(nodejs_exports); // pkg/error.ts var error_exports = {}; __export(error_exports, { UpstashError: () => UpstashError, UpstashJSONParseError: () => UpstashJSONParseError, UrlError: () => UrlError }); var UpstashError = class extends Error { constructor(message, options) { super(message, options); this.name = "UpstashError"; } }; var UrlError = class extends Error { constructor(url) { super( `Upstash Redis client was passed an invalid URL. You should pass a URL starting with https. Received: "${url}". ` ); this.name = "UrlError"; } }; var UpstashJSONParseError = class extends UpstashError { constructor(body, options) { const truncatedBody = body.length > 200 ? body.slice(0, 200) + "..." : body; super(`Unable to parse response body: ${truncatedBody}`, options); this.name = "UpstashJSONParseError"; } }; // pkg/util.ts function parseRecursive(obj) { const parsed = Array.isArray(obj) ? obj.map((o) => { try { return parseRecursive(o); } catch { return o; } }) : JSON.parse(obj); if (typeof parsed === "number" && parsed.toString() !== obj) { return obj; } return parsed; } function parseResponse(result) { try { return parseRecursive(result); } catch { return result; } } function deserializeScanResponse(result) { return [result[0], ...parseResponse(result.slice(1))]; } function deserializeScanWithTypesResponse(result) { const [cursor, keys] = result; const parsedKeys = []; for (let i = 0; i < keys.length; i += 2) { parsedKeys.push({ key: keys[i], type: keys[i + 1] }); } return [cursor, parsedKeys]; } function mergeHeaders(...headers) { const merged = {}; for (const header of headers) { if (!header) continue; for (const [key, value] of Object.entries(header)) { if (value !== void 0 && value !== null) { merged[key] = value; } } } return merged; } // pkg/http.ts var HttpClient = class { baseUrl; headers; options; readYourWrites; upstashSyncToken = ""; hasCredentials; retry; constructor(config) { this.options = { backend: config.options?.backend, agent: config.agent, responseEncoding: config.responseEncoding ?? "base64", // default to base64 cache: config.cache, signal: config.signal, keepAlive: config.keepAlive ?? true }; this.upstashSyncToken = ""; this.readYourWrites = config.readYourWrites ?? true; this.baseUrl = (config.baseUrl || "").replace(/\/$/, ""); const urlRegex = /^https?:\/\/[^\s#$./?].\S*$/; if (this.baseUrl && !urlRegex.test(this.baseUrl)) { throw new UrlError(this.baseUrl); } this.headers = { "Content-Type": "application/json", ...config.headers }; this.hasCredentials = Boolean(this.baseUrl && this.headers.authorization.split(" ")[1]); if (this.options.responseEncoding === "base64") { this.headers["Upstash-Encoding"] = "base64"; } this.retry = typeof config.retry === "boolean" && !config.retry ? { attempts: 1, backoff: () => 0 } : { attempts: config.retry?.retries ?? 5, backoff: config.retry?.backoff ?? ((retryCount) => Math.exp(retryCount) * 50) }; } mergeTelemetry(telemetry) { this.headers = merge(this.headers, "Upstash-Telemetry-Runtime", telemetry.runtime); this.headers = merge(this.headers, "Upstash-Telemetry-Platform", telemetry.platform); this.headers = merge(this.headers, "Upstash-Telemetry-Sdk", telemetry.sdk); } async request(req) { const requestHeaders = mergeHeaders(this.headers, req.headers ?? {}); const requestUrl = [this.baseUrl, ...req.path ?? []].join("/"); const isEventStream = requestHeaders.Accept === "text/event-stream"; const signal = req.signal ?? this.options.signal; const isSignalFunction = typeof signal === "function"; const requestOptions = { //@ts-expect-error this should throw due to bun regression cache: this.options.cache, method: "POST", headers: requestHeaders, body: JSON.stringify(req.body), keepalive: this.options.keepAlive, agent: this.options.agent, signal: isSignalFunction ? signal() : signal, /** * Fastly specific */ backend: this.options.backend }; if (!this.hasCredentials) { console.warn( "[Upstash Redis] Redis client was initialized without url or token. Failed to execute command." ); } if (this.readYourWrites) { const newHeader = this.upstashSyncToken; this.headers["upstash-sync-token"] = newHeader; } let res = null; let error = null; for (let i = 0; i <= this.retry.attempts; i++) { try { res = await fetch(requestUrl, requestOptions); break; } catch (error_) { if (requestOptions.signal?.aborted && isSignalFunction) { throw error_; } else if (requestOptions.signal?.aborted) { const myBlob = new Blob([ JSON.stringify({ result: requestOptions.signal.reason ?? "Aborted" }) ]); const myOptions = { status: 200, statusText: requestOptions.signal.reason ?? "Aborted" }; res = new Response(myBlob, myOptions); break; } error = error_; if (i < this.retry.attempts) { await new Promise((r) => setTimeout(r, this.retry.backoff(i))); } } } if (!res) { throw error ?? new Error("Exhausted all retries"); } if (!res.ok) { let body2; const rawBody2 = await res.text(); try { body2 = JSON.parse(rawBody2); } catch (error2) { throw new UpstashJSONParseError(rawBody2, { cause: error2 }); } throw new UpstashError(`${body2.error}, command was: ${JSON.stringify(req.body)}`); } if (this.readYourWrites) { const headers = res.headers; this.upstashSyncToken = headers.get("upstash-sync-token") ?? ""; } if (isEventStream && req && req.onMessage && res.body) { const reader = res.body.getReader(); const decoder = new TextDecoder(); (async () => { try { while (true) { const { value, done } = await reader.read(); if (done) break; const chunk = decoder.decode(value); const lines = chunk.split("\n"); for (const line of lines) { if (line.startsWith("data: ")) { const data = line.slice(6); req.onMessage?.(data); } } } } catch (error2) { if (error2 instanceof Error && error2.name === "AbortError") { } else { console.error("Stream reading error:", error2); } } finally { try { await reader.cancel(); } catch { } } })(); return { result: 1 }; } let body; const rawBody = await res.text(); try { body = JSON.parse(rawBody); } catch (error2) { throw new UpstashJSONParseError(rawBody, { cause: error2 }); } if (this.readYourWrites) { const headers = res.headers; this.upstashSyncToken = headers.get("upstash-sync-token") ?? ""; } if (this.options.responseEncoding === "base64") { if (Array.isArray(body)) { return body.map(({ result: result2, error: error2 }) => ({ result: decode(result2), error: error2 })); } const result = decode(body.result); return { result, error: body.error }; } return body; } }; function base64decode(b64) { let dec = ""; try { const binString = atob(b64); const size = binString.length; const bytes = new Uint8Array(size); for (let i = 0; i < size; i++) { bytes[i] = binString.charCodeAt(i); } dec = new TextDecoder().decode(bytes); } catch { dec = b64; } return dec; } function decode(raw) { let result = void 0; switch (typeof raw) { case "undefined": { return raw; } case "number": { result = raw; break; } case "object": { if (Array.isArray(raw)) { result = raw.map( (v) => typeof v === "string" ? base64decode(v) : Array.isArray(v) ? v.map((element) => decode(element)) : v ); } else { result = null; } break; } case "string": { result = raw === "OK" ? "OK" : base64decode(raw); break; } default: { break; } } return result; } function merge(obj, key, value) { if (!value) { return obj; } obj[key] = obj[key] ? [obj[key], value].join(",") : value; return obj; } // pkg/auto-pipeline.ts var EXCLUDE_COMMANDS = /* @__PURE__ */ new Set([ "scan", "keys", "flushdb", "flushall", "dbsize", "hscan", "hgetall", "hkeys", "lrange", "sscan", "smembers", "xrange", "xrevrange", "zscan", "zrange", "exec" ]); function createAutoPipelineProxy(_redis, json) { const redis = _redis; if (!redis.autoPipelineExecutor) { redis.autoPipelineExecutor = new AutoPipelineExecutor(redis); } return new Proxy(redis, { get: (redis2, command) => { if (command === "pipelineCounter") { return redis2.autoPipelineExecutor.pipelineCounter; } if (command === "json") { return createAutoPipelineProxy(redis2, true); } const commandInRedisButNotPipeline = command in redis2 && !(command in redis2.autoPipelineExecutor.pipeline); const isCommandExcluded = EXCLUDE_COMMANDS.has(command); if (commandInRedisButNotPipeline || isCommandExcluded) { return redis2[command]; } const isFunction = json ? typeof redis2.autoPipelineExecutor.pipeline.json[command] === "function" : typeof redis2.autoPipelineExecutor.pipeline[command] === "function"; if (isFunction) { return (...args) => { return redis2.autoPipelineExecutor.withAutoPipeline((pipeline) => { if (json) { pipeline.json[command]( ...args ); } else { pipeline[command](...args); } }); }; } return redis2.autoPipelineExecutor.pipeline[command]; } }); } var AutoPipelineExecutor = class { pipelinePromises = /* @__PURE__ */ new WeakMap(); activePipeline = null; indexInCurrentPipeline = 0; redis; pipeline; // only to make sure that proxy can work pipelineCounter = 0; // to keep track of how many times a pipeline was executed constructor(redis) { this.redis = redis; this.pipeline = redis.pipeline(); } async withAutoPipeline(executeWithPipeline) { const pipeline = this.activePipeline ?? this.redis.pipeline(); if (!this.activePipeline) { this.activePipeline = pipeline; this.indexInCurrentPipeline = 0; } const index = this.indexInCurrentPipeline++; executeWithPipeline(pipeline); const pipelineDone = this.deferExecution().then(() => { if (!this.pipelinePromises.has(pipeline)) { const pipelinePromise = pipeline.exec({ keepErrors: true }); this.pipelineCounter += 1; this.pipelinePromises.set(pipeline, pipelinePromise); this.activePipeline = null; } return this.pipelinePromises.get(pipeline); }); const results = await pipelineDone; const commandResult = results[index]; if (commandResult.error) { throw new UpstashError(`Command failed: ${commandResult.error}`); } return commandResult.result; } async deferExecution() { await Promise.resolve(); await Promise.resolve(); } }; // pkg/commands/command.ts var defaultSerializer = (c) => { switch (typeof c) { case "string": case "number": case "boolean": { return c; } default: { return JSON.stringify(c); } } }; var Command = class { command; serialize; deserialize; headers; path; onMessage; isStreaming; signal; /** * Create a new command instance. * * You can define a custom `deserialize` function. By default we try to deserialize as json. */ constructor(command, opts) { this.serialize = defaultSerializer; this.deserialize = opts?.automaticDeserialization === void 0 || opts.automaticDeserialization ? opts?.deserialize ?? parseResponse : (x) => x; this.command = command.map((c) => this.serialize(c)); this.headers = opts?.headers; this.path = opts?.path; this.onMessage = opts?.streamOptions?.onMessage; this.isStreaming = opts?.streamOptions?.isStreaming ?? false; this.signal = opts?.streamOptions?.signal; if (opts?.latencyLogging) { const originalExec = this.exec.bind(this); this.exec = async (client) => { const start = performance.now(); const result = await originalExec(client); const end = performance.now(); const loggerResult = (end - start).toFixed(2); console.log( `Latency for \x1B[38;2;19;185;39m${this.command[0].toString().toUpperCase()}\x1B[0m: \x1B[38;2;0;255;255m${loggerResult} ms\x1B[0m` ); return result; }; } } /** * Execute the command using a client. */ async exec(client) { const { result, error } = await client.request({ body: this.command, path: this.path, upstashSyncToken: client.upstashSyncToken, headers: this.headers, onMessage: this.onMessage, isStreaming: this.isStreaming, signal: this.signal }); if (error) { throw new UpstashError(error); } if (result === void 0) { throw new TypeError("Request did not return a result"); } return this.deserialize(result); } }; // pkg/commands/append.ts var AppendCommand = class extends Command { constructor(cmd, opts) { super(["append", ...cmd], opts); } }; // pkg/commands/bitcount.ts var BitCountCommand = class extends Command { constructor([key, start, end], opts) { const command = ["bitcount", key]; if (typeof start === "number") { command.push(start); } if (typeof end === "number") { command.push(end); } super(command, opts); } }; // pkg/commands/bitfield.ts var BitFieldCommand = class { constructor(args, client, opts, execOperation = (command) => command.exec(this.client)) { this.client = client; this.opts = opts; this.execOperation = execOperation; this.command = ["bitfield", ...args]; } command; chain(...args) { this.command.push(...args); return this; } get(...args) { return this.chain("get", ...args); } set(...args) { return this.chain("set", ...args); } incrby(...args) { return this.chain("incrby", ...args); } overflow(overflow) { return this.chain("overflow", overflow); } exec() { const command = new Command(this.command, this.opts); return this.execOperation(command); } }; // pkg/commands/bitop.ts var BitOpCommand = class extends Command { constructor(cmd, opts) { super(["bitop", ...cmd], opts); } }; // pkg/commands/bitpos.ts var BitPosCommand = class extends Command { constructor(cmd, opts) { super(["bitpos", ...cmd], opts); } }; // pkg/commands/copy.ts var CopyCommand = class extends Command { constructor([key, destinationKey, opts], commandOptions) { super(["COPY", key, destinationKey, ...opts?.replace ? ["REPLACE"] : []], { ...commandOptions, deserialize(result) { if (result > 0) { return "COPIED"; } return "NOT_COPIED"; } }); } }; // pkg/commands/dbsize.ts var DBSizeCommand = class extends Command { constructor(opts) { super(["dbsize"], opts); } }; // pkg/commands/decr.ts var DecrCommand = class extends Command { constructor(cmd, opts) { super(["decr", ...cmd], opts); } }; // pkg/commands/decrby.ts var DecrByCommand = class extends Command { constructor(cmd, opts) { super(["decrby", ...cmd], opts); } }; // pkg/commands/del.ts var DelCommand = class extends Command { constructor(cmd, opts) { super(["del", ...cmd], opts); } }; // pkg/commands/echo.ts var EchoCommand = class extends Command { constructor(cmd, opts) { super(["echo", ...cmd], opts); } }; // pkg/commands/evalRo.ts var EvalROCommand = class extends Command { constructor([script, keys, args], opts) { super(["eval_ro", script, keys.length, ...keys, ...args ?? []], opts); } }; // pkg/commands/eval.ts var EvalCommand = class extends Command { constructor([script, keys, args], opts) { super(["eval", script, keys.length, ...keys, ...args ?? []], opts); } }; // pkg/commands/evalshaRo.ts var EvalshaROCommand = class extends Command { constructor([sha, keys, args], opts) { super(["evalsha_ro", sha, keys.length, ...keys, ...args ?? []], opts); } }; // pkg/commands/evalsha.ts var EvalshaCommand = class extends Command { constructor([sha, keys, args], opts) { super(["evalsha", sha, keys.length, ...keys, ...args ?? []], opts); } }; // pkg/commands/exec.ts var ExecCommand = class extends Command { constructor(cmd, opts) { const normalizedCmd = cmd.map((arg) => typeof arg === "string" ? arg : String(arg)); super(normalizedCmd, opts); } }; // pkg/commands/exists.ts var ExistsCommand = class extends Command { constructor(cmd, opts) { super(["exists", ...cmd], opts); } }; // pkg/commands/expire.ts var ExpireCommand = class extends Command { constructor(cmd, opts) { super(["expire", ...cmd.filter(Boolean)], opts); } }; // pkg/commands/expireat.ts var ExpireAtCommand = class extends Command { constructor(cmd, opts) { super(["expireat", ...cmd], opts); } }; // pkg/commands/flushall.ts var FlushAllCommand = class extends Command { constructor(args, opts) { const command = ["flushall"]; if (args && args.length > 0 && args[0].async) { command.push("async"); } super(command, opts); } }; // pkg/commands/flushdb.ts var FlushDBCommand = class extends Command { constructor([opts], cmdOpts) { const command = ["flushdb"]; if (opts?.async) { command.push("async"); } super(command, cmdOpts); } }; // pkg/commands/geo_add.ts var GeoAddCommand = class extends Command { constructor([key, arg1, ...arg2], opts) { const command = ["geoadd", key]; if ("nx" in arg1 && arg1.nx) { command.push("nx"); } else if ("xx" in arg1 && arg1.xx) { command.push("xx"); } if ("ch" in arg1 && arg1.ch) { command.push("ch"); } if ("latitude" in arg1 && arg1.latitude) { command.push(arg1.longitude, arg1.latitude, arg1.member); } command.push( ...arg2.flatMap(({ latitude, longitude, member }) => [longitude, latitude, member]) ); super(command, opts); } }; // pkg/commands/geo_dist.ts var GeoDistCommand = class extends Command { constructor([key, member1, member2, unit = "M"], opts) { super(["GEODIST", key, member1, member2, unit], opts); } }; // pkg/commands/geo_hash.ts var GeoHashCommand = class extends Command { constructor(cmd, opts) { const [key] = cmd; const members = Array.isArray(cmd[1]) ? cmd[1] : cmd.slice(1); super(["GEOHASH", key, ...members], opts); } }; // pkg/commands/geo_pos.ts var GeoPosCommand = class extends Command { constructor(cmd, opts) { const [key] = cmd; const members = Array.isArray(cmd[1]) ? cmd[1] : cmd.slice(1); super(["GEOPOS", key, ...members], { deserialize: (result) => transform(result), ...opts }); } }; function transform(result) { const final = []; for (const pos of result) { if (!pos?.[0] || !pos?.[1]) { continue; } final.push({ lng: Number.parseFloat(pos[0]), lat: Number.parseFloat(pos[1]) }); } return final; } // pkg/commands/geo_search.ts var GeoSearchCommand = class extends Command { constructor([key, centerPoint, shape, order, opts], commandOptions) { const command = ["GEOSEARCH", key]; if (centerPoint.type === "FROMMEMBER" || centerPoint.type === "frommember") { command.push(centerPoint.type, centerPoint.member); } if (centerPoint.type === "FROMLONLAT" || centerPoint.type === "fromlonlat") { command.push(centerPoint.type, centerPoint.coordinate.lon, centerPoint.coordinate.lat); } if (shape.type === "BYRADIUS" || shape.type === "byradius") { command.push(shape.type, shape.radius, shape.radiusType); } if (shape.type === "BYBOX" || shape.type === "bybox") { command.push(shape.type, shape.rect.width, shape.rect.height, shape.rectType); } command.push(order); if (opts?.count) { command.push("COUNT", opts.count.limit, ...opts.count.any ? ["ANY"] : []); } const transform2 = (result) => { if (!opts?.withCoord && !opts?.withDist && !opts?.withHash) { return result.map((member) => { try { return { member: JSON.parse(member) }; } catch { return { member }; } }); } return result.map((members) => { let counter = 1; const obj = {}; try { obj.member = JSON.parse(members[0]); } catch { obj.member = members[0]; } if (opts.withDist) { obj.dist = Number.parseFloat(members[counter++]); } if (opts.withHash) { obj.hash = members[counter++].toString(); } if (opts.withCoord) { obj.coord = { long: Number.parseFloat(members[counter][0]), lat: Number.parseFloat(members[counter][1]) }; } return obj; }); }; super( [ ...command, ...opts?.withCoord ? ["WITHCOORD"] : [], ...opts?.withDist ? ["WITHDIST"] : [], ...opts?.withHash ? ["WITHHASH"] : [] ], { deserialize: transform2, ...commandOptions } ); } }; // pkg/commands/geo_search_store.ts var GeoSearchStoreCommand = class extends Command { constructor([destination, key, centerPoint, shape, order, opts], commandOptions) { const command = ["GEOSEARCHSTORE", destination, key]; if (centerPoint.type === "FROMMEMBER" || centerPoint.type === "frommember") { command.push(centerPoint.type, centerPoint.member); } if (centerPoint.type === "FROMLONLAT" || centerPoint.type === "fromlonlat") { command.push(centerPoint.type, centerPoint.coordinate.lon, centerPoint.coordinate.lat); } if (shape.type === "BYRADIUS" || shape.type === "byradius") { command.push(shape.type, shape.radius, shape.radiusType); } if (shape.type === "BYBOX" || shape.type === "bybox") { command.push(shape.type, shape.rect.width, shape.rect.height, shape.rectType); } command.push(order); if (opts?.count) { command.push("COUNT", opts.count.limit, ...opts.count.any ? ["ANY"] : []); } super([...command, ...opts?.storeDist ? ["STOREDIST"] : []], commandOptions); } }; // pkg/commands/get.ts var GetCommand = class extends Command { constructor(cmd, opts) { super(["get", ...cmd], opts); } }; // pkg/commands/getbit.ts var GetBitCommand = class extends Command { constructor(cmd, opts) { super(["getbit", ...cmd], opts); } }; // pkg/commands/getdel.ts var GetDelCommand = class extends Command { constructor(cmd, opts) { super(["getdel", ...cmd], opts); } }; // pkg/commands/getex.ts var GetExCommand = class extends Command { constructor([key, opts], cmdOpts) { const command = ["getex", key]; if (opts) { if ("ex" in opts && typeof opts.ex === "number") { command.push("ex", opts.ex); } else if ("px" in opts && typeof opts.px === "number") { command.push("px", opts.px); } else if ("exat" in opts && typeof opts.exat === "number") { command.push("exat", opts.exat); } else if ("pxat" in opts && typeof opts.pxat === "number") { command.push("pxat", opts.pxat); } else if ("persist" in opts && opts.persist) { command.push("persist"); } } super(command, cmdOpts); } }; // pkg/commands/getrange.ts var GetRangeCommand = class extends Command { constructor(cmd, opts) { super(["getrange", ...cmd], opts); } }; // pkg/commands/getset.ts var GetSetCommand = class extends Command { constructor(cmd, opts) { super(["getset", ...cmd], opts); } }; // pkg/commands/hdel.ts var HDelCommand = class extends Command { constructor(cmd, opts) { super(["hdel", ...cmd], opts); } }; // pkg/commands/hexists.ts var HExistsCommand = class extends Command { constructor(cmd, opts) { super(["hexists", ...cmd], opts); } }; // pkg/commands/hexpire.ts var HExpireCommand = class extends Command { constructor(cmd, opts) { const [key, fields, seconds, option] = cmd; const fieldArray = Array.isArray(fields) ? fields : [fields]; super( [ "hexpire", key, seconds, ...option ? [option] : [], "FIELDS", fieldArray.length, ...fieldArray ], opts ); } }; // pkg/commands/hexpireat.ts var HExpireAtCommand = class extends Command { constructor(cmd, opts) { const [key, fields, timestamp, option] = cmd; const fieldArray = Array.isArray(fields) ? fields : [fields]; super( [ "hexpireat", key, timestamp, ...option ? [option] : [], "FIELDS", fieldArray.length, ...fieldArray ], opts ); } }; // pkg/commands/hexpiretime.ts var HExpireTimeCommand = class extends Command { constructor(cmd, opts) { const [key, fields] = cmd; const fieldArray = Array.isArray(fields) ? fields : [fields]; super(["hexpiretime", key, "FIELDS", fieldArray.length, ...fieldArray], opts); } }; // pkg/commands/hpersist.ts var HPersistCommand = class extends Command { constructor(cmd, opts) { const [key, fields] = cmd; const fieldArray = Array.isArray(fields) ? fields : [fields]; super(["hpersist", key, "FIELDS", fieldArray.length, ...fieldArray], opts); } }; // pkg/commands/hpexpire.ts var HPExpireCommand = class extends Command { constructor(cmd, opts) { const [key, fields, milliseconds, option] = cmd; const fieldArray = Array.isArray(fields) ? fields : [fields]; super( [ "hpexpire", key, milliseconds, ...option ? [option] : [], "FIELDS", fieldArray.length, ...fieldArray ], opts ); } }; // pkg/commands/hpexpireat.ts var HPExpireAtCommand = class extends Command { constructor(cmd, opts) { const [key, fields, timestamp, option] = cmd; const fieldArray = Array.isArray(fields) ? fields : [fields]; super( [ "hpexpireat", key, timestamp, ...option ? [option] : [], "FIELDS", fieldArray.length, ...fieldArray ], opts ); } }; // pkg/commands/hpexpiretime.ts var HPExpireTimeCommand = class extends Command { constructor(cmd, opts) { const [key, fields] = cmd; const fieldArray = Array.isArray(fields) ? fields : [fields]; super(["hpexpiretime", key, "FIELDS", fieldArray.length, ...fieldArray], opts); } }; // pkg/commands/hpttl.ts var HPTtlCommand = class extends Command { constructor(cmd, opts) { const [key, fields] = cmd; const fieldArray = Array.isArray(fields) ? fields : [fields]; super(["hpttl", key, "FIELDS", fieldArray.length, ...fieldArray], opts); } }; // pkg/commands/hget.ts var HGetCommand = class extends Command { constructor(cmd, opts) { super(["hget", ...cmd], opts); } }; // pkg/commands/hgetall.ts function deserialize(result) { if (result.length === 0) { return null; } const obj = {}; for (let i = 0; i < result.length; i += 2) { const key = result[i]; const value = result[i + 1]; try { const valueIsNumberAndNotSafeInteger = !Number.isNaN(Number(value)) && !Number.isSafeInteger(Number(value)); obj[key] = valueIsNumberAndNotSafeInteger ? value : JSON.parse(value); } catch { obj[key] = value; } } return obj; } var HGetAllCommand = class extends Command { constructor(cmd, opts) { super(["hgetall", ...cmd], { deserialize: (result) => deserialize(result), ...opts }); } }; // pkg/commands/hincrby.ts var HIncrByCommand = class extends Command { constructor(cmd, opts) { super(["hincrby", ...cmd], opts); } }; // pkg/commands/hincrbyfloat.ts var HIncrByFloatCommand = class extends Command { constructor(cmd, opts) { super(["hincrbyfloat", ...cmd], opts); } }; // pkg/commands/hkeys.ts var HKeysCommand = class extends Command { constructor([key], opts) { super(["hkeys", key], opts); } }; // pkg/commands/hlen.ts var HLenCommand = class extends Command { constructor(cmd, opts) { super(["hlen", ...cmd], opts); } }; // pkg/commands/hmget.ts function deserialize2(fields, result) { if (result.every((field) => field === null)) { return null; } const obj = {}; for (const [i, field] of fields.entries()) { try { obj[field] = JSON.parse(result[i]); } catch { obj[field] = result[i]; } } return obj; } var HMGetCommand = class extends Command { constructor([key, ...fields], opts) { super(["hmget", key, ...fields], { deserialize: (result) => deserialize2(fields, result), ...opts }); } }; // pkg/commands/hmset.ts var HMSetCommand = class extends Command { constructor([key, kv], opts) { super(["hmset", key, ...Object.entries(kv).flatMap(([field, value]) => [field, value])], opts); } }; // pkg/commands/hrandfield.ts function deserialize3(result) { if (result.length === 0) { return null; } const obj = {}; for (let i = 0; i < result.length; i += 2) { const key = result[i]; const value = result[i + 1]; try { obj[key] = JSON.parse(value); } catch { obj[key] = value; } } return obj; } var HRandFieldCommand = class extends Command { constructor(cmd, opts) { const command = ["hrandfield", cmd[0]]; if (typeof cmd[1] === "number") { command.push(cmd[1]); } if (cmd[2]) { command.push("WITHVALUES"); } super(command, { // @ts-expect-error to silence compiler deserialize: cmd[2] ? (result) => deserialize3(result) : opts?.deserialize, ...opts }); } }; // pkg/commands/hscan.ts var HScanCommand = class extends Command { constructor([key, cursor, cmdOpts], opts) { const command = ["hscan", key, cursor]; if (cmdOpts?.match) { command.push("match", cmdOpts.match); } if (typeof cmdOpts?.count === "number") { command.push("count", cmdOpts.count); } super(command, { deserialize: deserializeScanResponse, ...opts }); } }; // pkg/commands/hset.ts var HSetCommand = class extends Command { constructor([key, kv], opts) { super(["hset", key, ...Object.entries(kv).flatMap(([field, value]) => [field, value])], opts); } }; // pkg/commands/hsetnx.ts var HSetNXCommand = class extends Command { constructor(cmd, opts) { super(["hsetnx", ...cmd], opts); } }; // pkg/commands/hstrlen.ts var HStrLenCommand = class extends Command { constructor(cmd, opts) { super(["hstrlen", ...cmd], opts); } }; // pkg/commands/httl.ts var HTtlCommand = class extends Command { constructor(cmd, opts) { const [key, fields] = cmd; const fieldArray = Array.isArray(fields) ? fields : [fields]; super(["httl", key, "FIELDS", fieldArray.length, ...fieldArray], opts); } }; // pkg/commands/hvals.ts var HValsCommand = class extends Command { constructor(cmd, opts) { super(["hvals", ...cmd], opts); } }; // pkg/commands/incr.ts var IncrCommand = class extends Command { constructor(cmd, opts) { super(["incr", ...cmd], opts); } }; // pkg/commands/incrby.ts var IncrByCommand = class extends Command { constructor(cmd, opts) { super(["incrby", ...cmd], opts); } }; // pkg/commands/incrbyfloat.ts var IncrByFloatCommand = class extends Command { constructor(cmd, opts) { super(["incrbyfloat", ...cmd], opts); } }; // pkg/commands/json_arrappend.ts var JsonArrAppendCommand = class extends Command { constructor(cmd, opts) { super(["JSON.ARRAPPEND", ...cmd], opts); } }; // pkg/commands/json_arrindex.ts var JsonArrIndexCommand = class extends Command { constructor(cmd, opts) { super(["JSON.ARRINDEX", ...cmd], opts); } }; // pkg/commands/json_arrinsert.ts var JsonArrInsertCommand = class extends Command { constructor(cmd, opts) { super(["JSON.ARRINSERT", ...cmd], opts); } }; // pkg/commands/json_arrlen.ts var JsonArrLenCommand = class extends Command { constructor(cmd, opts) { super(["JSON.ARRLEN", cmd[0], cmd[1] ?? "$"], opts); } }; // pkg/commands/json_arrpop.ts var JsonArrPopCommand = class extends Command { constructor(cmd, opts) { super(["JSON.ARRPOP", ...cmd], opts); } }; // pkg/commands/json_arrtrim.ts var JsonArrTrimCommand = class extends Command { constructor(cmd, opts) { const path = cmd[1] ?? "$"; const start = cmd[2] ?? 0; const stop = cmd[3] ?? 0; super(["JSON.ARRTRIM", cmd[0], path, start, stop], opts); } }; // pkg/commands/json_clear.ts var JsonClearCommand = class extends Command { constructor(cmd, opts) { super(["JSON.CLEAR", ...cmd], opts); } }; // pkg/commands/json_del.ts var JsonDelCommand = class extends Command { constructor(cmd, opts) { super(["JSON.DEL", ...cmd], opts); } }; // pkg/commands/json_forget.ts var JsonForgetCommand = class extends Command { constructor(cmd, opts) { super(["JSON.FORGET", ...cmd], opts); } }; // pkg/commands/json_get.ts var JsonGetCommand = class extends Command { constructor(cmd, opts) { const command = ["JSON.GET"]; if (typeof cmd[1] === "string") { command.push(...cmd); } else { command.push(cmd[0]); if (cmd[1]) { if (cmd[1].indent) { command.push("INDENT", cmd[1].indent); } if (cmd[1].newline) { command.push("NEWLINE", cmd[1].newline); } if (cmd[1].space) { command.push("SPACE", cmd[1].space); } } command.push(...cmd.slice(2)); } super(command, opts); } }; // pkg/commands/json_merge.ts var JsonMergeCommand = class extends Command { constructor(cmd, opts) { const command = ["JSON.MERGE", ...cmd]; super(command, opts); } }; // pkg/commands/json_mget.ts var JsonMGetCommand = class extends Command { constructor(cmd, opts) { super(["JSON.MGET", ...cmd[0], cmd[1]], opts); } }; // pkg/commands/json_mset.ts var JsonMSetCommand = class extends Command { constructor(cmd, opts) { const command = ["JSON.MSET"]; for (const c of cmd) { command.push(c.key, c.path, c.value); } super(command, opts); } }; // pkg/commands/json_numincrby.ts var JsonNumIncrByCommand = class extends Command { constructor(cmd, opts) { super(["JSON.NUMINCRBY", ...cmd], opts); } }; // pkg/commands/json_nummultby.ts var JsonNumMultByCommand = class extends Command { constructor(cmd, opts) { super(["JSON.NUMMULTBY", ...cmd], opts); } }; // pkg/commands/json_objkeys.ts var JsonObjKeysCommand = class extends Command { constructor(cmd, opts) { super(["JSON.OBJKEYS", ...cmd], opts); } }; // pkg/commands/json_objlen.ts var JsonObjLenCommand = class extends Command { constructor(cmd, opts) { super(["JSON.OBJLEN", ...cmd], opts); } }; // pkg/commands/json_resp.ts var JsonRespCommand = class extends Command { constructor(cmd, opts) { super(["JSON.RESP", ...cmd], opts); } }; // pkg/commands/json_set.ts var JsonSetCommand = class extends Command { constructor(cmd, opts) { const command = ["JSON.SET", cmd[0], cmd[1], cmd[2]]; if (cmd[3]) { if (cmd[3].nx) { command.push("NX"); } else if (cmd[3].xx) { command.push("XX"); } } super(command, opts); } }; // pkg/commands/json_strappend.ts var JsonStrAppendCommand = class extends Command { constructor(cmd, opts) { super(["JSON.STRAPPEND", ...cmd], opts); } }; // pkg/commands/json_strlen.ts var JsonStrLenCommand = class extends Command { constructor(cmd, opts) { super(["JSON.STRLEN", ...cmd], opts); } }; // pkg/commands/json_toggle.ts var JsonToggleCommand = class extends Command { constructor(cmd, opts) { super(["JSON.TOGGLE", ...cmd], opts); } }; // pkg/commands/json_type.ts var JsonTypeCommand = class extends Command { constructor(cmd, opts) { super(["JSON.TYPE", ...cmd], opts); } }; // pkg/commands/keys.ts var KeysCommand = class extends Command { constructor(cmd, opts) { super(["keys", ...cmd], opts); } }; // pkg/commands/lindex.ts var LIndexCommand = class extends Command { constructor(cmd, opts) { super(["lindex", ...cmd], opts); } }; // pkg/commands/linsert.ts var LInsertCommand = class extends Command { constructor(cmd, opts) { super(["linsert", ...cmd], opts); } }; // pkg/commands/llen.ts var LLenCommand = class extends Command { constructor(cmd, opts) { super(["llen", ...cmd], opts); } }; // pkg/commands/lmove.ts var LMoveCommand = class extends Command { constructor(cmd, opts) { super(["lmove", ...cmd], opts); } }; // pkg/commands/lmpop.ts var LmPopCommand = class extends Command { constructor(cmd, opts) { const [numkeys, keys, direction, count] = cmd; super(["LMPOP", numkeys, ...keys, direction, ...count ? ["COUNT", count] : []], opts); } }; // pkg/commands/lpop.ts var LPopCommand = class extends Command { constructor(cmd, opts) { super(["lpop", ...cmd], opts); } }; // pkg/commands/lpos.ts var LPosCommand = class extends Command { constructor(cmd, opts) { const args = ["lpos", cmd[0], cmd[1]]; if (typeof cmd[2]?.rank === "number") { args.push("rank", cmd[2].rank); } if (typeof cmd[2]?.count === "number") { args.push("count", cmd[2].count); } if (typeof cmd[2]?.maxLen === "number") { args.push("maxLen", cmd[2].maxLen); } super(args, opts); } }; // pkg/commands/lpush.ts var LPushCommand = class extends Command { constructor(cmd, opts) { super(["lpush", ...cmd], opts); } }; // pkg/commands/lpushx.ts var LPushXCommand = class extends Command { constructor(cmd, opts) { super(["lpushx", ...cmd], opts); } }; // pkg/commands/lrange.ts var LRangeCommand = class extends Command { constructor(cmd, opts) { super(["lrange", ...cmd], opts); } }; // pkg/commands/lrem.ts var LRemCommand = class extends Command { constructor(cmd, opts) { super(["lrem", ...cmd], opts); } }; // pkg/commands/lset.ts var LSetCommand = class extends Command { constructor(cmd, opts) { super(["lset", ...cmd], opts); } }; // pkg/commands/ltrim.ts var LTrimCommand = class extends Command { constructor(cmd, opts) { super(["ltrim", ...cmd], opts); } }; // pkg/commands/mget.ts var MGetCommand = class extends Command { constructor(cmd, opts) { const keys = Array.isArray(cmd[0]) ? cmd[0] : cmd; super(["mget", ...keys], opts); } }; // pkg/commands/mset.ts var MSetCommand = class extends Command { constructor([kv], opts) { super(["mset", ...Object.entries(kv).flatMap(([key, value]) => [key, value])], opts); } }; // pkg/commands/msetnx.ts var MSetNXCommand = class extends Command { constructor([kv], opts) { super(["msetnx", ...Object.entries(kv).flat()], opts); } }; // pkg/commands/persist.ts var PersistCommand = class extends Command { constructor(cmd, opts) { super(["persist", ...cmd], opts); } }; // pkg/commands/pexpire.ts var PExpireCommand = class extends Command { constructor(cmd, opts) { super(["pexpire", ...cmd], opts); } }; // pkg/commands/pexpireat.ts var PExpireAtCommand = class extends Command { constructor(cmd, opts) { super(["pexpireat", ...cmd], opts); } }; // pkg/commands/pfadd.ts var PfAddCommand = class extends Command { constructor(cmd, opts) { super(["pfadd", ...cmd], opts); } }; // pkg/commands/pfcount.ts var PfCountCommand = class extends Command { constructor(cmd, opts) { super(["pfcount", ...cmd], opts); } }; // pkg/commands/pfmerge.ts var PfMergeCommand = class extends Command { constructor(cmd, opts) { super(["pfmerge", ...cmd], opts); } }; // pkg/commands/ping.ts var PingCommand = class extends Command { constructor(cmd, opts) { const command = ["ping"]; if (cmd?.[0] !== void 0) { command.push(cmd[0]); } super(command, opts); } }; // pkg/commands/psetex.ts var PSetEXCommand = class extends Command { constructor(cmd, opts) { super(["psetex", ...cmd], opts); } }; // pkg/commands/pttl.ts var PTtlCommand = class extends Command { constructor(cmd, opts) { super(["pttl", ...cmd], opts); } }; // pkg/commands/publish.ts var PublishCommand = class extends Command { constructor(cmd, opts) { super(["publish", ...cmd], opts); } }; // pkg/commands/randomkey.ts var RandomKeyCommand = class extends Command { constructor(opts) { super(["randomkey"], opts); } }; // pkg/commands/rename.ts var RenameCommand = class extends Command { constructor(cmd, opts) { super(["rename", ...cmd], opts); } }; // pkg/commands/renamenx.ts var RenameNXCommand = class extends Command { constructor(cmd, opts) { super(["renamenx", ...cmd], opts); } }; // pkg/commands/rpop.ts var RPopCommand = class extends Command { constructor(cmd, opts) { super(["rpop", ...cmd], opts); } }; // pkg/commands/rpush.ts var RPushCommand = class extends Command { constructor(cmd, opts) { super(["rpush", ...cmd], opts); } }; // pkg/commands/rpushx.ts var RPushXCommand = class extends Command { constructor(cmd, opts) { super(["rpushx", ...cmd], opts); } }; // pkg/commands/sadd.ts var SAddCommand = class extends Command { constructor(cmd, opts) { super(["sadd", ...cmd], opts); } }; // pkg/commands/scan.ts var ScanCommand = class extends Command { constructor([cursor, opts], cmdOpts) { const command = ["scan", cursor]; if (opts?.match) { command.push("match", opts.match); } if (typeof opts?.count === "number") { command.push("count", opts.count); } if (opts && "withType" in opts && opts.withType === true) { command.push("withtype"); } else if (opts && "type" in opts && opts.type && opts.type.length > 0) { command.push("type", opts.type); } super(command, { // @ts-expect-error ignore types here deserialize: opts?.withType ? deserializeScanWithTypesResponse : deserializeScanResponse, ...cmdOpts }); } }; // pkg/commands/scard.ts var SCardCommand = class extends Command { constructor(cmd, opts) { super(["scard", ...cmd], opts); } }; // pkg/commands/script_exists.ts var ScriptExistsCommand = class extends Command { constructor(hashes, opts) { super(["script", "exists", ...hashes], { deserialize: (result) => result, ...opts }); } }; // pkg/commands/script_flush.ts var ScriptFlushCommand = class extends Command { constructor([opts], cmdOpts) { const cmd = ["script", "flush"]; if (opts?.sync) { cmd.push("sync"); } else if (opts?.async) { cmd.push("async"); } super(cmd, cmdOpts); } }; // pkg/commands/script_load.ts var ScriptLoadCommand = class extends Command { constructor(args, opts) { super(["script", "load", ...args], opts); } }; // pkg/commands/sdiff.ts var SDiffCommand = class extends Command { constructor(cmd, opts) { super(["sdiff", ...cmd], opts); } }; // pkg/commands/sdiffstore.ts var SDiffStoreCommand = class extends Command { constructor(cmd, opts) { super(["sdiffstore", ...cmd], opts); } }; // pkg/commands/set.ts var SetCommand = class extends Command { constructor([key, value, opts], cmdOpts) { const command = ["set", key, value]; if (opts) { if ("nx" in opts && opts.nx) { command.push("nx"); } else if ("xx" in opts && opts.xx) { command.push("xx"); } if ("get" in opts && opts.get) { command.push("get"); } if ("ex" in opts && typeof opts.ex === "number") { command.push("ex", opts.ex); } else if ("px" in opts && typeof opts.px === "number") { command.push("px", opts.px); } else if ("exat" in opts && typeof opts.exat === "number") { command.push("exat", opts.exat); } else if ("pxat" in opts && typeof opts.pxat === "number") { command.push("pxat", opts.pxat); } else if ("keepTtl" in opts && opts.keepTtl) { command.push("keepTtl"); } } super(command, cmdOpts); } }; // pkg/commands/setbit.ts var SetBitCommand = class extends Command { constructor(cmd, opts) { super(["setbit", ...cmd], opts); } }; // pkg/commands/setex.ts var SetExCommand = class extends Command { constructor(cmd, opts) { super(["setex", ...cmd], opts); } }; // pkg/commands/setnx.ts var SetNxCommand = class extends Command { constructor(cmd, opts) { super(["setnx", ...cmd], opts); } }; // pkg/commands/setrange.ts var SetRangeCommand = class extends Command { constructor(cmd, opts) { super(["setrange", ...cmd], opts); } }; // pkg/commands/sinter.ts var SInterCommand = class extends Command { constructor(cmd, opts) { super(["sinter", ...cmd], opts); } }; // pkg/commands/sinterstore.ts var SInterStoreCommand = class extends Command { constructor(cmd, opts) { super(["sinterstore", ...cmd], opts); } }; // pkg/commands/sismember.ts var SIsMemberCommand = class extends Command { constructor(cmd, opts) { super(["sismember", ...cmd], opts); } }; // pkg/commands/smembers.ts var SMembersCommand = class extends Command { constructor(cmd, opts) { super(["smembers", ...cmd], opts); } }; // pkg/commands/smismember.ts var SMIsMemberCommand = class extends Command { constructor(cmd, opts) { super(["smismember", cmd[0], ...cmd[1]], opts); } }; // pkg/commands/smove.ts var SMoveCommand = class extends Command { constructor(cmd, opts) { super(["smove", ...cmd], opts); } }; // pkg/commands/spop.ts var SPopCommand = class extends Command { constructor([key, count], opts) { const command = ["spop", key]; if (typeof count === "number") { command.push(count); } super(command, opts); } }; // pkg/commands/srandmember.ts var SRandMemberCommand = class extends Command { constructor([key, count], opts) { const command = ["srandmember", key]; if (typeof count === "number") { command.push(count); } super(command, opts); } }; // pkg/commands/srem.ts var SRemCommand = class extends Command { constructor(cmd, opts) { super(["srem", ...cmd], opts); } }; // pkg/commands/sscan.ts var SScanCommand = class extends Command { constructor([key, cursor, opts], cmdOpts) { const command = ["sscan", key, cursor]; if (opts?.match) { command.push("match", opts.match); } if (typeof opts?.count === "number") { command.push("count", opts.count); } super(command, { deserialize: deserializeScanResponse, ...cmdOpts }); } }; // pkg/commands/strlen.ts var StrLenCommand = class extends Command { constructor(cmd, opts) { super(["strlen", ...cmd], opts); } }; // pkg/commands/sunion.ts var SUnionCommand = class extends Command { constructor(cmd, opts) { super(["sunion", ...cmd], opts); } }; // pkg/commands/sunionstore.ts var SUnionStoreCommand = class extends Command { constructor(cmd, opts) { super(["sunionstore", ...cmd], opts); } }; // pkg/commands/time.ts var TimeCommand = class extends Command { constructor(opts) { super(["time"], opts); } }; // pkg/commands/touch.ts var TouchCommand = class extends Command { constructor(cmd, opts) { super(["touch", ...cmd], opts); } }; // pkg/commands/ttl.ts var TtlCommand = class extends Command { constructor(cmd, opts) { super(["ttl", ...cmd], opts); } }; // pkg/commands/type.ts var TypeCommand = class extends Command { constructor(cmd, opts) { super(["type", ...cmd], opts); } }; // pkg/commands/unlink.ts var UnlinkCommand = class extends Command { constructor(cmd, opts) { super(["unlink", ...cmd], opts); } }; // pkg/commands/xack.ts var XAckCommand = class extends Command { constructor([key, group, id], opts) { const ids = Array.isArray(id) ? [...id] : [id]; super(["XACK", key, group, ...ids], opts); } }; // pkg/commands/xadd.ts var XAddCommand = class extends Command { constructor([key, id, entries, opts], commandOptions) { const command = ["XADD", key];