@upstash/redis 0.0.0-ci.e9b0c868305a820aaed7d68c8407b277da5a093e-20241008121230 → 0.0.0-ci.e9ff702fe7d2dd2495b4383b5432fe9b93f5a6e7-20250729064656
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/{chunk-3A3BS427.mjs → chunk-IRVZXPJO.mjs} +767 -87
- package/cloudflare.d.mts +3 -3
- package/cloudflare.d.ts +3 -3
- package/cloudflare.js +772 -104
- package/cloudflare.mjs +6 -8
- package/fastly.d.mts +2 -2
- package/fastly.d.ts +2 -2
- package/fastly.js +772 -104
- package/fastly.mjs +6 -8
- package/nodejs.d.mts +3 -3
- package/nodejs.d.ts +3 -3
- package/nodejs.js +774 -106
- package/nodejs.mjs +8 -10
- package/package.json +1 -1
- package/{zmscore-BLgYk16R.d.mts → zmscore-CgRD7oFR.d.mts} +616 -53
- package/{zmscore-BLgYk16R.d.ts → zmscore-CgRD7oFR.d.ts} +616 -53
|
@@ -25,6 +25,51 @@ var UrlError = class extends Error {
|
|
|
25
25
|
}
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
+
// pkg/util.ts
|
|
29
|
+
function parseRecursive(obj) {
|
|
30
|
+
const parsed = Array.isArray(obj) ? obj.map((o) => {
|
|
31
|
+
try {
|
|
32
|
+
return parseRecursive(o);
|
|
33
|
+
} catch {
|
|
34
|
+
return o;
|
|
35
|
+
}
|
|
36
|
+
}) : JSON.parse(obj);
|
|
37
|
+
if (typeof parsed === "number" && parsed.toString() !== obj) {
|
|
38
|
+
return obj;
|
|
39
|
+
}
|
|
40
|
+
return parsed;
|
|
41
|
+
}
|
|
42
|
+
function parseResponse(result) {
|
|
43
|
+
try {
|
|
44
|
+
return parseRecursive(result);
|
|
45
|
+
} catch {
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function deserializeScanResponse(result) {
|
|
50
|
+
return [result[0], ...parseResponse(result.slice(1))];
|
|
51
|
+
}
|
|
52
|
+
function deserializeScanWithTypesResponse(result) {
|
|
53
|
+
const [cursor, keys] = result;
|
|
54
|
+
const parsedKeys = [];
|
|
55
|
+
for (let i = 0; i < keys.length; i += 2) {
|
|
56
|
+
parsedKeys.push({ key: keys[i], type: keys[i + 1] });
|
|
57
|
+
}
|
|
58
|
+
return [cursor, parsedKeys];
|
|
59
|
+
}
|
|
60
|
+
function mergeHeaders(...headers) {
|
|
61
|
+
const merged = {};
|
|
62
|
+
for (const header of headers) {
|
|
63
|
+
if (!header) continue;
|
|
64
|
+
for (const [key, value] of Object.entries(header)) {
|
|
65
|
+
if (value !== void 0 && value !== null) {
|
|
66
|
+
merged[key] = value;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return merged;
|
|
71
|
+
}
|
|
72
|
+
|
|
28
73
|
// pkg/http.ts
|
|
29
74
|
var HttpClient = class {
|
|
30
75
|
baseUrl;
|
|
@@ -46,7 +91,7 @@ var HttpClient = class {
|
|
|
46
91
|
};
|
|
47
92
|
this.upstashSyncToken = "";
|
|
48
93
|
this.readYourWrites = config.readYourWrites ?? true;
|
|
49
|
-
this.baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
94
|
+
this.baseUrl = (config.baseUrl || "").replace(/\/$/, "");
|
|
50
95
|
const urlRegex = /^https?:\/\/[^\s#$./?].\S*$/;
|
|
51
96
|
if (this.baseUrl && !urlRegex.test(this.baseUrl)) {
|
|
52
97
|
throw new UrlError(this.baseUrl);
|
|
@@ -73,22 +118,27 @@ var HttpClient = class {
|
|
|
73
118
|
this.headers = merge(this.headers, "Upstash-Telemetry-Sdk", telemetry.sdk);
|
|
74
119
|
}
|
|
75
120
|
async request(req) {
|
|
121
|
+
const requestHeaders = mergeHeaders(this.headers, req.headers ?? {});
|
|
122
|
+
const requestUrl = [this.baseUrl, ...req.path ?? []].join("/");
|
|
123
|
+
const isEventStream = requestHeaders.Accept === "text/event-stream";
|
|
124
|
+
const signal = req.signal ?? this.options.signal;
|
|
125
|
+
const isSignalFunction = typeof signal === "function";
|
|
76
126
|
const requestOptions = {
|
|
77
127
|
//@ts-expect-error this should throw due to bun regression
|
|
78
128
|
cache: this.options.cache,
|
|
79
129
|
method: "POST",
|
|
80
|
-
headers:
|
|
130
|
+
headers: requestHeaders,
|
|
81
131
|
body: JSON.stringify(req.body),
|
|
82
132
|
keepalive: this.options.keepAlive,
|
|
83
133
|
agent: this.options.agent,
|
|
84
|
-
signal:
|
|
134
|
+
signal: isSignalFunction ? signal() : signal,
|
|
85
135
|
/**
|
|
86
136
|
* Fastly specific
|
|
87
137
|
*/
|
|
88
138
|
backend: this.options.backend
|
|
89
139
|
};
|
|
90
140
|
if (!this.hasCredentials) {
|
|
91
|
-
|
|
141
|
+
console.warn(
|
|
92
142
|
"[Upstash Redis] Redis client was initialized without url or token. Failed to execute command."
|
|
93
143
|
);
|
|
94
144
|
}
|
|
@@ -100,35 +150,71 @@ var HttpClient = class {
|
|
|
100
150
|
let error = null;
|
|
101
151
|
for (let i = 0; i <= this.retry.attempts; i++) {
|
|
102
152
|
try {
|
|
103
|
-
res = await fetch(
|
|
153
|
+
res = await fetch(requestUrl, requestOptions);
|
|
104
154
|
break;
|
|
105
155
|
} catch (error_) {
|
|
106
|
-
if (
|
|
156
|
+
if (requestOptions.signal?.aborted && isSignalFunction) {
|
|
157
|
+
throw error_;
|
|
158
|
+
} else if (requestOptions.signal?.aborted) {
|
|
107
159
|
const myBlob = new Blob([
|
|
108
|
-
JSON.stringify({ result:
|
|
160
|
+
JSON.stringify({ result: requestOptions.signal.reason ?? "Aborted" })
|
|
109
161
|
]);
|
|
110
162
|
const myOptions = {
|
|
111
163
|
status: 200,
|
|
112
|
-
statusText:
|
|
164
|
+
statusText: requestOptions.signal.reason ?? "Aborted"
|
|
113
165
|
};
|
|
114
166
|
res = new Response(myBlob, myOptions);
|
|
115
167
|
break;
|
|
116
168
|
}
|
|
117
169
|
error = error_;
|
|
118
|
-
|
|
170
|
+
if (i < this.retry.attempts) {
|
|
171
|
+
await new Promise((r) => setTimeout(r, this.retry.backoff(i)));
|
|
172
|
+
}
|
|
119
173
|
}
|
|
120
174
|
}
|
|
121
175
|
if (!res) {
|
|
122
176
|
throw error ?? new Error("Exhausted all retries");
|
|
123
177
|
}
|
|
124
|
-
const body = await res.json();
|
|
125
178
|
if (!res.ok) {
|
|
126
|
-
|
|
179
|
+
const body2 = await res.json();
|
|
180
|
+
throw new UpstashError(`${body2.error}, command was: ${JSON.stringify(req.body)}`);
|
|
127
181
|
}
|
|
128
182
|
if (this.readYourWrites) {
|
|
129
183
|
const headers = res.headers;
|
|
130
184
|
this.upstashSyncToken = headers.get("upstash-sync-token") ?? "";
|
|
131
185
|
}
|
|
186
|
+
if (isEventStream && req && req.onMessage && res.body) {
|
|
187
|
+
const reader = res.body.getReader();
|
|
188
|
+
const decoder = new TextDecoder();
|
|
189
|
+
(async () => {
|
|
190
|
+
try {
|
|
191
|
+
while (true) {
|
|
192
|
+
const { value, done } = await reader.read();
|
|
193
|
+
if (done) break;
|
|
194
|
+
const chunk = decoder.decode(value);
|
|
195
|
+
const lines = chunk.split("\n");
|
|
196
|
+
for (const line of lines) {
|
|
197
|
+
if (line.startsWith("data: ")) {
|
|
198
|
+
const data = line.slice(6);
|
|
199
|
+
req.onMessage?.(data);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
} catch (error2) {
|
|
204
|
+
if (error2 instanceof Error && error2.name === "AbortError") {
|
|
205
|
+
} else {
|
|
206
|
+
console.error("Stream reading error:", error2);
|
|
207
|
+
}
|
|
208
|
+
} finally {
|
|
209
|
+
try {
|
|
210
|
+
await reader.cancel();
|
|
211
|
+
} catch {
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
})();
|
|
215
|
+
return { result: 1 };
|
|
216
|
+
}
|
|
217
|
+
const body = await res.json();
|
|
132
218
|
if (this.readYourWrites) {
|
|
133
219
|
const headers = res.headers;
|
|
134
220
|
this.upstashSyncToken = headers.get("upstash-sync-token") ?? "";
|
|
@@ -199,31 +285,6 @@ function merge(obj, key, value) {
|
|
|
199
285
|
return obj;
|
|
200
286
|
}
|
|
201
287
|
|
|
202
|
-
// pkg/util.ts
|
|
203
|
-
function parseRecursive(obj) {
|
|
204
|
-
const parsed = Array.isArray(obj) ? obj.map((o) => {
|
|
205
|
-
try {
|
|
206
|
-
return parseRecursive(o);
|
|
207
|
-
} catch {
|
|
208
|
-
return o;
|
|
209
|
-
}
|
|
210
|
-
}) : JSON.parse(obj);
|
|
211
|
-
if (typeof parsed === "number" && parsed.toString() !== obj) {
|
|
212
|
-
return obj;
|
|
213
|
-
}
|
|
214
|
-
return parsed;
|
|
215
|
-
}
|
|
216
|
-
function parseResponse(result) {
|
|
217
|
-
try {
|
|
218
|
-
return parseRecursive(result);
|
|
219
|
-
} catch {
|
|
220
|
-
return result;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
function deserializeScanResponse(result) {
|
|
224
|
-
return [result[0], ...parseResponse(result.slice(1))];
|
|
225
|
-
}
|
|
226
|
-
|
|
227
288
|
// pkg/commands/command.ts
|
|
228
289
|
var defaultSerializer = (c) => {
|
|
229
290
|
switch (typeof c) {
|
|
@@ -241,6 +302,11 @@ var Command = class {
|
|
|
241
302
|
command;
|
|
242
303
|
serialize;
|
|
243
304
|
deserialize;
|
|
305
|
+
headers;
|
|
306
|
+
path;
|
|
307
|
+
onMessage;
|
|
308
|
+
isStreaming;
|
|
309
|
+
signal;
|
|
244
310
|
/**
|
|
245
311
|
* Create a new command instance.
|
|
246
312
|
*
|
|
@@ -250,6 +316,11 @@ var Command = class {
|
|
|
250
316
|
this.serialize = defaultSerializer;
|
|
251
317
|
this.deserialize = opts?.automaticDeserialization === void 0 || opts.automaticDeserialization ? opts?.deserialize ?? parseResponse : (x) => x;
|
|
252
318
|
this.command = command.map((c) => this.serialize(c));
|
|
319
|
+
this.headers = opts?.headers;
|
|
320
|
+
this.path = opts?.path;
|
|
321
|
+
this.onMessage = opts?.streamOptions?.onMessage;
|
|
322
|
+
this.isStreaming = opts?.streamOptions?.isStreaming ?? false;
|
|
323
|
+
this.signal = opts?.streamOptions?.signal;
|
|
253
324
|
if (opts?.latencyLogging) {
|
|
254
325
|
const originalExec = this.exec.bind(this);
|
|
255
326
|
this.exec = async (client) => {
|
|
@@ -270,7 +341,12 @@ var Command = class {
|
|
|
270
341
|
async exec(client) {
|
|
271
342
|
const { result, error } = await client.request({
|
|
272
343
|
body: this.command,
|
|
273
|
-
|
|
344
|
+
path: this.path,
|
|
345
|
+
upstashSyncToken: client.upstashSyncToken,
|
|
346
|
+
headers: this.headers,
|
|
347
|
+
onMessage: this.onMessage,
|
|
348
|
+
isStreaming: this.isStreaming,
|
|
349
|
+
signal: this.signal
|
|
274
350
|
});
|
|
275
351
|
if (error) {
|
|
276
352
|
throw new UpstashError(error);
|
|
@@ -288,9 +364,9 @@ function deserialize(result) {
|
|
|
288
364
|
return null;
|
|
289
365
|
}
|
|
290
366
|
const obj = {};
|
|
291
|
-
|
|
292
|
-
const key = result
|
|
293
|
-
const value = result
|
|
367
|
+
for (let i = 0; i < result.length; i += 2) {
|
|
368
|
+
const key = result[i];
|
|
369
|
+
const value = result[i + 1];
|
|
294
370
|
try {
|
|
295
371
|
obj[key] = JSON.parse(value);
|
|
296
372
|
} catch {
|
|
@@ -432,6 +508,13 @@ var EchoCommand = class extends Command {
|
|
|
432
508
|
}
|
|
433
509
|
};
|
|
434
510
|
|
|
511
|
+
// pkg/commands/evalRo.ts
|
|
512
|
+
var EvalROCommand = class extends Command {
|
|
513
|
+
constructor([script, keys, args], opts) {
|
|
514
|
+
super(["eval_ro", script, keys.length, ...keys, ...args ?? []], opts);
|
|
515
|
+
}
|
|
516
|
+
};
|
|
517
|
+
|
|
435
518
|
// pkg/commands/eval.ts
|
|
436
519
|
var EvalCommand = class extends Command {
|
|
437
520
|
constructor([script, keys, args], opts) {
|
|
@@ -439,6 +522,13 @@ var EvalCommand = class extends Command {
|
|
|
439
522
|
}
|
|
440
523
|
};
|
|
441
524
|
|
|
525
|
+
// pkg/commands/evalshaRo.ts
|
|
526
|
+
var EvalshaROCommand = class extends Command {
|
|
527
|
+
constructor([sha, keys, args], opts) {
|
|
528
|
+
super(["evalsha_ro", sha, keys.length, ...keys, ...args ?? []], opts);
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
|
|
442
532
|
// pkg/commands/evalsha.ts
|
|
443
533
|
var EvalshaCommand = class extends Command {
|
|
444
534
|
constructor([sha, keys, args], opts) {
|
|
@@ -446,6 +536,14 @@ var EvalshaCommand = class extends Command {
|
|
|
446
536
|
}
|
|
447
537
|
};
|
|
448
538
|
|
|
539
|
+
// pkg/commands/exec.ts
|
|
540
|
+
var ExecCommand = class extends Command {
|
|
541
|
+
constructor(cmd, opts) {
|
|
542
|
+
const normalizedCmd = cmd.map((arg) => typeof arg === "string" ? arg : String(arg));
|
|
543
|
+
super(normalizedCmd, opts);
|
|
544
|
+
}
|
|
545
|
+
};
|
|
546
|
+
|
|
449
547
|
// pkg/commands/exists.ts
|
|
450
548
|
var ExistsCommand = class extends Command {
|
|
451
549
|
constructor(cmd, opts) {
|
|
@@ -662,6 +760,27 @@ var GetDelCommand = class extends Command {
|
|
|
662
760
|
}
|
|
663
761
|
};
|
|
664
762
|
|
|
763
|
+
// pkg/commands/getex.ts
|
|
764
|
+
var GetExCommand = class extends Command {
|
|
765
|
+
constructor([key, opts], cmdOpts) {
|
|
766
|
+
const command = ["getex", key];
|
|
767
|
+
if (opts) {
|
|
768
|
+
if ("ex" in opts && typeof opts.ex === "number") {
|
|
769
|
+
command.push("ex", opts.ex);
|
|
770
|
+
} else if ("px" in opts && typeof opts.px === "number") {
|
|
771
|
+
command.push("px", opts.px);
|
|
772
|
+
} else if ("exat" in opts && typeof opts.exat === "number") {
|
|
773
|
+
command.push("exat", opts.exat);
|
|
774
|
+
} else if ("pxat" in opts && typeof opts.pxat === "number") {
|
|
775
|
+
command.push("pxat", opts.pxat);
|
|
776
|
+
} else if ("persist" in opts && opts.persist) {
|
|
777
|
+
command.push("persist");
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
super(command, cmdOpts);
|
|
781
|
+
}
|
|
782
|
+
};
|
|
783
|
+
|
|
665
784
|
// pkg/commands/getrange.ts
|
|
666
785
|
var GetRangeCommand = class extends Command {
|
|
667
786
|
constructor(cmd, opts) {
|
|
@@ -690,6 +809,122 @@ var HExistsCommand = class extends Command {
|
|
|
690
809
|
}
|
|
691
810
|
};
|
|
692
811
|
|
|
812
|
+
// pkg/commands/hexpire.ts
|
|
813
|
+
var HExpireCommand = class extends Command {
|
|
814
|
+
constructor(cmd, opts) {
|
|
815
|
+
const [key, fields, seconds, option] = cmd;
|
|
816
|
+
const fieldArray = Array.isArray(fields) ? fields : [fields];
|
|
817
|
+
super(
|
|
818
|
+
[
|
|
819
|
+
"hexpire",
|
|
820
|
+
key,
|
|
821
|
+
seconds,
|
|
822
|
+
...option ? [option] : [],
|
|
823
|
+
"FIELDS",
|
|
824
|
+
fieldArray.length,
|
|
825
|
+
...fieldArray
|
|
826
|
+
],
|
|
827
|
+
opts
|
|
828
|
+
);
|
|
829
|
+
}
|
|
830
|
+
};
|
|
831
|
+
|
|
832
|
+
// pkg/commands/hexpireat.ts
|
|
833
|
+
var HExpireAtCommand = class extends Command {
|
|
834
|
+
constructor(cmd, opts) {
|
|
835
|
+
const [key, fields, timestamp, option] = cmd;
|
|
836
|
+
const fieldArray = Array.isArray(fields) ? fields : [fields];
|
|
837
|
+
super(
|
|
838
|
+
[
|
|
839
|
+
"hexpireat",
|
|
840
|
+
key,
|
|
841
|
+
timestamp,
|
|
842
|
+
...option ? [option] : [],
|
|
843
|
+
"FIELDS",
|
|
844
|
+
fieldArray.length,
|
|
845
|
+
...fieldArray
|
|
846
|
+
],
|
|
847
|
+
opts
|
|
848
|
+
);
|
|
849
|
+
}
|
|
850
|
+
};
|
|
851
|
+
|
|
852
|
+
// pkg/commands/hexpiretime.ts
|
|
853
|
+
var HExpireTimeCommand = class extends Command {
|
|
854
|
+
constructor(cmd, opts) {
|
|
855
|
+
const [key, fields] = cmd;
|
|
856
|
+
const fieldArray = Array.isArray(fields) ? fields : [fields];
|
|
857
|
+
super(["hexpiretime", key, "FIELDS", fieldArray.length, ...fieldArray], opts);
|
|
858
|
+
}
|
|
859
|
+
};
|
|
860
|
+
|
|
861
|
+
// pkg/commands/hpersist.ts
|
|
862
|
+
var HPersistCommand = class extends Command {
|
|
863
|
+
constructor(cmd, opts) {
|
|
864
|
+
const [key, fields] = cmd;
|
|
865
|
+
const fieldArray = Array.isArray(fields) ? fields : [fields];
|
|
866
|
+
super(["hpersist", key, "FIELDS", fieldArray.length, ...fieldArray], opts);
|
|
867
|
+
}
|
|
868
|
+
};
|
|
869
|
+
|
|
870
|
+
// pkg/commands/hpexpire.ts
|
|
871
|
+
var HPExpireCommand = class extends Command {
|
|
872
|
+
constructor(cmd, opts) {
|
|
873
|
+
const [key, fields, milliseconds, option] = cmd;
|
|
874
|
+
const fieldArray = Array.isArray(fields) ? fields : [fields];
|
|
875
|
+
super(
|
|
876
|
+
[
|
|
877
|
+
"hpexpire",
|
|
878
|
+
key,
|
|
879
|
+
milliseconds,
|
|
880
|
+
...option ? [option] : [],
|
|
881
|
+
"FIELDS",
|
|
882
|
+
fieldArray.length,
|
|
883
|
+
...fieldArray
|
|
884
|
+
],
|
|
885
|
+
opts
|
|
886
|
+
);
|
|
887
|
+
}
|
|
888
|
+
};
|
|
889
|
+
|
|
890
|
+
// pkg/commands/hpexpireat.ts
|
|
891
|
+
var HPExpireAtCommand = class extends Command {
|
|
892
|
+
constructor(cmd, opts) {
|
|
893
|
+
const [key, fields, timestamp, option] = cmd;
|
|
894
|
+
const fieldArray = Array.isArray(fields) ? fields : [fields];
|
|
895
|
+
super(
|
|
896
|
+
[
|
|
897
|
+
"hpexpireat",
|
|
898
|
+
key,
|
|
899
|
+
timestamp,
|
|
900
|
+
...option ? [option] : [],
|
|
901
|
+
"FIELDS",
|
|
902
|
+
fieldArray.length,
|
|
903
|
+
...fieldArray
|
|
904
|
+
],
|
|
905
|
+
opts
|
|
906
|
+
);
|
|
907
|
+
}
|
|
908
|
+
};
|
|
909
|
+
|
|
910
|
+
// pkg/commands/hpexpiretime.ts
|
|
911
|
+
var HPExpireTimeCommand = class extends Command {
|
|
912
|
+
constructor(cmd, opts) {
|
|
913
|
+
const [key, fields] = cmd;
|
|
914
|
+
const fieldArray = Array.isArray(fields) ? fields : [fields];
|
|
915
|
+
super(["hpexpiretime", key, "FIELDS", fieldArray.length, ...fieldArray], opts);
|
|
916
|
+
}
|
|
917
|
+
};
|
|
918
|
+
|
|
919
|
+
// pkg/commands/hpttl.ts
|
|
920
|
+
var HPTtlCommand = class extends Command {
|
|
921
|
+
constructor(cmd, opts) {
|
|
922
|
+
const [key, fields] = cmd;
|
|
923
|
+
const fieldArray = Array.isArray(fields) ? fields : [fields];
|
|
924
|
+
super(["hpttl", key, "FIELDS", fieldArray.length, ...fieldArray], opts);
|
|
925
|
+
}
|
|
926
|
+
};
|
|
927
|
+
|
|
693
928
|
// pkg/commands/hget.ts
|
|
694
929
|
var HGetCommand = class extends Command {
|
|
695
930
|
constructor(cmd, opts) {
|
|
@@ -703,9 +938,9 @@ function deserialize2(result) {
|
|
|
703
938
|
return null;
|
|
704
939
|
}
|
|
705
940
|
const obj = {};
|
|
706
|
-
|
|
707
|
-
const key = result
|
|
708
|
-
const value = result
|
|
941
|
+
for (let i = 0; i < result.length; i += 2) {
|
|
942
|
+
const key = result[i];
|
|
943
|
+
const value = result[i + 1];
|
|
709
944
|
try {
|
|
710
945
|
const valueIsNumberAndNotSafeInteger = !Number.isNaN(Number(value)) && !Number.isSafeInteger(Number(value));
|
|
711
946
|
obj[key] = valueIsNumberAndNotSafeInteger ? value : JSON.parse(value);
|
|
@@ -821,6 +1056,15 @@ var HStrLenCommand = class extends Command {
|
|
|
821
1056
|
}
|
|
822
1057
|
};
|
|
823
1058
|
|
|
1059
|
+
// pkg/commands/httl.ts
|
|
1060
|
+
var HTtlCommand = class extends Command {
|
|
1061
|
+
constructor(cmd, opts) {
|
|
1062
|
+
const [key, fields] = cmd;
|
|
1063
|
+
const fieldArray = Array.isArray(fields) ? fields : [fields];
|
|
1064
|
+
super(["httl", key, "FIELDS", fieldArray.length, ...fieldArray], opts);
|
|
1065
|
+
}
|
|
1066
|
+
};
|
|
1067
|
+
|
|
824
1068
|
// pkg/commands/hvals.ts
|
|
825
1069
|
var HValsCommand = class extends Command {
|
|
826
1070
|
constructor(cmd, opts) {
|
|
@@ -940,6 +1184,14 @@ var JsonGetCommand = class extends Command {
|
|
|
940
1184
|
}
|
|
941
1185
|
};
|
|
942
1186
|
|
|
1187
|
+
// pkg/commands/json_merge.ts
|
|
1188
|
+
var JsonMergeCommand = class extends Command {
|
|
1189
|
+
constructor(cmd, opts) {
|
|
1190
|
+
const command = ["JSON.MERGE", ...cmd];
|
|
1191
|
+
super(command, opts);
|
|
1192
|
+
}
|
|
1193
|
+
};
|
|
1194
|
+
|
|
943
1195
|
// pkg/commands/json_mget.ts
|
|
944
1196
|
var JsonMGetCommand = class extends Command {
|
|
945
1197
|
constructor(cmd, opts) {
|
|
@@ -1300,11 +1552,14 @@ var ScanCommand = class extends Command {
|
|
|
1300
1552
|
if (typeof opts?.count === "number") {
|
|
1301
1553
|
command.push("count", opts.count);
|
|
1302
1554
|
}
|
|
1303
|
-
if (opts
|
|
1555
|
+
if (opts && "withType" in opts && opts.withType === true) {
|
|
1556
|
+
command.push("withtype");
|
|
1557
|
+
} else if (opts && "type" in opts && opts.type && opts.type.length > 0) {
|
|
1304
1558
|
command.push("type", opts.type);
|
|
1305
1559
|
}
|
|
1306
1560
|
super(command, {
|
|
1307
|
-
|
|
1561
|
+
// @ts-expect-error ignore types here
|
|
1562
|
+
deserialize: opts?.withType ? deserializeScanWithTypesResponse : deserializeScanResponse,
|
|
1308
1563
|
...cmdOpts
|
|
1309
1564
|
});
|
|
1310
1565
|
}
|
|
@@ -1730,15 +1985,15 @@ var XPendingCommand = class extends Command {
|
|
|
1730
1985
|
function deserialize4(result) {
|
|
1731
1986
|
const obj = {};
|
|
1732
1987
|
for (const e of result) {
|
|
1733
|
-
|
|
1734
|
-
const streamId = e
|
|
1735
|
-
const entries = e
|
|
1988
|
+
for (let i = 0; i < e.length; i += 2) {
|
|
1989
|
+
const streamId = e[i];
|
|
1990
|
+
const entries = e[i + 1];
|
|
1736
1991
|
if (!(streamId in obj)) {
|
|
1737
1992
|
obj[streamId] = {};
|
|
1738
1993
|
}
|
|
1739
|
-
|
|
1740
|
-
const field = entries
|
|
1741
|
-
const value = entries
|
|
1994
|
+
for (let j = 0; j < entries.length; j += 2) {
|
|
1995
|
+
const field = entries[j];
|
|
1996
|
+
const value = entries[j + 1];
|
|
1742
1997
|
try {
|
|
1743
1998
|
obj[streamId][field] = JSON.parse(value);
|
|
1744
1999
|
} catch {
|
|
@@ -1827,15 +2082,15 @@ var XRevRangeCommand = class extends Command {
|
|
|
1827
2082
|
function deserialize5(result) {
|
|
1828
2083
|
const obj = {};
|
|
1829
2084
|
for (const e of result) {
|
|
1830
|
-
|
|
1831
|
-
const streamId = e
|
|
1832
|
-
const entries = e
|
|
2085
|
+
for (let i = 0; i < e.length; i += 2) {
|
|
2086
|
+
const streamId = e[i];
|
|
2087
|
+
const entries = e[i + 1];
|
|
1833
2088
|
if (!(streamId in obj)) {
|
|
1834
2089
|
obj[streamId] = {};
|
|
1835
2090
|
}
|
|
1836
|
-
|
|
1837
|
-
const field = entries
|
|
1838
|
-
const value = entries
|
|
2091
|
+
for (let j = 0; j < entries.length; j += 2) {
|
|
2092
|
+
const field = entries[j];
|
|
2093
|
+
const value = entries[j + 1];
|
|
1839
2094
|
try {
|
|
1840
2095
|
obj[streamId][field] = JSON.parse(value);
|
|
1841
2096
|
} catch {
|
|
@@ -2122,9 +2377,9 @@ var Pipeline = class {
|
|
|
2122
2377
|
this.multiExec = opts.multiExec ?? false;
|
|
2123
2378
|
if (this.commandOptions?.latencyLogging) {
|
|
2124
2379
|
const originalExec = this.exec.bind(this);
|
|
2125
|
-
this.exec = async () => {
|
|
2380
|
+
this.exec = async (options) => {
|
|
2126
2381
|
const start = performance.now();
|
|
2127
|
-
const result = await originalExec();
|
|
2382
|
+
const result = await (options ? originalExec(options) : originalExec());
|
|
2128
2383
|
const end = performance.now();
|
|
2129
2384
|
const loggerResult = (end - start).toFixed(2);
|
|
2130
2385
|
console.log(
|
|
@@ -2134,19 +2389,7 @@ var Pipeline = class {
|
|
|
2134
2389
|
};
|
|
2135
2390
|
}
|
|
2136
2391
|
}
|
|
2137
|
-
|
|
2138
|
-
* Send the pipeline request to upstash.
|
|
2139
|
-
*
|
|
2140
|
-
* Returns an array with the results of all pipelined commands.
|
|
2141
|
-
*
|
|
2142
|
-
* If all commands are statically chained from start to finish, types are inferred. You can still define a return type manually if necessary though:
|
|
2143
|
-
* ```ts
|
|
2144
|
-
* const p = redis.pipeline()
|
|
2145
|
-
* p.get("key")
|
|
2146
|
-
* const result = p.exec<[{ greeting: string }]>()
|
|
2147
|
-
* ```
|
|
2148
|
-
*/
|
|
2149
|
-
exec = async () => {
|
|
2392
|
+
exec = async (options) => {
|
|
2150
2393
|
if (this.commands.length === 0) {
|
|
2151
2394
|
throw new Error("Pipeline is empty");
|
|
2152
2395
|
}
|
|
@@ -2155,7 +2398,12 @@ var Pipeline = class {
|
|
|
2155
2398
|
path,
|
|
2156
2399
|
body: Object.values(this.commands).map((c) => c.command)
|
|
2157
2400
|
});
|
|
2158
|
-
return res.map(({ error, result }, i) => {
|
|
2401
|
+
return options?.keepErrors ? res.map(({ error, result }, i) => {
|
|
2402
|
+
return {
|
|
2403
|
+
error,
|
|
2404
|
+
result: this.commands[i].deserialize(result)
|
|
2405
|
+
};
|
|
2406
|
+
}) : res.map(({ error, result }, i) => {
|
|
2159
2407
|
if (error) {
|
|
2160
2408
|
throw new UpstashError(
|
|
2161
2409
|
`Command ${i + 1} [ ${this.commands[i].command[0]} ] failed: ${error}`
|
|
@@ -2241,10 +2489,18 @@ var Pipeline = class {
|
|
|
2241
2489
|
* @see https://redis.io/commands/echo
|
|
2242
2490
|
*/
|
|
2243
2491
|
echo = (...args) => this.chain(new EchoCommand(args, this.commandOptions));
|
|
2492
|
+
/**
|
|
2493
|
+
* @see https://redis.io/commands/eval_ro
|
|
2494
|
+
*/
|
|
2495
|
+
evalRo = (...args) => this.chain(new EvalROCommand(args, this.commandOptions));
|
|
2244
2496
|
/**
|
|
2245
2497
|
* @see https://redis.io/commands/eval
|
|
2246
2498
|
*/
|
|
2247
2499
|
eval = (...args) => this.chain(new EvalCommand(args, this.commandOptions));
|
|
2500
|
+
/**
|
|
2501
|
+
* @see https://redis.io/commands/evalsha_ro
|
|
2502
|
+
*/
|
|
2503
|
+
evalshaRo = (...args) => this.chain(new EvalshaROCommand(args, this.commandOptions));
|
|
2248
2504
|
/**
|
|
2249
2505
|
* @see https://redis.io/commands/evalsha
|
|
2250
2506
|
*/
|
|
@@ -2305,6 +2561,10 @@ var Pipeline = class {
|
|
|
2305
2561
|
* @see https://redis.io/commands/getdel
|
|
2306
2562
|
*/
|
|
2307
2563
|
getdel = (...args) => this.chain(new GetDelCommand(args, this.commandOptions));
|
|
2564
|
+
/**
|
|
2565
|
+
* @see https://redis.io/commands/getex
|
|
2566
|
+
*/
|
|
2567
|
+
getex = (...args) => this.chain(new GetExCommand(args, this.commandOptions));
|
|
2308
2568
|
/**
|
|
2309
2569
|
* @see https://redis.io/commands/getrange
|
|
2310
2570
|
*/
|
|
@@ -2321,6 +2581,42 @@ var Pipeline = class {
|
|
|
2321
2581
|
* @see https://redis.io/commands/hexists
|
|
2322
2582
|
*/
|
|
2323
2583
|
hexists = (...args) => this.chain(new HExistsCommand(args, this.commandOptions));
|
|
2584
|
+
/**
|
|
2585
|
+
* @see https://redis.io/commands/hexpire
|
|
2586
|
+
*/
|
|
2587
|
+
hexpire = (...args) => this.chain(new HExpireCommand(args, this.commandOptions));
|
|
2588
|
+
/**
|
|
2589
|
+
* @see https://redis.io/commands/hexpireat
|
|
2590
|
+
*/
|
|
2591
|
+
hexpireat = (...args) => this.chain(new HExpireAtCommand(args, this.commandOptions));
|
|
2592
|
+
/**
|
|
2593
|
+
* @see https://redis.io/commands/hexpiretime
|
|
2594
|
+
*/
|
|
2595
|
+
hexpiretime = (...args) => this.chain(new HExpireTimeCommand(args, this.commandOptions));
|
|
2596
|
+
/**
|
|
2597
|
+
* @see https://redis.io/commands/httl
|
|
2598
|
+
*/
|
|
2599
|
+
httl = (...args) => this.chain(new HTtlCommand(args, this.commandOptions));
|
|
2600
|
+
/**
|
|
2601
|
+
* @see https://redis.io/commands/hpexpire
|
|
2602
|
+
*/
|
|
2603
|
+
hpexpire = (...args) => this.chain(new HPExpireCommand(args, this.commandOptions));
|
|
2604
|
+
/**
|
|
2605
|
+
* @see https://redis.io/commands/hpexpireat
|
|
2606
|
+
*/
|
|
2607
|
+
hpexpireat = (...args) => this.chain(new HPExpireAtCommand(args, this.commandOptions));
|
|
2608
|
+
/**
|
|
2609
|
+
* @see https://redis.io/commands/hpexpiretime
|
|
2610
|
+
*/
|
|
2611
|
+
hpexpiretime = (...args) => this.chain(new HPExpireTimeCommand(args, this.commandOptions));
|
|
2612
|
+
/**
|
|
2613
|
+
* @see https://redis.io/commands/hpttl
|
|
2614
|
+
*/
|
|
2615
|
+
hpttl = (...args) => this.chain(new HPTtlCommand(args, this.commandOptions));
|
|
2616
|
+
/**
|
|
2617
|
+
* @see https://redis.io/commands/hpersist
|
|
2618
|
+
*/
|
|
2619
|
+
hpersist = (...args) => this.chain(new HPersistCommand(args, this.commandOptions));
|
|
2324
2620
|
/**
|
|
2325
2621
|
* @see https://redis.io/commands/hget
|
|
2326
2622
|
*/
|
|
@@ -2838,6 +3134,10 @@ var Pipeline = class {
|
|
|
2838
3134
|
* @see https://redis.io/commands/json.get
|
|
2839
3135
|
*/
|
|
2840
3136
|
get: (...args) => this.chain(new JsonGetCommand(args, this.commandOptions)),
|
|
3137
|
+
/**
|
|
3138
|
+
* @see https://redis.io/commands/json.merge
|
|
3139
|
+
*/
|
|
3140
|
+
merge: (...args) => this.chain(new JsonMergeCommand(args, this.commandOptions)),
|
|
2841
3141
|
/**
|
|
2842
3142
|
* @see https://redis.io/commands/json.mget
|
|
2843
3143
|
*/
|
|
@@ -2891,6 +3191,23 @@ var Pipeline = class {
|
|
|
2891
3191
|
};
|
|
2892
3192
|
|
|
2893
3193
|
// pkg/auto-pipeline.ts
|
|
3194
|
+
var EXCLUDE_COMMANDS = /* @__PURE__ */ new Set([
|
|
3195
|
+
"scan",
|
|
3196
|
+
"keys",
|
|
3197
|
+
"flushdb",
|
|
3198
|
+
"flushall",
|
|
3199
|
+
"dbsize",
|
|
3200
|
+
"hscan",
|
|
3201
|
+
"hgetall",
|
|
3202
|
+
"hkeys",
|
|
3203
|
+
"lrange",
|
|
3204
|
+
"sscan",
|
|
3205
|
+
"smembers",
|
|
3206
|
+
"xrange",
|
|
3207
|
+
"xrevrange",
|
|
3208
|
+
"zscan",
|
|
3209
|
+
"zrange"
|
|
3210
|
+
]);
|
|
2894
3211
|
function createAutoPipelineProxy(_redis, json) {
|
|
2895
3212
|
const redis = _redis;
|
|
2896
3213
|
if (!redis.autoPipelineExecutor) {
|
|
@@ -2905,7 +3222,8 @@ function createAutoPipelineProxy(_redis, json) {
|
|
|
2905
3222
|
return createAutoPipelineProxy(redis2, true);
|
|
2906
3223
|
}
|
|
2907
3224
|
const commandInRedisButNotPipeline = command in redis2 && !(command in redis2.autoPipelineExecutor.pipeline);
|
|
2908
|
-
|
|
3225
|
+
const isCommandExcluded = EXCLUDE_COMMANDS.has(command);
|
|
3226
|
+
if (commandInRedisButNotPipeline || isCommandExcluded) {
|
|
2909
3227
|
return redis2[command];
|
|
2910
3228
|
}
|
|
2911
3229
|
const isFunction = json ? typeof redis2.autoPipelineExecutor.pipeline.json[command] === "function" : typeof redis2.autoPipelineExecutor.pipeline[command] === "function";
|
|
@@ -2949,7 +3267,7 @@ var AutoPipelineExecutor = class {
|
|
|
2949
3267
|
executeWithPipeline(pipeline);
|
|
2950
3268
|
const pipelineDone = this.deferExecution().then(() => {
|
|
2951
3269
|
if (!this.pipelinePromises.has(pipeline)) {
|
|
2952
|
-
const pipelinePromise = pipeline.exec();
|
|
3270
|
+
const pipelinePromise = pipeline.exec({ keepErrors: true });
|
|
2953
3271
|
this.pipelineCounter += 1;
|
|
2954
3272
|
this.pipelinePromises.set(pipeline, pipelinePromise);
|
|
2955
3273
|
this.activePipeline = null;
|
|
@@ -2957,7 +3275,11 @@ var AutoPipelineExecutor = class {
|
|
|
2957
3275
|
return this.pipelinePromises.get(pipeline);
|
|
2958
3276
|
});
|
|
2959
3277
|
const results = await pipelineDone;
|
|
2960
|
-
|
|
3278
|
+
const commandResult = results[index];
|
|
3279
|
+
if (commandResult.error) {
|
|
3280
|
+
throw new UpstashError(`Command failed: ${commandResult.error}`);
|
|
3281
|
+
}
|
|
3282
|
+
return commandResult.result;
|
|
2961
3283
|
}
|
|
2962
3284
|
async deferExecution() {
|
|
2963
3285
|
await Promise.resolve();
|
|
@@ -2965,28 +3287,221 @@ var AutoPipelineExecutor = class {
|
|
|
2965
3287
|
}
|
|
2966
3288
|
};
|
|
2967
3289
|
|
|
3290
|
+
// pkg/commands/psubscribe.ts
|
|
3291
|
+
var PSubscribeCommand = class extends Command {
|
|
3292
|
+
constructor(cmd, opts) {
|
|
3293
|
+
const sseHeaders = {
|
|
3294
|
+
Accept: "text/event-stream",
|
|
3295
|
+
"Cache-Control": "no-cache",
|
|
3296
|
+
Connection: "keep-alive"
|
|
3297
|
+
};
|
|
3298
|
+
super([], {
|
|
3299
|
+
...opts,
|
|
3300
|
+
headers: sseHeaders,
|
|
3301
|
+
path: ["psubscribe", ...cmd],
|
|
3302
|
+
streamOptions: {
|
|
3303
|
+
isStreaming: true,
|
|
3304
|
+
onMessage: opts?.streamOptions?.onMessage,
|
|
3305
|
+
signal: opts?.streamOptions?.signal
|
|
3306
|
+
}
|
|
3307
|
+
});
|
|
3308
|
+
}
|
|
3309
|
+
};
|
|
3310
|
+
|
|
3311
|
+
// pkg/commands/subscribe.ts
|
|
3312
|
+
var Subscriber = class extends EventTarget {
|
|
3313
|
+
subscriptions;
|
|
3314
|
+
client;
|
|
3315
|
+
listeners;
|
|
3316
|
+
constructor(client, channels, isPattern = false) {
|
|
3317
|
+
super();
|
|
3318
|
+
this.client = client;
|
|
3319
|
+
this.subscriptions = /* @__PURE__ */ new Map();
|
|
3320
|
+
this.listeners = /* @__PURE__ */ new Map();
|
|
3321
|
+
for (const channel of channels) {
|
|
3322
|
+
if (isPattern) {
|
|
3323
|
+
this.subscribeToPattern(channel);
|
|
3324
|
+
} else {
|
|
3325
|
+
this.subscribeToChannel(channel);
|
|
3326
|
+
}
|
|
3327
|
+
}
|
|
3328
|
+
}
|
|
3329
|
+
subscribeToChannel(channel) {
|
|
3330
|
+
const controller = new AbortController();
|
|
3331
|
+
const command = new SubscribeCommand([channel], {
|
|
3332
|
+
streamOptions: {
|
|
3333
|
+
signal: controller.signal,
|
|
3334
|
+
onMessage: (data) => this.handleMessage(data, false)
|
|
3335
|
+
}
|
|
3336
|
+
});
|
|
3337
|
+
command.exec(this.client).catch((error) => {
|
|
3338
|
+
if (error.name !== "AbortError") {
|
|
3339
|
+
this.dispatchToListeners("error", error);
|
|
3340
|
+
}
|
|
3341
|
+
});
|
|
3342
|
+
this.subscriptions.set(channel, {
|
|
3343
|
+
command,
|
|
3344
|
+
controller,
|
|
3345
|
+
isPattern: false
|
|
3346
|
+
});
|
|
3347
|
+
}
|
|
3348
|
+
subscribeToPattern(pattern) {
|
|
3349
|
+
const controller = new AbortController();
|
|
3350
|
+
const command = new PSubscribeCommand([pattern], {
|
|
3351
|
+
streamOptions: {
|
|
3352
|
+
signal: controller.signal,
|
|
3353
|
+
onMessage: (data) => this.handleMessage(data, true)
|
|
3354
|
+
}
|
|
3355
|
+
});
|
|
3356
|
+
command.exec(this.client).catch((error) => {
|
|
3357
|
+
if (error.name !== "AbortError") {
|
|
3358
|
+
this.dispatchToListeners("error", error);
|
|
3359
|
+
}
|
|
3360
|
+
});
|
|
3361
|
+
this.subscriptions.set(pattern, {
|
|
3362
|
+
command,
|
|
3363
|
+
controller,
|
|
3364
|
+
isPattern: true
|
|
3365
|
+
});
|
|
3366
|
+
}
|
|
3367
|
+
handleMessage(data, isPattern) {
|
|
3368
|
+
const messageData = data.replace(/^data:\s*/, "");
|
|
3369
|
+
const firstCommaIndex = messageData.indexOf(",");
|
|
3370
|
+
const secondCommaIndex = messageData.indexOf(",", firstCommaIndex + 1);
|
|
3371
|
+
const thirdCommaIndex = isPattern ? messageData.indexOf(",", secondCommaIndex + 1) : -1;
|
|
3372
|
+
if (firstCommaIndex !== -1 && secondCommaIndex !== -1) {
|
|
3373
|
+
const type = messageData.slice(0, firstCommaIndex);
|
|
3374
|
+
if (isPattern && type === "pmessage" && thirdCommaIndex !== -1) {
|
|
3375
|
+
const pattern = messageData.slice(firstCommaIndex + 1, secondCommaIndex);
|
|
3376
|
+
const channel = messageData.slice(secondCommaIndex + 1, thirdCommaIndex);
|
|
3377
|
+
const messageStr = messageData.slice(thirdCommaIndex + 1);
|
|
3378
|
+
try {
|
|
3379
|
+
const message = JSON.parse(messageStr);
|
|
3380
|
+
this.dispatchToListeners("pmessage", { pattern, channel, message });
|
|
3381
|
+
this.dispatchToListeners(`pmessage:${pattern}`, { pattern, channel, message });
|
|
3382
|
+
} catch (error) {
|
|
3383
|
+
this.dispatchToListeners("error", new Error(`Failed to parse message: ${error}`));
|
|
3384
|
+
}
|
|
3385
|
+
} else {
|
|
3386
|
+
const channel = messageData.slice(firstCommaIndex + 1, secondCommaIndex);
|
|
3387
|
+
const messageStr = messageData.slice(secondCommaIndex + 1);
|
|
3388
|
+
try {
|
|
3389
|
+
if (type === "subscribe" || type === "psubscribe" || type === "unsubscribe" || type === "punsubscribe") {
|
|
3390
|
+
const count = Number.parseInt(messageStr);
|
|
3391
|
+
this.dispatchToListeners(type, count);
|
|
3392
|
+
} else {
|
|
3393
|
+
const message = JSON.parse(messageStr);
|
|
3394
|
+
this.dispatchToListeners(type, { channel, message });
|
|
3395
|
+
this.dispatchToListeners(`${type}:${channel}`, { channel, message });
|
|
3396
|
+
}
|
|
3397
|
+
} catch (error) {
|
|
3398
|
+
this.dispatchToListeners("error", new Error(`Failed to parse message: ${error}`));
|
|
3399
|
+
}
|
|
3400
|
+
}
|
|
3401
|
+
}
|
|
3402
|
+
}
|
|
3403
|
+
dispatchToListeners(type, data) {
|
|
3404
|
+
const listeners = this.listeners.get(type);
|
|
3405
|
+
if (listeners) {
|
|
3406
|
+
for (const listener of listeners) {
|
|
3407
|
+
listener(data);
|
|
3408
|
+
}
|
|
3409
|
+
}
|
|
3410
|
+
}
|
|
3411
|
+
on(type, listener) {
|
|
3412
|
+
if (!this.listeners.has(type)) {
|
|
3413
|
+
this.listeners.set(type, /* @__PURE__ */ new Set());
|
|
3414
|
+
}
|
|
3415
|
+
this.listeners.get(type)?.add(listener);
|
|
3416
|
+
}
|
|
3417
|
+
removeAllListeners() {
|
|
3418
|
+
this.listeners.clear();
|
|
3419
|
+
}
|
|
3420
|
+
async unsubscribe(channels) {
|
|
3421
|
+
if (channels) {
|
|
3422
|
+
for (const channel of channels) {
|
|
3423
|
+
const subscription = this.subscriptions.get(channel);
|
|
3424
|
+
if (subscription) {
|
|
3425
|
+
try {
|
|
3426
|
+
subscription.controller.abort();
|
|
3427
|
+
} catch {
|
|
3428
|
+
}
|
|
3429
|
+
this.subscriptions.delete(channel);
|
|
3430
|
+
}
|
|
3431
|
+
}
|
|
3432
|
+
} else {
|
|
3433
|
+
for (const subscription of this.subscriptions.values()) {
|
|
3434
|
+
try {
|
|
3435
|
+
subscription.controller.abort();
|
|
3436
|
+
} catch {
|
|
3437
|
+
}
|
|
3438
|
+
}
|
|
3439
|
+
this.subscriptions.clear();
|
|
3440
|
+
this.removeAllListeners();
|
|
3441
|
+
}
|
|
3442
|
+
}
|
|
3443
|
+
getSubscribedChannels() {
|
|
3444
|
+
return [...this.subscriptions.keys()];
|
|
3445
|
+
}
|
|
3446
|
+
};
|
|
3447
|
+
var SubscribeCommand = class extends Command {
|
|
3448
|
+
constructor(cmd, opts) {
|
|
3449
|
+
const sseHeaders = {
|
|
3450
|
+
Accept: "text/event-stream",
|
|
3451
|
+
"Cache-Control": "no-cache",
|
|
3452
|
+
Connection: "keep-alive"
|
|
3453
|
+
};
|
|
3454
|
+
super([], {
|
|
3455
|
+
...opts,
|
|
3456
|
+
headers: sseHeaders,
|
|
3457
|
+
path: ["subscribe", ...cmd],
|
|
3458
|
+
streamOptions: {
|
|
3459
|
+
isStreaming: true,
|
|
3460
|
+
onMessage: opts?.streamOptions?.onMessage,
|
|
3461
|
+
signal: opts?.streamOptions?.signal
|
|
3462
|
+
}
|
|
3463
|
+
});
|
|
3464
|
+
}
|
|
3465
|
+
};
|
|
3466
|
+
|
|
2968
3467
|
// pkg/script.ts
|
|
2969
|
-
import
|
|
2970
|
-
import sha1 from "crypto-js/sha1.js";
|
|
3468
|
+
import { subtle } from "uncrypto";
|
|
2971
3469
|
var Script = class {
|
|
2972
3470
|
script;
|
|
3471
|
+
/**
|
|
3472
|
+
* @deprecated This property is initialized to an empty string and will be set in the init method
|
|
3473
|
+
* asynchronously. Do not use this property immidiately after the constructor.
|
|
3474
|
+
*
|
|
3475
|
+
* This property is only exposed for backwards compatibility and will be removed in the
|
|
3476
|
+
* future major release.
|
|
3477
|
+
*/
|
|
2973
3478
|
sha1;
|
|
2974
3479
|
redis;
|
|
2975
3480
|
constructor(redis, script) {
|
|
2976
3481
|
this.redis = redis;
|
|
2977
|
-
this.sha1 = this.digest(script);
|
|
2978
3482
|
this.script = script;
|
|
3483
|
+
this.sha1 = "";
|
|
3484
|
+
void this.init(script);
|
|
3485
|
+
}
|
|
3486
|
+
/**
|
|
3487
|
+
* Initialize the script by computing its SHA-1 hash.
|
|
3488
|
+
*/
|
|
3489
|
+
async init(script) {
|
|
3490
|
+
if (this.sha1) return;
|
|
3491
|
+
this.sha1 = await this.digest(script);
|
|
2979
3492
|
}
|
|
2980
3493
|
/**
|
|
2981
3494
|
* Send an `EVAL` command to redis.
|
|
2982
3495
|
*/
|
|
2983
3496
|
async eval(keys, args) {
|
|
3497
|
+
await this.init(this.script);
|
|
2984
3498
|
return await this.redis.eval(this.script, keys, args);
|
|
2985
3499
|
}
|
|
2986
3500
|
/**
|
|
2987
3501
|
* Calculates the sha1 hash of the script and then calls `EVALSHA`.
|
|
2988
3502
|
*/
|
|
2989
3503
|
async evalsha(keys, args) {
|
|
3504
|
+
await this.init(this.script);
|
|
2990
3505
|
return await this.redis.evalsha(this.sha1, keys, args);
|
|
2991
3506
|
}
|
|
2992
3507
|
/**
|
|
@@ -2996,6 +3511,7 @@ var Script = class {
|
|
|
2996
3511
|
* Following calls will be able to use the cached script
|
|
2997
3512
|
*/
|
|
2998
3513
|
async exec(keys, args) {
|
|
3514
|
+
await this.init(this.script);
|
|
2999
3515
|
const res = await this.redis.evalsha(this.sha1, keys, args).catch(async (error) => {
|
|
3000
3516
|
if (error instanceof Error && error.message.toLowerCase().includes("noscript")) {
|
|
3001
3517
|
return await this.redis.eval(this.script, keys, args);
|
|
@@ -3007,8 +3523,75 @@ var Script = class {
|
|
|
3007
3523
|
/**
|
|
3008
3524
|
* Compute the sha1 hash of the script and return its hex representation.
|
|
3009
3525
|
*/
|
|
3010
|
-
digest(s) {
|
|
3011
|
-
|
|
3526
|
+
async digest(s) {
|
|
3527
|
+
const data = new TextEncoder().encode(s);
|
|
3528
|
+
const hashBuffer = await subtle.digest("SHA-1", data);
|
|
3529
|
+
const hashArray = [...new Uint8Array(hashBuffer)];
|
|
3530
|
+
return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
3531
|
+
}
|
|
3532
|
+
};
|
|
3533
|
+
|
|
3534
|
+
// pkg/scriptRo.ts
|
|
3535
|
+
import { subtle as subtle2 } from "uncrypto";
|
|
3536
|
+
var ScriptRO = class {
|
|
3537
|
+
script;
|
|
3538
|
+
/**
|
|
3539
|
+
* @deprecated This property is initialized to an empty string and will be set in the init method
|
|
3540
|
+
* asynchronously. Do not use this property immidiately after the constructor.
|
|
3541
|
+
*
|
|
3542
|
+
* This property is only exposed for backwards compatibility and will be removed in the
|
|
3543
|
+
* future major release.
|
|
3544
|
+
*/
|
|
3545
|
+
sha1;
|
|
3546
|
+
redis;
|
|
3547
|
+
constructor(redis, script) {
|
|
3548
|
+
this.redis = redis;
|
|
3549
|
+
this.sha1 = "";
|
|
3550
|
+
this.script = script;
|
|
3551
|
+
void this.init(script);
|
|
3552
|
+
}
|
|
3553
|
+
async init(script) {
|
|
3554
|
+
if (this.sha1) return;
|
|
3555
|
+
this.sha1 = await this.digest(script);
|
|
3556
|
+
}
|
|
3557
|
+
/**
|
|
3558
|
+
* Send an `EVAL_RO` command to redis.
|
|
3559
|
+
*/
|
|
3560
|
+
async evalRo(keys, args) {
|
|
3561
|
+
await this.init(this.script);
|
|
3562
|
+
return await this.redis.evalRo(this.script, keys, args);
|
|
3563
|
+
}
|
|
3564
|
+
/**
|
|
3565
|
+
* Calculates the sha1 hash of the script and then calls `EVALSHA_RO`.
|
|
3566
|
+
*/
|
|
3567
|
+
async evalshaRo(keys, args) {
|
|
3568
|
+
await this.init(this.script);
|
|
3569
|
+
return await this.redis.evalshaRo(this.sha1, keys, args);
|
|
3570
|
+
}
|
|
3571
|
+
/**
|
|
3572
|
+
* Optimistically try to run `EVALSHA_RO` first.
|
|
3573
|
+
* If the script is not loaded in redis, it will fall back and try again with `EVAL_RO`.
|
|
3574
|
+
*
|
|
3575
|
+
* Following calls will be able to use the cached script
|
|
3576
|
+
*/
|
|
3577
|
+
async exec(keys, args) {
|
|
3578
|
+
await this.init(this.script);
|
|
3579
|
+
const res = await this.redis.evalshaRo(this.sha1, keys, args).catch(async (error) => {
|
|
3580
|
+
if (error instanceof Error && error.message.toLowerCase().includes("noscript")) {
|
|
3581
|
+
return await this.redis.evalRo(this.script, keys, args);
|
|
3582
|
+
}
|
|
3583
|
+
throw error;
|
|
3584
|
+
});
|
|
3585
|
+
return res;
|
|
3586
|
+
}
|
|
3587
|
+
/**
|
|
3588
|
+
* Compute the sha1 hash of the script and return its hex representation.
|
|
3589
|
+
*/
|
|
3590
|
+
async digest(s) {
|
|
3591
|
+
const data = new TextEncoder().encode(s);
|
|
3592
|
+
const hashBuffer = await subtle2.digest("SHA-1", data);
|
|
3593
|
+
const hashArray = [...new Uint8Array(hashBuffer)];
|
|
3594
|
+
return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
3012
3595
|
}
|
|
3013
3596
|
};
|
|
3014
3597
|
|
|
@@ -3086,6 +3669,10 @@ var Redis = class {
|
|
|
3086
3669
|
* @see https://redis.io/commands/json.get
|
|
3087
3670
|
*/
|
|
3088
3671
|
get: (...args) => new JsonGetCommand(args, this.opts).exec(this.client),
|
|
3672
|
+
/**
|
|
3673
|
+
* @see https://redis.io/commands/json.merge
|
|
3674
|
+
*/
|
|
3675
|
+
merge: (...args) => new JsonMergeCommand(args, this.opts).exec(this.client),
|
|
3089
3676
|
/**
|
|
3090
3677
|
* @see https://redis.io/commands/json.mget
|
|
3091
3678
|
*/
|
|
@@ -3155,8 +3742,36 @@ var Redis = class {
|
|
|
3155
3742
|
} catch {
|
|
3156
3743
|
}
|
|
3157
3744
|
};
|
|
3158
|
-
|
|
3159
|
-
|
|
3745
|
+
/**
|
|
3746
|
+
* Creates a new script.
|
|
3747
|
+
*
|
|
3748
|
+
* Scripts offer the ability to optimistically try to execute a script without having to send the
|
|
3749
|
+
* entire script to the server. If the script is loaded on the server, it tries again by sending
|
|
3750
|
+
* the entire script. Afterwards, the script is cached on the server.
|
|
3751
|
+
*
|
|
3752
|
+
* @param script - The script to create
|
|
3753
|
+
* @param opts - Optional options to pass to the script `{ readonly?: boolean }`
|
|
3754
|
+
* @returns A new script
|
|
3755
|
+
*
|
|
3756
|
+
* @example
|
|
3757
|
+
* ```ts
|
|
3758
|
+
* const redis = new Redis({...})
|
|
3759
|
+
*
|
|
3760
|
+
* const script = redis.createScript<string>("return ARGV[1];")
|
|
3761
|
+
* const arg1 = await script.eval([], ["Hello World"])
|
|
3762
|
+
* expect(arg1, "Hello World")
|
|
3763
|
+
* ```
|
|
3764
|
+
* @example
|
|
3765
|
+
* ```ts
|
|
3766
|
+
* const redis = new Redis({...})
|
|
3767
|
+
*
|
|
3768
|
+
* const script = redis.createScript<string>("return ARGV[1];", { readonly: true })
|
|
3769
|
+
* const arg1 = await script.evalRo([], ["Hello World"])
|
|
3770
|
+
* expect(arg1, "Hello World")
|
|
3771
|
+
* ```
|
|
3772
|
+
*/
|
|
3773
|
+
createScript(script, opts) {
|
|
3774
|
+
return opts?.readonly ? new ScriptRO(this, script) : new Script(this, script);
|
|
3160
3775
|
}
|
|
3161
3776
|
/**
|
|
3162
3777
|
* Create a new pipeline that allows you to send requests in bulk.
|
|
@@ -3243,14 +3858,26 @@ var Redis = class {
|
|
|
3243
3858
|
* @see https://redis.io/commands/echo
|
|
3244
3859
|
*/
|
|
3245
3860
|
echo = (...args) => new EchoCommand(args, this.opts).exec(this.client);
|
|
3861
|
+
/**
|
|
3862
|
+
* @see https://redis.io/commands/eval_ro
|
|
3863
|
+
*/
|
|
3864
|
+
evalRo = (...args) => new EvalROCommand(args, this.opts).exec(this.client);
|
|
3246
3865
|
/**
|
|
3247
3866
|
* @see https://redis.io/commands/eval
|
|
3248
3867
|
*/
|
|
3249
3868
|
eval = (...args) => new EvalCommand(args, this.opts).exec(this.client);
|
|
3869
|
+
/**
|
|
3870
|
+
* @see https://redis.io/commands/evalsha_ro
|
|
3871
|
+
*/
|
|
3872
|
+
evalshaRo = (...args) => new EvalshaROCommand(args, this.opts).exec(this.client);
|
|
3250
3873
|
/**
|
|
3251
3874
|
* @see https://redis.io/commands/evalsha
|
|
3252
3875
|
*/
|
|
3253
3876
|
evalsha = (...args) => new EvalshaCommand(args, this.opts).exec(this.client);
|
|
3877
|
+
/**
|
|
3878
|
+
* Generic method to execute any Redis command.
|
|
3879
|
+
*/
|
|
3880
|
+
exec = (args) => new ExecCommand(args, this.opts).exec(this.client);
|
|
3254
3881
|
/**
|
|
3255
3882
|
* @see https://redis.io/commands/exists
|
|
3256
3883
|
*/
|
|
@@ -3307,6 +3934,10 @@ var Redis = class {
|
|
|
3307
3934
|
* @see https://redis.io/commands/getdel
|
|
3308
3935
|
*/
|
|
3309
3936
|
getdel = (...args) => new GetDelCommand(args, this.opts).exec(this.client);
|
|
3937
|
+
/**
|
|
3938
|
+
* @see https://redis.io/commands/getex
|
|
3939
|
+
*/
|
|
3940
|
+
getex = (...args) => new GetExCommand(args, this.opts).exec(this.client);
|
|
3310
3941
|
/**
|
|
3311
3942
|
* @see https://redis.io/commands/getrange
|
|
3312
3943
|
*/
|
|
@@ -3323,6 +3954,42 @@ var Redis = class {
|
|
|
3323
3954
|
* @see https://redis.io/commands/hexists
|
|
3324
3955
|
*/
|
|
3325
3956
|
hexists = (...args) => new HExistsCommand(args, this.opts).exec(this.client);
|
|
3957
|
+
/**
|
|
3958
|
+
* @see https://redis.io/commands/hexpire
|
|
3959
|
+
*/
|
|
3960
|
+
hexpire = (...args) => new HExpireCommand(args, this.opts).exec(this.client);
|
|
3961
|
+
/**
|
|
3962
|
+
* @see https://redis.io/commands/hexpireat
|
|
3963
|
+
*/
|
|
3964
|
+
hexpireat = (...args) => new HExpireAtCommand(args, this.opts).exec(this.client);
|
|
3965
|
+
/**
|
|
3966
|
+
* @see https://redis.io/commands/hexpiretime
|
|
3967
|
+
*/
|
|
3968
|
+
hexpiretime = (...args) => new HExpireTimeCommand(args, this.opts).exec(this.client);
|
|
3969
|
+
/**
|
|
3970
|
+
* @see https://redis.io/commands/httl
|
|
3971
|
+
*/
|
|
3972
|
+
httl = (...args) => new HTtlCommand(args, this.opts).exec(this.client);
|
|
3973
|
+
/**
|
|
3974
|
+
* @see https://redis.io/commands/hpexpire
|
|
3975
|
+
*/
|
|
3976
|
+
hpexpire = (...args) => new HPExpireCommand(args, this.opts).exec(this.client);
|
|
3977
|
+
/**
|
|
3978
|
+
* @see https://redis.io/commands/hpexpireat
|
|
3979
|
+
*/
|
|
3980
|
+
hpexpireat = (...args) => new HPExpireAtCommand(args, this.opts).exec(this.client);
|
|
3981
|
+
/**
|
|
3982
|
+
* @see https://redis.io/commands/hpexpiretime
|
|
3983
|
+
*/
|
|
3984
|
+
hpexpiretime = (...args) => new HPExpireTimeCommand(args, this.opts).exec(this.client);
|
|
3985
|
+
/**
|
|
3986
|
+
* @see https://redis.io/commands/hpttl
|
|
3987
|
+
*/
|
|
3988
|
+
hpttl = (...args) => new HPTtlCommand(args, this.opts).exec(this.client);
|
|
3989
|
+
/**
|
|
3990
|
+
* @see https://redis.io/commands/hpersist
|
|
3991
|
+
*/
|
|
3992
|
+
hpersist = (...args) => new HPersistCommand(args, this.opts).exec(this.client);
|
|
3326
3993
|
/**
|
|
3327
3994
|
* @see https://redis.io/commands/hget
|
|
3328
3995
|
*/
|
|
@@ -3491,6 +4158,13 @@ var Redis = class {
|
|
|
3491
4158
|
* @see https://redis.io/commands/psetex
|
|
3492
4159
|
*/
|
|
3493
4160
|
psetex = (key, ttl, value) => new PSetEXCommand([key, ttl, value], this.opts).exec(this.client);
|
|
4161
|
+
/**
|
|
4162
|
+
* @see https://redis.io/commands/psubscribe
|
|
4163
|
+
*/
|
|
4164
|
+
psubscribe = (patterns) => {
|
|
4165
|
+
const patternArray = Array.isArray(patterns) ? patterns : [patterns];
|
|
4166
|
+
return new Subscriber(this.client, patternArray, true);
|
|
4167
|
+
};
|
|
3494
4168
|
/**
|
|
3495
4169
|
* @see https://redis.io/commands/pttl
|
|
3496
4170
|
*/
|
|
@@ -3527,10 +4201,9 @@ var Redis = class {
|
|
|
3527
4201
|
* @see https://redis.io/commands/sadd
|
|
3528
4202
|
*/
|
|
3529
4203
|
sadd = (key, member, ...members) => new SAddCommand([key, member, ...members], this.opts).exec(this.client);
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
scan = (...args) => new ScanCommand(args, this.opts).exec(this.client);
|
|
4204
|
+
scan(cursor, opts) {
|
|
4205
|
+
return new ScanCommand([cursor, opts], this.opts).exec(this.client);
|
|
4206
|
+
}
|
|
3534
4207
|
/**
|
|
3535
4208
|
* @see https://redis.io/commands/scard
|
|
3536
4209
|
*/
|
|
@@ -3619,6 +4292,13 @@ var Redis = class {
|
|
|
3619
4292
|
* @see https://redis.io/commands/strlen
|
|
3620
4293
|
*/
|
|
3621
4294
|
strlen = (...args) => new StrLenCommand(args, this.opts).exec(this.client);
|
|
4295
|
+
/**
|
|
4296
|
+
* @see https://redis.io/commands/subscribe
|
|
4297
|
+
*/
|
|
4298
|
+
subscribe = (channels) => {
|
|
4299
|
+
const channelArray = Array.isArray(channels) ? channels : [channels];
|
|
4300
|
+
return new Subscriber(this.client, channelArray);
|
|
4301
|
+
};
|
|
3622
4302
|
/**
|
|
3623
4303
|
* @see https://redis.io/commands/sunion
|
|
3624
4304
|
*/
|