@upstash/redis 0.0.0-ci.8bd938831856fbab2f4aadc67ecb9de61efb6123 → 0.0.0-ci.8c525689f9001cdc6f09b0d60915e4f4a8d934a6-20250918133539

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/fastly.js CHANGED
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,36 +15,90 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
19
 
30
20
  // platforms/fastly.ts
31
21
  var fastly_exports = {};
32
22
  __export(fastly_exports, {
33
- Redis: () => Redis2
23
+ Redis: () => Redis2,
24
+ errors: () => error_exports
34
25
  });
35
26
  module.exports = __toCommonJS(fastly_exports);
36
27
 
37
28
  // pkg/error.ts
29
+ var error_exports = {};
30
+ __export(error_exports, {
31
+ UpstashError: () => UpstashError,
32
+ UrlError: () => UrlError
33
+ });
38
34
  var UpstashError = class extends Error {
39
35
  constructor(message) {
40
36
  super(message);
41
37
  this.name = "UpstashError";
42
38
  }
43
39
  };
40
+ var UrlError = class extends Error {
41
+ constructor(url) {
42
+ super(
43
+ `Upstash Redis client was passed an invalid URL. You should pass a URL starting with https. Received: "${url}". `
44
+ );
45
+ this.name = "UrlError";
46
+ }
47
+ };
48
+
49
+ // pkg/util.ts
50
+ function parseRecursive(obj) {
51
+ const parsed = Array.isArray(obj) ? obj.map((o) => {
52
+ try {
53
+ return parseRecursive(o);
54
+ } catch {
55
+ return o;
56
+ }
57
+ }) : JSON.parse(obj);
58
+ if (typeof parsed === "number" && parsed.toString() !== obj) {
59
+ return obj;
60
+ }
61
+ return parsed;
62
+ }
63
+ function parseResponse(result) {
64
+ try {
65
+ return parseRecursive(result);
66
+ } catch {
67
+ return result;
68
+ }
69
+ }
70
+ function deserializeScanResponse(result) {
71
+ return [result[0], ...parseResponse(result.slice(1))];
72
+ }
73
+ function deserializeScanWithTypesResponse(result) {
74
+ const [cursor, keys] = result;
75
+ const parsedKeys = [];
76
+ for (let i = 0; i < keys.length; i += 2) {
77
+ parsedKeys.push({ key: keys[i], type: keys[i + 1] });
78
+ }
79
+ return [cursor, parsedKeys];
80
+ }
81
+ function mergeHeaders(...headers) {
82
+ const merged = {};
83
+ for (const header of headers) {
84
+ if (!header) continue;
85
+ for (const [key, value] of Object.entries(header)) {
86
+ if (value !== void 0 && value !== null) {
87
+ merged[key] = value;
88
+ }
89
+ }
90
+ }
91
+ return merged;
92
+ }
44
93
 
45
94
  // pkg/http.ts
46
95
  var HttpClient = class {
47
96
  baseUrl;
48
97
  headers;
49
98
  options;
99
+ readYourWrites;
100
+ upstashSyncToken = "";
101
+ hasCredentials;
50
102
  retry;
51
103
  constructor(config) {
52
104
  this.options = {
@@ -54,76 +106,141 @@ var HttpClient = class {
54
106
  agent: config.agent,
55
107
  responseEncoding: config.responseEncoding ?? "base64",
56
108
  // default to base64
57
- cache: config.cache
109
+ cache: config.cache,
110
+ signal: config.signal,
111
+ keepAlive: config.keepAlive ?? true
58
112
  };
59
- this.baseUrl = config.baseUrl.replace(/\/$/, "");
113
+ this.upstashSyncToken = "";
114
+ this.readYourWrites = config.readYourWrites ?? true;
115
+ this.baseUrl = (config.baseUrl || "").replace(/\/$/, "");
116
+ const urlRegex = /^https?:\/\/[^\s#$./?].\S*$/;
117
+ if (this.baseUrl && !urlRegex.test(this.baseUrl)) {
118
+ throw new UrlError(this.baseUrl);
119
+ }
60
120
  this.headers = {
61
121
  "Content-Type": "application/json",
62
122
  ...config.headers
63
123
  };
124
+ this.hasCredentials = Boolean(this.baseUrl && this.headers.authorization.split(" ")[1]);
64
125
  if (this.options.responseEncoding === "base64") {
65
126
  this.headers["Upstash-Encoding"] = "base64";
66
127
  }
67
- if (typeof config?.retry === "boolean" && config?.retry === false) {
68
- this.retry = {
69
- attempts: 1,
70
- backoff: () => 0
71
- };
72
- } else {
73
- this.retry = {
74
- attempts: config?.retry?.retries ?? 5,
75
- backoff: config?.retry?.backoff ?? ((retryCount) => Math.exp(retryCount) * 50)
76
- };
77
- }
128
+ this.retry = typeof config.retry === "boolean" && !config.retry ? {
129
+ attempts: 1,
130
+ backoff: () => 0
131
+ } : {
132
+ attempts: config.retry?.retries ?? 5,
133
+ backoff: config.retry?.backoff ?? ((retryCount) => Math.exp(retryCount) * 50)
134
+ };
78
135
  }
79
136
  mergeTelemetry(telemetry) {
80
- function merge(obj, key, value) {
81
- if (!value) {
82
- return obj;
83
- }
84
- if (obj[key]) {
85
- obj[key] = [obj[key], value].join(",");
86
- } else {
87
- obj[key] = value;
88
- }
89
- return obj;
90
- }
91
137
  this.headers = merge(this.headers, "Upstash-Telemetry-Runtime", telemetry.runtime);
92
138
  this.headers = merge(this.headers, "Upstash-Telemetry-Platform", telemetry.platform);
93
139
  this.headers = merge(this.headers, "Upstash-Telemetry-Sdk", telemetry.sdk);
94
140
  }
95
141
  async request(req) {
142
+ const requestHeaders = mergeHeaders(this.headers, req.headers ?? {});
143
+ const requestUrl = [this.baseUrl, ...req.path ?? []].join("/");
144
+ const isEventStream = requestHeaders.Accept === "text/event-stream";
145
+ const signal = req.signal ?? this.options.signal;
146
+ const isSignalFunction = typeof signal === "function";
96
147
  const requestOptions = {
148
+ //@ts-expect-error this should throw due to bun regression
97
149
  cache: this.options.cache,
98
150
  method: "POST",
99
- headers: this.headers,
151
+ headers: requestHeaders,
100
152
  body: JSON.stringify(req.body),
101
- keepalive: true,
102
- agent: this.options?.agent,
153
+ keepalive: this.options.keepAlive,
154
+ agent: this.options.agent,
155
+ signal: isSignalFunction ? signal() : signal,
103
156
  /**
104
157
  * Fastly specific
105
158
  */
106
- backend: this.options?.backend
159
+ backend: this.options.backend
107
160
  };
161
+ if (!this.hasCredentials) {
162
+ console.warn(
163
+ "[Upstash Redis] Redis client was initialized without url or token. Failed to execute command."
164
+ );
165
+ }
166
+ if (this.readYourWrites) {
167
+ const newHeader = this.upstashSyncToken;
168
+ this.headers["upstash-sync-token"] = newHeader;
169
+ }
108
170
  let res = null;
109
171
  let error = null;
110
172
  for (let i = 0; i <= this.retry.attempts; i++) {
111
173
  try {
112
- res = await fetch([this.baseUrl, ...req.path ?? []].join("/"), requestOptions);
174
+ res = await fetch(requestUrl, requestOptions);
113
175
  break;
114
- } catch (err) {
115
- error = err;
116
- await new Promise((r) => setTimeout(r, this.retry.backoff(i)));
176
+ } catch (error_) {
177
+ if (requestOptions.signal?.aborted && isSignalFunction) {
178
+ throw error_;
179
+ } else if (requestOptions.signal?.aborted) {
180
+ const myBlob = new Blob([
181
+ JSON.stringify({ result: requestOptions.signal.reason ?? "Aborted" })
182
+ ]);
183
+ const myOptions = {
184
+ status: 200,
185
+ statusText: requestOptions.signal.reason ?? "Aborted"
186
+ };
187
+ res = new Response(myBlob, myOptions);
188
+ break;
189
+ }
190
+ error = error_;
191
+ if (i < this.retry.attempts) {
192
+ await new Promise((r) => setTimeout(r, this.retry.backoff(i)));
193
+ }
117
194
  }
118
195
  }
119
196
  if (!res) {
120
197
  throw error ?? new Error("Exhausted all retries");
121
198
  }
122
- const body = await res.json();
123
199
  if (!res.ok) {
124
- throw new UpstashError(`${body.error}, command was: ${JSON.stringify(req.body)}`);
200
+ const body2 = await res.json();
201
+ throw new UpstashError(`${body2.error}, command was: ${JSON.stringify(req.body)}`);
125
202
  }
126
- if (this.options?.responseEncoding === "base64") {
203
+ if (this.readYourWrites) {
204
+ const headers = res.headers;
205
+ this.upstashSyncToken = headers.get("upstash-sync-token") ?? "";
206
+ }
207
+ if (isEventStream && req && req.onMessage && res.body) {
208
+ const reader = res.body.getReader();
209
+ const decoder = new TextDecoder();
210
+ (async () => {
211
+ try {
212
+ while (true) {
213
+ const { value, done } = await reader.read();
214
+ if (done) break;
215
+ const chunk = decoder.decode(value);
216
+ const lines = chunk.split("\n");
217
+ for (const line of lines) {
218
+ if (line.startsWith("data: ")) {
219
+ const data = line.slice(6);
220
+ req.onMessage?.(data);
221
+ }
222
+ }
223
+ }
224
+ } catch (error2) {
225
+ if (error2 instanceof Error && error2.name === "AbortError") {
226
+ } else {
227
+ console.error("Stream reading error:", error2);
228
+ }
229
+ } finally {
230
+ try {
231
+ await reader.cancel();
232
+ } catch {
233
+ }
234
+ }
235
+ })();
236
+ return { result: 1 };
237
+ }
238
+ const body = await res.json();
239
+ if (this.readYourWrites) {
240
+ const headers = res.headers;
241
+ this.upstashSyncToken = headers.get("upstash-sync-token") ?? "";
242
+ }
243
+ if (this.options.responseEncoding === "base64") {
127
244
  if (Array.isArray(body)) {
128
245
  return body.map(({ result: result2, error: error2 }) => ({
129
246
  result: decode(result2),
@@ -154,8 +271,9 @@ function base64decode(b64) {
154
271
  function decode(raw) {
155
272
  let result = void 0;
156
273
  switch (typeof raw) {
157
- case "undefined":
274
+ case "undefined": {
158
275
  return raw;
276
+ }
159
277
  case "number": {
160
278
  result = raw;
161
279
  break;
@@ -163,7 +281,7 @@ function decode(raw) {
163
281
  case "object": {
164
282
  if (Array.isArray(raw)) {
165
283
  result = raw.map(
166
- (v) => typeof v === "string" ? base64decode(v) : Array.isArray(v) ? v.map(decode) : v
284
+ (v) => typeof v === "string" ? base64decode(v) : Array.isArray(v) ? v.map((element) => decode(element)) : v
167
285
  );
168
286
  } else {
169
287
  result = null;
@@ -174,49 +292,140 @@ function decode(raw) {
174
292
  result = raw === "OK" ? "OK" : base64decode(raw);
175
293
  break;
176
294
  }
177
- default:
295
+ default: {
178
296
  break;
297
+ }
179
298
  }
180
299
  return result;
181
300
  }
182
-
183
- // pkg/util.ts
184
- function parseRecursive(obj) {
185
- const parsed = Array.isArray(obj) ? obj.map((o) => {
186
- try {
187
- return parseRecursive(o);
188
- } catch {
189
- return o;
190
- }
191
- }) : JSON.parse(obj);
192
- if (typeof parsed === "number" && parsed.toString() !== obj) {
301
+ function merge(obj, key, value) {
302
+ if (!value) {
193
303
  return obj;
194
304
  }
195
- return parsed;
305
+ obj[key] = obj[key] ? [obj[key], value].join(",") : value;
306
+ return obj;
196
307
  }
197
- function parseResponse(result) {
198
- try {
199
- return parseRecursive(result);
200
- } catch {
201
- return result;
202
- }
308
+
309
+ // pkg/auto-pipeline.ts
310
+ var EXCLUDE_COMMANDS = /* @__PURE__ */ new Set([
311
+ "scan",
312
+ "keys",
313
+ "flushdb",
314
+ "flushall",
315
+ "dbsize",
316
+ "hscan",
317
+ "hgetall",
318
+ "hkeys",
319
+ "lrange",
320
+ "sscan",
321
+ "smembers",
322
+ "xrange",
323
+ "xrevrange",
324
+ "zscan",
325
+ "zrange",
326
+ "exec"
327
+ ]);
328
+ function createAutoPipelineProxy(_redis, json) {
329
+ const redis = _redis;
330
+ if (!redis.autoPipelineExecutor) {
331
+ redis.autoPipelineExecutor = new AutoPipelineExecutor(redis);
332
+ }
333
+ return new Proxy(redis, {
334
+ get: (redis2, command) => {
335
+ if (command === "pipelineCounter") {
336
+ return redis2.autoPipelineExecutor.pipelineCounter;
337
+ }
338
+ if (command === "json") {
339
+ return createAutoPipelineProxy(redis2, true);
340
+ }
341
+ const commandInRedisButNotPipeline = command in redis2 && !(command in redis2.autoPipelineExecutor.pipeline);
342
+ const isCommandExcluded = EXCLUDE_COMMANDS.has(command);
343
+ if (commandInRedisButNotPipeline || isCommandExcluded) {
344
+ return redis2[command];
345
+ }
346
+ const isFunction = json ? typeof redis2.autoPipelineExecutor.pipeline.json[command] === "function" : typeof redis2.autoPipelineExecutor.pipeline[command] === "function";
347
+ if (isFunction) {
348
+ return (...args) => {
349
+ return redis2.autoPipelineExecutor.withAutoPipeline((pipeline) => {
350
+ if (json) {
351
+ pipeline.json[command](
352
+ ...args
353
+ );
354
+ } else {
355
+ pipeline[command](...args);
356
+ }
357
+ });
358
+ };
359
+ }
360
+ return redis2.autoPipelineExecutor.pipeline[command];
361
+ }
362
+ });
203
363
  }
364
+ var AutoPipelineExecutor = class {
365
+ pipelinePromises = /* @__PURE__ */ new WeakMap();
366
+ activePipeline = null;
367
+ indexInCurrentPipeline = 0;
368
+ redis;
369
+ pipeline;
370
+ // only to make sure that proxy can work
371
+ pipelineCounter = 0;
372
+ // to keep track of how many times a pipeline was executed
373
+ constructor(redis) {
374
+ this.redis = redis;
375
+ this.pipeline = redis.pipeline();
376
+ }
377
+ async withAutoPipeline(executeWithPipeline) {
378
+ const pipeline = this.activePipeline ?? this.redis.pipeline();
379
+ if (!this.activePipeline) {
380
+ this.activePipeline = pipeline;
381
+ this.indexInCurrentPipeline = 0;
382
+ }
383
+ const index = this.indexInCurrentPipeline++;
384
+ executeWithPipeline(pipeline);
385
+ const pipelineDone = this.deferExecution().then(() => {
386
+ if (!this.pipelinePromises.has(pipeline)) {
387
+ const pipelinePromise = pipeline.exec({ keepErrors: true });
388
+ this.pipelineCounter += 1;
389
+ this.pipelinePromises.set(pipeline, pipelinePromise);
390
+ this.activePipeline = null;
391
+ }
392
+ return this.pipelinePromises.get(pipeline);
393
+ });
394
+ const results = await pipelineDone;
395
+ const commandResult = results[index];
396
+ if (commandResult.error) {
397
+ throw new UpstashError(`Command failed: ${commandResult.error}`);
398
+ }
399
+ return commandResult.result;
400
+ }
401
+ async deferExecution() {
402
+ await Promise.resolve();
403
+ await Promise.resolve();
404
+ }
405
+ };
204
406
 
205
407
  // pkg/commands/command.ts
206
408
  var defaultSerializer = (c) => {
207
409
  switch (typeof c) {
208
410
  case "string":
209
411
  case "number":
210
- case "boolean":
412
+ case "boolean": {
211
413
  return c;
212
- default:
414
+ }
415
+ default: {
213
416
  return JSON.stringify(c);
417
+ }
214
418
  }
215
419
  };
216
420
  var Command = class {
217
421
  command;
218
422
  serialize;
219
423
  deserialize;
424
+ headers;
425
+ path;
426
+ onMessage;
427
+ isStreaming;
428
+ signal;
220
429
  /**
221
430
  * Create a new command instance.
222
431
  *
@@ -224,21 +433,45 @@ var Command = class {
224
433
  */
225
434
  constructor(command, opts) {
226
435
  this.serialize = defaultSerializer;
227
- this.deserialize = typeof opts?.automaticDeserialization === "undefined" || opts.automaticDeserialization ? opts?.deserialize ?? parseResponse : (x) => x;
436
+ this.deserialize = opts?.automaticDeserialization === void 0 || opts.automaticDeserialization ? opts?.deserialize ?? parseResponse : (x) => x;
228
437
  this.command = command.map((c) => this.serialize(c));
438
+ this.headers = opts?.headers;
439
+ this.path = opts?.path;
440
+ this.onMessage = opts?.streamOptions?.onMessage;
441
+ this.isStreaming = opts?.streamOptions?.isStreaming ?? false;
442
+ this.signal = opts?.streamOptions?.signal;
443
+ if (opts?.latencyLogging) {
444
+ const originalExec = this.exec.bind(this);
445
+ this.exec = async (client) => {
446
+ const start = performance.now();
447
+ const result = await originalExec(client);
448
+ const end = performance.now();
449
+ const loggerResult = (end - start).toFixed(2);
450
+ console.log(
451
+ `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`
452
+ );
453
+ return result;
454
+ };
455
+ }
229
456
  }
230
457
  /**
231
458
  * Execute the command using a client.
232
459
  */
233
460
  async exec(client) {
234
461
  const { result, error } = await client.request({
235
- body: this.command
462
+ body: this.command,
463
+ path: this.path,
464
+ upstashSyncToken: client.upstashSyncToken,
465
+ headers: this.headers,
466
+ onMessage: this.onMessage,
467
+ isStreaming: this.isStreaming,
468
+ signal: this.signal
236
469
  });
237
470
  if (error) {
238
471
  throw new UpstashError(error);
239
472
  }
240
- if (typeof result === "undefined") {
241
- throw new Error("Request did not return a result");
473
+ if (result === void 0) {
474
+ throw new TypeError("Request did not return a result");
242
475
  }
243
476
  return this.deserialize(result);
244
477
  }
@@ -265,6 +498,37 @@ var BitCountCommand = class extends Command {
265
498
  }
266
499
  };
267
500
 
501
+ // pkg/commands/bitfield.ts
502
+ var BitFieldCommand = class {
503
+ constructor(args, client, opts, execOperation = (command) => command.exec(this.client)) {
504
+ this.client = client;
505
+ this.opts = opts;
506
+ this.execOperation = execOperation;
507
+ this.command = ["bitfield", ...args];
508
+ }
509
+ command;
510
+ chain(...args) {
511
+ this.command.push(...args);
512
+ return this;
513
+ }
514
+ get(...args) {
515
+ return this.chain("get", ...args);
516
+ }
517
+ set(...args) {
518
+ return this.chain("set", ...args);
519
+ }
520
+ incrby(...args) {
521
+ return this.chain("incrby", ...args);
522
+ }
523
+ overflow(overflow) {
524
+ return this.chain("overflow", overflow);
525
+ }
526
+ exec() {
527
+ const command = new Command(this.command, this.opts);
528
+ return this.execOperation(command);
529
+ }
530
+ };
531
+
268
532
  // pkg/commands/bitop.ts
269
533
  var BitOpCommand = class extends Command {
270
534
  constructor(cmd, opts) {
@@ -279,6 +543,21 @@ var BitPosCommand = class extends Command {
279
543
  }
280
544
  };
281
545
 
546
+ // pkg/commands/copy.ts
547
+ var CopyCommand = class extends Command {
548
+ constructor([key, destinationKey, opts], commandOptions) {
549
+ super(["COPY", key, destinationKey, ...opts?.replace ? ["REPLACE"] : []], {
550
+ ...commandOptions,
551
+ deserialize(result) {
552
+ if (result > 0) {
553
+ return "COPIED";
554
+ }
555
+ return "NOT_COPIED";
556
+ }
557
+ });
558
+ }
559
+ };
560
+
282
561
  // pkg/commands/dbsize.ts
283
562
  var DBSizeCommand = class extends Command {
284
563
  constructor(opts) {
@@ -314,6 +593,13 @@ var EchoCommand = class extends Command {
314
593
  }
315
594
  };
316
595
 
596
+ // pkg/commands/evalRo.ts
597
+ var EvalROCommand = class extends Command {
598
+ constructor([script, keys, args], opts) {
599
+ super(["eval_ro", script, keys.length, ...keys, ...args ?? []], opts);
600
+ }
601
+ };
602
+
317
603
  // pkg/commands/eval.ts
318
604
  var EvalCommand = class extends Command {
319
605
  constructor([script, keys, args], opts) {
@@ -321,6 +607,13 @@ var EvalCommand = class extends Command {
321
607
  }
322
608
  };
323
609
 
610
+ // pkg/commands/evalshaRo.ts
611
+ var EvalshaROCommand = class extends Command {
612
+ constructor([sha, keys, args], opts) {
613
+ super(["evalsha_ro", sha, keys.length, ...keys, ...args ?? []], opts);
614
+ }
615
+ };
616
+
324
617
  // pkg/commands/evalsha.ts
325
618
  var EvalshaCommand = class extends Command {
326
619
  constructor([sha, keys, args], opts) {
@@ -328,6 +621,14 @@ var EvalshaCommand = class extends Command {
328
621
  }
329
622
  };
330
623
 
624
+ // pkg/commands/exec.ts
625
+ var ExecCommand = class extends Command {
626
+ constructor(cmd, opts) {
627
+ const normalizedCmd = cmd.map((arg) => typeof arg === "string" ? arg : String(arg));
628
+ super(normalizedCmd, opts);
629
+ }
630
+ };
631
+
331
632
  // pkg/commands/exists.ts
332
633
  var ExistsCommand = class extends Command {
333
634
  constructor(cmd, opts) {
@@ -338,7 +639,7 @@ var ExistsCommand = class extends Command {
338
639
  // pkg/commands/expire.ts
339
640
  var ExpireCommand = class extends Command {
340
641
  constructor(cmd, opts) {
341
- super(["expire", ...cmd], opts);
642
+ super(["expire", ...cmd.filter(Boolean)], opts);
342
643
  }
343
644
  };
344
645
 
@@ -400,6 +701,129 @@ var GeoDistCommand = class extends Command {
400
701
  }
401
702
  };
402
703
 
704
+ // pkg/commands/geo_hash.ts
705
+ var GeoHashCommand = class extends Command {
706
+ constructor(cmd, opts) {
707
+ const [key] = cmd;
708
+ const members = Array.isArray(cmd[1]) ? cmd[1] : cmd.slice(1);
709
+ super(["GEOHASH", key, ...members], opts);
710
+ }
711
+ };
712
+
713
+ // pkg/commands/geo_pos.ts
714
+ var GeoPosCommand = class extends Command {
715
+ constructor(cmd, opts) {
716
+ const [key] = cmd;
717
+ const members = Array.isArray(cmd[1]) ? cmd[1] : cmd.slice(1);
718
+ super(["GEOPOS", key, ...members], {
719
+ deserialize: (result) => transform(result),
720
+ ...opts
721
+ });
722
+ }
723
+ };
724
+ function transform(result) {
725
+ const final = [];
726
+ for (const pos of result) {
727
+ if (!pos?.[0] || !pos?.[1]) {
728
+ continue;
729
+ }
730
+ final.push({ lng: Number.parseFloat(pos[0]), lat: Number.parseFloat(pos[1]) });
731
+ }
732
+ return final;
733
+ }
734
+
735
+ // pkg/commands/geo_search.ts
736
+ var GeoSearchCommand = class extends Command {
737
+ constructor([key, centerPoint, shape, order, opts], commandOptions) {
738
+ const command = ["GEOSEARCH", key];
739
+ if (centerPoint.type === "FROMMEMBER" || centerPoint.type === "frommember") {
740
+ command.push(centerPoint.type, centerPoint.member);
741
+ }
742
+ if (centerPoint.type === "FROMLONLAT" || centerPoint.type === "fromlonlat") {
743
+ command.push(centerPoint.type, centerPoint.coordinate.lon, centerPoint.coordinate.lat);
744
+ }
745
+ if (shape.type === "BYRADIUS" || shape.type === "byradius") {
746
+ command.push(shape.type, shape.radius, shape.radiusType);
747
+ }
748
+ if (shape.type === "BYBOX" || shape.type === "bybox") {
749
+ command.push(shape.type, shape.rect.width, shape.rect.height, shape.rectType);
750
+ }
751
+ command.push(order);
752
+ if (opts?.count) {
753
+ command.push("COUNT", opts.count.limit, ...opts.count.any ? ["ANY"] : []);
754
+ }
755
+ const transform2 = (result) => {
756
+ if (!opts?.withCoord && !opts?.withDist && !opts?.withHash) {
757
+ return result.map((member) => {
758
+ try {
759
+ return { member: JSON.parse(member) };
760
+ } catch {
761
+ return { member };
762
+ }
763
+ });
764
+ }
765
+ return result.map((members) => {
766
+ let counter = 1;
767
+ const obj = {};
768
+ try {
769
+ obj.member = JSON.parse(members[0]);
770
+ } catch {
771
+ obj.member = members[0];
772
+ }
773
+ if (opts.withDist) {
774
+ obj.dist = Number.parseFloat(members[counter++]);
775
+ }
776
+ if (opts.withHash) {
777
+ obj.hash = members[counter++].toString();
778
+ }
779
+ if (opts.withCoord) {
780
+ obj.coord = {
781
+ long: Number.parseFloat(members[counter][0]),
782
+ lat: Number.parseFloat(members[counter][1])
783
+ };
784
+ }
785
+ return obj;
786
+ });
787
+ };
788
+ super(
789
+ [
790
+ ...command,
791
+ ...opts?.withCoord ? ["WITHCOORD"] : [],
792
+ ...opts?.withDist ? ["WITHDIST"] : [],
793
+ ...opts?.withHash ? ["WITHHASH"] : []
794
+ ],
795
+ {
796
+ deserialize: transform2,
797
+ ...commandOptions
798
+ }
799
+ );
800
+ }
801
+ };
802
+
803
+ // pkg/commands/geo_search_store.ts
804
+ var GeoSearchStoreCommand = class extends Command {
805
+ constructor([destination, key, centerPoint, shape, order, opts], commandOptions) {
806
+ const command = ["GEOSEARCHSTORE", destination, key];
807
+ if (centerPoint.type === "FROMMEMBER" || centerPoint.type === "frommember") {
808
+ command.push(centerPoint.type, centerPoint.member);
809
+ }
810
+ if (centerPoint.type === "FROMLONLAT" || centerPoint.type === "fromlonlat") {
811
+ command.push(centerPoint.type, centerPoint.coordinate.lon, centerPoint.coordinate.lat);
812
+ }
813
+ if (shape.type === "BYRADIUS" || shape.type === "byradius") {
814
+ command.push(shape.type, shape.radius, shape.radiusType);
815
+ }
816
+ if (shape.type === "BYBOX" || shape.type === "bybox") {
817
+ command.push(shape.type, shape.rect.width, shape.rect.height, shape.rectType);
818
+ }
819
+ command.push(order);
820
+ if (opts?.count) {
821
+ command.push("COUNT", opts.count.limit, ...opts.count.any ? ["ANY"] : []);
822
+ }
823
+ super([...command, ...opts?.storeDist ? ["STOREDIST"] : []], commandOptions);
824
+ }
825
+ };
826
+
403
827
  // pkg/commands/get.ts
404
828
  var GetCommand = class extends Command {
405
829
  constructor(cmd, opts) {
@@ -421,6 +845,27 @@ var GetDelCommand = class extends Command {
421
845
  }
422
846
  };
423
847
 
848
+ // pkg/commands/getex.ts
849
+ var GetExCommand = class extends Command {
850
+ constructor([key, opts], cmdOpts) {
851
+ const command = ["getex", key];
852
+ if (opts) {
853
+ if ("ex" in opts && typeof opts.ex === "number") {
854
+ command.push("ex", opts.ex);
855
+ } else if ("px" in opts && typeof opts.px === "number") {
856
+ command.push("px", opts.px);
857
+ } else if ("exat" in opts && typeof opts.exat === "number") {
858
+ command.push("exat", opts.exat);
859
+ } else if ("pxat" in opts && typeof opts.pxat === "number") {
860
+ command.push("pxat", opts.pxat);
861
+ } else if ("persist" in opts && opts.persist) {
862
+ command.push("persist");
863
+ }
864
+ }
865
+ super(command, cmdOpts);
866
+ }
867
+ };
868
+
424
869
  // pkg/commands/getrange.ts
425
870
  var GetRangeCommand = class extends Command {
426
871
  constructor(cmd, opts) {
@@ -449,6 +894,122 @@ var HExistsCommand = class extends Command {
449
894
  }
450
895
  };
451
896
 
897
+ // pkg/commands/hexpire.ts
898
+ var HExpireCommand = class extends Command {
899
+ constructor(cmd, opts) {
900
+ const [key, fields, seconds, option] = cmd;
901
+ const fieldArray = Array.isArray(fields) ? fields : [fields];
902
+ super(
903
+ [
904
+ "hexpire",
905
+ key,
906
+ seconds,
907
+ ...option ? [option] : [],
908
+ "FIELDS",
909
+ fieldArray.length,
910
+ ...fieldArray
911
+ ],
912
+ opts
913
+ );
914
+ }
915
+ };
916
+
917
+ // pkg/commands/hexpireat.ts
918
+ var HExpireAtCommand = class extends Command {
919
+ constructor(cmd, opts) {
920
+ const [key, fields, timestamp, option] = cmd;
921
+ const fieldArray = Array.isArray(fields) ? fields : [fields];
922
+ super(
923
+ [
924
+ "hexpireat",
925
+ key,
926
+ timestamp,
927
+ ...option ? [option] : [],
928
+ "FIELDS",
929
+ fieldArray.length,
930
+ ...fieldArray
931
+ ],
932
+ opts
933
+ );
934
+ }
935
+ };
936
+
937
+ // pkg/commands/hexpiretime.ts
938
+ var HExpireTimeCommand = class extends Command {
939
+ constructor(cmd, opts) {
940
+ const [key, fields] = cmd;
941
+ const fieldArray = Array.isArray(fields) ? fields : [fields];
942
+ super(["hexpiretime", key, "FIELDS", fieldArray.length, ...fieldArray], opts);
943
+ }
944
+ };
945
+
946
+ // pkg/commands/hpersist.ts
947
+ var HPersistCommand = class extends Command {
948
+ constructor(cmd, opts) {
949
+ const [key, fields] = cmd;
950
+ const fieldArray = Array.isArray(fields) ? fields : [fields];
951
+ super(["hpersist", key, "FIELDS", fieldArray.length, ...fieldArray], opts);
952
+ }
953
+ };
954
+
955
+ // pkg/commands/hpexpire.ts
956
+ var HPExpireCommand = class extends Command {
957
+ constructor(cmd, opts) {
958
+ const [key, fields, milliseconds, option] = cmd;
959
+ const fieldArray = Array.isArray(fields) ? fields : [fields];
960
+ super(
961
+ [
962
+ "hpexpire",
963
+ key,
964
+ milliseconds,
965
+ ...option ? [option] : [],
966
+ "FIELDS",
967
+ fieldArray.length,
968
+ ...fieldArray
969
+ ],
970
+ opts
971
+ );
972
+ }
973
+ };
974
+
975
+ // pkg/commands/hpexpireat.ts
976
+ var HPExpireAtCommand = class extends Command {
977
+ constructor(cmd, opts) {
978
+ const [key, fields, timestamp, option] = cmd;
979
+ const fieldArray = Array.isArray(fields) ? fields : [fields];
980
+ super(
981
+ [
982
+ "hpexpireat",
983
+ key,
984
+ timestamp,
985
+ ...option ? [option] : [],
986
+ "FIELDS",
987
+ fieldArray.length,
988
+ ...fieldArray
989
+ ],
990
+ opts
991
+ );
992
+ }
993
+ };
994
+
995
+ // pkg/commands/hpexpiretime.ts
996
+ var HPExpireTimeCommand = class extends Command {
997
+ constructor(cmd, opts) {
998
+ const [key, fields] = cmd;
999
+ const fieldArray = Array.isArray(fields) ? fields : [fields];
1000
+ super(["hpexpiretime", key, "FIELDS", fieldArray.length, ...fieldArray], opts);
1001
+ }
1002
+ };
1003
+
1004
+ // pkg/commands/hpttl.ts
1005
+ var HPTtlCommand = class extends Command {
1006
+ constructor(cmd, opts) {
1007
+ const [key, fields] = cmd;
1008
+ const fieldArray = Array.isArray(fields) ? fields : [fields];
1009
+ super(["hpttl", key, "FIELDS", fieldArray.length, ...fieldArray], opts);
1010
+ }
1011
+ };
1012
+
452
1013
  // pkg/commands/hget.ts
453
1014
  var HGetCommand = class extends Command {
454
1015
  constructor(cmd, opts) {
@@ -462,16 +1023,12 @@ function deserialize(result) {
462
1023
  return null;
463
1024
  }
464
1025
  const obj = {};
465
- while (result.length >= 2) {
466
- const key = result.shift();
467
- const value = result.shift();
1026
+ for (let i = 0; i < result.length; i += 2) {
1027
+ const key = result[i];
1028
+ const value = result[i + 1];
468
1029
  try {
469
- const valueIsNumberAndNotSafeInteger = !Number.isNaN(Number(value)) && !Number.isSafeInteger(value);
470
- if (valueIsNumberAndNotSafeInteger) {
471
- obj[key] = value;
472
- } else {
473
- obj[key] = JSON.parse(value);
474
- }
1030
+ const valueIsNumberAndNotSafeInteger = !Number.isNaN(Number(value)) && !Number.isSafeInteger(Number(value));
1031
+ obj[key] = valueIsNumberAndNotSafeInteger ? value : JSON.parse(value);
475
1032
  } catch {
476
1033
  obj[key] = value;
477
1034
  }
@@ -517,15 +1074,15 @@ var HLenCommand = class extends Command {
517
1074
 
518
1075
  // pkg/commands/hmget.ts
519
1076
  function deserialize2(fields, result) {
520
- if (result.length === 0 || result.every((field) => field === null)) {
1077
+ if (result.every((field) => field === null)) {
521
1078
  return null;
522
1079
  }
523
1080
  const obj = {};
524
- for (let i = 0; i < fields.length; i++) {
1081
+ for (const [i, field] of fields.entries()) {
525
1082
  try {
526
- obj[fields[i]] = JSON.parse(result[i]);
1083
+ obj[field] = JSON.parse(result[i]);
527
1084
  } catch {
528
- obj[fields[i]] = result[i];
1085
+ obj[field] = result[i];
529
1086
  }
530
1087
  }
531
1088
  return obj;
@@ -552,9 +1109,9 @@ function deserialize3(result) {
552
1109
  return null;
553
1110
  }
554
1111
  const obj = {};
555
- while (result.length >= 2) {
556
- const key = result.shift();
557
- const value = result.shift();
1112
+ for (let i = 0; i < result.length; i += 2) {
1113
+ const key = result[i];
1114
+ const value = result[i + 1];
558
1115
  try {
559
1116
  obj[key] = JSON.parse(value);
560
1117
  } catch {
@@ -573,7 +1130,7 @@ var HRandFieldCommand = class extends Command {
573
1130
  command.push("WITHVALUES");
574
1131
  }
575
1132
  super(command, {
576
- // @ts-ignore TODO:
1133
+ // @ts-expect-error to silence compiler
577
1134
  deserialize: cmd[2] ? (result) => deserialize3(result) : opts?.deserialize,
578
1135
  ...opts
579
1136
  });
@@ -590,7 +1147,10 @@ var HScanCommand = class extends Command {
590
1147
  if (typeof cmdOpts?.count === "number") {
591
1148
  command.push("count", cmdOpts.count);
592
1149
  }
593
- super(command, opts);
1150
+ super(command, {
1151
+ deserialize: deserializeScanResponse,
1152
+ ...opts
1153
+ });
594
1154
  }
595
1155
  };
596
1156
 
@@ -615,6 +1175,15 @@ var HStrLenCommand = class extends Command {
615
1175
  }
616
1176
  };
617
1177
 
1178
+ // pkg/commands/httl.ts
1179
+ var HTtlCommand = class extends Command {
1180
+ constructor(cmd, opts) {
1181
+ const [key, fields] = cmd;
1182
+ const fieldArray = Array.isArray(fields) ? fields : [fields];
1183
+ super(["httl", key, "FIELDS", fieldArray.length, ...fieldArray], opts);
1184
+ }
1185
+ };
1186
+
618
1187
  // pkg/commands/hvals.ts
619
1188
  var HValsCommand = class extends Command {
620
1189
  constructor(cmd, opts) {
@@ -734,6 +1303,14 @@ var JsonGetCommand = class extends Command {
734
1303
  }
735
1304
  };
736
1305
 
1306
+ // pkg/commands/json_merge.ts
1307
+ var JsonMergeCommand = class extends Command {
1308
+ constructor(cmd, opts) {
1309
+ const command = ["JSON.MERGE", ...cmd];
1310
+ super(command, opts);
1311
+ }
1312
+ };
1313
+
737
1314
  // pkg/commands/json_mget.ts
738
1315
  var JsonMGetCommand = class extends Command {
739
1316
  constructor(cmd, opts) {
@@ -741,6 +1318,17 @@ var JsonMGetCommand = class extends Command {
741
1318
  }
742
1319
  };
743
1320
 
1321
+ // pkg/commands/json_mset.ts
1322
+ var JsonMSetCommand = class extends Command {
1323
+ constructor(cmd, opts) {
1324
+ const command = ["JSON.MSET"];
1325
+ for (const c of cmd) {
1326
+ command.push(c.key, c.path, c.value);
1327
+ }
1328
+ super(command, opts);
1329
+ }
1330
+ };
1331
+
744
1332
  // pkg/commands/json_numincrby.ts
745
1333
  var JsonNumIncrByCommand = class extends Command {
746
1334
  constructor(cmd, opts) {
@@ -854,6 +1442,14 @@ var LMoveCommand = class extends Command {
854
1442
  }
855
1443
  };
856
1444
 
1445
+ // pkg/commands/lmpop.ts
1446
+ var LmPopCommand = class extends Command {
1447
+ constructor(cmd, opts) {
1448
+ const [numkeys, keys, direction, count] = cmd;
1449
+ super(["LMPOP", numkeys, ...keys, direction, ...count ? ["COUNT", count] : []], opts);
1450
+ }
1451
+ };
1452
+
857
1453
  // pkg/commands/lpop.ts
858
1454
  var LPopCommand = class extends Command {
859
1455
  constructor(cmd, opts) {
@@ -938,7 +1534,7 @@ var MSetCommand = class extends Command {
938
1534
  // pkg/commands/msetnx.ts
939
1535
  var MSetNXCommand = class extends Command {
940
1536
  constructor([kv], opts) {
941
- super(["msetnx", ...Object.entries(kv).flatMap((_) => _)], opts);
1537
+ super(["msetnx", ...Object.entries(kv).flat()], opts);
942
1538
  }
943
1539
  };
944
1540
 
@@ -963,11 +1559,32 @@ var PExpireAtCommand = class extends Command {
963
1559
  }
964
1560
  };
965
1561
 
1562
+ // pkg/commands/pfadd.ts
1563
+ var PfAddCommand = class extends Command {
1564
+ constructor(cmd, opts) {
1565
+ super(["pfadd", ...cmd], opts);
1566
+ }
1567
+ };
1568
+
1569
+ // pkg/commands/pfcount.ts
1570
+ var PfCountCommand = class extends Command {
1571
+ constructor(cmd, opts) {
1572
+ super(["pfcount", ...cmd], opts);
1573
+ }
1574
+ };
1575
+
1576
+ // pkg/commands/pfmerge.ts
1577
+ var PfMergeCommand = class extends Command {
1578
+ constructor(cmd, opts) {
1579
+ super(["pfmerge", ...cmd], opts);
1580
+ }
1581
+ };
1582
+
966
1583
  // pkg/commands/ping.ts
967
1584
  var PingCommand = class extends Command {
968
1585
  constructor(cmd, opts) {
969
1586
  const command = ["ping"];
970
- if (typeof cmd !== "undefined" && typeof cmd[0] !== "undefined") {
1587
+ if (cmd?.[0] !== void 0) {
971
1588
  command.push(cmd[0]);
972
1589
  }
973
1590
  super(command, opts);
@@ -1054,10 +1671,16 @@ var ScanCommand = class extends Command {
1054
1671
  if (typeof opts?.count === "number") {
1055
1672
  command.push("count", opts.count);
1056
1673
  }
1057
- if (opts?.type && opts.type.length > 0) {
1674
+ if (opts && "withType" in opts && opts.withType === true) {
1675
+ command.push("withtype");
1676
+ } else if (opts && "type" in opts && opts.type && opts.type.length > 0) {
1058
1677
  command.push("type", opts.type);
1059
1678
  }
1060
- super(command, cmdOpts);
1679
+ super(command, {
1680
+ // @ts-expect-error ignore types here
1681
+ deserialize: opts?.withType ? deserializeScanWithTypesResponse : deserializeScanResponse,
1682
+ ...cmdOpts
1683
+ });
1061
1684
  }
1062
1685
  };
1063
1686
 
@@ -1250,7 +1873,10 @@ var SScanCommand = class extends Command {
1250
1873
  if (typeof opts?.count === "number") {
1251
1874
  command.push("count", opts.count);
1252
1875
  }
1253
- super(command, cmdOpts);
1876
+ super(command, {
1877
+ deserialize: deserializeScanResponse,
1878
+ ...cmdOpts
1879
+ });
1254
1880
  }
1255
1881
  };
1256
1882
 
@@ -1310,6 +1936,14 @@ var UnlinkCommand = class extends Command {
1310
1936
  }
1311
1937
  };
1312
1938
 
1939
+ // pkg/commands/xack.ts
1940
+ var XAckCommand = class extends Command {
1941
+ constructor([key, group, id], opts) {
1942
+ const ids = Array.isArray(id) ? [...id] : [id];
1943
+ super(["XACK", key, group, ...ids], opts);
1944
+ }
1945
+ };
1946
+
1313
1947
  // pkg/commands/xadd.ts
1314
1948
  var XAddCommand = class extends Command {
1315
1949
  constructor([key, id, entries, opts], commandOptions) {
@@ -1320,7 +1954,7 @@ var XAddCommand = class extends Command {
1320
1954
  }
1321
1955
  if (opts.trim) {
1322
1956
  command.push(opts.trim.type, opts.trim.comparison, opts.trim.threshold);
1323
- if (typeof opts.trim.limit !== "undefined") {
1957
+ if (opts.trim.limit !== void 0) {
1324
1958
  command.push("LIMIT", opts.trim.limit);
1325
1959
  }
1326
1960
  }
@@ -1333,19 +1967,152 @@ var XAddCommand = class extends Command {
1333
1967
  }
1334
1968
  };
1335
1969
 
1970
+ // pkg/commands/xautoclaim.ts
1971
+ var XAutoClaim = class extends Command {
1972
+ constructor([key, group, consumer, minIdleTime, start, options], opts) {
1973
+ const commands = [];
1974
+ if (options?.count) {
1975
+ commands.push("COUNT", options.count);
1976
+ }
1977
+ if (options?.justId) {
1978
+ commands.push("JUSTID");
1979
+ }
1980
+ super(["XAUTOCLAIM", key, group, consumer, minIdleTime, start, ...commands], opts);
1981
+ }
1982
+ };
1983
+
1984
+ // pkg/commands/xclaim.ts
1985
+ var XClaimCommand = class extends Command {
1986
+ constructor([key, group, consumer, minIdleTime, id, options], opts) {
1987
+ const ids = Array.isArray(id) ? [...id] : [id];
1988
+ const commands = [];
1989
+ if (options?.idleMS) {
1990
+ commands.push("IDLE", options.idleMS);
1991
+ }
1992
+ if (options?.idleMS) {
1993
+ commands.push("TIME", options.timeMS);
1994
+ }
1995
+ if (options?.retryCount) {
1996
+ commands.push("RETRYCOUNT", options.retryCount);
1997
+ }
1998
+ if (options?.force) {
1999
+ commands.push("FORCE");
2000
+ }
2001
+ if (options?.justId) {
2002
+ commands.push("JUSTID");
2003
+ }
2004
+ if (options?.lastId) {
2005
+ commands.push("LASTID", options.lastId);
2006
+ }
2007
+ super(["XCLAIM", key, group, consumer, minIdleTime, ...ids, ...commands], opts);
2008
+ }
2009
+ };
2010
+
2011
+ // pkg/commands/xdel.ts
2012
+ var XDelCommand = class extends Command {
2013
+ constructor([key, ids], opts) {
2014
+ const cmds = Array.isArray(ids) ? [...ids] : [ids];
2015
+ super(["XDEL", key, ...cmds], opts);
2016
+ }
2017
+ };
2018
+
2019
+ // pkg/commands/xgroup.ts
2020
+ var XGroupCommand = class extends Command {
2021
+ constructor([key, opts], commandOptions) {
2022
+ const command = ["XGROUP"];
2023
+ switch (opts.type) {
2024
+ case "CREATE": {
2025
+ command.push("CREATE", key, opts.group, opts.id);
2026
+ if (opts.options) {
2027
+ if (opts.options.MKSTREAM) {
2028
+ command.push("MKSTREAM");
2029
+ }
2030
+ if (opts.options.ENTRIESREAD !== void 0) {
2031
+ command.push("ENTRIESREAD", opts.options.ENTRIESREAD.toString());
2032
+ }
2033
+ }
2034
+ break;
2035
+ }
2036
+ case "CREATECONSUMER": {
2037
+ command.push("CREATECONSUMER", key, opts.group, opts.consumer);
2038
+ break;
2039
+ }
2040
+ case "DELCONSUMER": {
2041
+ command.push("DELCONSUMER", key, opts.group, opts.consumer);
2042
+ break;
2043
+ }
2044
+ case "DESTROY": {
2045
+ command.push("DESTROY", key, opts.group);
2046
+ break;
2047
+ }
2048
+ case "SETID": {
2049
+ command.push("SETID", key, opts.group, opts.id);
2050
+ if (opts.options?.ENTRIESREAD !== void 0) {
2051
+ command.push("ENTRIESREAD", opts.options.ENTRIESREAD.toString());
2052
+ }
2053
+ break;
2054
+ }
2055
+ default: {
2056
+ throw new Error("Invalid XGROUP");
2057
+ }
2058
+ }
2059
+ super(command, commandOptions);
2060
+ }
2061
+ };
2062
+
2063
+ // pkg/commands/xinfo.ts
2064
+ var XInfoCommand = class extends Command {
2065
+ constructor([key, options], opts) {
2066
+ const cmds = [];
2067
+ if (options.type === "CONSUMERS") {
2068
+ cmds.push("CONSUMERS", key, options.group);
2069
+ } else {
2070
+ cmds.push("GROUPS", key);
2071
+ }
2072
+ super(["XINFO", ...cmds], opts);
2073
+ }
2074
+ };
2075
+
2076
+ // pkg/commands/xlen.ts
2077
+ var XLenCommand = class extends Command {
2078
+ constructor(cmd, opts) {
2079
+ super(["XLEN", ...cmd], opts);
2080
+ }
2081
+ };
2082
+
2083
+ // pkg/commands/xpending.ts
2084
+ var XPendingCommand = class extends Command {
2085
+ constructor([key, group, start, end, count, options], opts) {
2086
+ const consumers = options?.consumer === void 0 ? [] : Array.isArray(options.consumer) ? [...options.consumer] : [options.consumer];
2087
+ super(
2088
+ [
2089
+ "XPENDING",
2090
+ key,
2091
+ group,
2092
+ ...options?.idleTime ? ["IDLE", options.idleTime] : [],
2093
+ start,
2094
+ end,
2095
+ count,
2096
+ ...consumers
2097
+ ],
2098
+ opts
2099
+ );
2100
+ }
2101
+ };
2102
+
1336
2103
  // pkg/commands/xrange.ts
1337
2104
  function deserialize4(result) {
1338
2105
  const obj = {};
1339
2106
  for (const e of result) {
1340
- while (e.length >= 2) {
1341
- const streamId = e.shift();
1342
- const entries = e.shift();
2107
+ for (let i = 0; i < e.length; i += 2) {
2108
+ const streamId = e[i];
2109
+ const entries = e[i + 1];
1343
2110
  if (!(streamId in obj)) {
1344
2111
  obj[streamId] = {};
1345
2112
  }
1346
- while (entries.length >= 2) {
1347
- const field = entries.shift();
1348
- const value = entries.shift();
2113
+ for (let j = 0; j < entries.length; j += 2) {
2114
+ const field = entries[j];
2115
+ const value = entries[j + 1];
1349
2116
  try {
1350
2117
  obj[streamId][field] = JSON.parse(value);
1351
2118
  } catch {
@@ -1369,6 +2136,99 @@ var XRangeCommand = class extends Command {
1369
2136
  }
1370
2137
  };
1371
2138
 
2139
+ // pkg/commands/xread.ts
2140
+ var UNBALANCED_XREAD_ERR = "ERR Unbalanced XREAD list of streams: for each stream key an ID or '$' must be specified";
2141
+ var XReadCommand = class extends Command {
2142
+ constructor([key, id, options], opts) {
2143
+ if (Array.isArray(key) && Array.isArray(id) && key.length !== id.length) {
2144
+ throw new Error(UNBALANCED_XREAD_ERR);
2145
+ }
2146
+ const commands = [];
2147
+ if (typeof options?.count === "number") {
2148
+ commands.push("COUNT", options.count);
2149
+ }
2150
+ if (typeof options?.blockMS === "number") {
2151
+ commands.push("BLOCK", options.blockMS);
2152
+ }
2153
+ commands.push(
2154
+ "STREAMS",
2155
+ ...Array.isArray(key) ? [...key] : [key],
2156
+ ...Array.isArray(id) ? [...id] : [id]
2157
+ );
2158
+ super(["XREAD", ...commands], opts);
2159
+ }
2160
+ };
2161
+
2162
+ // pkg/commands/xreadgroup.ts
2163
+ var UNBALANCED_XREADGROUP_ERR = "ERR Unbalanced XREADGROUP list of streams: for each stream key an ID or '$' must be specified";
2164
+ var XReadGroupCommand = class extends Command {
2165
+ constructor([group, consumer, key, id, options], opts) {
2166
+ if (Array.isArray(key) && Array.isArray(id) && key.length !== id.length) {
2167
+ throw new Error(UNBALANCED_XREADGROUP_ERR);
2168
+ }
2169
+ const commands = [];
2170
+ if (typeof options?.count === "number") {
2171
+ commands.push("COUNT", options.count);
2172
+ }
2173
+ if (typeof options?.blockMS === "number") {
2174
+ commands.push("BLOCK", options.blockMS);
2175
+ }
2176
+ if (typeof options?.NOACK === "boolean" && options.NOACK) {
2177
+ commands.push("NOACK");
2178
+ }
2179
+ commands.push(
2180
+ "STREAMS",
2181
+ ...Array.isArray(key) ? [...key] : [key],
2182
+ ...Array.isArray(id) ? [...id] : [id]
2183
+ );
2184
+ super(["XREADGROUP", "GROUP", group, consumer, ...commands], opts);
2185
+ }
2186
+ };
2187
+
2188
+ // pkg/commands/xrevrange.ts
2189
+ var XRevRangeCommand = class extends Command {
2190
+ constructor([key, end, start, count], opts) {
2191
+ const command = ["XREVRANGE", key, end, start];
2192
+ if (typeof count === "number") {
2193
+ command.push("COUNT", count);
2194
+ }
2195
+ super(command, {
2196
+ deserialize: (result) => deserialize5(result),
2197
+ ...opts
2198
+ });
2199
+ }
2200
+ };
2201
+ function deserialize5(result) {
2202
+ const obj = {};
2203
+ for (const e of result) {
2204
+ for (let i = 0; i < e.length; i += 2) {
2205
+ const streamId = e[i];
2206
+ const entries = e[i + 1];
2207
+ if (!(streamId in obj)) {
2208
+ obj[streamId] = {};
2209
+ }
2210
+ for (let j = 0; j < entries.length; j += 2) {
2211
+ const field = entries[j];
2212
+ const value = entries[j + 1];
2213
+ try {
2214
+ obj[streamId][field] = JSON.parse(value);
2215
+ } catch {
2216
+ obj[streamId][field] = value;
2217
+ }
2218
+ }
2219
+ }
2220
+ }
2221
+ return obj;
2222
+ }
2223
+
2224
+ // pkg/commands/xtrim.ts
2225
+ var XTrimCommand = class extends Command {
2226
+ constructor([key, options], opts) {
2227
+ const { limit, strategy, threshold, exactness = "~" } = options;
2228
+ super(["XTRIM", key, strategy, exactness, threshold, ...limit ? ["LIMIT", limit] : []], opts);
2229
+ }
2230
+ };
2231
+
1372
2232
  // pkg/commands/zadd.ts
1373
2233
  var ZAddCommand = class extends Command {
1374
2234
  constructor([key, arg1, ...arg2], opts) {
@@ -1384,6 +2244,11 @@ var ZAddCommand = class extends Command {
1384
2244
  if ("incr" in arg1 && arg1.incr) {
1385
2245
  command.push("incr");
1386
2246
  }
2247
+ if ("lt" in arg1 && arg1.lt) {
2248
+ command.push("lt");
2249
+ } else if ("gt" in arg1 && arg1.gt) {
2250
+ command.push("gt");
2251
+ }
1387
2252
  if ("score" in arg1 && "member" in arg1) {
1388
2253
  command.push(arg1.score, arg1.member);
1389
2254
  }
@@ -1478,7 +2343,7 @@ var ZRangeCommand = class extends Command {
1478
2343
  if (opts?.rev) {
1479
2344
  command.push("rev");
1480
2345
  }
1481
- if (typeof opts?.count !== "undefined" && typeof opts?.offset !== "undefined") {
2346
+ if (opts?.count !== void 0 && opts.offset !== void 0) {
1482
2347
  command.push("limit", opts.offset, opts.count);
1483
2348
  }
1484
2349
  if (opts?.withScores) {
@@ -1540,7 +2405,10 @@ var ZScanCommand = class extends Command {
1540
2405
  if (typeof opts?.count === "number") {
1541
2406
  command.push("count", opts.count);
1542
2407
  }
1543
- super(command, cmdOpts);
2408
+ super(command, {
2409
+ deserialize: deserializeScanResponse,
2410
+ ...cmdOpts
2411
+ });
1544
2412
  }
1545
2413
  };
1546
2414
 
@@ -1569,7 +2437,7 @@ var ZUnionCommand = class extends Command {
1569
2437
  if ("aggregate" in opts) {
1570
2438
  command.push("aggregate", opts.aggregate);
1571
2439
  }
1572
- if (opts?.withScores) {
2440
+ if (opts.withScores) {
1573
2441
  command.push("withscores");
1574
2442
  }
1575
2443
  }
@@ -1600,6 +2468,183 @@ var ZUnionStoreCommand = class extends Command {
1600
2468
  }
1601
2469
  };
1602
2470
 
2471
+ // pkg/commands/psubscribe.ts
2472
+ var PSubscribeCommand = class extends Command {
2473
+ constructor(cmd, opts) {
2474
+ const sseHeaders = {
2475
+ Accept: "text/event-stream",
2476
+ "Cache-Control": "no-cache",
2477
+ Connection: "keep-alive"
2478
+ };
2479
+ super([], {
2480
+ ...opts,
2481
+ headers: sseHeaders,
2482
+ path: ["psubscribe", ...cmd],
2483
+ streamOptions: {
2484
+ isStreaming: true,
2485
+ onMessage: opts?.streamOptions?.onMessage,
2486
+ signal: opts?.streamOptions?.signal
2487
+ }
2488
+ });
2489
+ }
2490
+ };
2491
+
2492
+ // pkg/commands/subscribe.ts
2493
+ var Subscriber = class extends EventTarget {
2494
+ subscriptions;
2495
+ client;
2496
+ listeners;
2497
+ constructor(client, channels, isPattern = false) {
2498
+ super();
2499
+ this.client = client;
2500
+ this.subscriptions = /* @__PURE__ */ new Map();
2501
+ this.listeners = /* @__PURE__ */ new Map();
2502
+ for (const channel of channels) {
2503
+ if (isPattern) {
2504
+ this.subscribeToPattern(channel);
2505
+ } else {
2506
+ this.subscribeToChannel(channel);
2507
+ }
2508
+ }
2509
+ }
2510
+ subscribeToChannel(channel) {
2511
+ const controller = new AbortController();
2512
+ const command = new SubscribeCommand([channel], {
2513
+ streamOptions: {
2514
+ signal: controller.signal,
2515
+ onMessage: (data) => this.handleMessage(data, false)
2516
+ }
2517
+ });
2518
+ command.exec(this.client).catch((error) => {
2519
+ if (error.name !== "AbortError") {
2520
+ this.dispatchToListeners("error", error);
2521
+ }
2522
+ });
2523
+ this.subscriptions.set(channel, {
2524
+ command,
2525
+ controller,
2526
+ isPattern: false
2527
+ });
2528
+ }
2529
+ subscribeToPattern(pattern) {
2530
+ const controller = new AbortController();
2531
+ const command = new PSubscribeCommand([pattern], {
2532
+ streamOptions: {
2533
+ signal: controller.signal,
2534
+ onMessage: (data) => this.handleMessage(data, true)
2535
+ }
2536
+ });
2537
+ command.exec(this.client).catch((error) => {
2538
+ if (error.name !== "AbortError") {
2539
+ this.dispatchToListeners("error", error);
2540
+ }
2541
+ });
2542
+ this.subscriptions.set(pattern, {
2543
+ command,
2544
+ controller,
2545
+ isPattern: true
2546
+ });
2547
+ }
2548
+ handleMessage(data, isPattern) {
2549
+ const messageData = data.replace(/^data:\s*/, "");
2550
+ const firstCommaIndex = messageData.indexOf(",");
2551
+ const secondCommaIndex = messageData.indexOf(",", firstCommaIndex + 1);
2552
+ const thirdCommaIndex = isPattern ? messageData.indexOf(",", secondCommaIndex + 1) : -1;
2553
+ if (firstCommaIndex !== -1 && secondCommaIndex !== -1) {
2554
+ const type = messageData.slice(0, firstCommaIndex);
2555
+ if (isPattern && type === "pmessage" && thirdCommaIndex !== -1) {
2556
+ const pattern = messageData.slice(firstCommaIndex + 1, secondCommaIndex);
2557
+ const channel = messageData.slice(secondCommaIndex + 1, thirdCommaIndex);
2558
+ const messageStr = messageData.slice(thirdCommaIndex + 1);
2559
+ try {
2560
+ const message = JSON.parse(messageStr);
2561
+ this.dispatchToListeners("pmessage", { pattern, channel, message });
2562
+ this.dispatchToListeners(`pmessage:${pattern}`, { pattern, channel, message });
2563
+ } catch (error) {
2564
+ this.dispatchToListeners("error", new Error(`Failed to parse message: ${error}`));
2565
+ }
2566
+ } else {
2567
+ const channel = messageData.slice(firstCommaIndex + 1, secondCommaIndex);
2568
+ const messageStr = messageData.slice(secondCommaIndex + 1);
2569
+ try {
2570
+ if (type === "subscribe" || type === "psubscribe" || type === "unsubscribe" || type === "punsubscribe") {
2571
+ const count = Number.parseInt(messageStr);
2572
+ this.dispatchToListeners(type, count);
2573
+ } else {
2574
+ const message = JSON.parse(messageStr);
2575
+ this.dispatchToListeners(type, { channel, message });
2576
+ this.dispatchToListeners(`${type}:${channel}`, { channel, message });
2577
+ }
2578
+ } catch (error) {
2579
+ this.dispatchToListeners("error", new Error(`Failed to parse message: ${error}`));
2580
+ }
2581
+ }
2582
+ }
2583
+ }
2584
+ dispatchToListeners(type, data) {
2585
+ const listeners = this.listeners.get(type);
2586
+ if (listeners) {
2587
+ for (const listener of listeners) {
2588
+ listener(data);
2589
+ }
2590
+ }
2591
+ }
2592
+ on(type, listener) {
2593
+ if (!this.listeners.has(type)) {
2594
+ this.listeners.set(type, /* @__PURE__ */ new Set());
2595
+ }
2596
+ this.listeners.get(type)?.add(listener);
2597
+ }
2598
+ removeAllListeners() {
2599
+ this.listeners.clear();
2600
+ }
2601
+ async unsubscribe(channels) {
2602
+ if (channels) {
2603
+ for (const channel of channels) {
2604
+ const subscription = this.subscriptions.get(channel);
2605
+ if (subscription) {
2606
+ try {
2607
+ subscription.controller.abort();
2608
+ } catch {
2609
+ }
2610
+ this.subscriptions.delete(channel);
2611
+ }
2612
+ }
2613
+ } else {
2614
+ for (const subscription of this.subscriptions.values()) {
2615
+ try {
2616
+ subscription.controller.abort();
2617
+ } catch {
2618
+ }
2619
+ }
2620
+ this.subscriptions.clear();
2621
+ this.removeAllListeners();
2622
+ }
2623
+ }
2624
+ getSubscribedChannels() {
2625
+ return [...this.subscriptions.keys()];
2626
+ }
2627
+ };
2628
+ var SubscribeCommand = class extends Command {
2629
+ constructor(cmd, opts) {
2630
+ const sseHeaders = {
2631
+ Accept: "text/event-stream",
2632
+ "Cache-Control": "no-cache",
2633
+ Connection: "keep-alive"
2634
+ };
2635
+ super([], {
2636
+ ...opts,
2637
+ headers: sseHeaders,
2638
+ path: ["subscribe", ...cmd],
2639
+ streamOptions: {
2640
+ isStreaming: true,
2641
+ onMessage: opts?.streamOptions?.onMessage,
2642
+ signal: opts?.streamOptions?.signal
2643
+ }
2644
+ });
2645
+ }
2646
+ };
2647
+
1603
2648
  // pkg/commands/zdiffstore.ts
1604
2649
  var ZDiffStoreCommand = class extends Command {
1605
2650
  constructor(cmd, opts) {
@@ -1625,21 +2670,22 @@ var Pipeline = class {
1625
2670
  this.client = opts.client;
1626
2671
  this.commands = [];
1627
2672
  this.commandOptions = opts.commandOptions;
1628
- this.multiExec = opts.multiExec ?? false;
1629
- }
1630
- /**
1631
- * Send the pipeline request to upstash.
1632
- *
1633
- * Returns an array with the results of all pipelined commands.
1634
- *
1635
- * If all commands are statically chained from start to finish, types are inferred. You can still define a return type manually if necessary though:
1636
- * ```ts
1637
- * const p = redis.pipeline()
1638
- * p.get("key")
1639
- * const result = p.exec<[{ greeting: string }]>()
1640
- * ```
1641
- */
1642
- exec = async () => {
2673
+ this.multiExec = opts.multiExec ?? false;
2674
+ if (this.commandOptions?.latencyLogging) {
2675
+ const originalExec = this.exec.bind(this);
2676
+ this.exec = async (options) => {
2677
+ const start = performance.now();
2678
+ const result = await (options ? originalExec(options) : originalExec());
2679
+ const end = performance.now();
2680
+ const loggerResult = (end - start).toFixed(2);
2681
+ console.log(
2682
+ `Latency for \x1B[38;2;19;185;39m${this.multiExec ? ["MULTI-EXEC"] : ["PIPELINE"].toString().toUpperCase()}\x1B[0m: \x1B[38;2;0;255;255m${loggerResult} ms\x1B[0m`
2683
+ );
2684
+ return result;
2685
+ };
2686
+ }
2687
+ }
2688
+ exec = async (options) => {
1643
2689
  if (this.commands.length === 0) {
1644
2690
  throw new Error("Pipeline is empty");
1645
2691
  }
@@ -1648,7 +2694,12 @@ var Pipeline = class {
1648
2694
  path,
1649
2695
  body: Object.values(this.commands).map((c) => c.command)
1650
2696
  });
1651
- return res.map(({ error, result }, i) => {
2697
+ return options?.keepErrors ? res.map(({ error, result }, i) => {
2698
+ return {
2699
+ error,
2700
+ result: this.commands[i].deserialize(result)
2701
+ };
2702
+ }) : res.map(({ error, result }, i) => {
1652
2703
  if (error) {
1653
2704
  throw new UpstashError(
1654
2705
  `Command ${i + 1} [ ${this.commands[i].command[0]} ] failed: ${error}`
@@ -1679,6 +2730,23 @@ var Pipeline = class {
1679
2730
  * @see https://redis.io/commands/bitcount
1680
2731
  */
1681
2732
  bitcount = (...args) => this.chain(new BitCountCommand(args, this.commandOptions));
2733
+ /**
2734
+ * Returns an instance that can be used to execute `BITFIELD` commands on one key.
2735
+ *
2736
+ * @example
2737
+ * ```typescript
2738
+ * redis.set("mykey", 0);
2739
+ * const result = await redis.pipeline()
2740
+ * .bitfield("mykey")
2741
+ * .set("u4", 0, 16)
2742
+ * .incr("u4", "#1", 1)
2743
+ * .exec();
2744
+ * console.log(result); // [[0, 1]]
2745
+ * ```
2746
+ *
2747
+ * @see https://redis.io/commands/bitfield
2748
+ */
2749
+ bitfield = (...args) => new BitFieldCommand(args, this.client, this.commandOptions, this.chain.bind(this));
1682
2750
  /**
1683
2751
  * @see https://redis.io/commands/bitop
1684
2752
  */
@@ -1689,6 +2757,10 @@ var Pipeline = class {
1689
2757
  * @see https://redis.io/commands/bitpos
1690
2758
  */
1691
2759
  bitpos = (...args) => this.chain(new BitPosCommand(args, this.commandOptions));
2760
+ /**
2761
+ * @see https://redis.io/commands/copy
2762
+ */
2763
+ copy = (...args) => this.chain(new CopyCommand(args, this.commandOptions));
1692
2764
  /**
1693
2765
  * @see https://redis.io/commands/zdiffstore
1694
2766
  */
@@ -1713,10 +2785,18 @@ var Pipeline = class {
1713
2785
  * @see https://redis.io/commands/echo
1714
2786
  */
1715
2787
  echo = (...args) => this.chain(new EchoCommand(args, this.commandOptions));
2788
+ /**
2789
+ * @see https://redis.io/commands/eval_ro
2790
+ */
2791
+ evalRo = (...args) => this.chain(new EvalROCommand(args, this.commandOptions));
1716
2792
  /**
1717
2793
  * @see https://redis.io/commands/eval
1718
2794
  */
1719
2795
  eval = (...args) => this.chain(new EvalCommand(args, this.commandOptions));
2796
+ /**
2797
+ * @see https://redis.io/commands/evalsha_ro
2798
+ */
2799
+ evalshaRo = (...args) => this.chain(new EvalshaROCommand(args, this.commandOptions));
1720
2800
  /**
1721
2801
  * @see https://redis.io/commands/evalsha
1722
2802
  */
@@ -1741,6 +2821,30 @@ var Pipeline = class {
1741
2821
  * @see https://redis.io/commands/flushdb
1742
2822
  */
1743
2823
  flushdb = (...args) => this.chain(new FlushDBCommand(args, this.commandOptions));
2824
+ /**
2825
+ * @see https://redis.io/commands/geoadd
2826
+ */
2827
+ geoadd = (...args) => this.chain(new GeoAddCommand(args, this.commandOptions));
2828
+ /**
2829
+ * @see https://redis.io/commands/geodist
2830
+ */
2831
+ geodist = (...args) => this.chain(new GeoDistCommand(args, this.commandOptions));
2832
+ /**
2833
+ * @see https://redis.io/commands/geopos
2834
+ */
2835
+ geopos = (...args) => this.chain(new GeoPosCommand(args, this.commandOptions));
2836
+ /**
2837
+ * @see https://redis.io/commands/geohash
2838
+ */
2839
+ geohash = (...args) => this.chain(new GeoHashCommand(args, this.commandOptions));
2840
+ /**
2841
+ * @see https://redis.io/commands/geosearch
2842
+ */
2843
+ geosearch = (...args) => this.chain(new GeoSearchCommand(args, this.commandOptions));
2844
+ /**
2845
+ * @see https://redis.io/commands/geosearchstore
2846
+ */
2847
+ geosearchstore = (...args) => this.chain(new GeoSearchStoreCommand(args, this.commandOptions));
1744
2848
  /**
1745
2849
  * @see https://redis.io/commands/get
1746
2850
  */
@@ -1753,6 +2857,10 @@ var Pipeline = class {
1753
2857
  * @see https://redis.io/commands/getdel
1754
2858
  */
1755
2859
  getdel = (...args) => this.chain(new GetDelCommand(args, this.commandOptions));
2860
+ /**
2861
+ * @see https://redis.io/commands/getex
2862
+ */
2863
+ getex = (...args) => this.chain(new GetExCommand(args, this.commandOptions));
1756
2864
  /**
1757
2865
  * @see https://redis.io/commands/getrange
1758
2866
  */
@@ -1769,6 +2877,42 @@ var Pipeline = class {
1769
2877
  * @see https://redis.io/commands/hexists
1770
2878
  */
1771
2879
  hexists = (...args) => this.chain(new HExistsCommand(args, this.commandOptions));
2880
+ /**
2881
+ * @see https://redis.io/commands/hexpire
2882
+ */
2883
+ hexpire = (...args) => this.chain(new HExpireCommand(args, this.commandOptions));
2884
+ /**
2885
+ * @see https://redis.io/commands/hexpireat
2886
+ */
2887
+ hexpireat = (...args) => this.chain(new HExpireAtCommand(args, this.commandOptions));
2888
+ /**
2889
+ * @see https://redis.io/commands/hexpiretime
2890
+ */
2891
+ hexpiretime = (...args) => this.chain(new HExpireTimeCommand(args, this.commandOptions));
2892
+ /**
2893
+ * @see https://redis.io/commands/httl
2894
+ */
2895
+ httl = (...args) => this.chain(new HTtlCommand(args, this.commandOptions));
2896
+ /**
2897
+ * @see https://redis.io/commands/hpexpire
2898
+ */
2899
+ hpexpire = (...args) => this.chain(new HPExpireCommand(args, this.commandOptions));
2900
+ /**
2901
+ * @see https://redis.io/commands/hpexpireat
2902
+ */
2903
+ hpexpireat = (...args) => this.chain(new HPExpireAtCommand(args, this.commandOptions));
2904
+ /**
2905
+ * @see https://redis.io/commands/hpexpiretime
2906
+ */
2907
+ hpexpiretime = (...args) => this.chain(new HPExpireTimeCommand(args, this.commandOptions));
2908
+ /**
2909
+ * @see https://redis.io/commands/hpttl
2910
+ */
2911
+ hpttl = (...args) => this.chain(new HPTtlCommand(args, this.commandOptions));
2912
+ /**
2913
+ * @see https://redis.io/commands/hpersist
2914
+ */
2915
+ hpersist = (...args) => this.chain(new HPersistCommand(args, this.commandOptions));
1772
2916
  /**
1773
2917
  * @see https://redis.io/commands/hget
1774
2918
  */
@@ -1861,6 +3005,10 @@ var Pipeline = class {
1861
3005
  * @see https://redis.io/commands/lpop
1862
3006
  */
1863
3007
  lpop = (...args) => this.chain(new LPopCommand(args, this.commandOptions));
3008
+ /**
3009
+ * @see https://redis.io/commands/lmpop
3010
+ */
3011
+ lmpop = (...args) => this.chain(new LmPopCommand(args, this.commandOptions));
1864
3012
  /**
1865
3013
  * @see https://redis.io/commands/lpos
1866
3014
  */
@@ -1913,6 +3061,18 @@ var Pipeline = class {
1913
3061
  * @see https://redis.io/commands/pexpireat
1914
3062
  */
1915
3063
  pexpireat = (...args) => this.chain(new PExpireAtCommand(args, this.commandOptions));
3064
+ /**
3065
+ * @see https://redis.io/commands/pfadd
3066
+ */
3067
+ pfadd = (...args) => this.chain(new PfAddCommand(args, this.commandOptions));
3068
+ /**
3069
+ * @see https://redis.io/commands/pfcount
3070
+ */
3071
+ pfcount = (...args) => this.chain(new PfCountCommand(args, this.commandOptions));
3072
+ /**
3073
+ * @see https://redis.io/commands/pfmerge
3074
+ */
3075
+ pfmerge = (...args) => this.chain(new PfMergeCommand(args, this.commandOptions));
1916
3076
  /**
1917
3077
  * @see https://redis.io/commands/ping
1918
3078
  */
@@ -1956,7 +3116,7 @@ var Pipeline = class {
1956
3116
  /**
1957
3117
  * @see https://redis.io/commands/sadd
1958
3118
  */
1959
- sadd = (key, ...members) => this.chain(new SAddCommand([key, ...members], this.commandOptions));
3119
+ sadd = (key, member, ...members) => this.chain(new SAddCommand([key, member, ...members], this.commandOptions));
1960
3120
  /**
1961
3121
  * @see https://redis.io/commands/scan
1962
3122
  */
@@ -2083,10 +3243,7 @@ var Pipeline = class {
2083
3243
  zadd = (...args) => {
2084
3244
  if ("score" in args[1]) {
2085
3245
  return this.chain(
2086
- new ZAddCommand(
2087
- [args[0], args[1], ...args.slice(2)],
2088
- this.commandOptions
2089
- )
3246
+ new ZAddCommand([args[0], args[1], ...args.slice(2)], this.commandOptions)
2090
3247
  );
2091
3248
  }
2092
3249
  return this.chain(
@@ -2096,6 +3253,62 @@ var Pipeline = class {
2096
3253
  )
2097
3254
  );
2098
3255
  };
3256
+ /**
3257
+ * @see https://redis.io/commands/xadd
3258
+ */
3259
+ xadd = (...args) => this.chain(new XAddCommand(args, this.commandOptions));
3260
+ /**
3261
+ * @see https://redis.io/commands/xack
3262
+ */
3263
+ xack = (...args) => this.chain(new XAckCommand(args, this.commandOptions));
3264
+ /**
3265
+ * @see https://redis.io/commands/xdel
3266
+ */
3267
+ xdel = (...args) => this.chain(new XDelCommand(args, this.commandOptions));
3268
+ /**
3269
+ * @see https://redis.io/commands/xgroup
3270
+ */
3271
+ xgroup = (...args) => this.chain(new XGroupCommand(args, this.commandOptions));
3272
+ /**
3273
+ * @see https://redis.io/commands/xread
3274
+ */
3275
+ xread = (...args) => this.chain(new XReadCommand(args, this.commandOptions));
3276
+ /**
3277
+ * @see https://redis.io/commands/xreadgroup
3278
+ */
3279
+ xreadgroup = (...args) => this.chain(new XReadGroupCommand(args, this.commandOptions));
3280
+ /**
3281
+ * @see https://redis.io/commands/xinfo
3282
+ */
3283
+ xinfo = (...args) => this.chain(new XInfoCommand(args, this.commandOptions));
3284
+ /**
3285
+ * @see https://redis.io/commands/xlen
3286
+ */
3287
+ xlen = (...args) => this.chain(new XLenCommand(args, this.commandOptions));
3288
+ /**
3289
+ * @see https://redis.io/commands/xpending
3290
+ */
3291
+ xpending = (...args) => this.chain(new XPendingCommand(args, this.commandOptions));
3292
+ /**
3293
+ * @see https://redis.io/commands/xclaim
3294
+ */
3295
+ xclaim = (...args) => this.chain(new XClaimCommand(args, this.commandOptions));
3296
+ /**
3297
+ * @see https://redis.io/commands/xautoclaim
3298
+ */
3299
+ xautoclaim = (...args) => this.chain(new XAutoClaim(args, this.commandOptions));
3300
+ /**
3301
+ * @see https://redis.io/commands/xtrim
3302
+ */
3303
+ xtrim = (...args) => this.chain(new XTrimCommand(args, this.commandOptions));
3304
+ /**
3305
+ * @see https://redis.io/commands/xrange
3306
+ */
3307
+ xrange = (...args) => this.chain(new XRangeCommand(args, this.commandOptions));
3308
+ /**
3309
+ * @see https://redis.io/commands/xrevrange
3310
+ */
3311
+ xrevrange = (...args) => this.chain(new XRevRangeCommand(args, this.commandOptions));
2099
3312
  /**
2100
3313
  * @see https://redis.io/commands/zcard
2101
3314
  */
@@ -2213,22 +3426,22 @@ var Pipeline = class {
2213
3426
  * @see https://redis.io/commands/json.forget
2214
3427
  */
2215
3428
  forget: (...args) => this.chain(new JsonForgetCommand(args, this.commandOptions)),
2216
- /**
2217
- * @see https://redis.io/commands/geoadd
2218
- */
2219
- geoadd: (...args) => new GeoAddCommand(args, this.commandOptions).exec(this.client),
2220
- /**
2221
- * @see https://redis.io/commands/geodist
2222
- */
2223
- geodist: (...args) => new GeoDistCommand(args, this.commandOptions).exec(this.client),
2224
3429
  /**
2225
3430
  * @see https://redis.io/commands/json.get
2226
3431
  */
2227
3432
  get: (...args) => this.chain(new JsonGetCommand(args, this.commandOptions)),
3433
+ /**
3434
+ * @see https://redis.io/commands/json.merge
3435
+ */
3436
+ merge: (...args) => this.chain(new JsonMergeCommand(args, this.commandOptions)),
2228
3437
  /**
2229
3438
  * @see https://redis.io/commands/json.mget
2230
3439
  */
2231
3440
  mget: (...args) => this.chain(new JsonMGetCommand(args, this.commandOptions)),
3441
+ /**
3442
+ * @see https://redis.io/commands/json.mset
3443
+ */
3444
+ mset: (...args) => this.chain(new JsonMSetCommand(args, this.commandOptions)),
2232
3445
  /**
2233
3446
  * @see https://redis.io/commands/json.numincrby
2234
3447
  */
@@ -2274,27 +3487,43 @@ var Pipeline = class {
2274
3487
  };
2275
3488
 
2276
3489
  // pkg/script.ts
2277
- var import_enc_hex = __toESM(require("crypto-js/enc-hex"));
2278
- var import_sha1 = __toESM(require("crypto-js/sha1"));
3490
+ var import_uncrypto = require("uncrypto");
2279
3491
  var Script = class {
2280
3492
  script;
3493
+ /**
3494
+ * @deprecated This property is initialized to an empty string and will be set in the init method
3495
+ * asynchronously. Do not use this property immidiately after the constructor.
3496
+ *
3497
+ * This property is only exposed for backwards compatibility and will be removed in the
3498
+ * future major release.
3499
+ */
2281
3500
  sha1;
2282
3501
  redis;
2283
3502
  constructor(redis, script) {
2284
3503
  this.redis = redis;
2285
- this.sha1 = this.digest(script);
2286
3504
  this.script = script;
3505
+ this.sha1 = "";
3506
+ void this.init(script);
3507
+ }
3508
+ /**
3509
+ * Initialize the script by computing its SHA-1 hash.
3510
+ */
3511
+ async init(script) {
3512
+ if (this.sha1) return;
3513
+ this.sha1 = await this.digest(script);
2287
3514
  }
2288
3515
  /**
2289
3516
  * Send an `EVAL` command to redis.
2290
3517
  */
2291
3518
  async eval(keys, args) {
3519
+ await this.init(this.script);
2292
3520
  return await this.redis.eval(this.script, keys, args);
2293
3521
  }
2294
3522
  /**
2295
3523
  * Calculates the sha1 hash of the script and then calls `EVALSHA`.
2296
3524
  */
2297
3525
  async evalsha(keys, args) {
3526
+ await this.init(this.script);
2298
3527
  return await this.redis.evalsha(this.sha1, keys, args);
2299
3528
  }
2300
3529
  /**
@@ -2304,19 +3533,87 @@ var Script = class {
2304
3533
  * Following calls will be able to use the cached script
2305
3534
  */
2306
3535
  async exec(keys, args) {
2307
- const res = await this.redis.evalsha(this.sha1, keys, args).catch(async (err) => {
2308
- if (err instanceof Error && err.message.toLowerCase().includes("noscript")) {
3536
+ await this.init(this.script);
3537
+ const res = await this.redis.evalsha(this.sha1, keys, args).catch(async (error) => {
3538
+ if (error instanceof Error && error.message.toLowerCase().includes("noscript")) {
2309
3539
  return await this.redis.eval(this.script, keys, args);
2310
3540
  }
2311
- throw err;
3541
+ throw error;
3542
+ });
3543
+ return res;
3544
+ }
3545
+ /**
3546
+ * Compute the sha1 hash of the script and return its hex representation.
3547
+ */
3548
+ async digest(s) {
3549
+ const data = new TextEncoder().encode(s);
3550
+ const hashBuffer = await import_uncrypto.subtle.digest("SHA-1", data);
3551
+ const hashArray = [...new Uint8Array(hashBuffer)];
3552
+ return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
3553
+ }
3554
+ };
3555
+
3556
+ // pkg/scriptRo.ts
3557
+ var import_uncrypto2 = require("uncrypto");
3558
+ var ScriptRO = class {
3559
+ script;
3560
+ /**
3561
+ * @deprecated This property is initialized to an empty string and will be set in the init method
3562
+ * asynchronously. Do not use this property immidiately after the constructor.
3563
+ *
3564
+ * This property is only exposed for backwards compatibility and will be removed in the
3565
+ * future major release.
3566
+ */
3567
+ sha1;
3568
+ redis;
3569
+ constructor(redis, script) {
3570
+ this.redis = redis;
3571
+ this.sha1 = "";
3572
+ this.script = script;
3573
+ void this.init(script);
3574
+ }
3575
+ async init(script) {
3576
+ if (this.sha1) return;
3577
+ this.sha1 = await this.digest(script);
3578
+ }
3579
+ /**
3580
+ * Send an `EVAL_RO` command to redis.
3581
+ */
3582
+ async evalRo(keys, args) {
3583
+ await this.init(this.script);
3584
+ return await this.redis.evalRo(this.script, keys, args);
3585
+ }
3586
+ /**
3587
+ * Calculates the sha1 hash of the script and then calls `EVALSHA_RO`.
3588
+ */
3589
+ async evalshaRo(keys, args) {
3590
+ await this.init(this.script);
3591
+ return await this.redis.evalshaRo(this.sha1, keys, args);
3592
+ }
3593
+ /**
3594
+ * Optimistically try to run `EVALSHA_RO` first.
3595
+ * If the script is not loaded in redis, it will fall back and try again with `EVAL_RO`.
3596
+ *
3597
+ * Following calls will be able to use the cached script
3598
+ */
3599
+ async exec(keys, args) {
3600
+ await this.init(this.script);
3601
+ const res = await this.redis.evalshaRo(this.sha1, keys, args).catch(async (error) => {
3602
+ if (error instanceof Error && error.message.toLowerCase().includes("noscript")) {
3603
+ return await this.redis.evalRo(this.script, keys, args);
3604
+ }
3605
+ throw error;
2312
3606
  });
2313
3607
  return res;
2314
3608
  }
2315
3609
  /**
2316
3610
  * Compute the sha1 hash of the script and return its hex representation.
2317
3611
  */
2318
- digest(s) {
2319
- return import_enc_hex.default.stringify((0, import_sha1.default)(s));
3612
+ async digest(s) {
3613
+ const data = new TextEncoder().encode(s);
3614
+ const hashBuffer = await import_uncrypto2.subtle.digest("SHA-1", data);
3615
+ const hashArray = [...new Uint8Array(hashBuffer)];
3616
+ return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
2320
3617
  }
2321
3618
  };
2322
3619
 
@@ -2325,6 +3622,7 @@ var Redis = class {
2325
3622
  client;
2326
3623
  opts;
2327
3624
  enableTelemetry;
3625
+ enableAutoPipelining;
2328
3626
  /**
2329
3627
  * Create a new redis client
2330
3628
  *
@@ -2340,6 +3638,16 @@ var Redis = class {
2340
3638
  this.client = client;
2341
3639
  this.opts = opts;
2342
3640
  this.enableTelemetry = opts?.enableTelemetry ?? true;
3641
+ if (opts?.readYourWrites === false) {
3642
+ this.client.readYourWrites = false;
3643
+ }
3644
+ this.enableAutoPipelining = opts?.enableAutoPipelining ?? true;
3645
+ }
3646
+ get readYourWritesSyncToken() {
3647
+ return this.client.upstashSyncToken;
3648
+ }
3649
+ set readYourWritesSyncToken(session) {
3650
+ this.client.upstashSyncToken = session;
2343
3651
  }
2344
3652
  get json() {
2345
3653
  return {
@@ -2379,22 +3687,22 @@ var Redis = class {
2379
3687
  * @see https://redis.io/commands/json.forget
2380
3688
  */
2381
3689
  forget: (...args) => new JsonForgetCommand(args, this.opts).exec(this.client),
2382
- /**
2383
- * @see https://redis.io/commands/geoadd
2384
- */
2385
- geoadd: (...args) => new GeoAddCommand(args, this.opts).exec(this.client),
2386
- /**
2387
- * @see https://redis.io/commands/geodist
2388
- */
2389
- geodist: (...args) => new GeoDistCommand(args, this.opts).exec(this.client),
2390
3690
  /**
2391
3691
  * @see https://redis.io/commands/json.get
2392
3692
  */
2393
3693
  get: (...args) => new JsonGetCommand(args, this.opts).exec(this.client),
3694
+ /**
3695
+ * @see https://redis.io/commands/json.merge
3696
+ */
3697
+ merge: (...args) => new JsonMergeCommand(args, this.opts).exec(this.client),
2394
3698
  /**
2395
3699
  * @see https://redis.io/commands/json.mget
2396
3700
  */
2397
3701
  mget: (...args) => new JsonMGetCommand(args, this.opts).exec(this.client),
3702
+ /**
3703
+ * @see https://redis.io/commands/json.mset
3704
+ */
3705
+ mset: (...args) => new JsonMSetCommand(args, this.opts).exec(this.client),
2398
3706
  /**
2399
3707
  * @see https://redis.io/commands/json.numincrby
2400
3708
  */
@@ -2456,8 +3764,36 @@ var Redis = class {
2456
3764
  } catch {
2457
3765
  }
2458
3766
  };
2459
- createScript(script) {
2460
- return new Script(this, script);
3767
+ /**
3768
+ * Creates a new script.
3769
+ *
3770
+ * Scripts offer the ability to optimistically try to execute a script without having to send the
3771
+ * entire script to the server. If the script is loaded on the server, it tries again by sending
3772
+ * the entire script. Afterwards, the script is cached on the server.
3773
+ *
3774
+ * @param script - The script to create
3775
+ * @param opts - Optional options to pass to the script `{ readonly?: boolean }`
3776
+ * @returns A new script
3777
+ *
3778
+ * @example
3779
+ * ```ts
3780
+ * const redis = new Redis({...})
3781
+ *
3782
+ * const script = redis.createScript<string>("return ARGV[1];")
3783
+ * const arg1 = await script.eval([], ["Hello World"])
3784
+ * expect(arg1, "Hello World")
3785
+ * ```
3786
+ * @example
3787
+ * ```ts
3788
+ * const redis = new Redis({...})
3789
+ *
3790
+ * const script = redis.createScript<string>("return ARGV[1];", { readonly: true })
3791
+ * const arg1 = await script.evalRo([], ["Hello World"])
3792
+ * expect(arg1, "Hello World")
3793
+ * ```
3794
+ */
3795
+ createScript(script, opts) {
3796
+ return opts?.readonly ? new ScriptRO(this, script) : new Script(this, script);
2461
3797
  }
2462
3798
  /**
2463
3799
  * Create a new pipeline that allows you to send requests in bulk.
@@ -2469,6 +3805,9 @@ var Redis = class {
2469
3805
  commandOptions: this.opts,
2470
3806
  multiExec: false
2471
3807
  });
3808
+ autoPipeline = () => {
3809
+ return createAutoPipelineProxy(this);
3810
+ };
2472
3811
  /**
2473
3812
  * Create a new transaction to allow executing multiple steps atomically.
2474
3813
  *
@@ -2483,6 +3822,22 @@ var Redis = class {
2483
3822
  commandOptions: this.opts,
2484
3823
  multiExec: true
2485
3824
  });
3825
+ /**
3826
+ * Returns an instance that can be used to execute `BITFIELD` commands on one key.
3827
+ *
3828
+ * @example
3829
+ * ```typescript
3830
+ * redis.set("mykey", 0);
3831
+ * const result = await redis.bitfield("mykey")
3832
+ * .set("u4", 0, 16)
3833
+ * .incr("u4", "#1", 1)
3834
+ * .exec();
3835
+ * console.log(result); // [0, 1]
3836
+ * ```
3837
+ *
3838
+ * @see https://redis.io/commands/bitfield
3839
+ */
3840
+ bitfield = (...args) => new BitFieldCommand(args, this.client, this.opts);
2486
3841
  /**
2487
3842
  * @see https://redis.io/commands/append
2488
3843
  */
@@ -2501,6 +3856,10 @@ var Redis = class {
2501
3856
  * @see https://redis.io/commands/bitpos
2502
3857
  */
2503
3858
  bitpos = (...args) => new BitPosCommand(args, this.opts).exec(this.client);
3859
+ /**
3860
+ * @see https://redis.io/commands/copy
3861
+ */
3862
+ copy = (...args) => new CopyCommand(args, this.opts).exec(this.client);
2504
3863
  /**
2505
3864
  * @see https://redis.io/commands/dbsize
2506
3865
  */
@@ -2521,14 +3880,26 @@ var Redis = class {
2521
3880
  * @see https://redis.io/commands/echo
2522
3881
  */
2523
3882
  echo = (...args) => new EchoCommand(args, this.opts).exec(this.client);
3883
+ /**
3884
+ * @see https://redis.io/commands/eval_ro
3885
+ */
3886
+ evalRo = (...args) => new EvalROCommand(args, this.opts).exec(this.client);
2524
3887
  /**
2525
3888
  * @see https://redis.io/commands/eval
2526
3889
  */
2527
3890
  eval = (...args) => new EvalCommand(args, this.opts).exec(this.client);
3891
+ /**
3892
+ * @see https://redis.io/commands/evalsha_ro
3893
+ */
3894
+ evalshaRo = (...args) => new EvalshaROCommand(args, this.opts).exec(this.client);
2528
3895
  /**
2529
3896
  * @see https://redis.io/commands/evalsha
2530
3897
  */
2531
3898
  evalsha = (...args) => new EvalshaCommand(args, this.opts).exec(this.client);
3899
+ /**
3900
+ * Generic method to execute any Redis command.
3901
+ */
3902
+ exec = (args) => new ExecCommand(args, this.opts).exec(this.client);
2532
3903
  /**
2533
3904
  * @see https://redis.io/commands/exists
2534
3905
  */
@@ -2549,6 +3920,30 @@ var Redis = class {
2549
3920
  * @see https://redis.io/commands/flushdb
2550
3921
  */
2551
3922
  flushdb = (...args) => new FlushDBCommand(args, this.opts).exec(this.client);
3923
+ /**
3924
+ * @see https://redis.io/commands/geoadd
3925
+ */
3926
+ geoadd = (...args) => new GeoAddCommand(args, this.opts).exec(this.client);
3927
+ /**
3928
+ * @see https://redis.io/commands/geopos
3929
+ */
3930
+ geopos = (...args) => new GeoPosCommand(args, this.opts).exec(this.client);
3931
+ /**
3932
+ * @see https://redis.io/commands/geodist
3933
+ */
3934
+ geodist = (...args) => new GeoDistCommand(args, this.opts).exec(this.client);
3935
+ /**
3936
+ * @see https://redis.io/commands/geohash
3937
+ */
3938
+ geohash = (...args) => new GeoHashCommand(args, this.opts).exec(this.client);
3939
+ /**
3940
+ * @see https://redis.io/commands/geosearch
3941
+ */
3942
+ geosearch = (...args) => new GeoSearchCommand(args, this.opts).exec(this.client);
3943
+ /**
3944
+ * @see https://redis.io/commands/geosearchstore
3945
+ */
3946
+ geosearchstore = (...args) => new GeoSearchStoreCommand(args, this.opts).exec(this.client);
2552
3947
  /**
2553
3948
  * @see https://redis.io/commands/get
2554
3949
  */
@@ -2561,6 +3956,10 @@ var Redis = class {
2561
3956
  * @see https://redis.io/commands/getdel
2562
3957
  */
2563
3958
  getdel = (...args) => new GetDelCommand(args, this.opts).exec(this.client);
3959
+ /**
3960
+ * @see https://redis.io/commands/getex
3961
+ */
3962
+ getex = (...args) => new GetExCommand(args, this.opts).exec(this.client);
2564
3963
  /**
2565
3964
  * @see https://redis.io/commands/getrange
2566
3965
  */
@@ -2577,6 +3976,42 @@ var Redis = class {
2577
3976
  * @see https://redis.io/commands/hexists
2578
3977
  */
2579
3978
  hexists = (...args) => new HExistsCommand(args, this.opts).exec(this.client);
3979
+ /**
3980
+ * @see https://redis.io/commands/hexpire
3981
+ */
3982
+ hexpire = (...args) => new HExpireCommand(args, this.opts).exec(this.client);
3983
+ /**
3984
+ * @see https://redis.io/commands/hexpireat
3985
+ */
3986
+ hexpireat = (...args) => new HExpireAtCommand(args, this.opts).exec(this.client);
3987
+ /**
3988
+ * @see https://redis.io/commands/hexpiretime
3989
+ */
3990
+ hexpiretime = (...args) => new HExpireTimeCommand(args, this.opts).exec(this.client);
3991
+ /**
3992
+ * @see https://redis.io/commands/httl
3993
+ */
3994
+ httl = (...args) => new HTtlCommand(args, this.opts).exec(this.client);
3995
+ /**
3996
+ * @see https://redis.io/commands/hpexpire
3997
+ */
3998
+ hpexpire = (...args) => new HPExpireCommand(args, this.opts).exec(this.client);
3999
+ /**
4000
+ * @see https://redis.io/commands/hpexpireat
4001
+ */
4002
+ hpexpireat = (...args) => new HPExpireAtCommand(args, this.opts).exec(this.client);
4003
+ /**
4004
+ * @see https://redis.io/commands/hpexpiretime
4005
+ */
4006
+ hpexpiretime = (...args) => new HPExpireTimeCommand(args, this.opts).exec(this.client);
4007
+ /**
4008
+ * @see https://redis.io/commands/hpttl
4009
+ */
4010
+ hpttl = (...args) => new HPTtlCommand(args, this.opts).exec(this.client);
4011
+ /**
4012
+ * @see https://redis.io/commands/hpersist
4013
+ */
4014
+ hpersist = (...args) => new HPersistCommand(args, this.opts).exec(this.client);
2580
4015
  /**
2581
4016
  * @see https://redis.io/commands/hget
2582
4017
  */
@@ -2669,6 +4104,10 @@ var Redis = class {
2669
4104
  * @see https://redis.io/commands/lpop
2670
4105
  */
2671
4106
  lpop = (...args) => new LPopCommand(args, this.opts).exec(this.client);
4107
+ /**
4108
+ * @see https://redis.io/commands/lmpop
4109
+ */
4110
+ lmpop = (...args) => new LmPopCommand(args, this.opts).exec(this.client);
2672
4111
  /**
2673
4112
  * @see https://redis.io/commands/lpos
2674
4113
  */
@@ -2721,6 +4160,18 @@ var Redis = class {
2721
4160
  * @see https://redis.io/commands/pexpireat
2722
4161
  */
2723
4162
  pexpireat = (...args) => new PExpireAtCommand(args, this.opts).exec(this.client);
4163
+ /**
4164
+ * @see https://redis.io/commands/pfadd
4165
+ */
4166
+ pfadd = (...args) => new PfAddCommand(args, this.opts).exec(this.client);
4167
+ /**
4168
+ * @see https://redis.io/commands/pfcount
4169
+ */
4170
+ pfcount = (...args) => new PfCountCommand(args, this.opts).exec(this.client);
4171
+ /**
4172
+ * @see https://redis.io/commands/pfmerge
4173
+ */
4174
+ pfmerge = (...args) => new PfMergeCommand(args, this.opts).exec(this.client);
2724
4175
  /**
2725
4176
  * @see https://redis.io/commands/ping
2726
4177
  */
@@ -2729,6 +4180,13 @@ var Redis = class {
2729
4180
  * @see https://redis.io/commands/psetex
2730
4181
  */
2731
4182
  psetex = (key, ttl, value) => new PSetEXCommand([key, ttl, value], this.opts).exec(this.client);
4183
+ /**
4184
+ * @see https://redis.io/commands/psubscribe
4185
+ */
4186
+ psubscribe = (patterns) => {
4187
+ const patternArray = Array.isArray(patterns) ? patterns : [patterns];
4188
+ return new Subscriber(this.client, patternArray, true);
4189
+ };
2732
4190
  /**
2733
4191
  * @see https://redis.io/commands/pttl
2734
4192
  */
@@ -2764,11 +4222,10 @@ var Redis = class {
2764
4222
  /**
2765
4223
  * @see https://redis.io/commands/sadd
2766
4224
  */
2767
- sadd = (key, ...members) => new SAddCommand([key, ...members], this.opts).exec(this.client);
2768
- /**
2769
- * @see https://redis.io/commands/scan
2770
- */
2771
- scan = (...args) => new ScanCommand(args, this.opts).exec(this.client);
4225
+ sadd = (key, member, ...members) => new SAddCommand([key, member, ...members], this.opts).exec(this.client);
4226
+ scan(cursor, opts) {
4227
+ return new ScanCommand([cursor, opts], this.opts).exec(this.client);
4228
+ }
2772
4229
  /**
2773
4230
  * @see https://redis.io/commands/scard
2774
4231
  */
@@ -2857,6 +4314,13 @@ var Redis = class {
2857
4314
  * @see https://redis.io/commands/strlen
2858
4315
  */
2859
4316
  strlen = (...args) => new StrLenCommand(args, this.opts).exec(this.client);
4317
+ /**
4318
+ * @see https://redis.io/commands/subscribe
4319
+ */
4320
+ subscribe = (channels) => {
4321
+ const channelArray = Array.isArray(channels) ? channels : [channels];
4322
+ return new Subscriber(this.client, channelArray);
4323
+ };
2860
4324
  /**
2861
4325
  * @see https://redis.io/commands/sunion
2862
4326
  */
@@ -2889,19 +4353,66 @@ var Redis = class {
2889
4353
  * @see https://redis.io/commands/xadd
2890
4354
  */
2891
4355
  xadd = (...args) => new XAddCommand(args, this.opts).exec(this.client);
4356
+ /**
4357
+ * @see https://redis.io/commands/xack
4358
+ */
4359
+ xack = (...args) => new XAckCommand(args, this.opts).exec(this.client);
4360
+ /**
4361
+ * @see https://redis.io/commands/xdel
4362
+ */
4363
+ xdel = (...args) => new XDelCommand(args, this.opts).exec(this.client);
4364
+ /**
4365
+ * @see https://redis.io/commands/xgroup
4366
+ */
4367
+ xgroup = (...args) => new XGroupCommand(args, this.opts).exec(this.client);
4368
+ /**
4369
+ * @see https://redis.io/commands/xread
4370
+ */
4371
+ xread = (...args) => new XReadCommand(args, this.opts).exec(this.client);
4372
+ /**
4373
+ * @see https://redis.io/commands/xreadgroup
4374
+ */
4375
+ xreadgroup = (...args) => new XReadGroupCommand(args, this.opts).exec(this.client);
4376
+ /**
4377
+ * @see https://redis.io/commands/xinfo
4378
+ */
4379
+ xinfo = (...args) => new XInfoCommand(args, this.opts).exec(this.client);
4380
+ /**
4381
+ * @see https://redis.io/commands/xlen
4382
+ */
4383
+ xlen = (...args) => new XLenCommand(args, this.opts).exec(this.client);
4384
+ /**
4385
+ * @see https://redis.io/commands/xpending
4386
+ */
4387
+ xpending = (...args) => new XPendingCommand(args, this.opts).exec(this.client);
4388
+ /**
4389
+ * @see https://redis.io/commands/xclaim
4390
+ */
4391
+ xclaim = (...args) => new XClaimCommand(args, this.opts).exec(this.client);
4392
+ /**
4393
+ * @see https://redis.io/commands/xautoclaim
4394
+ */
4395
+ xautoclaim = (...args) => new XAutoClaim(args, this.opts).exec(this.client);
4396
+ /**
4397
+ * @see https://redis.io/commands/xtrim
4398
+ */
4399
+ xtrim = (...args) => new XTrimCommand(args, this.opts).exec(this.client);
2892
4400
  /**
2893
4401
  * @see https://redis.io/commands/xrange
2894
4402
  */
2895
4403
  xrange = (...args) => new XRangeCommand(args, this.opts).exec(this.client);
4404
+ /**
4405
+ * @see https://redis.io/commands/xrevrange
4406
+ */
4407
+ xrevrange = (...args) => new XRevRangeCommand(args, this.opts).exec(this.client);
2896
4408
  /**
2897
4409
  * @see https://redis.io/commands/zadd
2898
4410
  */
2899
4411
  zadd = (...args) => {
2900
4412
  if ("score" in args[1]) {
2901
- return new ZAddCommand(
2902
- [args[0], args[1], ...args.slice(2)],
2903
- this.opts
2904
- ).exec(this.client);
4413
+ return new ZAddCommand([args[0], args[1], ...args.slice(2)], this.opts).exec(
4414
+ this.client
4415
+ );
2905
4416
  }
2906
4417
  return new ZAddCommand(
2907
4418
  [args[0], args[1], ...args.slice(2)],
@@ -2991,7 +4502,7 @@ var Redis = class {
2991
4502
  };
2992
4503
 
2993
4504
  // version.ts
2994
- var VERSION = "v0.0.0-ci.8bd938831856fbab2f4aadc67ecb9de61efb6123";
4505
+ var VERSION = "v1.30.2";
2995
4506
 
2996
4507
  // platforms/fastly.ts
2997
4508
  var Redis2 = class extends Redis {
@@ -3008,30 +4519,48 @@ var Redis2 = class extends Redis {
3008
4519
  * ```
3009
4520
  */
3010
4521
  constructor(config) {
3011
- if (config.url.startsWith(" ") || config.url.endsWith(" ") || /\r|\n/.test(config.url)) {
3012
- console.warn("The redis url contains whitespace or newline, which can cause errors!");
4522
+ if (!config.url) {
4523
+ console.warn(
4524
+ `[Upstash Redis] The 'url' property is missing or undefined in your Redis config.`
4525
+ );
4526
+ } else if (config.url.startsWith(" ") || config.url.endsWith(" ") || /\r|\n/.test(config.url)) {
4527
+ console.warn(
4528
+ "[Upstash Redis] The redis url contains whitespace or newline, which can cause errors!"
4529
+ );
3013
4530
  }
3014
- if (config.token.startsWith(" ") || config.token.endsWith(" ") || /\r|\n/.test(config.token)) {
3015
- console.warn("The redis token contains whitespace or newline, which can cause errors!");
4531
+ if (!config.token) {
4532
+ console.warn(
4533
+ `[Upstash Redis] The 'token' property is missing or undefined in your Redis config.`
4534
+ );
4535
+ } else if (config.token.startsWith(" ") || config.token.endsWith(" ") || /\r|\n/.test(config.token)) {
4536
+ console.warn(
4537
+ "[Upstash Redis] The redis token contains whitespace or newline, which can cause errors!"
4538
+ );
3016
4539
  }
3017
4540
  const client = new HttpClient({
3018
4541
  baseUrl: config.url,
3019
4542
  retry: config.retry,
3020
4543
  headers: { authorization: `Bearer ${config.token}` },
3021
4544
  options: { backend: config.backend },
3022
- responseEncoding: config.responseEncoding
4545
+ responseEncoding: config.responseEncoding,
4546
+ keepAlive: config.keepAlive,
4547
+ readYourWrites: config.readYourWrites
3023
4548
  });
3024
4549
  super(client, {
3025
- automaticDeserialization: config.automaticDeserialization
4550
+ automaticDeserialization: config.automaticDeserialization,
4551
+ enableAutoPipelining: config.enableAutoPipelining
3026
4552
  });
3027
4553
  this.addTelemetry({
3028
4554
  sdk: `@upstash/redis@${VERSION}`,
3029
4555
  platform: "fastly"
3030
4556
  });
4557
+ if (this.enableAutoPipelining) {
4558
+ return this.autoPipeline();
4559
+ }
3031
4560
  }
3032
4561
  };
3033
4562
  // Annotate the CommonJS export names for ESM import in node:
3034
4563
  0 && (module.exports = {
3035
- Redis
4564
+ Redis,
4565
+ errors
3036
4566
  });
3037
- //# sourceMappingURL=fastly.js.map