@upstash/redis 0.0.0-ci.fe7ec0544f213f3f58bb19e23dfafafab828c00c-20241107145222 → 0.0.0-ci.ff91bb10adb82f9d009471b11db70c40b6dbf5f8-20251205205412

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/cloudflare.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,14 +15,6 @@ 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/cloudflare.ts
@@ -39,11 +29,12 @@ module.exports = __toCommonJS(cloudflare_exports);
39
29
  var error_exports = {};
40
30
  __export(error_exports, {
41
31
  UpstashError: () => UpstashError,
32
+ UpstashJSONParseError: () => UpstashJSONParseError,
42
33
  UrlError: () => UrlError
43
34
  });
44
35
  var UpstashError = class extends Error {
45
- constructor(message) {
46
- super(message);
36
+ constructor(message, options) {
37
+ super(message, options);
47
38
  this.name = "UpstashError";
48
39
  }
49
40
  };
@@ -55,6 +46,58 @@ var UrlError = class extends Error {
55
46
  this.name = "UrlError";
56
47
  }
57
48
  };
49
+ var UpstashJSONParseError = class extends UpstashError {
50
+ constructor(body, options) {
51
+ const truncatedBody = body.length > 200 ? body.slice(0, 200) + "..." : body;
52
+ super(`Unable to parse response body: ${truncatedBody}`, options);
53
+ this.name = "UpstashJSONParseError";
54
+ }
55
+ };
56
+
57
+ // pkg/util.ts
58
+ function parseRecursive(obj) {
59
+ const parsed = Array.isArray(obj) ? obj.map((o) => {
60
+ try {
61
+ return parseRecursive(o);
62
+ } catch {
63
+ return o;
64
+ }
65
+ }) : JSON.parse(obj);
66
+ if (typeof parsed === "number" && parsed.toString() !== obj) {
67
+ return obj;
68
+ }
69
+ return parsed;
70
+ }
71
+ function parseResponse(result) {
72
+ try {
73
+ return parseRecursive(result);
74
+ } catch {
75
+ return result;
76
+ }
77
+ }
78
+ function deserializeScanResponse(result) {
79
+ return [result[0], ...parseResponse(result.slice(1))];
80
+ }
81
+ function deserializeScanWithTypesResponse(result) {
82
+ const [cursor, keys] = result;
83
+ const parsedKeys = [];
84
+ for (let i = 0; i < keys.length; i += 2) {
85
+ parsedKeys.push({ key: keys[i], type: keys[i + 1] });
86
+ }
87
+ return [cursor, parsedKeys];
88
+ }
89
+ function mergeHeaders(...headers) {
90
+ const merged = {};
91
+ for (const header of headers) {
92
+ if (!header) continue;
93
+ for (const [key, value] of Object.entries(header)) {
94
+ if (value !== void 0 && value !== null) {
95
+ merged[key] = value;
96
+ }
97
+ }
98
+ }
99
+ return merged;
100
+ }
58
101
 
59
102
  // pkg/http.ts
60
103
  var HttpClient = class {
@@ -104,15 +147,20 @@ var HttpClient = class {
104
147
  this.headers = merge(this.headers, "Upstash-Telemetry-Sdk", telemetry.sdk);
105
148
  }
106
149
  async request(req) {
150
+ const requestHeaders = mergeHeaders(this.headers, req.headers ?? {});
151
+ const requestUrl = [this.baseUrl, ...req.path ?? []].join("/");
152
+ const isEventStream = requestHeaders.Accept === "text/event-stream";
153
+ const signal = req.signal ?? this.options.signal;
154
+ const isSignalFunction = typeof signal === "function";
107
155
  const requestOptions = {
108
156
  //@ts-expect-error this should throw due to bun regression
109
157
  cache: this.options.cache,
110
158
  method: "POST",
111
- headers: this.headers,
159
+ headers: requestHeaders,
112
160
  body: JSON.stringify(req.body),
113
161
  keepalive: this.options.keepAlive,
114
162
  agent: this.options.agent,
115
- signal: this.options.signal,
163
+ signal: isSignalFunction ? signal() : signal,
116
164
  /**
117
165
  * Fastly specific
118
166
  */
@@ -131,16 +179,18 @@ var HttpClient = class {
131
179
  let error = null;
132
180
  for (let i = 0; i <= this.retry.attempts; i++) {
133
181
  try {
134
- res = await fetch([this.baseUrl, ...req.path ?? []].join("/"), requestOptions);
182
+ res = await fetch(requestUrl, requestOptions);
135
183
  break;
136
184
  } catch (error_) {
137
- if (this.options.signal?.aborted) {
185
+ if (requestOptions.signal?.aborted && isSignalFunction) {
186
+ throw error_;
187
+ } else if (requestOptions.signal?.aborted) {
138
188
  const myBlob = new Blob([
139
- JSON.stringify({ result: this.options.signal.reason ?? "Aborted" })
189
+ JSON.stringify({ result: requestOptions.signal.reason ?? "Aborted" })
140
190
  ]);
141
191
  const myOptions = {
142
192
  status: 200,
143
- statusText: this.options.signal.reason ?? "Aborted"
193
+ statusText: requestOptions.signal.reason ?? "Aborted"
144
194
  };
145
195
  res = new Response(myBlob, myOptions);
146
196
  break;
@@ -154,14 +204,58 @@ var HttpClient = class {
154
204
  if (!res) {
155
205
  throw error ?? new Error("Exhausted all retries");
156
206
  }
157
- const body = await res.json();
158
207
  if (!res.ok) {
159
- throw new UpstashError(`${body.error}, command was: ${JSON.stringify(req.body)}`);
208
+ let body2;
209
+ const rawBody2 = await res.text();
210
+ try {
211
+ body2 = JSON.parse(rawBody2);
212
+ } catch (error2) {
213
+ throw new UpstashJSONParseError(rawBody2, { cause: error2 });
214
+ }
215
+ throw new UpstashError(`${body2.error}, command was: ${JSON.stringify(req.body)}`);
160
216
  }
161
217
  if (this.readYourWrites) {
162
218
  const headers = res.headers;
163
219
  this.upstashSyncToken = headers.get("upstash-sync-token") ?? "";
164
220
  }
221
+ if (isEventStream && req && req.onMessage && res.body) {
222
+ const reader = res.body.getReader();
223
+ const decoder = new TextDecoder();
224
+ (async () => {
225
+ try {
226
+ while (true) {
227
+ const { value, done } = await reader.read();
228
+ if (done) break;
229
+ const chunk = decoder.decode(value);
230
+ const lines = chunk.split("\n");
231
+ for (const line of lines) {
232
+ if (line.startsWith("data: ")) {
233
+ const data = line.slice(6);
234
+ req.onMessage?.(data);
235
+ }
236
+ }
237
+ }
238
+ } catch (error2) {
239
+ if (error2 instanceof Error && error2.name === "AbortError") {
240
+ } else {
241
+ console.error("Stream reading error:", error2);
242
+ }
243
+ } finally {
244
+ try {
245
+ await reader.cancel();
246
+ } catch {
247
+ }
248
+ }
249
+ })();
250
+ return { result: 1 };
251
+ }
252
+ let body;
253
+ const rawBody = await res.text();
254
+ try {
255
+ body = JSON.parse(rawBody);
256
+ } catch (error2) {
257
+ throw new UpstashJSONParseError(rawBody, { cause: error2 });
258
+ }
165
259
  if (this.readYourWrites) {
166
260
  const headers = res.headers;
167
261
  this.upstashSyncToken = headers.get("upstash-sync-token") ?? "";
@@ -233,6 +327,24 @@ function merge(obj, key, value) {
233
327
  }
234
328
 
235
329
  // pkg/auto-pipeline.ts
330
+ var EXCLUDE_COMMANDS = /* @__PURE__ */ new Set([
331
+ "scan",
332
+ "keys",
333
+ "flushdb",
334
+ "flushall",
335
+ "dbsize",
336
+ "hscan",
337
+ "hgetall",
338
+ "hkeys",
339
+ "lrange",
340
+ "sscan",
341
+ "smembers",
342
+ "xrange",
343
+ "xrevrange",
344
+ "zscan",
345
+ "zrange",
346
+ "exec"
347
+ ]);
236
348
  function createAutoPipelineProxy(_redis, json) {
237
349
  const redis = _redis;
238
350
  if (!redis.autoPipelineExecutor) {
@@ -247,7 +359,8 @@ function createAutoPipelineProxy(_redis, json) {
247
359
  return createAutoPipelineProxy(redis2, true);
248
360
  }
249
361
  const commandInRedisButNotPipeline = command in redis2 && !(command in redis2.autoPipelineExecutor.pipeline);
250
- if (commandInRedisButNotPipeline) {
362
+ const isCommandExcluded = EXCLUDE_COMMANDS.has(command);
363
+ if (commandInRedisButNotPipeline || isCommandExcluded) {
251
364
  return redis2[command];
252
365
  }
253
366
  const isFunction = json ? typeof redis2.autoPipelineExecutor.pipeline.json[command] === "function" : typeof redis2.autoPipelineExecutor.pipeline[command] === "function";
@@ -311,31 +424,6 @@ var AutoPipelineExecutor = class {
311
424
  }
312
425
  };
313
426
 
314
- // pkg/util.ts
315
- function parseRecursive(obj) {
316
- const parsed = Array.isArray(obj) ? obj.map((o) => {
317
- try {
318
- return parseRecursive(o);
319
- } catch {
320
- return o;
321
- }
322
- }) : JSON.parse(obj);
323
- if (typeof parsed === "number" && parsed.toString() !== obj) {
324
- return obj;
325
- }
326
- return parsed;
327
- }
328
- function parseResponse(result) {
329
- try {
330
- return parseRecursive(result);
331
- } catch {
332
- return result;
333
- }
334
- }
335
- function deserializeScanResponse(result) {
336
- return [result[0], ...parseResponse(result.slice(1))];
337
- }
338
-
339
427
  // pkg/commands/command.ts
340
428
  var defaultSerializer = (c) => {
341
429
  switch (typeof c) {
@@ -353,6 +441,11 @@ var Command = class {
353
441
  command;
354
442
  serialize;
355
443
  deserialize;
444
+ headers;
445
+ path;
446
+ onMessage;
447
+ isStreaming;
448
+ signal;
356
449
  /**
357
450
  * Create a new command instance.
358
451
  *
@@ -362,6 +455,11 @@ var Command = class {
362
455
  this.serialize = defaultSerializer;
363
456
  this.deserialize = opts?.automaticDeserialization === void 0 || opts.automaticDeserialization ? opts?.deserialize ?? parseResponse : (x) => x;
364
457
  this.command = command.map((c) => this.serialize(c));
458
+ this.headers = opts?.headers;
459
+ this.path = opts?.path;
460
+ this.onMessage = opts?.streamOptions?.onMessage;
461
+ this.isStreaming = opts?.streamOptions?.isStreaming ?? false;
462
+ this.signal = opts?.streamOptions?.signal;
365
463
  if (opts?.latencyLogging) {
366
464
  const originalExec = this.exec.bind(this);
367
465
  this.exec = async (client) => {
@@ -382,7 +480,12 @@ var Command = class {
382
480
  async exec(client) {
383
481
  const { result, error } = await client.request({
384
482
  body: this.command,
385
- upstashSyncToken: client.upstashSyncToken
483
+ path: this.path,
484
+ upstashSyncToken: client.upstashSyncToken,
485
+ headers: this.headers,
486
+ onMessage: this.onMessage,
487
+ isStreaming: this.isStreaming,
488
+ signal: this.signal
386
489
  });
387
490
  if (error) {
388
491
  throw new UpstashError(error);
@@ -510,6 +613,13 @@ var EchoCommand = class extends Command {
510
613
  }
511
614
  };
512
615
 
616
+ // pkg/commands/evalRo.ts
617
+ var EvalROCommand = class extends Command {
618
+ constructor([script, keys, args], opts) {
619
+ super(["eval_ro", script, keys.length, ...keys, ...args ?? []], opts);
620
+ }
621
+ };
622
+
513
623
  // pkg/commands/eval.ts
514
624
  var EvalCommand = class extends Command {
515
625
  constructor([script, keys, args], opts) {
@@ -517,6 +627,13 @@ var EvalCommand = class extends Command {
517
627
  }
518
628
  };
519
629
 
630
+ // pkg/commands/evalshaRo.ts
631
+ var EvalshaROCommand = class extends Command {
632
+ constructor([sha, keys, args], opts) {
633
+ super(["evalsha_ro", sha, keys.length, ...keys, ...args ?? []], opts);
634
+ }
635
+ };
636
+
520
637
  // pkg/commands/evalsha.ts
521
638
  var EvalshaCommand = class extends Command {
522
639
  constructor([sha, keys, args], opts) {
@@ -748,6 +865,27 @@ var GetDelCommand = class extends Command {
748
865
  }
749
866
  };
750
867
 
868
+ // pkg/commands/getex.ts
869
+ var GetExCommand = class extends Command {
870
+ constructor([key, opts], cmdOpts) {
871
+ const command = ["getex", key];
872
+ if (opts) {
873
+ if ("ex" in opts && typeof opts.ex === "number") {
874
+ command.push("ex", opts.ex);
875
+ } else if ("px" in opts && typeof opts.px === "number") {
876
+ command.push("px", opts.px);
877
+ } else if ("exat" in opts && typeof opts.exat === "number") {
878
+ command.push("exat", opts.exat);
879
+ } else if ("pxat" in opts && typeof opts.pxat === "number") {
880
+ command.push("pxat", opts.pxat);
881
+ } else if ("persist" in opts && opts.persist) {
882
+ command.push("persist");
883
+ }
884
+ }
885
+ super(command, cmdOpts);
886
+ }
887
+ };
888
+
751
889
  // pkg/commands/getrange.ts
752
890
  var GetRangeCommand = class extends Command {
753
891
  constructor(cmd, opts) {
@@ -776,6 +914,122 @@ var HExistsCommand = class extends Command {
776
914
  }
777
915
  };
778
916
 
917
+ // pkg/commands/hexpire.ts
918
+ var HExpireCommand = class extends Command {
919
+ constructor(cmd, opts) {
920
+ const [key, fields, seconds, option] = cmd;
921
+ const fieldArray = Array.isArray(fields) ? fields : [fields];
922
+ super(
923
+ [
924
+ "hexpire",
925
+ key,
926
+ seconds,
927
+ ...option ? [option] : [],
928
+ "FIELDS",
929
+ fieldArray.length,
930
+ ...fieldArray
931
+ ],
932
+ opts
933
+ );
934
+ }
935
+ };
936
+
937
+ // pkg/commands/hexpireat.ts
938
+ var HExpireAtCommand = class extends Command {
939
+ constructor(cmd, opts) {
940
+ const [key, fields, timestamp, option] = cmd;
941
+ const fieldArray = Array.isArray(fields) ? fields : [fields];
942
+ super(
943
+ [
944
+ "hexpireat",
945
+ key,
946
+ timestamp,
947
+ ...option ? [option] : [],
948
+ "FIELDS",
949
+ fieldArray.length,
950
+ ...fieldArray
951
+ ],
952
+ opts
953
+ );
954
+ }
955
+ };
956
+
957
+ // pkg/commands/hexpiretime.ts
958
+ var HExpireTimeCommand = class extends Command {
959
+ constructor(cmd, opts) {
960
+ const [key, fields] = cmd;
961
+ const fieldArray = Array.isArray(fields) ? fields : [fields];
962
+ super(["hexpiretime", key, "FIELDS", fieldArray.length, ...fieldArray], opts);
963
+ }
964
+ };
965
+
966
+ // pkg/commands/hpersist.ts
967
+ var HPersistCommand = class extends Command {
968
+ constructor(cmd, opts) {
969
+ const [key, fields] = cmd;
970
+ const fieldArray = Array.isArray(fields) ? fields : [fields];
971
+ super(["hpersist", key, "FIELDS", fieldArray.length, ...fieldArray], opts);
972
+ }
973
+ };
974
+
975
+ // pkg/commands/hpexpire.ts
976
+ var HPExpireCommand = class extends Command {
977
+ constructor(cmd, opts) {
978
+ const [key, fields, milliseconds, option] = cmd;
979
+ const fieldArray = Array.isArray(fields) ? fields : [fields];
980
+ super(
981
+ [
982
+ "hpexpire",
983
+ key,
984
+ milliseconds,
985
+ ...option ? [option] : [],
986
+ "FIELDS",
987
+ fieldArray.length,
988
+ ...fieldArray
989
+ ],
990
+ opts
991
+ );
992
+ }
993
+ };
994
+
995
+ // pkg/commands/hpexpireat.ts
996
+ var HPExpireAtCommand = class extends Command {
997
+ constructor(cmd, opts) {
998
+ const [key, fields, timestamp, option] = cmd;
999
+ const fieldArray = Array.isArray(fields) ? fields : [fields];
1000
+ super(
1001
+ [
1002
+ "hpexpireat",
1003
+ key,
1004
+ timestamp,
1005
+ ...option ? [option] : [],
1006
+ "FIELDS",
1007
+ fieldArray.length,
1008
+ ...fieldArray
1009
+ ],
1010
+ opts
1011
+ );
1012
+ }
1013
+ };
1014
+
1015
+ // pkg/commands/hpexpiretime.ts
1016
+ var HPExpireTimeCommand = class extends Command {
1017
+ constructor(cmd, opts) {
1018
+ const [key, fields] = cmd;
1019
+ const fieldArray = Array.isArray(fields) ? fields : [fields];
1020
+ super(["hpexpiretime", key, "FIELDS", fieldArray.length, ...fieldArray], opts);
1021
+ }
1022
+ };
1023
+
1024
+ // pkg/commands/hpttl.ts
1025
+ var HPTtlCommand = class extends Command {
1026
+ constructor(cmd, opts) {
1027
+ const [key, fields] = cmd;
1028
+ const fieldArray = Array.isArray(fields) ? fields : [fields];
1029
+ super(["hpttl", key, "FIELDS", fieldArray.length, ...fieldArray], opts);
1030
+ }
1031
+ };
1032
+
779
1033
  // pkg/commands/hget.ts
780
1034
  var HGetCommand = class extends Command {
781
1035
  constructor(cmd, opts) {
@@ -789,9 +1043,9 @@ function deserialize(result) {
789
1043
  return null;
790
1044
  }
791
1045
  const obj = {};
792
- while (result.length >= 2) {
793
- const key = result.shift();
794
- const value = result.shift();
1046
+ for (let i = 0; i < result.length; i += 2) {
1047
+ const key = result[i];
1048
+ const value = result[i + 1];
795
1049
  try {
796
1050
  const valueIsNumberAndNotSafeInteger = !Number.isNaN(Number(value)) && !Number.isSafeInteger(Number(value));
797
1051
  obj[key] = valueIsNumberAndNotSafeInteger ? value : JSON.parse(value);
@@ -875,9 +1129,9 @@ function deserialize3(result) {
875
1129
  return null;
876
1130
  }
877
1131
  const obj = {};
878
- while (result.length >= 2) {
879
- const key = result.shift();
880
- const value = result.shift();
1132
+ for (let i = 0; i < result.length; i += 2) {
1133
+ const key = result[i];
1134
+ const value = result[i + 1];
881
1135
  try {
882
1136
  obj[key] = JSON.parse(value);
883
1137
  } catch {
@@ -941,6 +1195,15 @@ var HStrLenCommand = class extends Command {
941
1195
  }
942
1196
  };
943
1197
 
1198
+ // pkg/commands/httl.ts
1199
+ var HTtlCommand = class extends Command {
1200
+ constructor(cmd, opts) {
1201
+ const [key, fields] = cmd;
1202
+ const fieldArray = Array.isArray(fields) ? fields : [fields];
1203
+ super(["httl", key, "FIELDS", fieldArray.length, ...fieldArray], opts);
1204
+ }
1205
+ };
1206
+
944
1207
  // pkg/commands/hvals.ts
945
1208
  var HValsCommand = class extends Command {
946
1209
  constructor(cmd, opts) {
@@ -1060,6 +1323,14 @@ var JsonGetCommand = class extends Command {
1060
1323
  }
1061
1324
  };
1062
1325
 
1326
+ // pkg/commands/json_merge.ts
1327
+ var JsonMergeCommand = class extends Command {
1328
+ constructor(cmd, opts) {
1329
+ const command = ["JSON.MERGE", ...cmd];
1330
+ super(command, opts);
1331
+ }
1332
+ };
1333
+
1063
1334
  // pkg/commands/json_mget.ts
1064
1335
  var JsonMGetCommand = class extends Command {
1065
1336
  constructor(cmd, opts) {
@@ -1420,11 +1691,14 @@ var ScanCommand = class extends Command {
1420
1691
  if (typeof opts?.count === "number") {
1421
1692
  command.push("count", opts.count);
1422
1693
  }
1423
- if (opts?.type && opts.type.length > 0) {
1694
+ if (opts && "withType" in opts && opts.withType === true) {
1695
+ command.push("withtype");
1696
+ } else if (opts && "type" in opts && opts.type && opts.type.length > 0) {
1424
1697
  command.push("type", opts.type);
1425
1698
  }
1426
1699
  super(command, {
1427
- deserialize: deserializeScanResponse,
1700
+ // @ts-expect-error ignore types here
1701
+ deserialize: opts?.withType ? deserializeScanWithTypesResponse : deserializeScanResponse,
1428
1702
  ...cmdOpts
1429
1703
  });
1430
1704
  }
@@ -1850,15 +2124,15 @@ var XPendingCommand = class extends Command {
1850
2124
  function deserialize4(result) {
1851
2125
  const obj = {};
1852
2126
  for (const e of result) {
1853
- while (e.length >= 2) {
1854
- const streamId = e.shift();
1855
- const entries = e.shift();
2127
+ for (let i = 0; i < e.length; i += 2) {
2128
+ const streamId = e[i];
2129
+ const entries = e[i + 1];
1856
2130
  if (!(streamId in obj)) {
1857
2131
  obj[streamId] = {};
1858
2132
  }
1859
- while (entries.length >= 2) {
1860
- const field = entries.shift();
1861
- const value = entries.shift();
2133
+ for (let j = 0; j < entries.length; j += 2) {
2134
+ const field = entries[j];
2135
+ const value = entries[j + 1];
1862
2136
  try {
1863
2137
  obj[streamId][field] = JSON.parse(value);
1864
2138
  } catch {
@@ -1947,15 +2221,15 @@ var XRevRangeCommand = class extends Command {
1947
2221
  function deserialize5(result) {
1948
2222
  const obj = {};
1949
2223
  for (const e of result) {
1950
- while (e.length >= 2) {
1951
- const streamId = e.shift();
1952
- const entries = e.shift();
2224
+ for (let i = 0; i < e.length; i += 2) {
2225
+ const streamId = e[i];
2226
+ const entries = e[i + 1];
1953
2227
  if (!(streamId in obj)) {
1954
2228
  obj[streamId] = {};
1955
2229
  }
1956
- while (entries.length >= 2) {
1957
- const field = entries.shift();
1958
- const value = entries.shift();
2230
+ for (let j = 0; j < entries.length; j += 2) {
2231
+ const field = entries[j];
2232
+ const value = entries[j + 1];
1959
2233
  try {
1960
2234
  obj[streamId][field] = JSON.parse(value);
1961
2235
  } catch {
@@ -2214,6 +2488,192 @@ var ZUnionStoreCommand = class extends Command {
2214
2488
  }
2215
2489
  };
2216
2490
 
2491
+ // pkg/commands/psubscribe.ts
2492
+ var PSubscribeCommand = class extends Command {
2493
+ constructor(cmd, opts) {
2494
+ const sseHeaders = {
2495
+ Accept: "text/event-stream",
2496
+ "Cache-Control": "no-cache",
2497
+ Connection: "keep-alive"
2498
+ };
2499
+ super([], {
2500
+ ...opts,
2501
+ headers: sseHeaders,
2502
+ path: ["psubscribe", ...cmd],
2503
+ streamOptions: {
2504
+ isStreaming: true,
2505
+ onMessage: opts?.streamOptions?.onMessage,
2506
+ signal: opts?.streamOptions?.signal
2507
+ }
2508
+ });
2509
+ }
2510
+ };
2511
+
2512
+ // pkg/commands/subscribe.ts
2513
+ var Subscriber = class extends EventTarget {
2514
+ subscriptions;
2515
+ client;
2516
+ listeners;
2517
+ opts;
2518
+ constructor(client, channels, isPattern = false, opts) {
2519
+ super();
2520
+ this.client = client;
2521
+ this.subscriptions = /* @__PURE__ */ new Map();
2522
+ this.listeners = /* @__PURE__ */ new Map();
2523
+ this.opts = opts;
2524
+ for (const channel of channels) {
2525
+ if (isPattern) {
2526
+ this.subscribeToPattern(channel);
2527
+ } else {
2528
+ this.subscribeToChannel(channel);
2529
+ }
2530
+ }
2531
+ }
2532
+ subscribeToChannel(channel) {
2533
+ const controller = new AbortController();
2534
+ const command = new SubscribeCommand([channel], {
2535
+ streamOptions: {
2536
+ signal: controller.signal,
2537
+ onMessage: (data) => this.handleMessage(data, false)
2538
+ }
2539
+ });
2540
+ command.exec(this.client).catch((error) => {
2541
+ if (error.name !== "AbortError") {
2542
+ this.dispatchToListeners("error", error);
2543
+ }
2544
+ });
2545
+ this.subscriptions.set(channel, {
2546
+ command,
2547
+ controller,
2548
+ isPattern: false
2549
+ });
2550
+ }
2551
+ subscribeToPattern(pattern) {
2552
+ const controller = new AbortController();
2553
+ const command = new PSubscribeCommand([pattern], {
2554
+ streamOptions: {
2555
+ signal: controller.signal,
2556
+ onMessage: (data) => this.handleMessage(data, true)
2557
+ }
2558
+ });
2559
+ command.exec(this.client).catch((error) => {
2560
+ if (error.name !== "AbortError") {
2561
+ this.dispatchToListeners("error", error);
2562
+ }
2563
+ });
2564
+ this.subscriptions.set(pattern, {
2565
+ command,
2566
+ controller,
2567
+ isPattern: true
2568
+ });
2569
+ }
2570
+ handleMessage(data, isPattern) {
2571
+ const messageData = data.replace(/^data:\s*/, "");
2572
+ const firstCommaIndex = messageData.indexOf(",");
2573
+ const secondCommaIndex = messageData.indexOf(",", firstCommaIndex + 1);
2574
+ const thirdCommaIndex = isPattern ? messageData.indexOf(",", secondCommaIndex + 1) : -1;
2575
+ if (firstCommaIndex !== -1 && secondCommaIndex !== -1) {
2576
+ const type = messageData.slice(0, firstCommaIndex);
2577
+ if (isPattern && type === "pmessage" && thirdCommaIndex !== -1) {
2578
+ const pattern = messageData.slice(firstCommaIndex + 1, secondCommaIndex);
2579
+ const channel = messageData.slice(secondCommaIndex + 1, thirdCommaIndex);
2580
+ const messageStr = messageData.slice(thirdCommaIndex + 1);
2581
+ try {
2582
+ const message = this.opts?.automaticDeserialization === false ? messageStr : JSON.parse(messageStr);
2583
+ this.dispatchToListeners("pmessage", { pattern, channel, message });
2584
+ this.dispatchToListeners(`pmessage:${pattern}`, { pattern, channel, message });
2585
+ } catch (error) {
2586
+ this.dispatchToListeners("error", new Error(`Failed to parse message: ${error}`));
2587
+ }
2588
+ } else {
2589
+ const channel = messageData.slice(firstCommaIndex + 1, secondCommaIndex);
2590
+ const messageStr = messageData.slice(secondCommaIndex + 1);
2591
+ try {
2592
+ if (type === "subscribe" || type === "psubscribe" || type === "unsubscribe" || type === "punsubscribe") {
2593
+ const count = Number.parseInt(messageStr);
2594
+ this.dispatchToListeners(type, count);
2595
+ } else {
2596
+ const message = this.opts?.automaticDeserialization === false ? messageStr : parseWithTryCatch(messageStr);
2597
+ this.dispatchToListeners(type, { channel, message });
2598
+ this.dispatchToListeners(`${type}:${channel}`, { channel, message });
2599
+ }
2600
+ } catch (error) {
2601
+ this.dispatchToListeners("error", new Error(`Failed to parse message: ${error}`));
2602
+ }
2603
+ }
2604
+ }
2605
+ }
2606
+ dispatchToListeners(type, data) {
2607
+ const listeners = this.listeners.get(type);
2608
+ if (listeners) {
2609
+ for (const listener of listeners) {
2610
+ listener(data);
2611
+ }
2612
+ }
2613
+ }
2614
+ on(type, listener) {
2615
+ if (!this.listeners.has(type)) {
2616
+ this.listeners.set(type, /* @__PURE__ */ new Set());
2617
+ }
2618
+ this.listeners.get(type)?.add(listener);
2619
+ }
2620
+ removeAllListeners() {
2621
+ this.listeners.clear();
2622
+ }
2623
+ async unsubscribe(channels) {
2624
+ if (channels) {
2625
+ for (const channel of channels) {
2626
+ const subscription = this.subscriptions.get(channel);
2627
+ if (subscription) {
2628
+ try {
2629
+ subscription.controller.abort();
2630
+ } catch {
2631
+ }
2632
+ this.subscriptions.delete(channel);
2633
+ }
2634
+ }
2635
+ } else {
2636
+ for (const subscription of this.subscriptions.values()) {
2637
+ try {
2638
+ subscription.controller.abort();
2639
+ } catch {
2640
+ }
2641
+ }
2642
+ this.subscriptions.clear();
2643
+ this.removeAllListeners();
2644
+ }
2645
+ }
2646
+ getSubscribedChannels() {
2647
+ return [...this.subscriptions.keys()];
2648
+ }
2649
+ };
2650
+ var SubscribeCommand = class extends Command {
2651
+ constructor(cmd, opts) {
2652
+ const sseHeaders = {
2653
+ Accept: "text/event-stream",
2654
+ "Cache-Control": "no-cache",
2655
+ Connection: "keep-alive"
2656
+ };
2657
+ super([], {
2658
+ ...opts,
2659
+ headers: sseHeaders,
2660
+ path: ["subscribe", ...cmd],
2661
+ streamOptions: {
2662
+ isStreaming: true,
2663
+ onMessage: opts?.streamOptions?.onMessage,
2664
+ signal: opts?.streamOptions?.signal
2665
+ }
2666
+ });
2667
+ }
2668
+ };
2669
+ var parseWithTryCatch = (str) => {
2670
+ try {
2671
+ return JSON.parse(str);
2672
+ } catch {
2673
+ return str;
2674
+ }
2675
+ };
2676
+
2217
2677
  // pkg/commands/zdiffstore.ts
2218
2678
  var ZDiffStoreCommand = class extends Command {
2219
2679
  constructor(cmd, opts) {
@@ -2354,10 +2814,18 @@ var Pipeline = class {
2354
2814
  * @see https://redis.io/commands/echo
2355
2815
  */
2356
2816
  echo = (...args) => this.chain(new EchoCommand(args, this.commandOptions));
2817
+ /**
2818
+ * @see https://redis.io/commands/eval_ro
2819
+ */
2820
+ evalRo = (...args) => this.chain(new EvalROCommand(args, this.commandOptions));
2357
2821
  /**
2358
2822
  * @see https://redis.io/commands/eval
2359
2823
  */
2360
2824
  eval = (...args) => this.chain(new EvalCommand(args, this.commandOptions));
2825
+ /**
2826
+ * @see https://redis.io/commands/evalsha_ro
2827
+ */
2828
+ evalshaRo = (...args) => this.chain(new EvalshaROCommand(args, this.commandOptions));
2361
2829
  /**
2362
2830
  * @see https://redis.io/commands/evalsha
2363
2831
  */
@@ -2418,6 +2886,10 @@ var Pipeline = class {
2418
2886
  * @see https://redis.io/commands/getdel
2419
2887
  */
2420
2888
  getdel = (...args) => this.chain(new GetDelCommand(args, this.commandOptions));
2889
+ /**
2890
+ * @see https://redis.io/commands/getex
2891
+ */
2892
+ getex = (...args) => this.chain(new GetExCommand(args, this.commandOptions));
2421
2893
  /**
2422
2894
  * @see https://redis.io/commands/getrange
2423
2895
  */
@@ -2434,6 +2906,42 @@ var Pipeline = class {
2434
2906
  * @see https://redis.io/commands/hexists
2435
2907
  */
2436
2908
  hexists = (...args) => this.chain(new HExistsCommand(args, this.commandOptions));
2909
+ /**
2910
+ * @see https://redis.io/commands/hexpire
2911
+ */
2912
+ hexpire = (...args) => this.chain(new HExpireCommand(args, this.commandOptions));
2913
+ /**
2914
+ * @see https://redis.io/commands/hexpireat
2915
+ */
2916
+ hexpireat = (...args) => this.chain(new HExpireAtCommand(args, this.commandOptions));
2917
+ /**
2918
+ * @see https://redis.io/commands/hexpiretime
2919
+ */
2920
+ hexpiretime = (...args) => this.chain(new HExpireTimeCommand(args, this.commandOptions));
2921
+ /**
2922
+ * @see https://redis.io/commands/httl
2923
+ */
2924
+ httl = (...args) => this.chain(new HTtlCommand(args, this.commandOptions));
2925
+ /**
2926
+ * @see https://redis.io/commands/hpexpire
2927
+ */
2928
+ hpexpire = (...args) => this.chain(new HPExpireCommand(args, this.commandOptions));
2929
+ /**
2930
+ * @see https://redis.io/commands/hpexpireat
2931
+ */
2932
+ hpexpireat = (...args) => this.chain(new HPExpireAtCommand(args, this.commandOptions));
2933
+ /**
2934
+ * @see https://redis.io/commands/hpexpiretime
2935
+ */
2936
+ hpexpiretime = (...args) => this.chain(new HPExpireTimeCommand(args, this.commandOptions));
2937
+ /**
2938
+ * @see https://redis.io/commands/hpttl
2939
+ */
2940
+ hpttl = (...args) => this.chain(new HPTtlCommand(args, this.commandOptions));
2941
+ /**
2942
+ * @see https://redis.io/commands/hpersist
2943
+ */
2944
+ hpersist = (...args) => this.chain(new HPersistCommand(args, this.commandOptions));
2437
2945
  /**
2438
2946
  * @see https://redis.io/commands/hget
2439
2947
  */
@@ -2951,6 +3459,10 @@ var Pipeline = class {
2951
3459
  * @see https://redis.io/commands/json.get
2952
3460
  */
2953
3461
  get: (...args) => this.chain(new JsonGetCommand(args, this.commandOptions)),
3462
+ /**
3463
+ * @see https://redis.io/commands/json.merge
3464
+ */
3465
+ merge: (...args) => this.chain(new JsonMergeCommand(args, this.commandOptions)),
2954
3466
  /**
2955
3467
  * @see https://redis.io/commands/json.mget
2956
3468
  */
@@ -3004,27 +3516,43 @@ var Pipeline = class {
3004
3516
  };
3005
3517
 
3006
3518
  // pkg/script.ts
3007
- var import_enc_hex = __toESM(require("crypto-js/enc-hex.js"));
3008
- var import_sha1 = __toESM(require("crypto-js/sha1.js"));
3519
+ var import_uncrypto = require("uncrypto");
3009
3520
  var Script = class {
3010
3521
  script;
3522
+ /**
3523
+ * @deprecated This property is initialized to an empty string and will be set in the init method
3524
+ * asynchronously. Do not use this property immidiately after the constructor.
3525
+ *
3526
+ * This property is only exposed for backwards compatibility and will be removed in the
3527
+ * future major release.
3528
+ */
3011
3529
  sha1;
3012
3530
  redis;
3013
3531
  constructor(redis, script) {
3014
3532
  this.redis = redis;
3015
- this.sha1 = this.digest(script);
3016
3533
  this.script = script;
3534
+ this.sha1 = "";
3535
+ void this.init(script);
3536
+ }
3537
+ /**
3538
+ * Initialize the script by computing its SHA-1 hash.
3539
+ */
3540
+ async init(script) {
3541
+ if (this.sha1) return;
3542
+ this.sha1 = await this.digest(script);
3017
3543
  }
3018
3544
  /**
3019
3545
  * Send an `EVAL` command to redis.
3020
3546
  */
3021
3547
  async eval(keys, args) {
3548
+ await this.init(this.script);
3022
3549
  return await this.redis.eval(this.script, keys, args);
3023
3550
  }
3024
3551
  /**
3025
3552
  * Calculates the sha1 hash of the script and then calls `EVALSHA`.
3026
3553
  */
3027
3554
  async evalsha(keys, args) {
3555
+ await this.init(this.script);
3028
3556
  return await this.redis.evalsha(this.sha1, keys, args);
3029
3557
  }
3030
3558
  /**
@@ -3034,6 +3562,7 @@ var Script = class {
3034
3562
  * Following calls will be able to use the cached script
3035
3563
  */
3036
3564
  async exec(keys, args) {
3565
+ await this.init(this.script);
3037
3566
  const res = await this.redis.evalsha(this.sha1, keys, args).catch(async (error) => {
3038
3567
  if (error instanceof Error && error.message.toLowerCase().includes("noscript")) {
3039
3568
  return await this.redis.eval(this.script, keys, args);
@@ -3045,8 +3574,75 @@ var Script = class {
3045
3574
  /**
3046
3575
  * Compute the sha1 hash of the script and return its hex representation.
3047
3576
  */
3048
- digest(s) {
3049
- return import_enc_hex.default.stringify((0, import_sha1.default)(s));
3577
+ async digest(s) {
3578
+ const data = new TextEncoder().encode(s);
3579
+ const hashBuffer = await import_uncrypto.subtle.digest("SHA-1", data);
3580
+ const hashArray = [...new Uint8Array(hashBuffer)];
3581
+ return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
3582
+ }
3583
+ };
3584
+
3585
+ // pkg/scriptRo.ts
3586
+ var import_uncrypto2 = require("uncrypto");
3587
+ var ScriptRO = class {
3588
+ script;
3589
+ /**
3590
+ * @deprecated This property is initialized to an empty string and will be set in the init method
3591
+ * asynchronously. Do not use this property immidiately after the constructor.
3592
+ *
3593
+ * This property is only exposed for backwards compatibility and will be removed in the
3594
+ * future major release.
3595
+ */
3596
+ sha1;
3597
+ redis;
3598
+ constructor(redis, script) {
3599
+ this.redis = redis;
3600
+ this.sha1 = "";
3601
+ this.script = script;
3602
+ void this.init(script);
3603
+ }
3604
+ async init(script) {
3605
+ if (this.sha1) return;
3606
+ this.sha1 = await this.digest(script);
3607
+ }
3608
+ /**
3609
+ * Send an `EVAL_RO` command to redis.
3610
+ */
3611
+ async evalRo(keys, args) {
3612
+ await this.init(this.script);
3613
+ return await this.redis.evalRo(this.script, keys, args);
3614
+ }
3615
+ /**
3616
+ * Calculates the sha1 hash of the script and then calls `EVALSHA_RO`.
3617
+ */
3618
+ async evalshaRo(keys, args) {
3619
+ await this.init(this.script);
3620
+ return await this.redis.evalshaRo(this.sha1, keys, args);
3621
+ }
3622
+ /**
3623
+ * Optimistically try to run `EVALSHA_RO` first.
3624
+ * If the script is not loaded in redis, it will fall back and try again with `EVAL_RO`.
3625
+ *
3626
+ * Following calls will be able to use the cached script
3627
+ */
3628
+ async exec(keys, args) {
3629
+ await this.init(this.script);
3630
+ const res = await this.redis.evalshaRo(this.sha1, keys, args).catch(async (error) => {
3631
+ if (error instanceof Error && error.message.toLowerCase().includes("noscript")) {
3632
+ return await this.redis.evalRo(this.script, keys, args);
3633
+ }
3634
+ throw error;
3635
+ });
3636
+ return res;
3637
+ }
3638
+ /**
3639
+ * Compute the sha1 hash of the script and return its hex representation.
3640
+ */
3641
+ async digest(s) {
3642
+ const data = new TextEncoder().encode(s);
3643
+ const hashBuffer = await import_uncrypto2.subtle.digest("SHA-1", data);
3644
+ const hashArray = [...new Uint8Array(hashBuffer)];
3645
+ return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
3050
3646
  }
3051
3647
  };
3052
3648
 
@@ -3124,6 +3720,10 @@ var Redis = class {
3124
3720
  * @see https://redis.io/commands/json.get
3125
3721
  */
3126
3722
  get: (...args) => new JsonGetCommand(args, this.opts).exec(this.client),
3723
+ /**
3724
+ * @see https://redis.io/commands/json.merge
3725
+ */
3726
+ merge: (...args) => new JsonMergeCommand(args, this.opts).exec(this.client),
3127
3727
  /**
3128
3728
  * @see https://redis.io/commands/json.mget
3129
3729
  */
@@ -3193,8 +3793,36 @@ var Redis = class {
3193
3793
  } catch {
3194
3794
  }
3195
3795
  };
3196
- createScript(script) {
3197
- return new Script(this, script);
3796
+ /**
3797
+ * Creates a new script.
3798
+ *
3799
+ * Scripts offer the ability to optimistically try to execute a script without having to send the
3800
+ * entire script to the server. If the script is loaded on the server, it tries again by sending
3801
+ * the entire script. Afterwards, the script is cached on the server.
3802
+ *
3803
+ * @param script - The script to create
3804
+ * @param opts - Optional options to pass to the script `{ readonly?: boolean }`
3805
+ * @returns A new script
3806
+ *
3807
+ * @example
3808
+ * ```ts
3809
+ * const redis = new Redis({...})
3810
+ *
3811
+ * const script = redis.createScript<string>("return ARGV[1];")
3812
+ * const arg1 = await script.eval([], ["Hello World"])
3813
+ * expect(arg1, "Hello World")
3814
+ * ```
3815
+ * @example
3816
+ * ```ts
3817
+ * const redis = new Redis({...})
3818
+ *
3819
+ * const script = redis.createScript<string>("return ARGV[1];", { readonly: true })
3820
+ * const arg1 = await script.evalRo([], ["Hello World"])
3821
+ * expect(arg1, "Hello World")
3822
+ * ```
3823
+ */
3824
+ createScript(script, opts) {
3825
+ return opts?.readonly ? new ScriptRO(this, script) : new Script(this, script);
3198
3826
  }
3199
3827
  /**
3200
3828
  * Create a new pipeline that allows you to send requests in bulk.
@@ -3281,10 +3909,18 @@ var Redis = class {
3281
3909
  * @see https://redis.io/commands/echo
3282
3910
  */
3283
3911
  echo = (...args) => new EchoCommand(args, this.opts).exec(this.client);
3912
+ /**
3913
+ * @see https://redis.io/commands/eval_ro
3914
+ */
3915
+ evalRo = (...args) => new EvalROCommand(args, this.opts).exec(this.client);
3284
3916
  /**
3285
3917
  * @see https://redis.io/commands/eval
3286
3918
  */
3287
3919
  eval = (...args) => new EvalCommand(args, this.opts).exec(this.client);
3920
+ /**
3921
+ * @see https://redis.io/commands/evalsha_ro
3922
+ */
3923
+ evalshaRo = (...args) => new EvalshaROCommand(args, this.opts).exec(this.client);
3288
3924
  /**
3289
3925
  * @see https://redis.io/commands/evalsha
3290
3926
  */
@@ -3349,6 +3985,10 @@ var Redis = class {
3349
3985
  * @see https://redis.io/commands/getdel
3350
3986
  */
3351
3987
  getdel = (...args) => new GetDelCommand(args, this.opts).exec(this.client);
3988
+ /**
3989
+ * @see https://redis.io/commands/getex
3990
+ */
3991
+ getex = (...args) => new GetExCommand(args, this.opts).exec(this.client);
3352
3992
  /**
3353
3993
  * @see https://redis.io/commands/getrange
3354
3994
  */
@@ -3365,6 +4005,42 @@ var Redis = class {
3365
4005
  * @see https://redis.io/commands/hexists
3366
4006
  */
3367
4007
  hexists = (...args) => new HExistsCommand(args, this.opts).exec(this.client);
4008
+ /**
4009
+ * @see https://redis.io/commands/hexpire
4010
+ */
4011
+ hexpire = (...args) => new HExpireCommand(args, this.opts).exec(this.client);
4012
+ /**
4013
+ * @see https://redis.io/commands/hexpireat
4014
+ */
4015
+ hexpireat = (...args) => new HExpireAtCommand(args, this.opts).exec(this.client);
4016
+ /**
4017
+ * @see https://redis.io/commands/hexpiretime
4018
+ */
4019
+ hexpiretime = (...args) => new HExpireTimeCommand(args, this.opts).exec(this.client);
4020
+ /**
4021
+ * @see https://redis.io/commands/httl
4022
+ */
4023
+ httl = (...args) => new HTtlCommand(args, this.opts).exec(this.client);
4024
+ /**
4025
+ * @see https://redis.io/commands/hpexpire
4026
+ */
4027
+ hpexpire = (...args) => new HPExpireCommand(args, this.opts).exec(this.client);
4028
+ /**
4029
+ * @see https://redis.io/commands/hpexpireat
4030
+ */
4031
+ hpexpireat = (...args) => new HPExpireAtCommand(args, this.opts).exec(this.client);
4032
+ /**
4033
+ * @see https://redis.io/commands/hpexpiretime
4034
+ */
4035
+ hpexpiretime = (...args) => new HPExpireTimeCommand(args, this.opts).exec(this.client);
4036
+ /**
4037
+ * @see https://redis.io/commands/hpttl
4038
+ */
4039
+ hpttl = (...args) => new HPTtlCommand(args, this.opts).exec(this.client);
4040
+ /**
4041
+ * @see https://redis.io/commands/hpersist
4042
+ */
4043
+ hpersist = (...args) => new HPersistCommand(args, this.opts).exec(this.client);
3368
4044
  /**
3369
4045
  * @see https://redis.io/commands/hget
3370
4046
  */
@@ -3533,6 +4209,13 @@ var Redis = class {
3533
4209
  * @see https://redis.io/commands/psetex
3534
4210
  */
3535
4211
  psetex = (key, ttl, value) => new PSetEXCommand([key, ttl, value], this.opts).exec(this.client);
4212
+ /**
4213
+ * @see https://redis.io/commands/psubscribe
4214
+ */
4215
+ psubscribe = (patterns) => {
4216
+ const patternArray = Array.isArray(patterns) ? patterns : [patterns];
4217
+ return new Subscriber(this.client, patternArray, true, this.opts);
4218
+ };
3536
4219
  /**
3537
4220
  * @see https://redis.io/commands/pttl
3538
4221
  */
@@ -3569,10 +4252,9 @@ var Redis = class {
3569
4252
  * @see https://redis.io/commands/sadd
3570
4253
  */
3571
4254
  sadd = (key, member, ...members) => new SAddCommand([key, member, ...members], this.opts).exec(this.client);
3572
- /**
3573
- * @see https://redis.io/commands/scan
3574
- */
3575
- scan = (...args) => new ScanCommand(args, this.opts).exec(this.client);
4255
+ scan(cursor, opts) {
4256
+ return new ScanCommand([cursor, opts], this.opts).exec(this.client);
4257
+ }
3576
4258
  /**
3577
4259
  * @see https://redis.io/commands/scard
3578
4260
  */
@@ -3661,6 +4343,13 @@ var Redis = class {
3661
4343
  * @see https://redis.io/commands/strlen
3662
4344
  */
3663
4345
  strlen = (...args) => new StrLenCommand(args, this.opts).exec(this.client);
4346
+ /**
4347
+ * @see https://redis.io/commands/subscribe
4348
+ */
4349
+ subscribe = (channels) => {
4350
+ const channelArray = Array.isArray(channels) ? channels : [channels];
4351
+ return new Subscriber(this.client, channelArray, false, this.opts);
4352
+ };
3664
4353
  /**
3665
4354
  * @see https://redis.io/commands/sunion
3666
4355
  */
@@ -3886,7 +4575,7 @@ var Redis2 = class _Redis extends Redis {
3886
4575
  readYourWrites: config.readYourWrites
3887
4576
  });
3888
4577
  super(client, {
3889
- enableTelemetry: !env?.UPSTASH_DISABLE_TELEMETRY,
4578
+ enableTelemetry: config.enableTelemetry ?? !env?.UPSTASH_DISABLE_TELEMETRY,
3890
4579
  automaticDeserialization: config.automaticDeserialization,
3891
4580
  latencyLogging: config.latencyLogging,
3892
4581
  enableAutoPipelining: config.enableAutoPipelining