@upstash/redis 0.0.0-ci.9722909577fc3b6b939d0c937c6ba5f8e8287ee4 → 0.0.0-ci.998046a844b4998e6b7de8c128d5f41be5545cdf-20241002104435

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/nodejs.js CHANGED
@@ -30,23 +30,39 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // platforms/nodejs.ts
31
31
  var nodejs_exports = {};
32
32
  __export(nodejs_exports, {
33
- Redis: () => Redis2
33
+ Redis: () => Redis2,
34
+ errors: () => error_exports
34
35
  });
35
36
  module.exports = __toCommonJS(nodejs_exports);
36
37
 
37
38
  // pkg/error.ts
39
+ var error_exports = {};
40
+ __export(error_exports, {
41
+ UpstashError: () => UpstashError,
42
+ UrlError: () => UrlError
43
+ });
38
44
  var UpstashError = class extends Error {
39
45
  constructor(message) {
40
46
  super(message);
41
47
  this.name = "UpstashError";
42
48
  }
43
49
  };
50
+ var UrlError = class extends Error {
51
+ constructor(url) {
52
+ super(
53
+ `Upstash Redis client was passed an invalid URL. You should pass the URL together with https. Received: "${url}". `
54
+ );
55
+ this.name = "UrlError";
56
+ }
57
+ };
44
58
 
45
59
  // pkg/http.ts
46
60
  var HttpClient = class {
47
61
  baseUrl;
48
62
  headers;
49
63
  options;
64
+ readYourWrites;
65
+ upstashSyncToken = "";
50
66
  retry;
51
67
  constructor(config) {
52
68
  this.options = {
@@ -54,9 +70,17 @@ var HttpClient = class {
54
70
  agent: config.agent,
55
71
  responseEncoding: config.responseEncoding ?? "base64",
56
72
  // default to base64
57
- cache: config.cache
73
+ cache: config.cache,
74
+ signal: config.signal,
75
+ keepAlive: config.keepAlive ?? true
58
76
  };
77
+ this.upstashSyncToken = "";
78
+ this.readYourWrites = config.readYourWrites ?? true;
59
79
  this.baseUrl = config.baseUrl.replace(/\/$/, "");
80
+ const urlRegex = /^https?:\/\/[^\s#$./?].\S*$/;
81
+ if (!urlRegex.test(this.baseUrl)) {
82
+ throw new UrlError(this.baseUrl);
83
+ }
60
84
  this.headers = {
61
85
  "Content-Type": "application/json",
62
86
  ...config.headers
@@ -64,55 +88,57 @@ var HttpClient = class {
64
88
  if (this.options.responseEncoding === "base64") {
65
89
  this.headers["Upstash-Encoding"] = "base64";
66
90
  }
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
- }
91
+ this.retry = typeof config.retry === "boolean" && !config.retry ? {
92
+ attempts: 1,
93
+ backoff: () => 0
94
+ } : {
95
+ attempts: config.retry?.retries ?? 5,
96
+ backoff: config.retry?.backoff ?? ((retryCount) => Math.exp(retryCount) * 50)
97
+ };
78
98
  }
79
99
  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
100
  this.headers = merge(this.headers, "Upstash-Telemetry-Runtime", telemetry.runtime);
92
101
  this.headers = merge(this.headers, "Upstash-Telemetry-Platform", telemetry.platform);
93
102
  this.headers = merge(this.headers, "Upstash-Telemetry-Sdk", telemetry.sdk);
94
103
  }
95
104
  async request(req) {
96
105
  const requestOptions = {
106
+ //@ts-expect-error this should throw due to bun regression
97
107
  cache: this.options.cache,
98
108
  method: "POST",
99
109
  headers: this.headers,
100
110
  body: JSON.stringify(req.body),
101
- keepalive: true,
102
- agent: this.options?.agent,
111
+ keepalive: this.options.keepAlive,
112
+ agent: this.options.agent,
113
+ signal: this.options.signal,
103
114
  /**
104
115
  * Fastly specific
105
116
  */
106
- backend: this.options?.backend
117
+ backend: this.options.backend
107
118
  };
119
+ if (this.readYourWrites) {
120
+ const newHeader = this.upstashSyncToken;
121
+ this.headers["upstash-sync-token"] = newHeader;
122
+ }
108
123
  let res = null;
109
124
  let error = null;
110
125
  for (let i = 0; i <= this.retry.attempts; i++) {
111
126
  try {
112
127
  res = await fetch([this.baseUrl, ...req.path ?? []].join("/"), requestOptions);
113
128
  break;
114
- } catch (err) {
115
- error = err;
129
+ } catch (error_) {
130
+ if (this.options.signal?.aborted) {
131
+ const myBlob = new Blob([
132
+ JSON.stringify({ result: this.options.signal.reason ?? "Aborted" })
133
+ ]);
134
+ const myOptions = {
135
+ status: 200,
136
+ statusText: this.options.signal.reason ?? "Aborted"
137
+ };
138
+ res = new Response(myBlob, myOptions);
139
+ break;
140
+ }
141
+ error = error_;
116
142
  await new Promise((r) => setTimeout(r, this.retry.backoff(i)));
117
143
  }
118
144
  }
@@ -123,7 +149,15 @@ var HttpClient = class {
123
149
  if (!res.ok) {
124
150
  throw new UpstashError(`${body.error}, command was: ${JSON.stringify(req.body)}`);
125
151
  }
126
- if (this.options?.responseEncoding === "base64") {
152
+ if (this.readYourWrites) {
153
+ const headers = res.headers;
154
+ this.upstashSyncToken = headers.get("upstash-sync-token") ?? "";
155
+ }
156
+ if (this.readYourWrites) {
157
+ const headers = res.headers;
158
+ this.upstashSyncToken = headers.get("upstash-sync-token") ?? "";
159
+ }
160
+ if (this.options.responseEncoding === "base64") {
127
161
  if (Array.isArray(body)) {
128
162
  return body.map(({ result: result2, error: error2 }) => ({
129
163
  result: decode(result2),
@@ -154,8 +188,9 @@ function base64decode(b64) {
154
188
  function decode(raw) {
155
189
  let result = void 0;
156
190
  switch (typeof raw) {
157
- case "undefined":
191
+ case "undefined": {
158
192
  return raw;
193
+ }
159
194
  case "number": {
160
195
  result = raw;
161
196
  break;
@@ -163,7 +198,7 @@ function decode(raw) {
163
198
  case "object": {
164
199
  if (Array.isArray(raw)) {
165
200
  result = raw.map(
166
- (v) => typeof v === "string" ? base64decode(v) : Array.isArray(v) ? v.map(decode) : v
201
+ (v) => typeof v === "string" ? base64decode(v) : Array.isArray(v) ? v.map((element) => decode(element)) : v
167
202
  );
168
203
  } else {
169
204
  result = null;
@@ -174,11 +209,94 @@ function decode(raw) {
174
209
  result = raw === "OK" ? "OK" : base64decode(raw);
175
210
  break;
176
211
  }
177
- default:
212
+ default: {
178
213
  break;
214
+ }
179
215
  }
180
216
  return result;
181
217
  }
218
+ function merge(obj, key, value) {
219
+ if (!value) {
220
+ return obj;
221
+ }
222
+ obj[key] = obj[key] ? [obj[key], value].join(",") : value;
223
+ return obj;
224
+ }
225
+
226
+ // pkg/auto-pipeline.ts
227
+ function createAutoPipelineProxy(_redis, json) {
228
+ const redis = _redis;
229
+ if (!redis.autoPipelineExecutor) {
230
+ redis.autoPipelineExecutor = new AutoPipelineExecutor(redis);
231
+ }
232
+ return new Proxy(redis, {
233
+ get: (redis2, command) => {
234
+ if (command === "pipelineCounter") {
235
+ return redis2.autoPipelineExecutor.pipelineCounter;
236
+ }
237
+ if (command === "json") {
238
+ return createAutoPipelineProxy(redis2, true);
239
+ }
240
+ const commandInRedisButNotPipeline = command in redis2 && !(command in redis2.autoPipelineExecutor.pipeline);
241
+ if (commandInRedisButNotPipeline) {
242
+ return redis2[command];
243
+ }
244
+ const isFunction = json ? typeof redis2.autoPipelineExecutor.pipeline.json[command] === "function" : typeof redis2.autoPipelineExecutor.pipeline[command] === "function";
245
+ if (isFunction) {
246
+ return (...args) => {
247
+ return redis2.autoPipelineExecutor.withAutoPipeline((pipeline) => {
248
+ if (json) {
249
+ pipeline.json[command](
250
+ ...args
251
+ );
252
+ } else {
253
+ pipeline[command](...args);
254
+ }
255
+ });
256
+ };
257
+ }
258
+ return redis2.autoPipelineExecutor.pipeline[command];
259
+ }
260
+ });
261
+ }
262
+ var AutoPipelineExecutor = class {
263
+ pipelinePromises = /* @__PURE__ */ new WeakMap();
264
+ activePipeline = null;
265
+ indexInCurrentPipeline = 0;
266
+ redis;
267
+ pipeline;
268
+ // only to make sure that proxy can work
269
+ pipelineCounter = 0;
270
+ // to keep track of how many times a pipeline was executed
271
+ constructor(redis) {
272
+ this.redis = redis;
273
+ this.pipeline = redis.pipeline();
274
+ }
275
+ async withAutoPipeline(executeWithPipeline) {
276
+ const pipeline = this.activePipeline ?? this.redis.pipeline();
277
+ if (!this.activePipeline) {
278
+ this.activePipeline = pipeline;
279
+ this.indexInCurrentPipeline = 0;
280
+ }
281
+ const index = this.indexInCurrentPipeline++;
282
+ executeWithPipeline(pipeline);
283
+ const pipelineDone = this.deferExecution().then(() => {
284
+ if (!this.pipelinePromises.has(pipeline)) {
285
+ const pipelinePromise = pipeline.exec();
286
+ this.pipelineCounter += 1;
287
+ this.pipelinePromises.set(pipeline, pipelinePromise);
288
+ this.activePipeline = null;
289
+ }
290
+ return this.pipelinePromises.get(pipeline);
291
+ });
292
+ const results = await pipelineDone;
293
+ return results[index];
294
+ }
295
+ async deferExecution() {
296
+ await Promise.resolve();
297
+ await Promise.resolve();
298
+ }
299
+ };
182
300
 
183
301
  // pkg/util.ts
184
302
  function parseRecursive(obj) {
@@ -201,16 +319,21 @@ function parseResponse(result) {
201
319
  return result;
202
320
  }
203
321
  }
322
+ function deserializeScanResponse(result) {
323
+ return [result[0], ...parseResponse(result.slice(1))];
324
+ }
204
325
 
205
326
  // pkg/commands/command.ts
206
327
  var defaultSerializer = (c) => {
207
328
  switch (typeof c) {
208
329
  case "string":
209
330
  case "number":
210
- case "boolean":
331
+ case "boolean": {
211
332
  return c;
212
- default:
333
+ }
334
+ default: {
213
335
  return JSON.stringify(c);
336
+ }
214
337
  }
215
338
  };
216
339
  var Command = class {
@@ -224,21 +347,35 @@ var Command = class {
224
347
  */
225
348
  constructor(command, opts) {
226
349
  this.serialize = defaultSerializer;
227
- this.deserialize = typeof opts?.automaticDeserialization === "undefined" || opts.automaticDeserialization ? opts?.deserialize ?? parseResponse : (x) => x;
350
+ this.deserialize = opts?.automaticDeserialization === void 0 || opts.automaticDeserialization ? opts?.deserialize ?? parseResponse : (x) => x;
228
351
  this.command = command.map((c) => this.serialize(c));
352
+ if (opts?.latencyLogging) {
353
+ const originalExec = this.exec.bind(this);
354
+ this.exec = async (client) => {
355
+ const start = performance.now();
356
+ const result = await originalExec(client);
357
+ const end = performance.now();
358
+ const loggerResult = (end - start).toFixed(2);
359
+ console.log(
360
+ `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`
361
+ );
362
+ return result;
363
+ };
364
+ }
229
365
  }
230
366
  /**
231
367
  * Execute the command using a client.
232
368
  */
233
369
  async exec(client) {
234
370
  const { result, error } = await client.request({
235
- body: this.command
371
+ body: this.command,
372
+ upstashSyncToken: client.upstashSyncToken
236
373
  });
237
374
  if (error) {
238
375
  throw new UpstashError(error);
239
376
  }
240
- if (typeof result === "undefined") {
241
- throw new Error("Request did not return a result");
377
+ if (result === void 0) {
378
+ throw new TypeError("Request did not return a result");
242
379
  }
243
380
  return this.deserialize(result);
244
381
  }
@@ -265,6 +402,37 @@ var BitCountCommand = class extends Command {
265
402
  }
266
403
  };
267
404
 
405
+ // pkg/commands/bitfield.ts
406
+ var BitFieldCommand = class {
407
+ constructor(args, client, opts, execOperation = (command) => command.exec(this.client)) {
408
+ this.client = client;
409
+ this.opts = opts;
410
+ this.execOperation = execOperation;
411
+ this.command = ["bitfield", ...args];
412
+ }
413
+ command;
414
+ chain(...args) {
415
+ this.command.push(...args);
416
+ return this;
417
+ }
418
+ get(...args) {
419
+ return this.chain("get", ...args);
420
+ }
421
+ set(...args) {
422
+ return this.chain("set", ...args);
423
+ }
424
+ incrby(...args) {
425
+ return this.chain("incrby", ...args);
426
+ }
427
+ overflow(overflow) {
428
+ return this.chain("overflow", overflow);
429
+ }
430
+ exec() {
431
+ const command = new Command(this.command, this.opts);
432
+ return this.execOperation(command);
433
+ }
434
+ };
435
+
268
436
  // pkg/commands/bitop.ts
269
437
  var BitOpCommand = class extends Command {
270
438
  constructor(cmd, opts) {
@@ -279,6 +447,21 @@ var BitPosCommand = class extends Command {
279
447
  }
280
448
  };
281
449
 
450
+ // pkg/commands/copy.ts
451
+ var CopyCommand = class extends Command {
452
+ constructor([key, destinationKey, opts], commandOptions) {
453
+ super(["COPY", key, destinationKey, ...opts?.replace ? ["REPLACE"] : []], {
454
+ ...commandOptions,
455
+ deserialize(result) {
456
+ if (result > 0) {
457
+ return "COPIED";
458
+ }
459
+ return "NOT_COPIED";
460
+ }
461
+ });
462
+ }
463
+ };
464
+
282
465
  // pkg/commands/dbsize.ts
283
466
  var DBSizeCommand = class extends Command {
284
467
  constructor(opts) {
@@ -338,7 +521,7 @@ var ExistsCommand = class extends Command {
338
521
  // pkg/commands/expire.ts
339
522
  var ExpireCommand = class extends Command {
340
523
  constructor(cmd, opts) {
341
- super(["expire", ...cmd], opts);
524
+ super(["expire", ...cmd.filter(Boolean)], opts);
342
525
  }
343
526
  };
344
527
 
@@ -400,6 +583,129 @@ var GeoDistCommand = class extends Command {
400
583
  }
401
584
  };
402
585
 
586
+ // pkg/commands/geo_hash.ts
587
+ var GeoHashCommand = class extends Command {
588
+ constructor(cmd, opts) {
589
+ const [key] = cmd;
590
+ const members = Array.isArray(cmd[1]) ? cmd[1] : cmd.slice(1);
591
+ super(["GEOHASH", key, ...members], opts);
592
+ }
593
+ };
594
+
595
+ // pkg/commands/geo_pos.ts
596
+ var GeoPosCommand = class extends Command {
597
+ constructor(cmd, opts) {
598
+ const [key] = cmd;
599
+ const members = Array.isArray(cmd[1]) ? cmd[1] : cmd.slice(1);
600
+ super(["GEOPOS", key, ...members], {
601
+ deserialize: (result) => transform(result),
602
+ ...opts
603
+ });
604
+ }
605
+ };
606
+ function transform(result) {
607
+ const final = [];
608
+ for (const pos of result) {
609
+ if (!pos?.[0] || !pos?.[1]) {
610
+ continue;
611
+ }
612
+ final.push({ lng: Number.parseFloat(pos[0]), lat: Number.parseFloat(pos[1]) });
613
+ }
614
+ return final;
615
+ }
616
+
617
+ // pkg/commands/geo_search.ts
618
+ var GeoSearchCommand = class extends Command {
619
+ constructor([key, centerPoint, shape, order, opts], commandOptions) {
620
+ const command = ["GEOSEARCH", key];
621
+ if (centerPoint.type === "FROMMEMBER" || centerPoint.type === "frommember") {
622
+ command.push(centerPoint.type, centerPoint.member);
623
+ }
624
+ if (centerPoint.type === "FROMLONLAT" || centerPoint.type === "fromlonlat") {
625
+ command.push(centerPoint.type, centerPoint.coordinate.lon, centerPoint.coordinate.lat);
626
+ }
627
+ if (shape.type === "BYRADIUS" || shape.type === "byradius") {
628
+ command.push(shape.type, shape.radius, shape.radiusType);
629
+ }
630
+ if (shape.type === "BYBOX" || shape.type === "bybox") {
631
+ command.push(shape.type, shape.rect.width, shape.rect.height, shape.rectType);
632
+ }
633
+ command.push(order);
634
+ if (opts?.count) {
635
+ command.push("COUNT", opts.count.limit, ...opts.count.any ? ["ANY"] : []);
636
+ }
637
+ const transform2 = (result) => {
638
+ if (!opts?.withCoord && !opts?.withDist && !opts?.withHash) {
639
+ return result.map((member) => {
640
+ try {
641
+ return { member: JSON.parse(member) };
642
+ } catch {
643
+ return { member };
644
+ }
645
+ });
646
+ }
647
+ return result.map((members) => {
648
+ let counter = 1;
649
+ const obj = {};
650
+ try {
651
+ obj.member = JSON.parse(members[0]);
652
+ } catch {
653
+ obj.member = members[0];
654
+ }
655
+ if (opts.withDist) {
656
+ obj.dist = Number.parseFloat(members[counter++]);
657
+ }
658
+ if (opts.withHash) {
659
+ obj.hash = members[counter++].toString();
660
+ }
661
+ if (opts.withCoord) {
662
+ obj.coord = {
663
+ long: Number.parseFloat(members[counter][0]),
664
+ lat: Number.parseFloat(members[counter][1])
665
+ };
666
+ }
667
+ return obj;
668
+ });
669
+ };
670
+ super(
671
+ [
672
+ ...command,
673
+ ...opts?.withCoord ? ["WITHCOORD"] : [],
674
+ ...opts?.withDist ? ["WITHDIST"] : [],
675
+ ...opts?.withHash ? ["WITHHASH"] : []
676
+ ],
677
+ {
678
+ deserialize: transform2,
679
+ ...commandOptions
680
+ }
681
+ );
682
+ }
683
+ };
684
+
685
+ // pkg/commands/geo_search_store.ts
686
+ var GeoSearchStoreCommand = class extends Command {
687
+ constructor([destination, key, centerPoint, shape, order, opts], commandOptions) {
688
+ const command = ["GEOSEARCHSTORE", destination, key];
689
+ if (centerPoint.type === "FROMMEMBER" || centerPoint.type === "frommember") {
690
+ command.push(centerPoint.type, centerPoint.member);
691
+ }
692
+ if (centerPoint.type === "FROMLONLAT" || centerPoint.type === "fromlonlat") {
693
+ command.push(centerPoint.type, centerPoint.coordinate.lon, centerPoint.coordinate.lat);
694
+ }
695
+ if (shape.type === "BYRADIUS" || shape.type === "byradius") {
696
+ command.push(shape.type, shape.radius, shape.radiusType);
697
+ }
698
+ if (shape.type === "BYBOX" || shape.type === "bybox") {
699
+ command.push(shape.type, shape.rect.width, shape.rect.height, shape.rectType);
700
+ }
701
+ command.push(order);
702
+ if (opts?.count) {
703
+ command.push("COUNT", opts.count.limit, ...opts.count.any ? ["ANY"] : []);
704
+ }
705
+ super([...command, ...opts?.storeDist ? ["STOREDIST"] : []], commandOptions);
706
+ }
707
+ };
708
+
403
709
  // pkg/commands/get.ts
404
710
  var GetCommand = class extends Command {
405
711
  constructor(cmd, opts) {
@@ -466,12 +772,8 @@ function deserialize(result) {
466
772
  const key = result.shift();
467
773
  const value = result.shift();
468
774
  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
- }
775
+ const valueIsNumberAndNotSafeInteger = !Number.isNaN(Number(value)) && !Number.isSafeInteger(Number(value));
776
+ obj[key] = valueIsNumberAndNotSafeInteger ? value : JSON.parse(value);
475
777
  } catch {
476
778
  obj[key] = value;
477
779
  }
@@ -517,15 +819,15 @@ var HLenCommand = class extends Command {
517
819
 
518
820
  // pkg/commands/hmget.ts
519
821
  function deserialize2(fields, result) {
520
- if (result.length === 0 || result.every((field) => field === null)) {
822
+ if (result.every((field) => field === null)) {
521
823
  return null;
522
824
  }
523
825
  const obj = {};
524
- for (let i = 0; i < fields.length; i++) {
826
+ for (const [i, field] of fields.entries()) {
525
827
  try {
526
- obj[fields[i]] = JSON.parse(result[i]);
828
+ obj[field] = JSON.parse(result[i]);
527
829
  } catch {
528
- obj[fields[i]] = result[i];
830
+ obj[field] = result[i];
529
831
  }
530
832
  }
531
833
  return obj;
@@ -573,7 +875,7 @@ var HRandFieldCommand = class extends Command {
573
875
  command.push("WITHVALUES");
574
876
  }
575
877
  super(command, {
576
- // @ts-ignore TODO:
878
+ // @ts-expect-error to silence compiler
577
879
  deserialize: cmd[2] ? (result) => deserialize3(result) : opts?.deserialize,
578
880
  ...opts
579
881
  });
@@ -590,7 +892,10 @@ var HScanCommand = class extends Command {
590
892
  if (typeof cmdOpts?.count === "number") {
591
893
  command.push("count", cmdOpts.count);
592
894
  }
593
- super(command, opts);
895
+ super(command, {
896
+ deserialize: deserializeScanResponse,
897
+ ...opts
898
+ });
594
899
  }
595
900
  };
596
901
 
@@ -741,6 +1046,17 @@ var JsonMGetCommand = class extends Command {
741
1046
  }
742
1047
  };
743
1048
 
1049
+ // pkg/commands/json_mset.ts
1050
+ var JsonMSetCommand = class extends Command {
1051
+ constructor(cmd, opts) {
1052
+ const command = ["JSON.MSET"];
1053
+ for (const c of cmd) {
1054
+ command.push(c.key, c.path, c.value);
1055
+ }
1056
+ super(command, opts);
1057
+ }
1058
+ };
1059
+
744
1060
  // pkg/commands/json_numincrby.ts
745
1061
  var JsonNumIncrByCommand = class extends Command {
746
1062
  constructor(cmd, opts) {
@@ -854,6 +1170,14 @@ var LMoveCommand = class extends Command {
854
1170
  }
855
1171
  };
856
1172
 
1173
+ // pkg/commands/lmpop.ts
1174
+ var LmPopCommand = class extends Command {
1175
+ constructor(cmd, opts) {
1176
+ const [numkeys, keys, direction, count] = cmd;
1177
+ super(["LMPOP", numkeys, ...keys, direction, ...count ? ["COUNT", count] : []], opts);
1178
+ }
1179
+ };
1180
+
857
1181
  // pkg/commands/lpop.ts
858
1182
  var LPopCommand = class extends Command {
859
1183
  constructor(cmd, opts) {
@@ -938,7 +1262,7 @@ var MSetCommand = class extends Command {
938
1262
  // pkg/commands/msetnx.ts
939
1263
  var MSetNXCommand = class extends Command {
940
1264
  constructor([kv], opts) {
941
- super(["msetnx", ...Object.entries(kv).flatMap((_) => _)], opts);
1265
+ super(["msetnx", ...Object.entries(kv).flat()], opts);
942
1266
  }
943
1267
  };
944
1268
 
@@ -963,11 +1287,32 @@ var PExpireAtCommand = class extends Command {
963
1287
  }
964
1288
  };
965
1289
 
1290
+ // pkg/commands/pfadd.ts
1291
+ var PfAddCommand = class extends Command {
1292
+ constructor(cmd, opts) {
1293
+ super(["pfadd", ...cmd], opts);
1294
+ }
1295
+ };
1296
+
1297
+ // pkg/commands/pfcount.ts
1298
+ var PfCountCommand = class extends Command {
1299
+ constructor(cmd, opts) {
1300
+ super(["pfcount", ...cmd], opts);
1301
+ }
1302
+ };
1303
+
1304
+ // pkg/commands/pfmerge.ts
1305
+ var PfMergeCommand = class extends Command {
1306
+ constructor(cmd, opts) {
1307
+ super(["pfmerge", ...cmd], opts);
1308
+ }
1309
+ };
1310
+
966
1311
  // pkg/commands/ping.ts
967
1312
  var PingCommand = class extends Command {
968
1313
  constructor(cmd, opts) {
969
1314
  const command = ["ping"];
970
- if (typeof cmd !== "undefined" && typeof cmd[0] !== "undefined") {
1315
+ if (cmd?.[0] !== void 0) {
971
1316
  command.push(cmd[0]);
972
1317
  }
973
1318
  super(command, opts);
@@ -1057,7 +1402,10 @@ var ScanCommand = class extends Command {
1057
1402
  if (opts?.type && opts.type.length > 0) {
1058
1403
  command.push("type", opts.type);
1059
1404
  }
1060
- super(command, cmdOpts);
1405
+ super(command, {
1406
+ deserialize: deserializeScanResponse,
1407
+ ...cmdOpts
1408
+ });
1061
1409
  }
1062
1410
  };
1063
1411
 
@@ -1250,7 +1598,10 @@ var SScanCommand = class extends Command {
1250
1598
  if (typeof opts?.count === "number") {
1251
1599
  command.push("count", opts.count);
1252
1600
  }
1253
- super(command, cmdOpts);
1601
+ super(command, {
1602
+ deserialize: deserializeScanResponse,
1603
+ ...cmdOpts
1604
+ });
1254
1605
  }
1255
1606
  };
1256
1607
 
@@ -1310,6 +1661,14 @@ var UnlinkCommand = class extends Command {
1310
1661
  }
1311
1662
  };
1312
1663
 
1664
+ // pkg/commands/xack.ts
1665
+ var XAckCommand = class extends Command {
1666
+ constructor([key, group, id], opts) {
1667
+ const ids = Array.isArray(id) ? [...id] : [id];
1668
+ super(["XACK", key, group, ...ids], opts);
1669
+ }
1670
+ };
1671
+
1313
1672
  // pkg/commands/xadd.ts
1314
1673
  var XAddCommand = class extends Command {
1315
1674
  constructor([key, id, entries, opts], commandOptions) {
@@ -1320,7 +1679,7 @@ var XAddCommand = class extends Command {
1320
1679
  }
1321
1680
  if (opts.trim) {
1322
1681
  command.push(opts.trim.type, opts.trim.comparison, opts.trim.threshold);
1323
- if (typeof opts.trim.limit !== "undefined") {
1682
+ if (opts.trim.limit !== void 0) {
1324
1683
  command.push("LIMIT", opts.trim.limit);
1325
1684
  }
1326
1685
  }
@@ -1333,6 +1692,139 @@ var XAddCommand = class extends Command {
1333
1692
  }
1334
1693
  };
1335
1694
 
1695
+ // pkg/commands/xautoclaim.ts
1696
+ var XAutoClaim = class extends Command {
1697
+ constructor([key, group, consumer, minIdleTime, start, options], opts) {
1698
+ const commands = [];
1699
+ if (options?.count) {
1700
+ commands.push("COUNT", options.count);
1701
+ }
1702
+ if (options?.justId) {
1703
+ commands.push("JUSTID");
1704
+ }
1705
+ super(["XAUTOCLAIM", key, group, consumer, minIdleTime, start, ...commands], opts);
1706
+ }
1707
+ };
1708
+
1709
+ // pkg/commands/xclaim.ts
1710
+ var XClaimCommand = class extends Command {
1711
+ constructor([key, group, consumer, minIdleTime, id, options], opts) {
1712
+ const ids = Array.isArray(id) ? [...id] : [id];
1713
+ const commands = [];
1714
+ if (options?.idleMS) {
1715
+ commands.push("IDLE", options.idleMS);
1716
+ }
1717
+ if (options?.idleMS) {
1718
+ commands.push("TIME", options.timeMS);
1719
+ }
1720
+ if (options?.retryCount) {
1721
+ commands.push("RETRYCOUNT", options.retryCount);
1722
+ }
1723
+ if (options?.force) {
1724
+ commands.push("FORCE");
1725
+ }
1726
+ if (options?.justId) {
1727
+ commands.push("JUSTID");
1728
+ }
1729
+ if (options?.lastId) {
1730
+ commands.push("LASTID", options.lastId);
1731
+ }
1732
+ super(["XCLAIM", key, group, consumer, minIdleTime, ...ids, ...commands], opts);
1733
+ }
1734
+ };
1735
+
1736
+ // pkg/commands/xdel.ts
1737
+ var XDelCommand = class extends Command {
1738
+ constructor([key, ids], opts) {
1739
+ const cmds = Array.isArray(ids) ? [...ids] : [ids];
1740
+ super(["XDEL", key, ...cmds], opts);
1741
+ }
1742
+ };
1743
+
1744
+ // pkg/commands/xgroup.ts
1745
+ var XGroupCommand = class extends Command {
1746
+ constructor([key, opts], commandOptions) {
1747
+ const command = ["XGROUP"];
1748
+ switch (opts.type) {
1749
+ case "CREATE": {
1750
+ command.push("CREATE", key, opts.group, opts.id);
1751
+ if (opts.options) {
1752
+ if (opts.options.MKSTREAM) {
1753
+ command.push("MKSTREAM");
1754
+ }
1755
+ if (opts.options.ENTRIESREAD !== void 0) {
1756
+ command.push("ENTRIESREAD", opts.options.ENTRIESREAD.toString());
1757
+ }
1758
+ }
1759
+ break;
1760
+ }
1761
+ case "CREATECONSUMER": {
1762
+ command.push("CREATECONSUMER", key, opts.group, opts.consumer);
1763
+ break;
1764
+ }
1765
+ case "DELCONSUMER": {
1766
+ command.push("DELCONSUMER", key, opts.group, opts.consumer);
1767
+ break;
1768
+ }
1769
+ case "DESTROY": {
1770
+ command.push("DESTROY", key, opts.group);
1771
+ break;
1772
+ }
1773
+ case "SETID": {
1774
+ command.push("SETID", key, opts.group, opts.id);
1775
+ if (opts.options?.ENTRIESREAD !== void 0) {
1776
+ command.push("ENTRIESREAD", opts.options.ENTRIESREAD.toString());
1777
+ }
1778
+ break;
1779
+ }
1780
+ default: {
1781
+ throw new Error("Invalid XGROUP");
1782
+ }
1783
+ }
1784
+ super(command, commandOptions);
1785
+ }
1786
+ };
1787
+
1788
+ // pkg/commands/xinfo.ts
1789
+ var XInfoCommand = class extends Command {
1790
+ constructor([key, options], opts) {
1791
+ const cmds = [];
1792
+ if (options.type === "CONSUMERS") {
1793
+ cmds.push("CONSUMERS", key, options.group);
1794
+ } else {
1795
+ cmds.push("GROUPS", key);
1796
+ }
1797
+ super(["XINFO", ...cmds], opts);
1798
+ }
1799
+ };
1800
+
1801
+ // pkg/commands/xlen.ts
1802
+ var XLenCommand = class extends Command {
1803
+ constructor(cmd, opts) {
1804
+ super(["XLEN", ...cmd], opts);
1805
+ }
1806
+ };
1807
+
1808
+ // pkg/commands/xpending.ts
1809
+ var XPendingCommand = class extends Command {
1810
+ constructor([key, group, start, end, count, options], opts) {
1811
+ const consumers = options?.consumer === void 0 ? [] : Array.isArray(options.consumer) ? [...options.consumer] : [options.consumer];
1812
+ super(
1813
+ [
1814
+ "XPENDING",
1815
+ key,
1816
+ group,
1817
+ ...options?.idleTime ? ["IDLE", options.idleTime] : [],
1818
+ start,
1819
+ end,
1820
+ count,
1821
+ ...consumers
1822
+ ],
1823
+ opts
1824
+ );
1825
+ }
1826
+ };
1827
+
1336
1828
  // pkg/commands/xrange.ts
1337
1829
  function deserialize4(result) {
1338
1830
  const obj = {};
@@ -1369,6 +1861,99 @@ var XRangeCommand = class extends Command {
1369
1861
  }
1370
1862
  };
1371
1863
 
1864
+ // pkg/commands/xread.ts
1865
+ var UNBALANCED_XREAD_ERR = "ERR Unbalanced XREAD list of streams: for each stream key an ID or '$' must be specified";
1866
+ var XReadCommand = class extends Command {
1867
+ constructor([key, id, options], opts) {
1868
+ if (Array.isArray(key) && Array.isArray(id) && key.length !== id.length) {
1869
+ throw new Error(UNBALANCED_XREAD_ERR);
1870
+ }
1871
+ const commands = [];
1872
+ if (typeof options?.count === "number") {
1873
+ commands.push("COUNT", options.count);
1874
+ }
1875
+ if (typeof options?.blockMS === "number") {
1876
+ commands.push("BLOCK", options.blockMS);
1877
+ }
1878
+ commands.push(
1879
+ "STREAMS",
1880
+ ...Array.isArray(key) ? [...key] : [key],
1881
+ ...Array.isArray(id) ? [...id] : [id]
1882
+ );
1883
+ super(["XREAD", ...commands], opts);
1884
+ }
1885
+ };
1886
+
1887
+ // pkg/commands/xreadgroup.ts
1888
+ var UNBALANCED_XREADGROUP_ERR = "ERR Unbalanced XREADGROUP list of streams: for each stream key an ID or '$' must be specified";
1889
+ var XReadGroupCommand = class extends Command {
1890
+ constructor([group, consumer, key, id, options], opts) {
1891
+ if (Array.isArray(key) && Array.isArray(id) && key.length !== id.length) {
1892
+ throw new Error(UNBALANCED_XREADGROUP_ERR);
1893
+ }
1894
+ const commands = [];
1895
+ if (typeof options?.count === "number") {
1896
+ commands.push("COUNT", options.count);
1897
+ }
1898
+ if (typeof options?.blockMS === "number") {
1899
+ commands.push("BLOCK", options.blockMS);
1900
+ }
1901
+ if (typeof options?.NOACK === "boolean" && options.NOACK) {
1902
+ commands.push("NOACK");
1903
+ }
1904
+ commands.push(
1905
+ "STREAMS",
1906
+ ...Array.isArray(key) ? [...key] : [key],
1907
+ ...Array.isArray(id) ? [...id] : [id]
1908
+ );
1909
+ super(["XREADGROUP", "GROUP", group, consumer, ...commands], opts);
1910
+ }
1911
+ };
1912
+
1913
+ // pkg/commands/xrevrange.ts
1914
+ var XRevRangeCommand = class extends Command {
1915
+ constructor([key, end, start, count], opts) {
1916
+ const command = ["XREVRANGE", key, end, start];
1917
+ if (typeof count === "number") {
1918
+ command.push("COUNT", count);
1919
+ }
1920
+ super(command, {
1921
+ deserialize: (result) => deserialize5(result),
1922
+ ...opts
1923
+ });
1924
+ }
1925
+ };
1926
+ function deserialize5(result) {
1927
+ const obj = {};
1928
+ for (const e of result) {
1929
+ while (e.length >= 2) {
1930
+ const streamId = e.shift();
1931
+ const entries = e.shift();
1932
+ if (!(streamId in obj)) {
1933
+ obj[streamId] = {};
1934
+ }
1935
+ while (entries.length >= 2) {
1936
+ const field = entries.shift();
1937
+ const value = entries.shift();
1938
+ try {
1939
+ obj[streamId][field] = JSON.parse(value);
1940
+ } catch {
1941
+ obj[streamId][field] = value;
1942
+ }
1943
+ }
1944
+ }
1945
+ }
1946
+ return obj;
1947
+ }
1948
+
1949
+ // pkg/commands/xtrim.ts
1950
+ var XTrimCommand = class extends Command {
1951
+ constructor([key, options], opts) {
1952
+ const { limit, strategy, threshold, exactness = "~" } = options;
1953
+ super(["XTRIM", key, strategy, exactness, threshold, ...limit ? ["LIMIT", limit] : []], opts);
1954
+ }
1955
+ };
1956
+
1372
1957
  // pkg/commands/zadd.ts
1373
1958
  var ZAddCommand = class extends Command {
1374
1959
  constructor([key, arg1, ...arg2], opts) {
@@ -1384,6 +1969,11 @@ var ZAddCommand = class extends Command {
1384
1969
  if ("incr" in arg1 && arg1.incr) {
1385
1970
  command.push("incr");
1386
1971
  }
1972
+ if ("lt" in arg1 && arg1.lt) {
1973
+ command.push("lt");
1974
+ } else if ("gt" in arg1 && arg1.gt) {
1975
+ command.push("gt");
1976
+ }
1387
1977
  if ("score" in arg1 && "member" in arg1) {
1388
1978
  command.push(arg1.score, arg1.member);
1389
1979
  }
@@ -1478,7 +2068,7 @@ var ZRangeCommand = class extends Command {
1478
2068
  if (opts?.rev) {
1479
2069
  command.push("rev");
1480
2070
  }
1481
- if (typeof opts?.count !== "undefined" && typeof opts?.offset !== "undefined") {
2071
+ if (opts?.count !== void 0 && opts.offset !== void 0) {
1482
2072
  command.push("limit", opts.offset, opts.count);
1483
2073
  }
1484
2074
  if (opts?.withScores) {
@@ -1540,7 +2130,10 @@ var ZScanCommand = class extends Command {
1540
2130
  if (typeof opts?.count === "number") {
1541
2131
  command.push("count", opts.count);
1542
2132
  }
1543
- super(command, cmdOpts);
2133
+ super(command, {
2134
+ deserialize: deserializeScanResponse,
2135
+ ...cmdOpts
2136
+ });
1544
2137
  }
1545
2138
  };
1546
2139
 
@@ -1569,7 +2162,7 @@ var ZUnionCommand = class extends Command {
1569
2162
  if ("aggregate" in opts) {
1570
2163
  command.push("aggregate", opts.aggregate);
1571
2164
  }
1572
- if (opts?.withScores) {
2165
+ if (opts.withScores) {
1573
2166
  command.push("withscores");
1574
2167
  }
1575
2168
  }
@@ -1626,6 +2219,19 @@ var Pipeline = class {
1626
2219
  this.commands = [];
1627
2220
  this.commandOptions = opts.commandOptions;
1628
2221
  this.multiExec = opts.multiExec ?? false;
2222
+ if (this.commandOptions?.latencyLogging) {
2223
+ const originalExec = this.exec.bind(this);
2224
+ this.exec = async () => {
2225
+ const start = performance.now();
2226
+ const result = await originalExec();
2227
+ const end = performance.now();
2228
+ const loggerResult = (end - start).toFixed(2);
2229
+ console.log(
2230
+ `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`
2231
+ );
2232
+ return result;
2233
+ };
2234
+ }
1629
2235
  }
1630
2236
  /**
1631
2237
  * Send the pipeline request to upstash.
@@ -1679,6 +2285,23 @@ var Pipeline = class {
1679
2285
  * @see https://redis.io/commands/bitcount
1680
2286
  */
1681
2287
  bitcount = (...args) => this.chain(new BitCountCommand(args, this.commandOptions));
2288
+ /**
2289
+ * Returns an instance that can be used to execute `BITFIELD` commands on one key.
2290
+ *
2291
+ * @example
2292
+ * ```typescript
2293
+ * redis.set("mykey", 0);
2294
+ * const result = await redis.pipeline()
2295
+ * .bitfield("mykey")
2296
+ * .set("u4", 0, 16)
2297
+ * .incr("u4", "#1", 1)
2298
+ * .exec();
2299
+ * console.log(result); // [[0, 1]]
2300
+ * ```
2301
+ *
2302
+ * @see https://redis.io/commands/bitfield
2303
+ */
2304
+ bitfield = (...args) => new BitFieldCommand(args, this.client, this.commandOptions, this.chain.bind(this));
1682
2305
  /**
1683
2306
  * @see https://redis.io/commands/bitop
1684
2307
  */
@@ -1689,6 +2312,10 @@ var Pipeline = class {
1689
2312
  * @see https://redis.io/commands/bitpos
1690
2313
  */
1691
2314
  bitpos = (...args) => this.chain(new BitPosCommand(args, this.commandOptions));
2315
+ /**
2316
+ * @see https://redis.io/commands/copy
2317
+ */
2318
+ copy = (...args) => this.chain(new CopyCommand(args, this.commandOptions));
1692
2319
  /**
1693
2320
  * @see https://redis.io/commands/zdiffstore
1694
2321
  */
@@ -1741,6 +2368,30 @@ var Pipeline = class {
1741
2368
  * @see https://redis.io/commands/flushdb
1742
2369
  */
1743
2370
  flushdb = (...args) => this.chain(new FlushDBCommand(args, this.commandOptions));
2371
+ /**
2372
+ * @see https://redis.io/commands/geoadd
2373
+ */
2374
+ geoadd = (...args) => this.chain(new GeoAddCommand(args, this.commandOptions));
2375
+ /**
2376
+ * @see https://redis.io/commands/geodist
2377
+ */
2378
+ geodist = (...args) => this.chain(new GeoDistCommand(args, this.commandOptions));
2379
+ /**
2380
+ * @see https://redis.io/commands/geopos
2381
+ */
2382
+ geopos = (...args) => this.chain(new GeoPosCommand(args, this.commandOptions));
2383
+ /**
2384
+ * @see https://redis.io/commands/geohash
2385
+ */
2386
+ geohash = (...args) => this.chain(new GeoHashCommand(args, this.commandOptions));
2387
+ /**
2388
+ * @see https://redis.io/commands/geosearch
2389
+ */
2390
+ geosearch = (...args) => this.chain(new GeoSearchCommand(args, this.commandOptions));
2391
+ /**
2392
+ * @see https://redis.io/commands/geosearchstore
2393
+ */
2394
+ geosearchstore = (...args) => this.chain(new GeoSearchStoreCommand(args, this.commandOptions));
1744
2395
  /**
1745
2396
  * @see https://redis.io/commands/get
1746
2397
  */
@@ -1861,6 +2512,10 @@ var Pipeline = class {
1861
2512
  * @see https://redis.io/commands/lpop
1862
2513
  */
1863
2514
  lpop = (...args) => this.chain(new LPopCommand(args, this.commandOptions));
2515
+ /**
2516
+ * @see https://redis.io/commands/lmpop
2517
+ */
2518
+ lmpop = (...args) => this.chain(new LmPopCommand(args, this.commandOptions));
1864
2519
  /**
1865
2520
  * @see https://redis.io/commands/lpos
1866
2521
  */
@@ -1913,6 +2568,18 @@ var Pipeline = class {
1913
2568
  * @see https://redis.io/commands/pexpireat
1914
2569
  */
1915
2570
  pexpireat = (...args) => this.chain(new PExpireAtCommand(args, this.commandOptions));
2571
+ /**
2572
+ * @see https://redis.io/commands/pfadd
2573
+ */
2574
+ pfadd = (...args) => this.chain(new PfAddCommand(args, this.commandOptions));
2575
+ /**
2576
+ * @see https://redis.io/commands/pfcount
2577
+ */
2578
+ pfcount = (...args) => this.chain(new PfCountCommand(args, this.commandOptions));
2579
+ /**
2580
+ * @see https://redis.io/commands/pfmerge
2581
+ */
2582
+ pfmerge = (...args) => this.chain(new PfMergeCommand(args, this.commandOptions));
1916
2583
  /**
1917
2584
  * @see https://redis.io/commands/ping
1918
2585
  */
@@ -1956,7 +2623,7 @@ var Pipeline = class {
1956
2623
  /**
1957
2624
  * @see https://redis.io/commands/sadd
1958
2625
  */
1959
- sadd = (key, ...members) => this.chain(new SAddCommand([key, ...members], this.commandOptions));
2626
+ sadd = (key, member, ...members) => this.chain(new SAddCommand([key, member, ...members], this.commandOptions));
1960
2627
  /**
1961
2628
  * @see https://redis.io/commands/scan
1962
2629
  */
@@ -2083,10 +2750,7 @@ var Pipeline = class {
2083
2750
  zadd = (...args) => {
2084
2751
  if ("score" in args[1]) {
2085
2752
  return this.chain(
2086
- new ZAddCommand(
2087
- [args[0], args[1], ...args.slice(2)],
2088
- this.commandOptions
2089
- )
2753
+ new ZAddCommand([args[0], args[1], ...args.slice(2)], this.commandOptions)
2090
2754
  );
2091
2755
  }
2092
2756
  return this.chain(
@@ -2096,6 +2760,62 @@ var Pipeline = class {
2096
2760
  )
2097
2761
  );
2098
2762
  };
2763
+ /**
2764
+ * @see https://redis.io/commands/xadd
2765
+ */
2766
+ xadd = (...args) => this.chain(new XAddCommand(args, this.commandOptions));
2767
+ /**
2768
+ * @see https://redis.io/commands/xack
2769
+ */
2770
+ xack = (...args) => this.chain(new XAckCommand(args, this.commandOptions));
2771
+ /**
2772
+ * @see https://redis.io/commands/xdel
2773
+ */
2774
+ xdel = (...args) => this.chain(new XDelCommand(args, this.commandOptions));
2775
+ /**
2776
+ * @see https://redis.io/commands/xgroup
2777
+ */
2778
+ xgroup = (...args) => this.chain(new XGroupCommand(args, this.commandOptions));
2779
+ /**
2780
+ * @see https://redis.io/commands/xread
2781
+ */
2782
+ xread = (...args) => this.chain(new XReadCommand(args, this.commandOptions));
2783
+ /**
2784
+ * @see https://redis.io/commands/xreadgroup
2785
+ */
2786
+ xreadgroup = (...args) => this.chain(new XReadGroupCommand(args, this.commandOptions));
2787
+ /**
2788
+ * @see https://redis.io/commands/xinfo
2789
+ */
2790
+ xinfo = (...args) => this.chain(new XInfoCommand(args, this.commandOptions));
2791
+ /**
2792
+ * @see https://redis.io/commands/xlen
2793
+ */
2794
+ xlen = (...args) => this.chain(new XLenCommand(args, this.commandOptions));
2795
+ /**
2796
+ * @see https://redis.io/commands/xpending
2797
+ */
2798
+ xpending = (...args) => this.chain(new XPendingCommand(args, this.commandOptions));
2799
+ /**
2800
+ * @see https://redis.io/commands/xclaim
2801
+ */
2802
+ xclaim = (...args) => this.chain(new XClaimCommand(args, this.commandOptions));
2803
+ /**
2804
+ * @see https://redis.io/commands/xautoclaim
2805
+ */
2806
+ xautoclaim = (...args) => this.chain(new XAutoClaim(args, this.commandOptions));
2807
+ /**
2808
+ * @see https://redis.io/commands/xtrim
2809
+ */
2810
+ xtrim = (...args) => this.chain(new XTrimCommand(args, this.commandOptions));
2811
+ /**
2812
+ * @see https://redis.io/commands/xrange
2813
+ */
2814
+ xrange = (...args) => this.chain(new XRangeCommand(args, this.commandOptions));
2815
+ /**
2816
+ * @see https://redis.io/commands/xrevrange
2817
+ */
2818
+ xrevrange = (...args) => this.chain(new XRevRangeCommand(args, this.commandOptions));
2099
2819
  /**
2100
2820
  * @see https://redis.io/commands/zcard
2101
2821
  */
@@ -2213,14 +2933,6 @@ var Pipeline = class {
2213
2933
  * @see https://redis.io/commands/json.forget
2214
2934
  */
2215
2935
  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
2936
  /**
2225
2937
  * @see https://redis.io/commands/json.get
2226
2938
  */
@@ -2229,6 +2941,10 @@ var Pipeline = class {
2229
2941
  * @see https://redis.io/commands/json.mget
2230
2942
  */
2231
2943
  mget: (...args) => this.chain(new JsonMGetCommand(args, this.commandOptions)),
2944
+ /**
2945
+ * @see https://redis.io/commands/json.mset
2946
+ */
2947
+ mset: (...args) => this.chain(new JsonMSetCommand(args, this.commandOptions)),
2232
2948
  /**
2233
2949
  * @see https://redis.io/commands/json.numincrby
2234
2950
  */
@@ -2274,8 +2990,8 @@ var Pipeline = class {
2274
2990
  };
2275
2991
 
2276
2992
  // pkg/script.ts
2277
- var import_enc_hex = __toESM(require("crypto-js/enc-hex"));
2278
- var import_sha1 = __toESM(require("crypto-js/sha1"));
2993
+ var import_enc_hex = __toESM(require("crypto-js/enc-hex.js"));
2994
+ var import_sha1 = __toESM(require("crypto-js/sha1.js"));
2279
2995
  var Script = class {
2280
2996
  script;
2281
2997
  sha1;
@@ -2304,11 +3020,11 @@ var Script = class {
2304
3020
  * Following calls will be able to use the cached script
2305
3021
  */
2306
3022
  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")) {
3023
+ const res = await this.redis.evalsha(this.sha1, keys, args).catch(async (error) => {
3024
+ if (error instanceof Error && error.message.toLowerCase().includes("noscript")) {
2309
3025
  return await this.redis.eval(this.script, keys, args);
2310
3026
  }
2311
- throw err;
3027
+ throw error;
2312
3028
  });
2313
3029
  return res;
2314
3030
  }
@@ -2325,6 +3041,7 @@ var Redis = class {
2325
3041
  client;
2326
3042
  opts;
2327
3043
  enableTelemetry;
3044
+ enableAutoPipelining;
2328
3045
  /**
2329
3046
  * Create a new redis client
2330
3047
  *
@@ -2340,6 +3057,16 @@ var Redis = class {
2340
3057
  this.client = client;
2341
3058
  this.opts = opts;
2342
3059
  this.enableTelemetry = opts?.enableTelemetry ?? true;
3060
+ if (opts?.readYourWrites === false) {
3061
+ this.client.readYourWrites = false;
3062
+ }
3063
+ this.enableAutoPipelining = opts?.enableAutoPipelining ?? true;
3064
+ }
3065
+ get readYourWritesSyncToken() {
3066
+ return this.client.upstashSyncToken;
3067
+ }
3068
+ set readYourWritesSyncToken(session) {
3069
+ this.client.upstashSyncToken = session;
2343
3070
  }
2344
3071
  get json() {
2345
3072
  return {
@@ -2379,14 +3106,6 @@ var Redis = class {
2379
3106
  * @see https://redis.io/commands/json.forget
2380
3107
  */
2381
3108
  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
3109
  /**
2391
3110
  * @see https://redis.io/commands/json.get
2392
3111
  */
@@ -2395,6 +3114,10 @@ var Redis = class {
2395
3114
  * @see https://redis.io/commands/json.mget
2396
3115
  */
2397
3116
  mget: (...args) => new JsonMGetCommand(args, this.opts).exec(this.client),
3117
+ /**
3118
+ * @see https://redis.io/commands/json.mset
3119
+ */
3120
+ mset: (...args) => new JsonMSetCommand(args, this.opts).exec(this.client),
2398
3121
  /**
2399
3122
  * @see https://redis.io/commands/json.numincrby
2400
3123
  */
@@ -2469,6 +3192,9 @@ var Redis = class {
2469
3192
  commandOptions: this.opts,
2470
3193
  multiExec: false
2471
3194
  });
3195
+ autoPipeline = () => {
3196
+ return createAutoPipelineProxy(this);
3197
+ };
2472
3198
  /**
2473
3199
  * Create a new transaction to allow executing multiple steps atomically.
2474
3200
  *
@@ -2483,6 +3209,22 @@ var Redis = class {
2483
3209
  commandOptions: this.opts,
2484
3210
  multiExec: true
2485
3211
  });
3212
+ /**
3213
+ * Returns an instance that can be used to execute `BITFIELD` commands on one key.
3214
+ *
3215
+ * @example
3216
+ * ```typescript
3217
+ * redis.set("mykey", 0);
3218
+ * const result = await redis.bitfield("mykey")
3219
+ * .set("u4", 0, 16)
3220
+ * .incr("u4", "#1", 1)
3221
+ * .exec();
3222
+ * console.log(result); // [0, 1]
3223
+ * ```
3224
+ *
3225
+ * @see https://redis.io/commands/bitfield
3226
+ */
3227
+ bitfield = (...args) => new BitFieldCommand(args, this.client, this.opts);
2486
3228
  /**
2487
3229
  * @see https://redis.io/commands/append
2488
3230
  */
@@ -2501,6 +3243,10 @@ var Redis = class {
2501
3243
  * @see https://redis.io/commands/bitpos
2502
3244
  */
2503
3245
  bitpos = (...args) => new BitPosCommand(args, this.opts).exec(this.client);
3246
+ /**
3247
+ * @see https://redis.io/commands/copy
3248
+ */
3249
+ copy = (...args) => new CopyCommand(args, this.opts).exec(this.client);
2504
3250
  /**
2505
3251
  * @see https://redis.io/commands/dbsize
2506
3252
  */
@@ -2549,6 +3295,30 @@ var Redis = class {
2549
3295
  * @see https://redis.io/commands/flushdb
2550
3296
  */
2551
3297
  flushdb = (...args) => new FlushDBCommand(args, this.opts).exec(this.client);
3298
+ /**
3299
+ * @see https://redis.io/commands/geoadd
3300
+ */
3301
+ geoadd = (...args) => new GeoAddCommand(args, this.opts).exec(this.client);
3302
+ /**
3303
+ * @see https://redis.io/commands/geopos
3304
+ */
3305
+ geopos = (...args) => new GeoPosCommand(args, this.opts).exec(this.client);
3306
+ /**
3307
+ * @see https://redis.io/commands/geodist
3308
+ */
3309
+ geodist = (...args) => new GeoDistCommand(args, this.opts).exec(this.client);
3310
+ /**
3311
+ * @see https://redis.io/commands/geohash
3312
+ */
3313
+ geohash = (...args) => new GeoHashCommand(args, this.opts).exec(this.client);
3314
+ /**
3315
+ * @see https://redis.io/commands/geosearch
3316
+ */
3317
+ geosearch = (...args) => new GeoSearchCommand(args, this.opts).exec(this.client);
3318
+ /**
3319
+ * @see https://redis.io/commands/geosearchstore
3320
+ */
3321
+ geosearchstore = (...args) => new GeoSearchStoreCommand(args, this.opts).exec(this.client);
2552
3322
  /**
2553
3323
  * @see https://redis.io/commands/get
2554
3324
  */
@@ -2669,6 +3439,10 @@ var Redis = class {
2669
3439
  * @see https://redis.io/commands/lpop
2670
3440
  */
2671
3441
  lpop = (...args) => new LPopCommand(args, this.opts).exec(this.client);
3442
+ /**
3443
+ * @see https://redis.io/commands/lmpop
3444
+ */
3445
+ lmpop = (...args) => new LmPopCommand(args, this.opts).exec(this.client);
2672
3446
  /**
2673
3447
  * @see https://redis.io/commands/lpos
2674
3448
  */
@@ -2721,6 +3495,18 @@ var Redis = class {
2721
3495
  * @see https://redis.io/commands/pexpireat
2722
3496
  */
2723
3497
  pexpireat = (...args) => new PExpireAtCommand(args, this.opts).exec(this.client);
3498
+ /**
3499
+ * @see https://redis.io/commands/pfadd
3500
+ */
3501
+ pfadd = (...args) => new PfAddCommand(args, this.opts).exec(this.client);
3502
+ /**
3503
+ * @see https://redis.io/commands/pfcount
3504
+ */
3505
+ pfcount = (...args) => new PfCountCommand(args, this.opts).exec(this.client);
3506
+ /**
3507
+ * @see https://redis.io/commands/pfmerge
3508
+ */
3509
+ pfmerge = (...args) => new PfMergeCommand(args, this.opts).exec(this.client);
2724
3510
  /**
2725
3511
  * @see https://redis.io/commands/ping
2726
3512
  */
@@ -2764,7 +3550,7 @@ var Redis = class {
2764
3550
  /**
2765
3551
  * @see https://redis.io/commands/sadd
2766
3552
  */
2767
- sadd = (key, ...members) => new SAddCommand([key, ...members], this.opts).exec(this.client);
3553
+ sadd = (key, member, ...members) => new SAddCommand([key, member, ...members], this.opts).exec(this.client);
2768
3554
  /**
2769
3555
  * @see https://redis.io/commands/scan
2770
3556
  */
@@ -2889,19 +3675,66 @@ var Redis = class {
2889
3675
  * @see https://redis.io/commands/xadd
2890
3676
  */
2891
3677
  xadd = (...args) => new XAddCommand(args, this.opts).exec(this.client);
3678
+ /**
3679
+ * @see https://redis.io/commands/xack
3680
+ */
3681
+ xack = (...args) => new XAckCommand(args, this.opts).exec(this.client);
3682
+ /**
3683
+ * @see https://redis.io/commands/xdel
3684
+ */
3685
+ xdel = (...args) => new XDelCommand(args, this.opts).exec(this.client);
3686
+ /**
3687
+ * @see https://redis.io/commands/xgroup
3688
+ */
3689
+ xgroup = (...args) => new XGroupCommand(args, this.opts).exec(this.client);
3690
+ /**
3691
+ * @see https://redis.io/commands/xread
3692
+ */
3693
+ xread = (...args) => new XReadCommand(args, this.opts).exec(this.client);
3694
+ /**
3695
+ * @see https://redis.io/commands/xreadgroup
3696
+ */
3697
+ xreadgroup = (...args) => new XReadGroupCommand(args, this.opts).exec(this.client);
3698
+ /**
3699
+ * @see https://redis.io/commands/xinfo
3700
+ */
3701
+ xinfo = (...args) => new XInfoCommand(args, this.opts).exec(this.client);
3702
+ /**
3703
+ * @see https://redis.io/commands/xlen
3704
+ */
3705
+ xlen = (...args) => new XLenCommand(args, this.opts).exec(this.client);
3706
+ /**
3707
+ * @see https://redis.io/commands/xpending
3708
+ */
3709
+ xpending = (...args) => new XPendingCommand(args, this.opts).exec(this.client);
3710
+ /**
3711
+ * @see https://redis.io/commands/xclaim
3712
+ */
3713
+ xclaim = (...args) => new XClaimCommand(args, this.opts).exec(this.client);
3714
+ /**
3715
+ * @see https://redis.io/commands/xautoclaim
3716
+ */
3717
+ xautoclaim = (...args) => new XAutoClaim(args, this.opts).exec(this.client);
3718
+ /**
3719
+ * @see https://redis.io/commands/xtrim
3720
+ */
3721
+ xtrim = (...args) => new XTrimCommand(args, this.opts).exec(this.client);
2892
3722
  /**
2893
3723
  * @see https://redis.io/commands/xrange
2894
3724
  */
2895
3725
  xrange = (...args) => new XRangeCommand(args, this.opts).exec(this.client);
3726
+ /**
3727
+ * @see https://redis.io/commands/xrevrange
3728
+ */
3729
+ xrevrange = (...args) => new XRevRangeCommand(args, this.opts).exec(this.client);
2896
3730
  /**
2897
3731
  * @see https://redis.io/commands/zadd
2898
3732
  */
2899
3733
  zadd = (...args) => {
2900
3734
  if ("score" in args[1]) {
2901
- return new ZAddCommand(
2902
- [args[0], args[1], ...args.slice(2)],
2903
- this.opts
2904
- ).exec(this.client);
3735
+ return new ZAddCommand([args[0], args[1], ...args.slice(2)], this.opts).exec(
3736
+ this.client
3737
+ );
2905
3738
  }
2906
3739
  return new ZAddCommand(
2907
3740
  [args[0], args[1], ...args.slice(2)],
@@ -2991,20 +3824,45 @@ var Redis = class {
2991
3824
  };
2992
3825
 
2993
3826
  // version.ts
2994
- var VERSION = "v0.0.0-ci.9722909577fc3b6b939d0c937c6ba5f8e8287ee4";
3827
+ var VERSION = "v1.30.2";
2995
3828
 
2996
3829
  // platforms/nodejs.ts
2997
3830
  if (typeof atob === "undefined") {
2998
- global.atob = function(b64) {
2999
- return Buffer.from(b64, "base64").toString("utf-8");
3000
- };
3831
+ global.atob = (b64) => Buffer.from(b64, "base64").toString("utf8");
3001
3832
  }
3002
3833
  var Redis2 = class _Redis extends Redis {
3834
+ /**
3835
+ * Create a new redis client by providing a custom `Requester` implementation
3836
+ *
3837
+ * @example
3838
+ * ```ts
3839
+ *
3840
+ * import { UpstashRequest, Requester, UpstashResponse, Redis } from "@upstash/redis"
3841
+ *
3842
+ * const requester: Requester = {
3843
+ * request: <TResult>(req: UpstashRequest): Promise<UpstashResponse<TResult>> => {
3844
+ * // ...
3845
+ * }
3846
+ * }
3847
+ *
3848
+ * const redis = new Redis(requester)
3849
+ * ```
3850
+ */
3003
3851
  constructor(configOrRequester) {
3004
3852
  if ("request" in configOrRequester) {
3005
3853
  super(configOrRequester);
3006
3854
  return;
3007
3855
  }
3856
+ if (!configOrRequester.url) {
3857
+ throw new Error(
3858
+ `[Upstash Redis] The 'url' property is missing or undefined in your Redis config.`
3859
+ );
3860
+ }
3861
+ if (!configOrRequester.token) {
3862
+ throw new Error(
3863
+ `[Upstash Redis] The 'token' property is missing or undefined in your Redis config.`
3864
+ );
3865
+ }
3008
3866
  if (configOrRequester.url.startsWith(" ") || configOrRequester.url.endsWith(" ") || /\r|\n/.test(configOrRequester.url)) {
3009
3867
  console.warn("The redis url contains whitespace or newline, which can cause errors!");
3010
3868
  }
@@ -3015,20 +3873,31 @@ var Redis2 = class _Redis extends Redis {
3015
3873
  baseUrl: configOrRequester.url,
3016
3874
  retry: configOrRequester.retry,
3017
3875
  headers: { authorization: `Bearer ${configOrRequester.token}` },
3876
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
3018
3877
  agent: configOrRequester.agent,
3019
3878
  responseEncoding: configOrRequester.responseEncoding,
3020
- cache: configOrRequester.cache || "no-store"
3879
+ cache: configOrRequester.cache ?? "no-store",
3880
+ signal: configOrRequester.signal,
3881
+ keepAlive: configOrRequester.keepAlive,
3882
+ readYourWrites: configOrRequester.readYourWrites
3021
3883
  });
3022
3884
  super(client, {
3023
3885
  automaticDeserialization: configOrRequester.automaticDeserialization,
3024
- enableTelemetry: !process.env.UPSTASH_DISABLE_TELEMETRY
3886
+ enableTelemetry: !process.env.UPSTASH_DISABLE_TELEMETRY,
3887
+ latencyLogging: configOrRequester.latencyLogging,
3888
+ enableAutoPipelining: configOrRequester.enableAutoPipelining
3025
3889
  });
3026
3890
  this.addTelemetry({
3027
- // @ts-ignore
3028
- runtime: typeof EdgeRuntime === "string" ? "edge-light" : `node@${process.version}`,
3891
+ runtime: (
3892
+ // @ts-expect-error to silence compiler
3893
+ typeof EdgeRuntime === "string" ? "edge-light" : `node@${process.version}`
3894
+ ),
3029
3895
  platform: process.env.VERCEL ? "vercel" : process.env.AWS_REGION ? "aws" : "unknown",
3030
3896
  sdk: `@upstash/redis@${VERSION}`
3031
3897
  });
3898
+ if (this.enableAutoPipelining) {
3899
+ return this.autoPipeline();
3900
+ }
3032
3901
  }
3033
3902
  /**
3034
3903
  * Create a new Upstash Redis instance from environment variables.
@@ -3040,16 +3909,16 @@ var Redis2 = class _Redis extends Redis {
3040
3909
  * your environment using `process.env`.
3041
3910
  */
3042
3911
  static fromEnv(config) {
3043
- if (typeof process?.env === "undefined") {
3044
- throw new Error(
3912
+ if (process.env === void 0) {
3913
+ throw new TypeError(
3045
3914
  'Unable to get environment variables, `process.env` is undefined. If you are deploying to cloudflare, please import from "@upstash/redis/cloudflare" instead'
3046
3915
  );
3047
3916
  }
3048
- const url = process?.env["UPSTASH_REDIS_REST_URL"];
3917
+ const url = process.env.UPSTASH_REDIS_REST_URL;
3049
3918
  if (!url) {
3050
3919
  throw new Error("Unable to find environment variable: `UPSTASH_REDIS_REST_URL`");
3051
3920
  }
3052
- const token = process?.env["UPSTASH_REDIS_REST_TOKEN"];
3921
+ const token = process.env.UPSTASH_REDIS_REST_TOKEN;
3053
3922
  if (!token) {
3054
3923
  throw new Error("Unable to find environment variable: `UPSTASH_REDIS_REST_TOKEN`");
3055
3924
  }
@@ -3058,6 +3927,6 @@ var Redis2 = class _Redis extends Redis {
3058
3927
  };
3059
3928
  // Annotate the CommonJS export names for ESM import in node:
3060
3929
  0 && (module.exports = {
3061
- Redis
3930
+ Redis,
3931
+ errors
3062
3932
  });
3063
- //# sourceMappingURL=nodejs.js.map