@upstash/redis 1.34.4 → 1.34.5
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-T6D4KAGH.mjs → chunk-NAQE7K3X.mjs} +285 -32
- package/cloudflare.d.mts +2 -2
- package/cloudflare.d.ts +2 -2
- package/cloudflare.js +285 -32
- package/cloudflare.mjs +1 -1
- package/fastly.d.mts +2 -2
- package/fastly.d.ts +2 -2
- package/fastly.js +285 -32
- package/fastly.mjs +1 -1
- package/nodejs.d.mts +2 -2
- package/nodejs.d.ts +2 -2
- package/nodejs.js +285 -32
- package/nodejs.mjs +1 -1
- package/package.json +1 -1
- package/{zmscore-C3G81zLz.d.mts → zmscore-BdNsMd17.d.mts} +90 -0
- package/{zmscore-C3G81zLz.d.ts → zmscore-BdNsMd17.d.ts} +90 -0
package/nodejs.js
CHANGED
|
@@ -56,6 +56,43 @@ var UrlError = class extends Error {
|
|
|
56
56
|
}
|
|
57
57
|
};
|
|
58
58
|
|
|
59
|
+
// pkg/util.ts
|
|
60
|
+
function parseRecursive(obj) {
|
|
61
|
+
const parsed = Array.isArray(obj) ? obj.map((o) => {
|
|
62
|
+
try {
|
|
63
|
+
return parseRecursive(o);
|
|
64
|
+
} catch {
|
|
65
|
+
return o;
|
|
66
|
+
}
|
|
67
|
+
}) : JSON.parse(obj);
|
|
68
|
+
if (typeof parsed === "number" && parsed.toString() !== obj) {
|
|
69
|
+
return obj;
|
|
70
|
+
}
|
|
71
|
+
return parsed;
|
|
72
|
+
}
|
|
73
|
+
function parseResponse(result) {
|
|
74
|
+
try {
|
|
75
|
+
return parseRecursive(result);
|
|
76
|
+
} catch {
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function deserializeScanResponse(result) {
|
|
81
|
+
return [result[0], ...parseResponse(result.slice(1))];
|
|
82
|
+
}
|
|
83
|
+
function mergeHeaders(...headers) {
|
|
84
|
+
const merged = {};
|
|
85
|
+
for (const header of headers) {
|
|
86
|
+
if (!header) continue;
|
|
87
|
+
for (const [key, value] of Object.entries(header)) {
|
|
88
|
+
if (value !== void 0 && value !== null) {
|
|
89
|
+
merged[key] = value;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return merged;
|
|
94
|
+
}
|
|
95
|
+
|
|
59
96
|
// pkg/http.ts
|
|
60
97
|
var HttpClient = class {
|
|
61
98
|
baseUrl;
|
|
@@ -104,15 +141,18 @@ var HttpClient = class {
|
|
|
104
141
|
this.headers = merge(this.headers, "Upstash-Telemetry-Sdk", telemetry.sdk);
|
|
105
142
|
}
|
|
106
143
|
async request(req) {
|
|
144
|
+
const requestHeaders = mergeHeaders(this.headers, req.headers ?? {});
|
|
145
|
+
const requestUrl = [this.baseUrl, ...req.path ?? []].join("/");
|
|
146
|
+
const isEventStream = requestHeaders.Accept === "text/event-stream";
|
|
107
147
|
const requestOptions = {
|
|
108
148
|
//@ts-expect-error this should throw due to bun regression
|
|
109
149
|
cache: this.options.cache,
|
|
110
150
|
method: "POST",
|
|
111
|
-
headers:
|
|
151
|
+
headers: requestHeaders,
|
|
112
152
|
body: JSON.stringify(req.body),
|
|
113
153
|
keepalive: this.options.keepAlive,
|
|
114
154
|
agent: this.options.agent,
|
|
115
|
-
signal: this.options.signal,
|
|
155
|
+
signal: req.signal ?? this.options.signal,
|
|
116
156
|
/**
|
|
117
157
|
* Fastly specific
|
|
118
158
|
*/
|
|
@@ -131,7 +171,7 @@ var HttpClient = class {
|
|
|
131
171
|
let error = null;
|
|
132
172
|
for (let i = 0; i <= this.retry.attempts; i++) {
|
|
133
173
|
try {
|
|
134
|
-
res = await fetch(
|
|
174
|
+
res = await fetch(requestUrl, requestOptions);
|
|
135
175
|
break;
|
|
136
176
|
} catch (error_) {
|
|
137
177
|
if (this.options.signal?.aborted) {
|
|
@@ -154,14 +194,46 @@ var HttpClient = class {
|
|
|
154
194
|
if (!res) {
|
|
155
195
|
throw error ?? new Error("Exhausted all retries");
|
|
156
196
|
}
|
|
157
|
-
const body = await res.json();
|
|
158
197
|
if (!res.ok) {
|
|
159
|
-
|
|
198
|
+
const body2 = await res.json();
|
|
199
|
+
throw new UpstashError(`${body2.error}, command was: ${JSON.stringify(req.body)}`);
|
|
160
200
|
}
|
|
161
201
|
if (this.readYourWrites) {
|
|
162
202
|
const headers = res.headers;
|
|
163
203
|
this.upstashSyncToken = headers.get("upstash-sync-token") ?? "";
|
|
164
204
|
}
|
|
205
|
+
if (isEventStream && req && req.onMessage && res.body) {
|
|
206
|
+
const reader = res.body.getReader();
|
|
207
|
+
const decoder = new TextDecoder();
|
|
208
|
+
(async () => {
|
|
209
|
+
try {
|
|
210
|
+
while (true) {
|
|
211
|
+
const { value, done } = await reader.read();
|
|
212
|
+
if (done) break;
|
|
213
|
+
const chunk = decoder.decode(value);
|
|
214
|
+
const lines = chunk.split("\n");
|
|
215
|
+
for (const line of lines) {
|
|
216
|
+
if (line.startsWith("data: ")) {
|
|
217
|
+
const data = line.slice(6);
|
|
218
|
+
req.onMessage?.(data);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
} catch (error2) {
|
|
223
|
+
if (error2 instanceof Error && error2.name === "AbortError") {
|
|
224
|
+
} else {
|
|
225
|
+
console.error("Stream reading error:", error2);
|
|
226
|
+
}
|
|
227
|
+
} finally {
|
|
228
|
+
try {
|
|
229
|
+
await reader.cancel();
|
|
230
|
+
} catch {
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
})();
|
|
234
|
+
return { result: 1 };
|
|
235
|
+
}
|
|
236
|
+
const body = await res.json();
|
|
165
237
|
if (this.readYourWrites) {
|
|
166
238
|
const headers = res.headers;
|
|
167
239
|
this.upstashSyncToken = headers.get("upstash-sync-token") ?? "";
|
|
@@ -311,31 +383,6 @@ var AutoPipelineExecutor = class {
|
|
|
311
383
|
}
|
|
312
384
|
};
|
|
313
385
|
|
|
314
|
-
// pkg/util.ts
|
|
315
|
-
function parseRecursive(obj) {
|
|
316
|
-
const parsed = Array.isArray(obj) ? obj.map((o) => {
|
|
317
|
-
try {
|
|
318
|
-
return parseRecursive(o);
|
|
319
|
-
} catch {
|
|
320
|
-
return o;
|
|
321
|
-
}
|
|
322
|
-
}) : JSON.parse(obj);
|
|
323
|
-
if (typeof parsed === "number" && parsed.toString() !== obj) {
|
|
324
|
-
return obj;
|
|
325
|
-
}
|
|
326
|
-
return parsed;
|
|
327
|
-
}
|
|
328
|
-
function parseResponse(result) {
|
|
329
|
-
try {
|
|
330
|
-
return parseRecursive(result);
|
|
331
|
-
} catch {
|
|
332
|
-
return result;
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
function deserializeScanResponse(result) {
|
|
336
|
-
return [result[0], ...parseResponse(result.slice(1))];
|
|
337
|
-
}
|
|
338
|
-
|
|
339
386
|
// pkg/commands/command.ts
|
|
340
387
|
var defaultSerializer = (c) => {
|
|
341
388
|
switch (typeof c) {
|
|
@@ -353,6 +400,11 @@ var Command = class {
|
|
|
353
400
|
command;
|
|
354
401
|
serialize;
|
|
355
402
|
deserialize;
|
|
403
|
+
headers;
|
|
404
|
+
path;
|
|
405
|
+
onMessage;
|
|
406
|
+
isStreaming;
|
|
407
|
+
signal;
|
|
356
408
|
/**
|
|
357
409
|
* Create a new command instance.
|
|
358
410
|
*
|
|
@@ -362,6 +414,11 @@ var Command = class {
|
|
|
362
414
|
this.serialize = defaultSerializer;
|
|
363
415
|
this.deserialize = opts?.automaticDeserialization === void 0 || opts.automaticDeserialization ? opts?.deserialize ?? parseResponse : (x) => x;
|
|
364
416
|
this.command = command.map((c) => this.serialize(c));
|
|
417
|
+
this.headers = opts?.headers;
|
|
418
|
+
this.path = opts?.path;
|
|
419
|
+
this.onMessage = opts?.streamOptions?.onMessage;
|
|
420
|
+
this.isStreaming = opts?.streamOptions?.isStreaming ?? false;
|
|
421
|
+
this.signal = opts?.streamOptions?.signal;
|
|
365
422
|
if (opts?.latencyLogging) {
|
|
366
423
|
const originalExec = this.exec.bind(this);
|
|
367
424
|
this.exec = async (client) => {
|
|
@@ -382,7 +439,12 @@ var Command = class {
|
|
|
382
439
|
async exec(client) {
|
|
383
440
|
const { result, error } = await client.request({
|
|
384
441
|
body: this.command,
|
|
385
|
-
|
|
442
|
+
path: this.path,
|
|
443
|
+
upstashSyncToken: client.upstashSyncToken,
|
|
444
|
+
headers: this.headers,
|
|
445
|
+
onMessage: this.onMessage,
|
|
446
|
+
isStreaming: this.isStreaming,
|
|
447
|
+
signal: this.signal
|
|
386
448
|
});
|
|
387
449
|
if (error) {
|
|
388
450
|
throw new UpstashError(error);
|
|
@@ -2235,6 +2297,183 @@ var ZUnionStoreCommand = class extends Command {
|
|
|
2235
2297
|
}
|
|
2236
2298
|
};
|
|
2237
2299
|
|
|
2300
|
+
// pkg/commands/psubscribe.ts
|
|
2301
|
+
var PSubscribeCommand = class extends Command {
|
|
2302
|
+
constructor(cmd, opts) {
|
|
2303
|
+
const sseHeaders = {
|
|
2304
|
+
Accept: "text/event-stream",
|
|
2305
|
+
"Cache-Control": "no-cache",
|
|
2306
|
+
Connection: "keep-alive"
|
|
2307
|
+
};
|
|
2308
|
+
super([], {
|
|
2309
|
+
...opts,
|
|
2310
|
+
headers: sseHeaders,
|
|
2311
|
+
path: ["psubscribe", ...cmd],
|
|
2312
|
+
streamOptions: {
|
|
2313
|
+
isStreaming: true,
|
|
2314
|
+
onMessage: opts?.streamOptions?.onMessage,
|
|
2315
|
+
signal: opts?.streamOptions?.signal
|
|
2316
|
+
}
|
|
2317
|
+
});
|
|
2318
|
+
}
|
|
2319
|
+
};
|
|
2320
|
+
|
|
2321
|
+
// pkg/commands/subscribe.ts
|
|
2322
|
+
var Subscriber = class extends EventTarget {
|
|
2323
|
+
subscriptions;
|
|
2324
|
+
client;
|
|
2325
|
+
listeners;
|
|
2326
|
+
constructor(client, channels, isPattern = false) {
|
|
2327
|
+
super();
|
|
2328
|
+
this.client = client;
|
|
2329
|
+
this.subscriptions = /* @__PURE__ */ new Map();
|
|
2330
|
+
this.listeners = /* @__PURE__ */ new Map();
|
|
2331
|
+
for (const channel of channels) {
|
|
2332
|
+
if (isPattern) {
|
|
2333
|
+
this.subscribeToPattern(channel);
|
|
2334
|
+
} else {
|
|
2335
|
+
this.subscribeToChannel(channel);
|
|
2336
|
+
}
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
subscribeToChannel(channel) {
|
|
2340
|
+
const controller = new AbortController();
|
|
2341
|
+
const command = new SubscribeCommand([channel], {
|
|
2342
|
+
streamOptions: {
|
|
2343
|
+
signal: controller.signal,
|
|
2344
|
+
onMessage: (data) => this.handleMessage(data, false)
|
|
2345
|
+
}
|
|
2346
|
+
});
|
|
2347
|
+
command.exec(this.client).catch((error) => {
|
|
2348
|
+
if (error.name !== "AbortError") {
|
|
2349
|
+
this.dispatchToListeners("error", error);
|
|
2350
|
+
}
|
|
2351
|
+
});
|
|
2352
|
+
this.subscriptions.set(channel, {
|
|
2353
|
+
command,
|
|
2354
|
+
controller,
|
|
2355
|
+
isPattern: false
|
|
2356
|
+
});
|
|
2357
|
+
}
|
|
2358
|
+
subscribeToPattern(pattern) {
|
|
2359
|
+
const controller = new AbortController();
|
|
2360
|
+
const command = new PSubscribeCommand([pattern], {
|
|
2361
|
+
streamOptions: {
|
|
2362
|
+
signal: controller.signal,
|
|
2363
|
+
onMessage: (data) => this.handleMessage(data, true)
|
|
2364
|
+
}
|
|
2365
|
+
});
|
|
2366
|
+
command.exec(this.client).catch((error) => {
|
|
2367
|
+
if (error.name !== "AbortError") {
|
|
2368
|
+
this.dispatchToListeners("error", error);
|
|
2369
|
+
}
|
|
2370
|
+
});
|
|
2371
|
+
this.subscriptions.set(pattern, {
|
|
2372
|
+
command,
|
|
2373
|
+
controller,
|
|
2374
|
+
isPattern: true
|
|
2375
|
+
});
|
|
2376
|
+
}
|
|
2377
|
+
handleMessage(data, isPattern) {
|
|
2378
|
+
const messageData = data.replace(/^data:\s*/, "");
|
|
2379
|
+
const firstCommaIndex = messageData.indexOf(",");
|
|
2380
|
+
const secondCommaIndex = messageData.indexOf(",", firstCommaIndex + 1);
|
|
2381
|
+
const thirdCommaIndex = isPattern ? messageData.indexOf(",", secondCommaIndex + 1) : -1;
|
|
2382
|
+
if (firstCommaIndex !== -1 && secondCommaIndex !== -1) {
|
|
2383
|
+
const type = messageData.slice(0, firstCommaIndex);
|
|
2384
|
+
if (isPattern && type === "pmessage" && thirdCommaIndex !== -1) {
|
|
2385
|
+
const pattern = messageData.slice(firstCommaIndex + 1, secondCommaIndex);
|
|
2386
|
+
const channel = messageData.slice(secondCommaIndex + 1, thirdCommaIndex);
|
|
2387
|
+
const messageStr = messageData.slice(thirdCommaIndex + 1);
|
|
2388
|
+
try {
|
|
2389
|
+
const message = JSON.parse(messageStr);
|
|
2390
|
+
this.dispatchToListeners("pmessage", { pattern, channel, message });
|
|
2391
|
+
this.dispatchToListeners(`pmessage:${pattern}`, { pattern, channel, message });
|
|
2392
|
+
} catch (error) {
|
|
2393
|
+
this.dispatchToListeners("error", new Error(`Failed to parse message: ${error}`));
|
|
2394
|
+
}
|
|
2395
|
+
} else {
|
|
2396
|
+
const channel = messageData.slice(firstCommaIndex + 1, secondCommaIndex);
|
|
2397
|
+
const messageStr = messageData.slice(secondCommaIndex + 1);
|
|
2398
|
+
try {
|
|
2399
|
+
if (type === "subscribe" || type === "psubscribe" || type === "unsubscribe" || type === "punsubscribe") {
|
|
2400
|
+
const count = Number.parseInt(messageStr);
|
|
2401
|
+
this.dispatchToListeners(type, count);
|
|
2402
|
+
} else {
|
|
2403
|
+
const message = JSON.parse(messageStr);
|
|
2404
|
+
this.dispatchToListeners(type, { channel, message });
|
|
2405
|
+
this.dispatchToListeners(`${type}:${channel}`, { channel, message });
|
|
2406
|
+
}
|
|
2407
|
+
} catch (error) {
|
|
2408
|
+
this.dispatchToListeners("error", new Error(`Failed to parse message: ${error}`));
|
|
2409
|
+
}
|
|
2410
|
+
}
|
|
2411
|
+
}
|
|
2412
|
+
}
|
|
2413
|
+
dispatchToListeners(type, data) {
|
|
2414
|
+
const listeners = this.listeners.get(type);
|
|
2415
|
+
if (listeners) {
|
|
2416
|
+
for (const listener of listeners) {
|
|
2417
|
+
listener(data);
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
}
|
|
2421
|
+
on(type, listener) {
|
|
2422
|
+
if (!this.listeners.has(type)) {
|
|
2423
|
+
this.listeners.set(type, /* @__PURE__ */ new Set());
|
|
2424
|
+
}
|
|
2425
|
+
this.listeners.get(type)?.add(listener);
|
|
2426
|
+
}
|
|
2427
|
+
removeAllListeners() {
|
|
2428
|
+
this.listeners.clear();
|
|
2429
|
+
}
|
|
2430
|
+
async unsubscribe(channels) {
|
|
2431
|
+
if (channels) {
|
|
2432
|
+
for (const channel of channels) {
|
|
2433
|
+
const subscription = this.subscriptions.get(channel);
|
|
2434
|
+
if (subscription) {
|
|
2435
|
+
try {
|
|
2436
|
+
subscription.controller.abort();
|
|
2437
|
+
} catch {
|
|
2438
|
+
}
|
|
2439
|
+
this.subscriptions.delete(channel);
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2442
|
+
} else {
|
|
2443
|
+
for (const subscription of this.subscriptions.values()) {
|
|
2444
|
+
try {
|
|
2445
|
+
subscription.controller.abort();
|
|
2446
|
+
} catch {
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2449
|
+
this.subscriptions.clear();
|
|
2450
|
+
this.removeAllListeners();
|
|
2451
|
+
}
|
|
2452
|
+
}
|
|
2453
|
+
getSubscribedChannels() {
|
|
2454
|
+
return [...this.subscriptions.keys()];
|
|
2455
|
+
}
|
|
2456
|
+
};
|
|
2457
|
+
var SubscribeCommand = class extends Command {
|
|
2458
|
+
constructor(cmd, opts) {
|
|
2459
|
+
const sseHeaders = {
|
|
2460
|
+
Accept: "text/event-stream",
|
|
2461
|
+
"Cache-Control": "no-cache",
|
|
2462
|
+
Connection: "keep-alive"
|
|
2463
|
+
};
|
|
2464
|
+
super([], {
|
|
2465
|
+
...opts,
|
|
2466
|
+
headers: sseHeaders,
|
|
2467
|
+
path: ["subscribe", ...cmd],
|
|
2468
|
+
streamOptions: {
|
|
2469
|
+
isStreaming: true,
|
|
2470
|
+
onMessage: opts?.streamOptions?.onMessage,
|
|
2471
|
+
signal: opts?.streamOptions?.signal
|
|
2472
|
+
}
|
|
2473
|
+
});
|
|
2474
|
+
}
|
|
2475
|
+
};
|
|
2476
|
+
|
|
2238
2477
|
// pkg/commands/zdiffstore.ts
|
|
2239
2478
|
var ZDiffStoreCommand = class extends Command {
|
|
2240
2479
|
constructor(cmd, opts) {
|
|
@@ -3562,6 +3801,13 @@ var Redis = class {
|
|
|
3562
3801
|
* @see https://redis.io/commands/psetex
|
|
3563
3802
|
*/
|
|
3564
3803
|
psetex = (key, ttl, value) => new PSetEXCommand([key, ttl, value], this.opts).exec(this.client);
|
|
3804
|
+
/**
|
|
3805
|
+
* @see https://redis.io/commands/psubscribe
|
|
3806
|
+
*/
|
|
3807
|
+
psubscribe = (patterns) => {
|
|
3808
|
+
const patternArray = Array.isArray(patterns) ? patterns : [patterns];
|
|
3809
|
+
return new Subscriber(this.client, patternArray, true);
|
|
3810
|
+
};
|
|
3565
3811
|
/**
|
|
3566
3812
|
* @see https://redis.io/commands/pttl
|
|
3567
3813
|
*/
|
|
@@ -3690,6 +3936,13 @@ var Redis = class {
|
|
|
3690
3936
|
* @see https://redis.io/commands/strlen
|
|
3691
3937
|
*/
|
|
3692
3938
|
strlen = (...args) => new StrLenCommand(args, this.opts).exec(this.client);
|
|
3939
|
+
/**
|
|
3940
|
+
* @see https://redis.io/commands/subscribe
|
|
3941
|
+
*/
|
|
3942
|
+
subscribe = (channels) => {
|
|
3943
|
+
const channelArray = Array.isArray(channels) ? channels : [channels];
|
|
3944
|
+
return new Subscriber(this.client, channelArray);
|
|
3945
|
+
};
|
|
3693
3946
|
/**
|
|
3694
3947
|
* @see https://redis.io/commands/sunion
|
|
3695
3948
|
*/
|
|
@@ -3871,7 +4124,7 @@ var Redis = class {
|
|
|
3871
4124
|
};
|
|
3872
4125
|
|
|
3873
4126
|
// version.ts
|
|
3874
|
-
var VERSION = "v1.34.
|
|
4127
|
+
var VERSION = "v1.34.5";
|
|
3875
4128
|
|
|
3876
4129
|
// platforms/nodejs.ts
|
|
3877
4130
|
if (typeof atob === "undefined") {
|
package/nodejs.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@upstash/redis","version":"v1.34.
|
|
1
|
+
{"name":"@upstash/redis","version":"v1.34.5","main":"./nodejs.js","module":"./nodejs.mjs","types":"./nodejs.d.ts","exports":{".":{"import":"./nodejs.mjs","require":"./nodejs.js"},"./node":{"import":"./nodejs.mjs","require":"./nodejs.js"},"./cloudflare":{"import":"./cloudflare.mjs","require":"./cloudflare.js"},"./cloudflare.js":{"import":"./cloudflare.mjs","require":"./cloudflare.js"},"./cloudflare.mjs":{"import":"./cloudflare.mjs","require":"./cloudflare.js"},"./fastly":{"import":"./fastly.mjs","require":"./fastly.js"},"./fastly.js":{"import":"./fastly.mjs","require":"./fastly.js"},"./fastly.mjs":{"import":"./fastly.mjs","require":"./fastly.js"}},"description":"An HTTP/REST based Redis client built on top of Upstash REST API.","repository":{"type":"git","url":"git+https://github.com/upstash/upstash-redis.git"},"keywords":["redis","database","serverless","edge","upstash"],"files":["./*"],"scripts":{"build":"tsup && cp package.json README.md LICENSE dist/","test":"bun test pkg","fmt":"prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"","lint":"eslint \"**/*.{js,ts,tsx}\" --quiet --fix","format":"prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"","format:check":"prettier --check \"**/*.{ts,tsx,js,jsx,json,md}\"","lint:fix":"eslint . -c .ts,.tsx,.js,.jsx --fix","commit":"cz","lint:format":"bun run lint:fix && bun run format","check-exports":"bun run build && cd dist && attw -P"},"author":"Andreas Thomas <dev@chronark.com>","license":"MIT","bugs":{"url":"https://github.com/upstash/upstash-redis/issues"},"homepage":"https://github.com/upstash/upstash-redis#readme","devDependencies":{"@biomejs/biome":"latest","@commitlint/cli":"^19.3.0","@commitlint/config-conventional":"^19.2.2","@types/crypto-js":"^4.1.3","@typescript-eslint/eslint-plugin":"8.4.0","@typescript-eslint/parser":"8.4.0","bun-types":"1.0.33","eslint":"9.10.0","eslint-plugin-unicorn":"55.0.0","husky":"^9.1.1","prettier":"^3.3.3","tsup":"^8.2.3","typescript":"latest"},"dependencies":{"crypto-js":"^4.2.0"}}
|
|
@@ -36,7 +36,23 @@ type UpstashRequest = {
|
|
|
36
36
|
* Request body will be serialized to json
|
|
37
37
|
*/
|
|
38
38
|
body?: unknown;
|
|
39
|
+
/**
|
|
40
|
+
* Additional headers for the request
|
|
41
|
+
*/
|
|
42
|
+
headers?: Record<string, string>;
|
|
39
43
|
upstashSyncToken?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Callback for handling streaming messages
|
|
46
|
+
*/
|
|
47
|
+
onMessage?: (data: string) => void;
|
|
48
|
+
/**
|
|
49
|
+
* Whether this request expects a streaming response
|
|
50
|
+
*/
|
|
51
|
+
isStreaming?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Abort signal for the request
|
|
54
|
+
*/
|
|
55
|
+
signal?: AbortSignal;
|
|
40
56
|
};
|
|
41
57
|
type UpstashResponse<TResult> = {
|
|
42
58
|
result?: TResult;
|
|
@@ -119,6 +135,31 @@ type CommandOptions<TResult, TData> = {
|
|
|
119
135
|
*/
|
|
120
136
|
automaticDeserialization?: boolean;
|
|
121
137
|
latencyLogging?: boolean;
|
|
138
|
+
/**
|
|
139
|
+
* Additional headers to be sent with the request
|
|
140
|
+
*/
|
|
141
|
+
headers?: Record<string, string>;
|
|
142
|
+
/**
|
|
143
|
+
* Path to append to the URL
|
|
144
|
+
*/
|
|
145
|
+
path?: string[];
|
|
146
|
+
/**
|
|
147
|
+
* Options for streaming requests, mainly used for subscribe, monitor commands
|
|
148
|
+
**/
|
|
149
|
+
streamOptions?: {
|
|
150
|
+
/**
|
|
151
|
+
* Callback to be called when a message is received
|
|
152
|
+
*/
|
|
153
|
+
onMessage?: (data: string) => void;
|
|
154
|
+
/**
|
|
155
|
+
* Whether the request is streaming
|
|
156
|
+
*/
|
|
157
|
+
isStreaming?: boolean;
|
|
158
|
+
/**
|
|
159
|
+
* Signal to abort the request
|
|
160
|
+
*/
|
|
161
|
+
signal?: AbortSignal;
|
|
162
|
+
};
|
|
122
163
|
};
|
|
123
164
|
/**
|
|
124
165
|
* Command offers default (de)serialization and the exec method to all commands.
|
|
@@ -130,6 +171,11 @@ declare class Command<TResult, TData> {
|
|
|
130
171
|
readonly command: (string | number | boolean)[];
|
|
131
172
|
readonly serialize: Serialize;
|
|
132
173
|
readonly deserialize: Deserialize<TResult, TData>;
|
|
174
|
+
protected readonly headers?: Record<string, string>;
|
|
175
|
+
protected readonly path?: string[];
|
|
176
|
+
protected readonly onMessage?: (data: string) => void;
|
|
177
|
+
protected readonly isStreaming: boolean;
|
|
178
|
+
protected readonly signal?: AbortSignal;
|
|
133
179
|
/**
|
|
134
180
|
* Create a new command instance.
|
|
135
181
|
*
|
|
@@ -1643,6 +1689,42 @@ declare class ZScoreCommand<TData> extends Command<string | null, number | null>
|
|
|
1643
1689
|
constructor(cmd: [key: string, member: TData], opts?: CommandOptions<string | null, number | null>);
|
|
1644
1690
|
}
|
|
1645
1691
|
|
|
1692
|
+
type BaseMessageData<TMessage> = {
|
|
1693
|
+
channel: string;
|
|
1694
|
+
message: TMessage;
|
|
1695
|
+
};
|
|
1696
|
+
type PatternMessageData<TMessage> = BaseMessageData<TMessage> & {
|
|
1697
|
+
pattern: string;
|
|
1698
|
+
};
|
|
1699
|
+
type SubscriptionCountEvent = number;
|
|
1700
|
+
type MessageEventMap<TMessage> = {
|
|
1701
|
+
message: BaseMessageData<TMessage>;
|
|
1702
|
+
subscribe: SubscriptionCountEvent;
|
|
1703
|
+
unsubscribe: SubscriptionCountEvent;
|
|
1704
|
+
pmessage: PatternMessageData<TMessage>;
|
|
1705
|
+
psubscribe: SubscriptionCountEvent;
|
|
1706
|
+
punsubscribe: SubscriptionCountEvent;
|
|
1707
|
+
error: Error;
|
|
1708
|
+
[key: `message:${string}`]: BaseMessageData<TMessage>;
|
|
1709
|
+
[key: `pmessage:${string}`]: PatternMessageData<TMessage>;
|
|
1710
|
+
};
|
|
1711
|
+
type EventType = keyof MessageEventMap<any>;
|
|
1712
|
+
type Listener<TMessage, T extends EventType> = (event: MessageEventMap<TMessage>[T]) => void;
|
|
1713
|
+
declare class Subscriber<TMessage = any> extends EventTarget {
|
|
1714
|
+
private subscriptions;
|
|
1715
|
+
private client;
|
|
1716
|
+
private listeners;
|
|
1717
|
+
constructor(client: Requester, channels: string[], isPattern?: boolean);
|
|
1718
|
+
private subscribeToChannel;
|
|
1719
|
+
private subscribeToPattern;
|
|
1720
|
+
private handleMessage;
|
|
1721
|
+
private dispatchToListeners;
|
|
1722
|
+
on<T extends keyof MessageEventMap<TMessage>>(type: T, listener: Listener<TMessage, T>): void;
|
|
1723
|
+
removeAllListeners(): void;
|
|
1724
|
+
unsubscribe(channels?: string[]): Promise<void>;
|
|
1725
|
+
getSubscribedChannels(): string[];
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1646
1728
|
type InferResponseData<T extends unknown[]> = {
|
|
1647
1729
|
[K in keyof T]: T[K] extends Command<any, infer TData> ? TData : unknown;
|
|
1648
1730
|
};
|
|
@@ -3236,6 +3318,10 @@ declare class Redis {
|
|
|
3236
3318
|
* @see https://redis.io/commands/psetex
|
|
3237
3319
|
*/
|
|
3238
3320
|
psetex: <TData>(key: string, ttl: number, value: TData) => Promise<string>;
|
|
3321
|
+
/**
|
|
3322
|
+
* @see https://redis.io/commands/psubscribe
|
|
3323
|
+
*/
|
|
3324
|
+
psubscribe: <TMessage>(patterns: string | string[]) => Subscriber<TMessage>;
|
|
3239
3325
|
/**
|
|
3240
3326
|
* @see https://redis.io/commands/pttl
|
|
3241
3327
|
*/
|
|
@@ -3364,6 +3450,10 @@ declare class Redis {
|
|
|
3364
3450
|
* @see https://redis.io/commands/strlen
|
|
3365
3451
|
*/
|
|
3366
3452
|
strlen: (key: string) => Promise<number>;
|
|
3453
|
+
/**
|
|
3454
|
+
* @see https://redis.io/commands/subscribe
|
|
3455
|
+
*/
|
|
3456
|
+
subscribe: <TMessage>(channels: string | string[]) => Subscriber<TMessage>;
|
|
3367
3457
|
/**
|
|
3368
3458
|
* @see https://redis.io/commands/sunion
|
|
3369
3459
|
*/
|
|
@@ -36,7 +36,23 @@ type UpstashRequest = {
|
|
|
36
36
|
* Request body will be serialized to json
|
|
37
37
|
*/
|
|
38
38
|
body?: unknown;
|
|
39
|
+
/**
|
|
40
|
+
* Additional headers for the request
|
|
41
|
+
*/
|
|
42
|
+
headers?: Record<string, string>;
|
|
39
43
|
upstashSyncToken?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Callback for handling streaming messages
|
|
46
|
+
*/
|
|
47
|
+
onMessage?: (data: string) => void;
|
|
48
|
+
/**
|
|
49
|
+
* Whether this request expects a streaming response
|
|
50
|
+
*/
|
|
51
|
+
isStreaming?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Abort signal for the request
|
|
54
|
+
*/
|
|
55
|
+
signal?: AbortSignal;
|
|
40
56
|
};
|
|
41
57
|
type UpstashResponse<TResult> = {
|
|
42
58
|
result?: TResult;
|
|
@@ -119,6 +135,31 @@ type CommandOptions<TResult, TData> = {
|
|
|
119
135
|
*/
|
|
120
136
|
automaticDeserialization?: boolean;
|
|
121
137
|
latencyLogging?: boolean;
|
|
138
|
+
/**
|
|
139
|
+
* Additional headers to be sent with the request
|
|
140
|
+
*/
|
|
141
|
+
headers?: Record<string, string>;
|
|
142
|
+
/**
|
|
143
|
+
* Path to append to the URL
|
|
144
|
+
*/
|
|
145
|
+
path?: string[];
|
|
146
|
+
/**
|
|
147
|
+
* Options for streaming requests, mainly used for subscribe, monitor commands
|
|
148
|
+
**/
|
|
149
|
+
streamOptions?: {
|
|
150
|
+
/**
|
|
151
|
+
* Callback to be called when a message is received
|
|
152
|
+
*/
|
|
153
|
+
onMessage?: (data: string) => void;
|
|
154
|
+
/**
|
|
155
|
+
* Whether the request is streaming
|
|
156
|
+
*/
|
|
157
|
+
isStreaming?: boolean;
|
|
158
|
+
/**
|
|
159
|
+
* Signal to abort the request
|
|
160
|
+
*/
|
|
161
|
+
signal?: AbortSignal;
|
|
162
|
+
};
|
|
122
163
|
};
|
|
123
164
|
/**
|
|
124
165
|
* Command offers default (de)serialization and the exec method to all commands.
|
|
@@ -130,6 +171,11 @@ declare class Command<TResult, TData> {
|
|
|
130
171
|
readonly command: (string | number | boolean)[];
|
|
131
172
|
readonly serialize: Serialize;
|
|
132
173
|
readonly deserialize: Deserialize<TResult, TData>;
|
|
174
|
+
protected readonly headers?: Record<string, string>;
|
|
175
|
+
protected readonly path?: string[];
|
|
176
|
+
protected readonly onMessage?: (data: string) => void;
|
|
177
|
+
protected readonly isStreaming: boolean;
|
|
178
|
+
protected readonly signal?: AbortSignal;
|
|
133
179
|
/**
|
|
134
180
|
* Create a new command instance.
|
|
135
181
|
*
|
|
@@ -1643,6 +1689,42 @@ declare class ZScoreCommand<TData> extends Command<string | null, number | null>
|
|
|
1643
1689
|
constructor(cmd: [key: string, member: TData], opts?: CommandOptions<string | null, number | null>);
|
|
1644
1690
|
}
|
|
1645
1691
|
|
|
1692
|
+
type BaseMessageData<TMessage> = {
|
|
1693
|
+
channel: string;
|
|
1694
|
+
message: TMessage;
|
|
1695
|
+
};
|
|
1696
|
+
type PatternMessageData<TMessage> = BaseMessageData<TMessage> & {
|
|
1697
|
+
pattern: string;
|
|
1698
|
+
};
|
|
1699
|
+
type SubscriptionCountEvent = number;
|
|
1700
|
+
type MessageEventMap<TMessage> = {
|
|
1701
|
+
message: BaseMessageData<TMessage>;
|
|
1702
|
+
subscribe: SubscriptionCountEvent;
|
|
1703
|
+
unsubscribe: SubscriptionCountEvent;
|
|
1704
|
+
pmessage: PatternMessageData<TMessage>;
|
|
1705
|
+
psubscribe: SubscriptionCountEvent;
|
|
1706
|
+
punsubscribe: SubscriptionCountEvent;
|
|
1707
|
+
error: Error;
|
|
1708
|
+
[key: `message:${string}`]: BaseMessageData<TMessage>;
|
|
1709
|
+
[key: `pmessage:${string}`]: PatternMessageData<TMessage>;
|
|
1710
|
+
};
|
|
1711
|
+
type EventType = keyof MessageEventMap<any>;
|
|
1712
|
+
type Listener<TMessage, T extends EventType> = (event: MessageEventMap<TMessage>[T]) => void;
|
|
1713
|
+
declare class Subscriber<TMessage = any> extends EventTarget {
|
|
1714
|
+
private subscriptions;
|
|
1715
|
+
private client;
|
|
1716
|
+
private listeners;
|
|
1717
|
+
constructor(client: Requester, channels: string[], isPattern?: boolean);
|
|
1718
|
+
private subscribeToChannel;
|
|
1719
|
+
private subscribeToPattern;
|
|
1720
|
+
private handleMessage;
|
|
1721
|
+
private dispatchToListeners;
|
|
1722
|
+
on<T extends keyof MessageEventMap<TMessage>>(type: T, listener: Listener<TMessage, T>): void;
|
|
1723
|
+
removeAllListeners(): void;
|
|
1724
|
+
unsubscribe(channels?: string[]): Promise<void>;
|
|
1725
|
+
getSubscribedChannels(): string[];
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1646
1728
|
type InferResponseData<T extends unknown[]> = {
|
|
1647
1729
|
[K in keyof T]: T[K] extends Command<any, infer TData> ? TData : unknown;
|
|
1648
1730
|
};
|
|
@@ -3236,6 +3318,10 @@ declare class Redis {
|
|
|
3236
3318
|
* @see https://redis.io/commands/psetex
|
|
3237
3319
|
*/
|
|
3238
3320
|
psetex: <TData>(key: string, ttl: number, value: TData) => Promise<string>;
|
|
3321
|
+
/**
|
|
3322
|
+
* @see https://redis.io/commands/psubscribe
|
|
3323
|
+
*/
|
|
3324
|
+
psubscribe: <TMessage>(patterns: string | string[]) => Subscriber<TMessage>;
|
|
3239
3325
|
/**
|
|
3240
3326
|
* @see https://redis.io/commands/pttl
|
|
3241
3327
|
*/
|
|
@@ -3364,6 +3450,10 @@ declare class Redis {
|
|
|
3364
3450
|
* @see https://redis.io/commands/strlen
|
|
3365
3451
|
*/
|
|
3366
3452
|
strlen: (key: string) => Promise<number>;
|
|
3453
|
+
/**
|
|
3454
|
+
* @see https://redis.io/commands/subscribe
|
|
3455
|
+
*/
|
|
3456
|
+
subscribe: <TMessage>(channels: string | string[]) => Subscriber<TMessage>;
|
|
3367
3457
|
/**
|
|
3368
3458
|
* @see https://redis.io/commands/sunion
|
|
3369
3459
|
*/
|