@upstash/redis 1.35.0-canary → 1.35.0
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/{dist/chunk-Q4ZBDYYE.mjs → chunk-QZ3IMTW7.mjs} +775 -86
- package/cloudflare.d.mts +55 -0
- package/cloudflare.d.ts +55 -0
- package/{dist/cloudflare.js → cloudflare.js} +789 -108
- package/{dist/cloudflare.mjs → cloudflare.mjs} +15 -13
- package/fastly.d.mts +48 -0
- package/fastly.d.ts +48 -0
- package/{dist/fastly.js → fastly.js} +785 -104
- package/{dist/fastly.mjs → fastly.mjs} +11 -9
- package/nodejs.d.mts +73 -0
- package/nodejs.d.ts +73 -0
- package/{dist/nodejs.js → nodejs.js} +792 -110
- package/{dist/nodejs.mjs → nodejs.mjs} +18 -15
- package/package.json +1 -1
- package/{dist/zmscore-BhX8yEQc.d.mts → zmscore-DzNHSWxc.d.mts} +575 -46
- package/{dist/zmscore-BhX8yEQc.d.ts → zmscore-DzNHSWxc.d.ts} +575 -46
- package/dist/cloudflare.d.mts +0 -55
- package/dist/cloudflare.d.ts +0 -55
- package/dist/fastly.d.mts +0 -48
- package/dist/fastly.d.ts +0 -48
- package/dist/nodejs.d.mts +0 -73
- package/dist/nodejs.d.ts +0 -73
|
@@ -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/fastly.ts
|
|
@@ -50,12 +40,57 @@ var UpstashError = class extends Error {
|
|
|
50
40
|
var UrlError = class extends Error {
|
|
51
41
|
constructor(url) {
|
|
52
42
|
super(
|
|
53
|
-
`Upstash Redis client was passed an invalid URL. You should pass
|
|
43
|
+
`Upstash Redis client was passed an invalid URL. You should pass a URL starting with https. Received: "${url}". `
|
|
54
44
|
);
|
|
55
45
|
this.name = "UrlError";
|
|
56
46
|
}
|
|
57
47
|
};
|
|
58
48
|
|
|
49
|
+
// pkg/util.ts
|
|
50
|
+
function parseRecursive(obj) {
|
|
51
|
+
const parsed = Array.isArray(obj) ? obj.map((o) => {
|
|
52
|
+
try {
|
|
53
|
+
return parseRecursive(o);
|
|
54
|
+
} catch {
|
|
55
|
+
return o;
|
|
56
|
+
}
|
|
57
|
+
}) : JSON.parse(obj);
|
|
58
|
+
if (typeof parsed === "number" && parsed.toString() !== obj) {
|
|
59
|
+
return obj;
|
|
60
|
+
}
|
|
61
|
+
return parsed;
|
|
62
|
+
}
|
|
63
|
+
function parseResponse(result) {
|
|
64
|
+
try {
|
|
65
|
+
return parseRecursive(result);
|
|
66
|
+
} catch {
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function deserializeScanResponse(result) {
|
|
71
|
+
return [result[0], ...parseResponse(result.slice(1))];
|
|
72
|
+
}
|
|
73
|
+
function deserializeScanWithTypesResponse(result) {
|
|
74
|
+
const [cursor, keys] = result;
|
|
75
|
+
const parsedKeys = [];
|
|
76
|
+
for (let i = 0; i < keys.length; i += 2) {
|
|
77
|
+
parsedKeys.push({ key: keys[i], type: keys[i + 1] });
|
|
78
|
+
}
|
|
79
|
+
return [cursor, parsedKeys];
|
|
80
|
+
}
|
|
81
|
+
function mergeHeaders(...headers) {
|
|
82
|
+
const merged = {};
|
|
83
|
+
for (const header of headers) {
|
|
84
|
+
if (!header) continue;
|
|
85
|
+
for (const [key, value] of Object.entries(header)) {
|
|
86
|
+
if (value !== void 0 && value !== null) {
|
|
87
|
+
merged[key] = value;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return merged;
|
|
92
|
+
}
|
|
93
|
+
|
|
59
94
|
// pkg/http.ts
|
|
60
95
|
var HttpClient = class {
|
|
61
96
|
baseUrl;
|
|
@@ -63,6 +98,7 @@ var HttpClient = class {
|
|
|
63
98
|
options;
|
|
64
99
|
readYourWrites;
|
|
65
100
|
upstashSyncToken = "";
|
|
101
|
+
hasCredentials;
|
|
66
102
|
retry;
|
|
67
103
|
constructor(config) {
|
|
68
104
|
this.options = {
|
|
@@ -76,15 +112,16 @@ var HttpClient = class {
|
|
|
76
112
|
};
|
|
77
113
|
this.upstashSyncToken = "";
|
|
78
114
|
this.readYourWrites = config.readYourWrites ?? true;
|
|
79
|
-
this.baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
115
|
+
this.baseUrl = (config.baseUrl || "").replace(/\/$/, "");
|
|
80
116
|
const urlRegex = /^https?:\/\/[^\s#$./?].\S*$/;
|
|
81
|
-
if (!urlRegex.test(this.baseUrl)) {
|
|
117
|
+
if (this.baseUrl && !urlRegex.test(this.baseUrl)) {
|
|
82
118
|
throw new UrlError(this.baseUrl);
|
|
83
119
|
}
|
|
84
120
|
this.headers = {
|
|
85
121
|
"Content-Type": "application/json",
|
|
86
122
|
...config.headers
|
|
87
123
|
};
|
|
124
|
+
this.hasCredentials = Boolean(this.baseUrl && this.headers.authorization.split(" ")[1]);
|
|
88
125
|
if (this.options.responseEncoding === "base64") {
|
|
89
126
|
this.headers["Upstash-Encoding"] = "base64";
|
|
90
127
|
}
|
|
@@ -102,20 +139,28 @@ var HttpClient = class {
|
|
|
102
139
|
this.headers = merge(this.headers, "Upstash-Telemetry-Sdk", telemetry.sdk);
|
|
103
140
|
}
|
|
104
141
|
async request(req) {
|
|
142
|
+
const requestHeaders = mergeHeaders(this.headers, req.headers ?? {});
|
|
143
|
+
const requestUrl = [this.baseUrl, ...req.path ?? []].join("/");
|
|
144
|
+
const isEventStream = requestHeaders.Accept === "text/event-stream";
|
|
105
145
|
const requestOptions = {
|
|
106
146
|
//@ts-expect-error this should throw due to bun regression
|
|
107
147
|
cache: this.options.cache,
|
|
108
148
|
method: "POST",
|
|
109
|
-
headers:
|
|
149
|
+
headers: requestHeaders,
|
|
110
150
|
body: JSON.stringify(req.body),
|
|
111
151
|
keepalive: this.options.keepAlive,
|
|
112
152
|
agent: this.options.agent,
|
|
113
|
-
signal: this.options.signal,
|
|
153
|
+
signal: req.signal ?? this.options.signal,
|
|
114
154
|
/**
|
|
115
155
|
* Fastly specific
|
|
116
156
|
*/
|
|
117
157
|
backend: this.options.backend
|
|
118
158
|
};
|
|
159
|
+
if (!this.hasCredentials) {
|
|
160
|
+
console.warn(
|
|
161
|
+
"[Upstash Redis] Redis client was initialized without url or token. Failed to execute command."
|
|
162
|
+
);
|
|
163
|
+
}
|
|
119
164
|
if (this.readYourWrites) {
|
|
120
165
|
const newHeader = this.upstashSyncToken;
|
|
121
166
|
this.headers["upstash-sync-token"] = newHeader;
|
|
@@ -124,7 +169,7 @@ var HttpClient = class {
|
|
|
124
169
|
let error = null;
|
|
125
170
|
for (let i = 0; i <= this.retry.attempts; i++) {
|
|
126
171
|
try {
|
|
127
|
-
res = await fetch(
|
|
172
|
+
res = await fetch(requestUrl, requestOptions);
|
|
128
173
|
break;
|
|
129
174
|
} catch (error_) {
|
|
130
175
|
if (this.options.signal?.aborted) {
|
|
@@ -139,20 +184,54 @@ var HttpClient = class {
|
|
|
139
184
|
break;
|
|
140
185
|
}
|
|
141
186
|
error = error_;
|
|
142
|
-
|
|
187
|
+
if (i < this.retry.attempts) {
|
|
188
|
+
await new Promise((r) => setTimeout(r, this.retry.backoff(i)));
|
|
189
|
+
}
|
|
143
190
|
}
|
|
144
191
|
}
|
|
145
192
|
if (!res) {
|
|
146
193
|
throw error ?? new Error("Exhausted all retries");
|
|
147
194
|
}
|
|
148
|
-
const body = await res.json();
|
|
149
195
|
if (!res.ok) {
|
|
150
|
-
|
|
196
|
+
const body2 = await res.json();
|
|
197
|
+
throw new UpstashError(`${body2.error}, command was: ${JSON.stringify(req.body)}`);
|
|
151
198
|
}
|
|
152
199
|
if (this.readYourWrites) {
|
|
153
200
|
const headers = res.headers;
|
|
154
201
|
this.upstashSyncToken = headers.get("upstash-sync-token") ?? "";
|
|
155
202
|
}
|
|
203
|
+
if (isEventStream && req && req.onMessage && res.body) {
|
|
204
|
+
const reader = res.body.getReader();
|
|
205
|
+
const decoder = new TextDecoder();
|
|
206
|
+
(async () => {
|
|
207
|
+
try {
|
|
208
|
+
while (true) {
|
|
209
|
+
const { value, done } = await reader.read();
|
|
210
|
+
if (done) break;
|
|
211
|
+
const chunk = decoder.decode(value);
|
|
212
|
+
const lines = chunk.split("\n");
|
|
213
|
+
for (const line of lines) {
|
|
214
|
+
if (line.startsWith("data: ")) {
|
|
215
|
+
const data = line.slice(6);
|
|
216
|
+
req.onMessage?.(data);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
} catch (error2) {
|
|
221
|
+
if (error2 instanceof Error && error2.name === "AbortError") {
|
|
222
|
+
} else {
|
|
223
|
+
console.error("Stream reading error:", error2);
|
|
224
|
+
}
|
|
225
|
+
} finally {
|
|
226
|
+
try {
|
|
227
|
+
await reader.cancel();
|
|
228
|
+
} catch {
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
})();
|
|
232
|
+
return { result: 1 };
|
|
233
|
+
}
|
|
234
|
+
const body = await res.json();
|
|
156
235
|
if (this.readYourWrites) {
|
|
157
236
|
const headers = res.headers;
|
|
158
237
|
this.upstashSyncToken = headers.get("upstash-sync-token") ?? "";
|
|
@@ -224,6 +303,23 @@ function merge(obj, key, value) {
|
|
|
224
303
|
}
|
|
225
304
|
|
|
226
305
|
// pkg/auto-pipeline.ts
|
|
306
|
+
var EXCLUDE_COMMANDS = /* @__PURE__ */ new Set([
|
|
307
|
+
"scan",
|
|
308
|
+
"keys",
|
|
309
|
+
"flushdb",
|
|
310
|
+
"flushall",
|
|
311
|
+
"dbsize",
|
|
312
|
+
"hscan",
|
|
313
|
+
"hgetall",
|
|
314
|
+
"hkeys",
|
|
315
|
+
"lrange",
|
|
316
|
+
"sscan",
|
|
317
|
+
"smembers",
|
|
318
|
+
"xrange",
|
|
319
|
+
"xrevrange",
|
|
320
|
+
"zscan",
|
|
321
|
+
"zrange"
|
|
322
|
+
]);
|
|
227
323
|
function createAutoPipelineProxy(_redis, json) {
|
|
228
324
|
const redis = _redis;
|
|
229
325
|
if (!redis.autoPipelineExecutor) {
|
|
@@ -238,7 +334,8 @@ function createAutoPipelineProxy(_redis, json) {
|
|
|
238
334
|
return createAutoPipelineProxy(redis2, true);
|
|
239
335
|
}
|
|
240
336
|
const commandInRedisButNotPipeline = command in redis2 && !(command in redis2.autoPipelineExecutor.pipeline);
|
|
241
|
-
|
|
337
|
+
const isCommandExcluded = EXCLUDE_COMMANDS.has(command);
|
|
338
|
+
if (commandInRedisButNotPipeline || isCommandExcluded) {
|
|
242
339
|
return redis2[command];
|
|
243
340
|
}
|
|
244
341
|
const isFunction = json ? typeof redis2.autoPipelineExecutor.pipeline.json[command] === "function" : typeof redis2.autoPipelineExecutor.pipeline[command] === "function";
|
|
@@ -282,7 +379,7 @@ var AutoPipelineExecutor = class {
|
|
|
282
379
|
executeWithPipeline(pipeline);
|
|
283
380
|
const pipelineDone = this.deferExecution().then(() => {
|
|
284
381
|
if (!this.pipelinePromises.has(pipeline)) {
|
|
285
|
-
const pipelinePromise = pipeline.exec();
|
|
382
|
+
const pipelinePromise = pipeline.exec({ keepErrors: true });
|
|
286
383
|
this.pipelineCounter += 1;
|
|
287
384
|
this.pipelinePromises.set(pipeline, pipelinePromise);
|
|
288
385
|
this.activePipeline = null;
|
|
@@ -290,7 +387,11 @@ var AutoPipelineExecutor = class {
|
|
|
290
387
|
return this.pipelinePromises.get(pipeline);
|
|
291
388
|
});
|
|
292
389
|
const results = await pipelineDone;
|
|
293
|
-
|
|
390
|
+
const commandResult = results[index];
|
|
391
|
+
if (commandResult.error) {
|
|
392
|
+
throw new UpstashError(`Command failed: ${commandResult.error}`);
|
|
393
|
+
}
|
|
394
|
+
return commandResult.result;
|
|
294
395
|
}
|
|
295
396
|
async deferExecution() {
|
|
296
397
|
await Promise.resolve();
|
|
@@ -298,31 +399,6 @@ var AutoPipelineExecutor = class {
|
|
|
298
399
|
}
|
|
299
400
|
};
|
|
300
401
|
|
|
301
|
-
// pkg/util.ts
|
|
302
|
-
function parseRecursive(obj) {
|
|
303
|
-
const parsed = Array.isArray(obj) ? obj.map((o) => {
|
|
304
|
-
try {
|
|
305
|
-
return parseRecursive(o);
|
|
306
|
-
} catch {
|
|
307
|
-
return o;
|
|
308
|
-
}
|
|
309
|
-
}) : JSON.parse(obj);
|
|
310
|
-
if (typeof parsed === "number" && parsed.toString() !== obj) {
|
|
311
|
-
return obj;
|
|
312
|
-
}
|
|
313
|
-
return parsed;
|
|
314
|
-
}
|
|
315
|
-
function parseResponse(result) {
|
|
316
|
-
try {
|
|
317
|
-
return parseRecursive(result);
|
|
318
|
-
} catch {
|
|
319
|
-
return result;
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
function deserializeScanResponse(result) {
|
|
323
|
-
return [result[0], ...parseResponse(result.slice(1))];
|
|
324
|
-
}
|
|
325
|
-
|
|
326
402
|
// pkg/commands/command.ts
|
|
327
403
|
var defaultSerializer = (c) => {
|
|
328
404
|
switch (typeof c) {
|
|
@@ -340,6 +416,11 @@ var Command = class {
|
|
|
340
416
|
command;
|
|
341
417
|
serialize;
|
|
342
418
|
deserialize;
|
|
419
|
+
headers;
|
|
420
|
+
path;
|
|
421
|
+
onMessage;
|
|
422
|
+
isStreaming;
|
|
423
|
+
signal;
|
|
343
424
|
/**
|
|
344
425
|
* Create a new command instance.
|
|
345
426
|
*
|
|
@@ -349,6 +430,11 @@ var Command = class {
|
|
|
349
430
|
this.serialize = defaultSerializer;
|
|
350
431
|
this.deserialize = opts?.automaticDeserialization === void 0 || opts.automaticDeserialization ? opts?.deserialize ?? parseResponse : (x) => x;
|
|
351
432
|
this.command = command.map((c) => this.serialize(c));
|
|
433
|
+
this.headers = opts?.headers;
|
|
434
|
+
this.path = opts?.path;
|
|
435
|
+
this.onMessage = opts?.streamOptions?.onMessage;
|
|
436
|
+
this.isStreaming = opts?.streamOptions?.isStreaming ?? false;
|
|
437
|
+
this.signal = opts?.streamOptions?.signal;
|
|
352
438
|
if (opts?.latencyLogging) {
|
|
353
439
|
const originalExec = this.exec.bind(this);
|
|
354
440
|
this.exec = async (client) => {
|
|
@@ -369,7 +455,12 @@ var Command = class {
|
|
|
369
455
|
async exec(client) {
|
|
370
456
|
const { result, error } = await client.request({
|
|
371
457
|
body: this.command,
|
|
372
|
-
|
|
458
|
+
path: this.path,
|
|
459
|
+
upstashSyncToken: client.upstashSyncToken,
|
|
460
|
+
headers: this.headers,
|
|
461
|
+
onMessage: this.onMessage,
|
|
462
|
+
isStreaming: this.isStreaming,
|
|
463
|
+
signal: this.signal
|
|
373
464
|
});
|
|
374
465
|
if (error) {
|
|
375
466
|
throw new UpstashError(error);
|
|
@@ -497,6 +588,13 @@ var EchoCommand = class extends Command {
|
|
|
497
588
|
}
|
|
498
589
|
};
|
|
499
590
|
|
|
591
|
+
// pkg/commands/evalRo.ts
|
|
592
|
+
var EvalROCommand = class extends Command {
|
|
593
|
+
constructor([script, keys, args], opts) {
|
|
594
|
+
super(["eval_ro", script, keys.length, ...keys, ...args ?? []], opts);
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
|
|
500
598
|
// pkg/commands/eval.ts
|
|
501
599
|
var EvalCommand = class extends Command {
|
|
502
600
|
constructor([script, keys, args], opts) {
|
|
@@ -504,6 +602,13 @@ var EvalCommand = class extends Command {
|
|
|
504
602
|
}
|
|
505
603
|
};
|
|
506
604
|
|
|
605
|
+
// pkg/commands/evalshaRo.ts
|
|
606
|
+
var EvalshaROCommand = class extends Command {
|
|
607
|
+
constructor([sha, keys, args], opts) {
|
|
608
|
+
super(["evalsha_ro", sha, keys.length, ...keys, ...args ?? []], opts);
|
|
609
|
+
}
|
|
610
|
+
};
|
|
611
|
+
|
|
507
612
|
// pkg/commands/evalsha.ts
|
|
508
613
|
var EvalshaCommand = class extends Command {
|
|
509
614
|
constructor([sha, keys, args], opts) {
|
|
@@ -511,6 +616,14 @@ var EvalshaCommand = class extends Command {
|
|
|
511
616
|
}
|
|
512
617
|
};
|
|
513
618
|
|
|
619
|
+
// pkg/commands/exec.ts
|
|
620
|
+
var ExecCommand = class extends Command {
|
|
621
|
+
constructor(cmd, opts) {
|
|
622
|
+
const normalizedCmd = cmd.map((arg) => typeof arg === "string" ? arg : String(arg));
|
|
623
|
+
super(normalizedCmd, opts);
|
|
624
|
+
}
|
|
625
|
+
};
|
|
626
|
+
|
|
514
627
|
// pkg/commands/exists.ts
|
|
515
628
|
var ExistsCommand = class extends Command {
|
|
516
629
|
constructor(cmd, opts) {
|
|
@@ -727,6 +840,27 @@ var GetDelCommand = class extends Command {
|
|
|
727
840
|
}
|
|
728
841
|
};
|
|
729
842
|
|
|
843
|
+
// pkg/commands/getex.ts
|
|
844
|
+
var GetExCommand = class extends Command {
|
|
845
|
+
constructor([key, opts], cmdOpts) {
|
|
846
|
+
const command = ["getex", key];
|
|
847
|
+
if (opts) {
|
|
848
|
+
if ("ex" in opts && typeof opts.ex === "number") {
|
|
849
|
+
command.push("ex", opts.ex);
|
|
850
|
+
} else if ("px" in opts && typeof opts.px === "number") {
|
|
851
|
+
command.push("px", opts.px);
|
|
852
|
+
} else if ("exat" in opts && typeof opts.exat === "number") {
|
|
853
|
+
command.push("exat", opts.exat);
|
|
854
|
+
} else if ("pxat" in opts && typeof opts.pxat === "number") {
|
|
855
|
+
command.push("pxat", opts.pxat);
|
|
856
|
+
} else if ("persist" in opts && opts.persist) {
|
|
857
|
+
command.push("persist");
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
super(command, cmdOpts);
|
|
861
|
+
}
|
|
862
|
+
};
|
|
863
|
+
|
|
730
864
|
// pkg/commands/getrange.ts
|
|
731
865
|
var GetRangeCommand = class extends Command {
|
|
732
866
|
constructor(cmd, opts) {
|
|
@@ -755,6 +889,122 @@ var HExistsCommand = class extends Command {
|
|
|
755
889
|
}
|
|
756
890
|
};
|
|
757
891
|
|
|
892
|
+
// pkg/commands/hexpire.ts
|
|
893
|
+
var HExpireCommand = class extends Command {
|
|
894
|
+
constructor(cmd, opts) {
|
|
895
|
+
const [key, fields, seconds, option] = cmd;
|
|
896
|
+
const fieldArray = Array.isArray(fields) ? fields : [fields];
|
|
897
|
+
super(
|
|
898
|
+
[
|
|
899
|
+
"hexpire",
|
|
900
|
+
key,
|
|
901
|
+
seconds,
|
|
902
|
+
...option ? [option] : [],
|
|
903
|
+
"FIELDS",
|
|
904
|
+
fieldArray.length,
|
|
905
|
+
...fieldArray
|
|
906
|
+
],
|
|
907
|
+
opts
|
|
908
|
+
);
|
|
909
|
+
}
|
|
910
|
+
};
|
|
911
|
+
|
|
912
|
+
// pkg/commands/hexpireat.ts
|
|
913
|
+
var HExpireAtCommand = class extends Command {
|
|
914
|
+
constructor(cmd, opts) {
|
|
915
|
+
const [key, fields, timestamp, option] = cmd;
|
|
916
|
+
const fieldArray = Array.isArray(fields) ? fields : [fields];
|
|
917
|
+
super(
|
|
918
|
+
[
|
|
919
|
+
"hexpireat",
|
|
920
|
+
key,
|
|
921
|
+
timestamp,
|
|
922
|
+
...option ? [option] : [],
|
|
923
|
+
"FIELDS",
|
|
924
|
+
fieldArray.length,
|
|
925
|
+
...fieldArray
|
|
926
|
+
],
|
|
927
|
+
opts
|
|
928
|
+
);
|
|
929
|
+
}
|
|
930
|
+
};
|
|
931
|
+
|
|
932
|
+
// pkg/commands/hexpiretime.ts
|
|
933
|
+
var HExpireTimeCommand = class extends Command {
|
|
934
|
+
constructor(cmd, opts) {
|
|
935
|
+
const [key, fields] = cmd;
|
|
936
|
+
const fieldArray = Array.isArray(fields) ? fields : [fields];
|
|
937
|
+
super(["hexpiretime", key, "FIELDS", fieldArray.length, ...fieldArray], opts);
|
|
938
|
+
}
|
|
939
|
+
};
|
|
940
|
+
|
|
941
|
+
// pkg/commands/hpersist.ts
|
|
942
|
+
var HPersistCommand = class extends Command {
|
|
943
|
+
constructor(cmd, opts) {
|
|
944
|
+
const [key, fields] = cmd;
|
|
945
|
+
const fieldArray = Array.isArray(fields) ? fields : [fields];
|
|
946
|
+
super(["hpersist", key, "FIELDS", fieldArray.length, ...fieldArray], opts);
|
|
947
|
+
}
|
|
948
|
+
};
|
|
949
|
+
|
|
950
|
+
// pkg/commands/hpexpire.ts
|
|
951
|
+
var HPExpireCommand = class extends Command {
|
|
952
|
+
constructor(cmd, opts) {
|
|
953
|
+
const [key, fields, milliseconds, option] = cmd;
|
|
954
|
+
const fieldArray = Array.isArray(fields) ? fields : [fields];
|
|
955
|
+
super(
|
|
956
|
+
[
|
|
957
|
+
"hpexpire",
|
|
958
|
+
key,
|
|
959
|
+
milliseconds,
|
|
960
|
+
...option ? [option] : [],
|
|
961
|
+
"FIELDS",
|
|
962
|
+
fieldArray.length,
|
|
963
|
+
...fieldArray
|
|
964
|
+
],
|
|
965
|
+
opts
|
|
966
|
+
);
|
|
967
|
+
}
|
|
968
|
+
};
|
|
969
|
+
|
|
970
|
+
// pkg/commands/hpexpireat.ts
|
|
971
|
+
var HPExpireAtCommand = class extends Command {
|
|
972
|
+
constructor(cmd, opts) {
|
|
973
|
+
const [key, fields, timestamp, option] = cmd;
|
|
974
|
+
const fieldArray = Array.isArray(fields) ? fields : [fields];
|
|
975
|
+
super(
|
|
976
|
+
[
|
|
977
|
+
"hpexpireat",
|
|
978
|
+
key,
|
|
979
|
+
timestamp,
|
|
980
|
+
...option ? [option] : [],
|
|
981
|
+
"FIELDS",
|
|
982
|
+
fieldArray.length,
|
|
983
|
+
...fieldArray
|
|
984
|
+
],
|
|
985
|
+
opts
|
|
986
|
+
);
|
|
987
|
+
}
|
|
988
|
+
};
|
|
989
|
+
|
|
990
|
+
// pkg/commands/hpexpiretime.ts
|
|
991
|
+
var HPExpireTimeCommand = class extends Command {
|
|
992
|
+
constructor(cmd, opts) {
|
|
993
|
+
const [key, fields] = cmd;
|
|
994
|
+
const fieldArray = Array.isArray(fields) ? fields : [fields];
|
|
995
|
+
super(["hpexpiretime", key, "FIELDS", fieldArray.length, ...fieldArray], opts);
|
|
996
|
+
}
|
|
997
|
+
};
|
|
998
|
+
|
|
999
|
+
// pkg/commands/hpttl.ts
|
|
1000
|
+
var HPTtlCommand = class extends Command {
|
|
1001
|
+
constructor(cmd, opts) {
|
|
1002
|
+
const [key, fields] = cmd;
|
|
1003
|
+
const fieldArray = Array.isArray(fields) ? fields : [fields];
|
|
1004
|
+
super(["hpttl", key, "FIELDS", fieldArray.length, ...fieldArray], opts);
|
|
1005
|
+
}
|
|
1006
|
+
};
|
|
1007
|
+
|
|
758
1008
|
// pkg/commands/hget.ts
|
|
759
1009
|
var HGetCommand = class extends Command {
|
|
760
1010
|
constructor(cmd, opts) {
|
|
@@ -768,9 +1018,9 @@ function deserialize(result) {
|
|
|
768
1018
|
return null;
|
|
769
1019
|
}
|
|
770
1020
|
const obj = {};
|
|
771
|
-
|
|
772
|
-
const key = result
|
|
773
|
-
const value = result
|
|
1021
|
+
for (let i = 0; i < result.length; i += 2) {
|
|
1022
|
+
const key = result[i];
|
|
1023
|
+
const value = result[i + 1];
|
|
774
1024
|
try {
|
|
775
1025
|
const valueIsNumberAndNotSafeInteger = !Number.isNaN(Number(value)) && !Number.isSafeInteger(Number(value));
|
|
776
1026
|
obj[key] = valueIsNumberAndNotSafeInteger ? value : JSON.parse(value);
|
|
@@ -854,9 +1104,9 @@ function deserialize3(result) {
|
|
|
854
1104
|
return null;
|
|
855
1105
|
}
|
|
856
1106
|
const obj = {};
|
|
857
|
-
|
|
858
|
-
const key = result
|
|
859
|
-
const value = result
|
|
1107
|
+
for (let i = 0; i < result.length; i += 2) {
|
|
1108
|
+
const key = result[i];
|
|
1109
|
+
const value = result[i + 1];
|
|
860
1110
|
try {
|
|
861
1111
|
obj[key] = JSON.parse(value);
|
|
862
1112
|
} catch {
|
|
@@ -920,6 +1170,15 @@ var HStrLenCommand = class extends Command {
|
|
|
920
1170
|
}
|
|
921
1171
|
};
|
|
922
1172
|
|
|
1173
|
+
// pkg/commands/httl.ts
|
|
1174
|
+
var HTtlCommand = class extends Command {
|
|
1175
|
+
constructor(cmd, opts) {
|
|
1176
|
+
const [key, fields] = cmd;
|
|
1177
|
+
const fieldArray = Array.isArray(fields) ? fields : [fields];
|
|
1178
|
+
super(["httl", key, "FIELDS", fieldArray.length, ...fieldArray], opts);
|
|
1179
|
+
}
|
|
1180
|
+
};
|
|
1181
|
+
|
|
923
1182
|
// pkg/commands/hvals.ts
|
|
924
1183
|
var HValsCommand = class extends Command {
|
|
925
1184
|
constructor(cmd, opts) {
|
|
@@ -1039,6 +1298,14 @@ var JsonGetCommand = class extends Command {
|
|
|
1039
1298
|
}
|
|
1040
1299
|
};
|
|
1041
1300
|
|
|
1301
|
+
// pkg/commands/json_merge.ts
|
|
1302
|
+
var JsonMergeCommand = class extends Command {
|
|
1303
|
+
constructor(cmd, opts) {
|
|
1304
|
+
const command = ["JSON.MERGE", ...cmd];
|
|
1305
|
+
super(command, opts);
|
|
1306
|
+
}
|
|
1307
|
+
};
|
|
1308
|
+
|
|
1042
1309
|
// pkg/commands/json_mget.ts
|
|
1043
1310
|
var JsonMGetCommand = class extends Command {
|
|
1044
1311
|
constructor(cmd, opts) {
|
|
@@ -1399,11 +1666,14 @@ var ScanCommand = class extends Command {
|
|
|
1399
1666
|
if (typeof opts?.count === "number") {
|
|
1400
1667
|
command.push("count", opts.count);
|
|
1401
1668
|
}
|
|
1402
|
-
if (opts
|
|
1669
|
+
if (opts && "withType" in opts && opts.withType === true) {
|
|
1670
|
+
command.push("withtype");
|
|
1671
|
+
} else if (opts && "type" in opts && opts.type && opts.type.length > 0) {
|
|
1403
1672
|
command.push("type", opts.type);
|
|
1404
1673
|
}
|
|
1405
1674
|
super(command, {
|
|
1406
|
-
|
|
1675
|
+
// @ts-expect-error ignore types here
|
|
1676
|
+
deserialize: opts?.withType ? deserializeScanWithTypesResponse : deserializeScanResponse,
|
|
1407
1677
|
...cmdOpts
|
|
1408
1678
|
});
|
|
1409
1679
|
}
|
|
@@ -1829,15 +2099,15 @@ var XPendingCommand = class extends Command {
|
|
|
1829
2099
|
function deserialize4(result) {
|
|
1830
2100
|
const obj = {};
|
|
1831
2101
|
for (const e of result) {
|
|
1832
|
-
|
|
1833
|
-
const streamId = e
|
|
1834
|
-
const entries = e
|
|
2102
|
+
for (let i = 0; i < e.length; i += 2) {
|
|
2103
|
+
const streamId = e[i];
|
|
2104
|
+
const entries = e[i + 1];
|
|
1835
2105
|
if (!(streamId in obj)) {
|
|
1836
2106
|
obj[streamId] = {};
|
|
1837
2107
|
}
|
|
1838
|
-
|
|
1839
|
-
const field = entries
|
|
1840
|
-
const value = entries
|
|
2108
|
+
for (let j = 0; j < entries.length; j += 2) {
|
|
2109
|
+
const field = entries[j];
|
|
2110
|
+
const value = entries[j + 1];
|
|
1841
2111
|
try {
|
|
1842
2112
|
obj[streamId][field] = JSON.parse(value);
|
|
1843
2113
|
} catch {
|
|
@@ -1926,15 +2196,15 @@ var XRevRangeCommand = class extends Command {
|
|
|
1926
2196
|
function deserialize5(result) {
|
|
1927
2197
|
const obj = {};
|
|
1928
2198
|
for (const e of result) {
|
|
1929
|
-
|
|
1930
|
-
const streamId = e
|
|
1931
|
-
const entries = e
|
|
2199
|
+
for (let i = 0; i < e.length; i += 2) {
|
|
2200
|
+
const streamId = e[i];
|
|
2201
|
+
const entries = e[i + 1];
|
|
1932
2202
|
if (!(streamId in obj)) {
|
|
1933
2203
|
obj[streamId] = {};
|
|
1934
2204
|
}
|
|
1935
|
-
|
|
1936
|
-
const field = entries
|
|
1937
|
-
const value = entries
|
|
2205
|
+
for (let j = 0; j < entries.length; j += 2) {
|
|
2206
|
+
const field = entries[j];
|
|
2207
|
+
const value = entries[j + 1];
|
|
1938
2208
|
try {
|
|
1939
2209
|
obj[streamId][field] = JSON.parse(value);
|
|
1940
2210
|
} catch {
|
|
@@ -2193,6 +2463,183 @@ var ZUnionStoreCommand = class extends Command {
|
|
|
2193
2463
|
}
|
|
2194
2464
|
};
|
|
2195
2465
|
|
|
2466
|
+
// pkg/commands/psubscribe.ts
|
|
2467
|
+
var PSubscribeCommand = class extends Command {
|
|
2468
|
+
constructor(cmd, opts) {
|
|
2469
|
+
const sseHeaders = {
|
|
2470
|
+
Accept: "text/event-stream",
|
|
2471
|
+
"Cache-Control": "no-cache",
|
|
2472
|
+
Connection: "keep-alive"
|
|
2473
|
+
};
|
|
2474
|
+
super([], {
|
|
2475
|
+
...opts,
|
|
2476
|
+
headers: sseHeaders,
|
|
2477
|
+
path: ["psubscribe", ...cmd],
|
|
2478
|
+
streamOptions: {
|
|
2479
|
+
isStreaming: true,
|
|
2480
|
+
onMessage: opts?.streamOptions?.onMessage,
|
|
2481
|
+
signal: opts?.streamOptions?.signal
|
|
2482
|
+
}
|
|
2483
|
+
});
|
|
2484
|
+
}
|
|
2485
|
+
};
|
|
2486
|
+
|
|
2487
|
+
// pkg/commands/subscribe.ts
|
|
2488
|
+
var Subscriber = class extends EventTarget {
|
|
2489
|
+
subscriptions;
|
|
2490
|
+
client;
|
|
2491
|
+
listeners;
|
|
2492
|
+
constructor(client, channels, isPattern = false) {
|
|
2493
|
+
super();
|
|
2494
|
+
this.client = client;
|
|
2495
|
+
this.subscriptions = /* @__PURE__ */ new Map();
|
|
2496
|
+
this.listeners = /* @__PURE__ */ new Map();
|
|
2497
|
+
for (const channel of channels) {
|
|
2498
|
+
if (isPattern) {
|
|
2499
|
+
this.subscribeToPattern(channel);
|
|
2500
|
+
} else {
|
|
2501
|
+
this.subscribeToChannel(channel);
|
|
2502
|
+
}
|
|
2503
|
+
}
|
|
2504
|
+
}
|
|
2505
|
+
subscribeToChannel(channel) {
|
|
2506
|
+
const controller = new AbortController();
|
|
2507
|
+
const command = new SubscribeCommand([channel], {
|
|
2508
|
+
streamOptions: {
|
|
2509
|
+
signal: controller.signal,
|
|
2510
|
+
onMessage: (data) => this.handleMessage(data, false)
|
|
2511
|
+
}
|
|
2512
|
+
});
|
|
2513
|
+
command.exec(this.client).catch((error) => {
|
|
2514
|
+
if (error.name !== "AbortError") {
|
|
2515
|
+
this.dispatchToListeners("error", error);
|
|
2516
|
+
}
|
|
2517
|
+
});
|
|
2518
|
+
this.subscriptions.set(channel, {
|
|
2519
|
+
command,
|
|
2520
|
+
controller,
|
|
2521
|
+
isPattern: false
|
|
2522
|
+
});
|
|
2523
|
+
}
|
|
2524
|
+
subscribeToPattern(pattern) {
|
|
2525
|
+
const controller = new AbortController();
|
|
2526
|
+
const command = new PSubscribeCommand([pattern], {
|
|
2527
|
+
streamOptions: {
|
|
2528
|
+
signal: controller.signal,
|
|
2529
|
+
onMessage: (data) => this.handleMessage(data, true)
|
|
2530
|
+
}
|
|
2531
|
+
});
|
|
2532
|
+
command.exec(this.client).catch((error) => {
|
|
2533
|
+
if (error.name !== "AbortError") {
|
|
2534
|
+
this.dispatchToListeners("error", error);
|
|
2535
|
+
}
|
|
2536
|
+
});
|
|
2537
|
+
this.subscriptions.set(pattern, {
|
|
2538
|
+
command,
|
|
2539
|
+
controller,
|
|
2540
|
+
isPattern: true
|
|
2541
|
+
});
|
|
2542
|
+
}
|
|
2543
|
+
handleMessage(data, isPattern) {
|
|
2544
|
+
const messageData = data.replace(/^data:\s*/, "");
|
|
2545
|
+
const firstCommaIndex = messageData.indexOf(",");
|
|
2546
|
+
const secondCommaIndex = messageData.indexOf(",", firstCommaIndex + 1);
|
|
2547
|
+
const thirdCommaIndex = isPattern ? messageData.indexOf(",", secondCommaIndex + 1) : -1;
|
|
2548
|
+
if (firstCommaIndex !== -1 && secondCommaIndex !== -1) {
|
|
2549
|
+
const type = messageData.slice(0, firstCommaIndex);
|
|
2550
|
+
if (isPattern && type === "pmessage" && thirdCommaIndex !== -1) {
|
|
2551
|
+
const pattern = messageData.slice(firstCommaIndex + 1, secondCommaIndex);
|
|
2552
|
+
const channel = messageData.slice(secondCommaIndex + 1, thirdCommaIndex);
|
|
2553
|
+
const messageStr = messageData.slice(thirdCommaIndex + 1);
|
|
2554
|
+
try {
|
|
2555
|
+
const message = JSON.parse(messageStr);
|
|
2556
|
+
this.dispatchToListeners("pmessage", { pattern, channel, message });
|
|
2557
|
+
this.dispatchToListeners(`pmessage:${pattern}`, { pattern, channel, message });
|
|
2558
|
+
} catch (error) {
|
|
2559
|
+
this.dispatchToListeners("error", new Error(`Failed to parse message: ${error}`));
|
|
2560
|
+
}
|
|
2561
|
+
} else {
|
|
2562
|
+
const channel = messageData.slice(firstCommaIndex + 1, secondCommaIndex);
|
|
2563
|
+
const messageStr = messageData.slice(secondCommaIndex + 1);
|
|
2564
|
+
try {
|
|
2565
|
+
if (type === "subscribe" || type === "psubscribe" || type === "unsubscribe" || type === "punsubscribe") {
|
|
2566
|
+
const count = Number.parseInt(messageStr);
|
|
2567
|
+
this.dispatchToListeners(type, count);
|
|
2568
|
+
} else {
|
|
2569
|
+
const message = JSON.parse(messageStr);
|
|
2570
|
+
this.dispatchToListeners(type, { channel, message });
|
|
2571
|
+
this.dispatchToListeners(`${type}:${channel}`, { channel, message });
|
|
2572
|
+
}
|
|
2573
|
+
} catch (error) {
|
|
2574
|
+
this.dispatchToListeners("error", new Error(`Failed to parse message: ${error}`));
|
|
2575
|
+
}
|
|
2576
|
+
}
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2579
|
+
dispatchToListeners(type, data) {
|
|
2580
|
+
const listeners = this.listeners.get(type);
|
|
2581
|
+
if (listeners) {
|
|
2582
|
+
for (const listener of listeners) {
|
|
2583
|
+
listener(data);
|
|
2584
|
+
}
|
|
2585
|
+
}
|
|
2586
|
+
}
|
|
2587
|
+
on(type, listener) {
|
|
2588
|
+
if (!this.listeners.has(type)) {
|
|
2589
|
+
this.listeners.set(type, /* @__PURE__ */ new Set());
|
|
2590
|
+
}
|
|
2591
|
+
this.listeners.get(type)?.add(listener);
|
|
2592
|
+
}
|
|
2593
|
+
removeAllListeners() {
|
|
2594
|
+
this.listeners.clear();
|
|
2595
|
+
}
|
|
2596
|
+
async unsubscribe(channels) {
|
|
2597
|
+
if (channels) {
|
|
2598
|
+
for (const channel of channels) {
|
|
2599
|
+
const subscription = this.subscriptions.get(channel);
|
|
2600
|
+
if (subscription) {
|
|
2601
|
+
try {
|
|
2602
|
+
subscription.controller.abort();
|
|
2603
|
+
} catch {
|
|
2604
|
+
}
|
|
2605
|
+
this.subscriptions.delete(channel);
|
|
2606
|
+
}
|
|
2607
|
+
}
|
|
2608
|
+
} else {
|
|
2609
|
+
for (const subscription of this.subscriptions.values()) {
|
|
2610
|
+
try {
|
|
2611
|
+
subscription.controller.abort();
|
|
2612
|
+
} catch {
|
|
2613
|
+
}
|
|
2614
|
+
}
|
|
2615
|
+
this.subscriptions.clear();
|
|
2616
|
+
this.removeAllListeners();
|
|
2617
|
+
}
|
|
2618
|
+
}
|
|
2619
|
+
getSubscribedChannels() {
|
|
2620
|
+
return [...this.subscriptions.keys()];
|
|
2621
|
+
}
|
|
2622
|
+
};
|
|
2623
|
+
var SubscribeCommand = class extends Command {
|
|
2624
|
+
constructor(cmd, opts) {
|
|
2625
|
+
const sseHeaders = {
|
|
2626
|
+
Accept: "text/event-stream",
|
|
2627
|
+
"Cache-Control": "no-cache",
|
|
2628
|
+
Connection: "keep-alive"
|
|
2629
|
+
};
|
|
2630
|
+
super([], {
|
|
2631
|
+
...opts,
|
|
2632
|
+
headers: sseHeaders,
|
|
2633
|
+
path: ["subscribe", ...cmd],
|
|
2634
|
+
streamOptions: {
|
|
2635
|
+
isStreaming: true,
|
|
2636
|
+
onMessage: opts?.streamOptions?.onMessage,
|
|
2637
|
+
signal: opts?.streamOptions?.signal
|
|
2638
|
+
}
|
|
2639
|
+
});
|
|
2640
|
+
}
|
|
2641
|
+
};
|
|
2642
|
+
|
|
2196
2643
|
// pkg/commands/zdiffstore.ts
|
|
2197
2644
|
var ZDiffStoreCommand = class extends Command {
|
|
2198
2645
|
constructor(cmd, opts) {
|
|
@@ -2221,9 +2668,9 @@ var Pipeline = class {
|
|
|
2221
2668
|
this.multiExec = opts.multiExec ?? false;
|
|
2222
2669
|
if (this.commandOptions?.latencyLogging) {
|
|
2223
2670
|
const originalExec = this.exec.bind(this);
|
|
2224
|
-
this.exec = async () => {
|
|
2671
|
+
this.exec = async (options) => {
|
|
2225
2672
|
const start = performance.now();
|
|
2226
|
-
const result = await originalExec();
|
|
2673
|
+
const result = await (options ? originalExec(options) : originalExec());
|
|
2227
2674
|
const end = performance.now();
|
|
2228
2675
|
const loggerResult = (end - start).toFixed(2);
|
|
2229
2676
|
console.log(
|
|
@@ -2233,19 +2680,7 @@ var Pipeline = class {
|
|
|
2233
2680
|
};
|
|
2234
2681
|
}
|
|
2235
2682
|
}
|
|
2236
|
-
|
|
2237
|
-
* Send the pipeline request to upstash.
|
|
2238
|
-
*
|
|
2239
|
-
* Returns an array with the results of all pipelined commands.
|
|
2240
|
-
*
|
|
2241
|
-
* If all commands are statically chained from start to finish, types are inferred. You can still define a return type manually if necessary though:
|
|
2242
|
-
* ```ts
|
|
2243
|
-
* const p = redis.pipeline()
|
|
2244
|
-
* p.get("key")
|
|
2245
|
-
* const result = p.exec<[{ greeting: string }]>()
|
|
2246
|
-
* ```
|
|
2247
|
-
*/
|
|
2248
|
-
exec = async () => {
|
|
2683
|
+
exec = async (options) => {
|
|
2249
2684
|
if (this.commands.length === 0) {
|
|
2250
2685
|
throw new Error("Pipeline is empty");
|
|
2251
2686
|
}
|
|
@@ -2254,7 +2689,12 @@ var Pipeline = class {
|
|
|
2254
2689
|
path,
|
|
2255
2690
|
body: Object.values(this.commands).map((c) => c.command)
|
|
2256
2691
|
});
|
|
2257
|
-
return res.map(({ error, result }, i) => {
|
|
2692
|
+
return options?.keepErrors ? res.map(({ error, result }, i) => {
|
|
2693
|
+
return {
|
|
2694
|
+
error,
|
|
2695
|
+
result: this.commands[i].deserialize(result)
|
|
2696
|
+
};
|
|
2697
|
+
}) : res.map(({ error, result }, i) => {
|
|
2258
2698
|
if (error) {
|
|
2259
2699
|
throw new UpstashError(
|
|
2260
2700
|
`Command ${i + 1} [ ${this.commands[i].command[0]} ] failed: ${error}`
|
|
@@ -2340,10 +2780,18 @@ var Pipeline = class {
|
|
|
2340
2780
|
* @see https://redis.io/commands/echo
|
|
2341
2781
|
*/
|
|
2342
2782
|
echo = (...args) => this.chain(new EchoCommand(args, this.commandOptions));
|
|
2783
|
+
/**
|
|
2784
|
+
* @see https://redis.io/commands/eval_ro
|
|
2785
|
+
*/
|
|
2786
|
+
evalRo = (...args) => this.chain(new EvalROCommand(args, this.commandOptions));
|
|
2343
2787
|
/**
|
|
2344
2788
|
* @see https://redis.io/commands/eval
|
|
2345
2789
|
*/
|
|
2346
2790
|
eval = (...args) => this.chain(new EvalCommand(args, this.commandOptions));
|
|
2791
|
+
/**
|
|
2792
|
+
* @see https://redis.io/commands/evalsha_ro
|
|
2793
|
+
*/
|
|
2794
|
+
evalshaRo = (...args) => this.chain(new EvalshaROCommand(args, this.commandOptions));
|
|
2347
2795
|
/**
|
|
2348
2796
|
* @see https://redis.io/commands/evalsha
|
|
2349
2797
|
*/
|
|
@@ -2404,6 +2852,10 @@ var Pipeline = class {
|
|
|
2404
2852
|
* @see https://redis.io/commands/getdel
|
|
2405
2853
|
*/
|
|
2406
2854
|
getdel = (...args) => this.chain(new GetDelCommand(args, this.commandOptions));
|
|
2855
|
+
/**
|
|
2856
|
+
* @see https://redis.io/commands/getex
|
|
2857
|
+
*/
|
|
2858
|
+
getex = (...args) => this.chain(new GetExCommand(args, this.commandOptions));
|
|
2407
2859
|
/**
|
|
2408
2860
|
* @see https://redis.io/commands/getrange
|
|
2409
2861
|
*/
|
|
@@ -2420,6 +2872,42 @@ var Pipeline = class {
|
|
|
2420
2872
|
* @see https://redis.io/commands/hexists
|
|
2421
2873
|
*/
|
|
2422
2874
|
hexists = (...args) => this.chain(new HExistsCommand(args, this.commandOptions));
|
|
2875
|
+
/**
|
|
2876
|
+
* @see https://redis.io/commands/hexpire
|
|
2877
|
+
*/
|
|
2878
|
+
hexpire = (...args) => this.chain(new HExpireCommand(args, this.commandOptions));
|
|
2879
|
+
/**
|
|
2880
|
+
* @see https://redis.io/commands/hexpireat
|
|
2881
|
+
*/
|
|
2882
|
+
hexpireat = (...args) => this.chain(new HExpireAtCommand(args, this.commandOptions));
|
|
2883
|
+
/**
|
|
2884
|
+
* @see https://redis.io/commands/hexpiretime
|
|
2885
|
+
*/
|
|
2886
|
+
hexpiretime = (...args) => this.chain(new HExpireTimeCommand(args, this.commandOptions));
|
|
2887
|
+
/**
|
|
2888
|
+
* @see https://redis.io/commands/httl
|
|
2889
|
+
*/
|
|
2890
|
+
httl = (...args) => this.chain(new HTtlCommand(args, this.commandOptions));
|
|
2891
|
+
/**
|
|
2892
|
+
* @see https://redis.io/commands/hpexpire
|
|
2893
|
+
*/
|
|
2894
|
+
hpexpire = (...args) => this.chain(new HPExpireCommand(args, this.commandOptions));
|
|
2895
|
+
/**
|
|
2896
|
+
* @see https://redis.io/commands/hpexpireat
|
|
2897
|
+
*/
|
|
2898
|
+
hpexpireat = (...args) => this.chain(new HPExpireAtCommand(args, this.commandOptions));
|
|
2899
|
+
/**
|
|
2900
|
+
* @see https://redis.io/commands/hpexpiretime
|
|
2901
|
+
*/
|
|
2902
|
+
hpexpiretime = (...args) => this.chain(new HPExpireTimeCommand(args, this.commandOptions));
|
|
2903
|
+
/**
|
|
2904
|
+
* @see https://redis.io/commands/hpttl
|
|
2905
|
+
*/
|
|
2906
|
+
hpttl = (...args) => this.chain(new HPTtlCommand(args, this.commandOptions));
|
|
2907
|
+
/**
|
|
2908
|
+
* @see https://redis.io/commands/hpersist
|
|
2909
|
+
*/
|
|
2910
|
+
hpersist = (...args) => this.chain(new HPersistCommand(args, this.commandOptions));
|
|
2423
2911
|
/**
|
|
2424
2912
|
* @see https://redis.io/commands/hget
|
|
2425
2913
|
*/
|
|
@@ -2937,6 +3425,10 @@ var Pipeline = class {
|
|
|
2937
3425
|
* @see https://redis.io/commands/json.get
|
|
2938
3426
|
*/
|
|
2939
3427
|
get: (...args) => this.chain(new JsonGetCommand(args, this.commandOptions)),
|
|
3428
|
+
/**
|
|
3429
|
+
* @see https://redis.io/commands/json.merge
|
|
3430
|
+
*/
|
|
3431
|
+
merge: (...args) => this.chain(new JsonMergeCommand(args, this.commandOptions)),
|
|
2940
3432
|
/**
|
|
2941
3433
|
* @see https://redis.io/commands/json.mget
|
|
2942
3434
|
*/
|
|
@@ -2990,27 +3482,43 @@ var Pipeline = class {
|
|
|
2990
3482
|
};
|
|
2991
3483
|
|
|
2992
3484
|
// pkg/script.ts
|
|
2993
|
-
var
|
|
2994
|
-
var import_sha1 = __toESM(require("crypto-js/sha1.js"));
|
|
3485
|
+
var import_uncrypto = require("uncrypto");
|
|
2995
3486
|
var Script = class {
|
|
2996
3487
|
script;
|
|
3488
|
+
/**
|
|
3489
|
+
* @deprecated This property is initialized to an empty string and will be set in the init method
|
|
3490
|
+
* asynchronously. Do not use this property immidiately after the constructor.
|
|
3491
|
+
*
|
|
3492
|
+
* This property is only exposed for backwards compatibility and will be removed in the
|
|
3493
|
+
* future major release.
|
|
3494
|
+
*/
|
|
2997
3495
|
sha1;
|
|
2998
3496
|
redis;
|
|
2999
3497
|
constructor(redis, script) {
|
|
3000
3498
|
this.redis = redis;
|
|
3001
|
-
this.sha1 = this.digest(script);
|
|
3002
3499
|
this.script = script;
|
|
3500
|
+
this.sha1 = "";
|
|
3501
|
+
void this.init(script);
|
|
3502
|
+
}
|
|
3503
|
+
/**
|
|
3504
|
+
* Initialize the script by computing its SHA-1 hash.
|
|
3505
|
+
*/
|
|
3506
|
+
async init(script) {
|
|
3507
|
+
if (this.sha1) return;
|
|
3508
|
+
this.sha1 = await this.digest(script);
|
|
3003
3509
|
}
|
|
3004
3510
|
/**
|
|
3005
3511
|
* Send an `EVAL` command to redis.
|
|
3006
3512
|
*/
|
|
3007
3513
|
async eval(keys, args) {
|
|
3514
|
+
await this.init(this.script);
|
|
3008
3515
|
return await this.redis.eval(this.script, keys, args);
|
|
3009
3516
|
}
|
|
3010
3517
|
/**
|
|
3011
3518
|
* Calculates the sha1 hash of the script and then calls `EVALSHA`.
|
|
3012
3519
|
*/
|
|
3013
3520
|
async evalsha(keys, args) {
|
|
3521
|
+
await this.init(this.script);
|
|
3014
3522
|
return await this.redis.evalsha(this.sha1, keys, args);
|
|
3015
3523
|
}
|
|
3016
3524
|
/**
|
|
@@ -3020,6 +3528,7 @@ var Script = class {
|
|
|
3020
3528
|
* Following calls will be able to use the cached script
|
|
3021
3529
|
*/
|
|
3022
3530
|
async exec(keys, args) {
|
|
3531
|
+
await this.init(this.script);
|
|
3023
3532
|
const res = await this.redis.evalsha(this.sha1, keys, args).catch(async (error) => {
|
|
3024
3533
|
if (error instanceof Error && error.message.toLowerCase().includes("noscript")) {
|
|
3025
3534
|
return await this.redis.eval(this.script, keys, args);
|
|
@@ -3031,8 +3540,75 @@ var Script = class {
|
|
|
3031
3540
|
/**
|
|
3032
3541
|
* Compute the sha1 hash of the script and return its hex representation.
|
|
3033
3542
|
*/
|
|
3034
|
-
digest(s) {
|
|
3035
|
-
|
|
3543
|
+
async digest(s) {
|
|
3544
|
+
const data = new TextEncoder().encode(s);
|
|
3545
|
+
const hashBuffer = await import_uncrypto.subtle.digest("SHA-1", data);
|
|
3546
|
+
const hashArray = [...new Uint8Array(hashBuffer)];
|
|
3547
|
+
return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
3548
|
+
}
|
|
3549
|
+
};
|
|
3550
|
+
|
|
3551
|
+
// pkg/scriptRo.ts
|
|
3552
|
+
var import_uncrypto2 = require("uncrypto");
|
|
3553
|
+
var ScriptRO = class {
|
|
3554
|
+
script;
|
|
3555
|
+
/**
|
|
3556
|
+
* @deprecated This property is initialized to an empty string and will be set in the init method
|
|
3557
|
+
* asynchronously. Do not use this property immidiately after the constructor.
|
|
3558
|
+
*
|
|
3559
|
+
* This property is only exposed for backwards compatibility and will be removed in the
|
|
3560
|
+
* future major release.
|
|
3561
|
+
*/
|
|
3562
|
+
sha1;
|
|
3563
|
+
redis;
|
|
3564
|
+
constructor(redis, script) {
|
|
3565
|
+
this.redis = redis;
|
|
3566
|
+
this.sha1 = "";
|
|
3567
|
+
this.script = script;
|
|
3568
|
+
void this.init(script);
|
|
3569
|
+
}
|
|
3570
|
+
async init(script) {
|
|
3571
|
+
if (this.sha1) return;
|
|
3572
|
+
this.sha1 = await this.digest(script);
|
|
3573
|
+
}
|
|
3574
|
+
/**
|
|
3575
|
+
* Send an `EVAL_RO` command to redis.
|
|
3576
|
+
*/
|
|
3577
|
+
async evalRo(keys, args) {
|
|
3578
|
+
await this.init(this.script);
|
|
3579
|
+
return await this.redis.evalRo(this.script, keys, args);
|
|
3580
|
+
}
|
|
3581
|
+
/**
|
|
3582
|
+
* Calculates the sha1 hash of the script and then calls `EVALSHA_RO`.
|
|
3583
|
+
*/
|
|
3584
|
+
async evalshaRo(keys, args) {
|
|
3585
|
+
await this.init(this.script);
|
|
3586
|
+
return await this.redis.evalshaRo(this.sha1, keys, args);
|
|
3587
|
+
}
|
|
3588
|
+
/**
|
|
3589
|
+
* Optimistically try to run `EVALSHA_RO` first.
|
|
3590
|
+
* If the script is not loaded in redis, it will fall back and try again with `EVAL_RO`.
|
|
3591
|
+
*
|
|
3592
|
+
* Following calls will be able to use the cached script
|
|
3593
|
+
*/
|
|
3594
|
+
async exec(keys, args) {
|
|
3595
|
+
await this.init(this.script);
|
|
3596
|
+
const res = await this.redis.evalshaRo(this.sha1, keys, args).catch(async (error) => {
|
|
3597
|
+
if (error instanceof Error && error.message.toLowerCase().includes("noscript")) {
|
|
3598
|
+
return await this.redis.evalRo(this.script, keys, args);
|
|
3599
|
+
}
|
|
3600
|
+
throw error;
|
|
3601
|
+
});
|
|
3602
|
+
return res;
|
|
3603
|
+
}
|
|
3604
|
+
/**
|
|
3605
|
+
* Compute the sha1 hash of the script and return its hex representation.
|
|
3606
|
+
*/
|
|
3607
|
+
async digest(s) {
|
|
3608
|
+
const data = new TextEncoder().encode(s);
|
|
3609
|
+
const hashBuffer = await import_uncrypto2.subtle.digest("SHA-1", data);
|
|
3610
|
+
const hashArray = [...new Uint8Array(hashBuffer)];
|
|
3611
|
+
return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
3036
3612
|
}
|
|
3037
3613
|
};
|
|
3038
3614
|
|
|
@@ -3062,6 +3638,12 @@ var Redis = class {
|
|
|
3062
3638
|
}
|
|
3063
3639
|
this.enableAutoPipelining = opts?.enableAutoPipelining ?? true;
|
|
3064
3640
|
}
|
|
3641
|
+
get readYourWritesSyncToken() {
|
|
3642
|
+
return this.client.upstashSyncToken;
|
|
3643
|
+
}
|
|
3644
|
+
set readYourWritesSyncToken(session) {
|
|
3645
|
+
this.client.upstashSyncToken = session;
|
|
3646
|
+
}
|
|
3065
3647
|
get json() {
|
|
3066
3648
|
return {
|
|
3067
3649
|
/**
|
|
@@ -3104,6 +3686,10 @@ var Redis = class {
|
|
|
3104
3686
|
* @see https://redis.io/commands/json.get
|
|
3105
3687
|
*/
|
|
3106
3688
|
get: (...args) => new JsonGetCommand(args, this.opts).exec(this.client),
|
|
3689
|
+
/**
|
|
3690
|
+
* @see https://redis.io/commands/json.merge
|
|
3691
|
+
*/
|
|
3692
|
+
merge: (...args) => new JsonMergeCommand(args, this.opts).exec(this.client),
|
|
3107
3693
|
/**
|
|
3108
3694
|
* @see https://redis.io/commands/json.mget
|
|
3109
3695
|
*/
|
|
@@ -3173,8 +3759,36 @@ var Redis = class {
|
|
|
3173
3759
|
} catch {
|
|
3174
3760
|
}
|
|
3175
3761
|
};
|
|
3176
|
-
|
|
3177
|
-
|
|
3762
|
+
/**
|
|
3763
|
+
* Creates a new script.
|
|
3764
|
+
*
|
|
3765
|
+
* Scripts offer the ability to optimistically try to execute a script without having to send the
|
|
3766
|
+
* entire script to the server. If the script is loaded on the server, it tries again by sending
|
|
3767
|
+
* the entire script. Afterwards, the script is cached on the server.
|
|
3768
|
+
*
|
|
3769
|
+
* @param script - The script to create
|
|
3770
|
+
* @param opts - Optional options to pass to the script `{ readonly?: boolean }`
|
|
3771
|
+
* @returns A new script
|
|
3772
|
+
*
|
|
3773
|
+
* @example
|
|
3774
|
+
* ```ts
|
|
3775
|
+
* const redis = new Redis({...})
|
|
3776
|
+
*
|
|
3777
|
+
* const script = redis.createScript<string>("return ARGV[1];")
|
|
3778
|
+
* const arg1 = await script.eval([], ["Hello World"])
|
|
3779
|
+
* expect(arg1, "Hello World")
|
|
3780
|
+
* ```
|
|
3781
|
+
* @example
|
|
3782
|
+
* ```ts
|
|
3783
|
+
* const redis = new Redis({...})
|
|
3784
|
+
*
|
|
3785
|
+
* const script = redis.createScript<string>("return ARGV[1];", { readonly: true })
|
|
3786
|
+
* const arg1 = await script.evalRo([], ["Hello World"])
|
|
3787
|
+
* expect(arg1, "Hello World")
|
|
3788
|
+
* ```
|
|
3789
|
+
*/
|
|
3790
|
+
createScript(script, opts) {
|
|
3791
|
+
return opts?.readonly ? new ScriptRO(this, script) : new Script(this, script);
|
|
3178
3792
|
}
|
|
3179
3793
|
/**
|
|
3180
3794
|
* Create a new pipeline that allows you to send requests in bulk.
|
|
@@ -3261,14 +3875,26 @@ var Redis = class {
|
|
|
3261
3875
|
* @see https://redis.io/commands/echo
|
|
3262
3876
|
*/
|
|
3263
3877
|
echo = (...args) => new EchoCommand(args, this.opts).exec(this.client);
|
|
3878
|
+
/**
|
|
3879
|
+
* @see https://redis.io/commands/eval_ro
|
|
3880
|
+
*/
|
|
3881
|
+
evalRo = (...args) => new EvalROCommand(args, this.opts).exec(this.client);
|
|
3264
3882
|
/**
|
|
3265
3883
|
* @see https://redis.io/commands/eval
|
|
3266
3884
|
*/
|
|
3267
3885
|
eval = (...args) => new EvalCommand(args, this.opts).exec(this.client);
|
|
3886
|
+
/**
|
|
3887
|
+
* @see https://redis.io/commands/evalsha_ro
|
|
3888
|
+
*/
|
|
3889
|
+
evalshaRo = (...args) => new EvalshaROCommand(args, this.opts).exec(this.client);
|
|
3268
3890
|
/**
|
|
3269
3891
|
* @see https://redis.io/commands/evalsha
|
|
3270
3892
|
*/
|
|
3271
3893
|
evalsha = (...args) => new EvalshaCommand(args, this.opts).exec(this.client);
|
|
3894
|
+
/**
|
|
3895
|
+
* Generic method to execute any Redis command.
|
|
3896
|
+
*/
|
|
3897
|
+
exec = (args) => new ExecCommand(args, this.opts).exec(this.client);
|
|
3272
3898
|
/**
|
|
3273
3899
|
* @see https://redis.io/commands/exists
|
|
3274
3900
|
*/
|
|
@@ -3325,6 +3951,10 @@ var Redis = class {
|
|
|
3325
3951
|
* @see https://redis.io/commands/getdel
|
|
3326
3952
|
*/
|
|
3327
3953
|
getdel = (...args) => new GetDelCommand(args, this.opts).exec(this.client);
|
|
3954
|
+
/**
|
|
3955
|
+
* @see https://redis.io/commands/getex
|
|
3956
|
+
*/
|
|
3957
|
+
getex = (...args) => new GetExCommand(args, this.opts).exec(this.client);
|
|
3328
3958
|
/**
|
|
3329
3959
|
* @see https://redis.io/commands/getrange
|
|
3330
3960
|
*/
|
|
@@ -3341,6 +3971,42 @@ var Redis = class {
|
|
|
3341
3971
|
* @see https://redis.io/commands/hexists
|
|
3342
3972
|
*/
|
|
3343
3973
|
hexists = (...args) => new HExistsCommand(args, this.opts).exec(this.client);
|
|
3974
|
+
/**
|
|
3975
|
+
* @see https://redis.io/commands/hexpire
|
|
3976
|
+
*/
|
|
3977
|
+
hexpire = (...args) => new HExpireCommand(args, this.opts).exec(this.client);
|
|
3978
|
+
/**
|
|
3979
|
+
* @see https://redis.io/commands/hexpireat
|
|
3980
|
+
*/
|
|
3981
|
+
hexpireat = (...args) => new HExpireAtCommand(args, this.opts).exec(this.client);
|
|
3982
|
+
/**
|
|
3983
|
+
* @see https://redis.io/commands/hexpiretime
|
|
3984
|
+
*/
|
|
3985
|
+
hexpiretime = (...args) => new HExpireTimeCommand(args, this.opts).exec(this.client);
|
|
3986
|
+
/**
|
|
3987
|
+
* @see https://redis.io/commands/httl
|
|
3988
|
+
*/
|
|
3989
|
+
httl = (...args) => new HTtlCommand(args, this.opts).exec(this.client);
|
|
3990
|
+
/**
|
|
3991
|
+
* @see https://redis.io/commands/hpexpire
|
|
3992
|
+
*/
|
|
3993
|
+
hpexpire = (...args) => new HPExpireCommand(args, this.opts).exec(this.client);
|
|
3994
|
+
/**
|
|
3995
|
+
* @see https://redis.io/commands/hpexpireat
|
|
3996
|
+
*/
|
|
3997
|
+
hpexpireat = (...args) => new HPExpireAtCommand(args, this.opts).exec(this.client);
|
|
3998
|
+
/**
|
|
3999
|
+
* @see https://redis.io/commands/hpexpiretime
|
|
4000
|
+
*/
|
|
4001
|
+
hpexpiretime = (...args) => new HPExpireTimeCommand(args, this.opts).exec(this.client);
|
|
4002
|
+
/**
|
|
4003
|
+
* @see https://redis.io/commands/hpttl
|
|
4004
|
+
*/
|
|
4005
|
+
hpttl = (...args) => new HPTtlCommand(args, this.opts).exec(this.client);
|
|
4006
|
+
/**
|
|
4007
|
+
* @see https://redis.io/commands/hpersist
|
|
4008
|
+
*/
|
|
4009
|
+
hpersist = (...args) => new HPersistCommand(args, this.opts).exec(this.client);
|
|
3344
4010
|
/**
|
|
3345
4011
|
* @see https://redis.io/commands/hget
|
|
3346
4012
|
*/
|
|
@@ -3509,6 +4175,13 @@ var Redis = class {
|
|
|
3509
4175
|
* @see https://redis.io/commands/psetex
|
|
3510
4176
|
*/
|
|
3511
4177
|
psetex = (key, ttl, value) => new PSetEXCommand([key, ttl, value], this.opts).exec(this.client);
|
|
4178
|
+
/**
|
|
4179
|
+
* @see https://redis.io/commands/psubscribe
|
|
4180
|
+
*/
|
|
4181
|
+
psubscribe = (patterns) => {
|
|
4182
|
+
const patternArray = Array.isArray(patterns) ? patterns : [patterns];
|
|
4183
|
+
return new Subscriber(this.client, patternArray, true);
|
|
4184
|
+
};
|
|
3512
4185
|
/**
|
|
3513
4186
|
* @see https://redis.io/commands/pttl
|
|
3514
4187
|
*/
|
|
@@ -3545,10 +4218,9 @@ var Redis = class {
|
|
|
3545
4218
|
* @see https://redis.io/commands/sadd
|
|
3546
4219
|
*/
|
|
3547
4220
|
sadd = (key, member, ...members) => new SAddCommand([key, member, ...members], this.opts).exec(this.client);
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
scan = (...args) => new ScanCommand(args, this.opts).exec(this.client);
|
|
4221
|
+
scan(cursor, opts) {
|
|
4222
|
+
return new ScanCommand([cursor, opts], this.opts).exec(this.client);
|
|
4223
|
+
}
|
|
3552
4224
|
/**
|
|
3553
4225
|
* @see https://redis.io/commands/scard
|
|
3554
4226
|
*/
|
|
@@ -3637,6 +4309,13 @@ var Redis = class {
|
|
|
3637
4309
|
* @see https://redis.io/commands/strlen
|
|
3638
4310
|
*/
|
|
3639
4311
|
strlen = (...args) => new StrLenCommand(args, this.opts).exec(this.client);
|
|
4312
|
+
/**
|
|
4313
|
+
* @see https://redis.io/commands/subscribe
|
|
4314
|
+
*/
|
|
4315
|
+
subscribe = (channels) => {
|
|
4316
|
+
const channelArray = Array.isArray(channels) ? channels : [channels];
|
|
4317
|
+
return new Subscriber(this.client, channelArray);
|
|
4318
|
+
};
|
|
3640
4319
|
/**
|
|
3641
4320
|
* @see https://redis.io/commands/sunion
|
|
3642
4321
|
*/
|
|
@@ -3818,7 +4497,7 @@ var Redis = class {
|
|
|
3818
4497
|
};
|
|
3819
4498
|
|
|
3820
4499
|
// version.ts
|
|
3821
|
-
var VERSION = "v1.35.0
|
|
4500
|
+
var VERSION = "v1.35.0";
|
|
3822
4501
|
|
|
3823
4502
|
// platforms/fastly.ts
|
|
3824
4503
|
var Redis2 = class extends Redis {
|
|
@@ -3836,20 +4515,22 @@ var Redis2 = class extends Redis {
|
|
|
3836
4515
|
*/
|
|
3837
4516
|
constructor(config) {
|
|
3838
4517
|
if (!config.url) {
|
|
3839
|
-
|
|
4518
|
+
console.warn(
|
|
3840
4519
|
`[Upstash Redis] The 'url' property is missing or undefined in your Redis config.`
|
|
3841
4520
|
);
|
|
4521
|
+
} else if (config.url.startsWith(" ") || config.url.endsWith(" ") || /\r|\n/.test(config.url)) {
|
|
4522
|
+
console.warn(
|
|
4523
|
+
"[Upstash Redis] The redis url contains whitespace or newline, which can cause errors!"
|
|
4524
|
+
);
|
|
3842
4525
|
}
|
|
3843
4526
|
if (!config.token) {
|
|
3844
|
-
|
|
4527
|
+
console.warn(
|
|
3845
4528
|
`[Upstash Redis] The 'token' property is missing or undefined in your Redis config.`
|
|
3846
4529
|
);
|
|
3847
|
-
}
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
if (config.token.startsWith(" ") || config.token.endsWith(" ") || /\r|\n/.test(config.token)) {
|
|
3852
|
-
console.warn("The redis token contains whitespace or newline, which can cause errors!");
|
|
4530
|
+
} else if (config.token.startsWith(" ") || config.token.endsWith(" ") || /\r|\n/.test(config.token)) {
|
|
4531
|
+
console.warn(
|
|
4532
|
+
"[Upstash Redis] The redis token contains whitespace or newline, which can cause errors!"
|
|
4533
|
+
);
|
|
3853
4534
|
}
|
|
3854
4535
|
const client = new HttpClient({
|
|
3855
4536
|
baseUrl: config.url,
|