@windrun-huaiin/backend-core 15.1.0 → 16.0.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/LICENSE +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +44 -0
- package/dist/index.mjs +8 -1
- package/dist/lib/index.js +19 -0
- package/dist/lib/index.mjs +1 -1
- package/dist/lib/upstash/qstash.d.ts +20 -7
- package/dist/lib/upstash/qstash.d.ts.map +1 -1
- package/dist/lib/upstash/qstash.js +33 -7
- package/dist/lib/upstash/qstash.mjs +33 -7
- package/dist/lib/upstash/redis-structures.d.ts +83 -0
- package/dist/lib/upstash/redis-structures.d.ts.map +1 -1
- package/dist/lib/upstash/redis-structures.js +220 -0
- package/dist/lib/upstash/redis-structures.mjs +202 -1
- package/dist/lib/upstash-config.d.ts.map +1 -1
- package/dist/lib/upstash-config.js +76 -4
- package/dist/lib/upstash-config.mjs +76 -4
- package/dist/services/ai/abort.d.ts +2 -0
- package/dist/services/ai/abort.d.ts.map +1 -0
- package/dist/services/ai/abort.js +24 -0
- package/dist/services/ai/abort.mjs +22 -0
- package/dist/services/ai/env.d.ts +21 -0
- package/dist/services/ai/env.d.ts.map +1 -0
- package/dist/services/ai/env.js +85 -0
- package/dist/services/ai/env.mjs +80 -0
- package/dist/services/ai/error.d.ts +3 -0
- package/dist/services/ai/error.d.ts.map +1 -0
- package/dist/services/ai/error.js +54 -0
- package/dist/services/ai/error.mjs +52 -0
- package/dist/services/ai/index.d.ts +9 -0
- package/dist/services/ai/index.d.ts.map +1 -0
- package/dist/services/ai/index.js +30 -0
- package/dist/services/ai/index.mjs +7 -0
- package/dist/services/ai/message-builder.d.ts +4 -0
- package/dist/services/ai/message-builder.d.ts.map +1 -0
- package/dist/services/ai/message-builder.js +15 -0
- package/dist/services/ai/message-builder.mjs +13 -0
- package/dist/services/ai/mock.d.ts +30 -0
- package/dist/services/ai/mock.d.ts.map +1 -0
- package/dist/services/ai/mock.js +314 -0
- package/dist/services/ai/mock.mjs +308 -0
- package/dist/services/ai/openrouter-client.d.ts +12 -0
- package/dist/services/ai/openrouter-client.d.ts.map +1 -0
- package/dist/services/ai/openrouter-client.js +81 -0
- package/dist/services/ai/openrouter-client.mjs +78 -0
- package/dist/services/ai/route.d.ts +6 -0
- package/dist/services/ai/route.d.ts.map +1 -0
- package/dist/services/ai/route.js +178 -0
- package/dist/services/ai/route.mjs +173 -0
- package/dist/services/ai/types.d.ts +98 -0
- package/dist/services/ai/types.d.ts.map +1 -0
- package/package.json +11 -4
- package/src/index.ts +1 -0
- package/src/lib/upstash/qstash.ts +55 -15
- package/src/lib/upstash/redis-structures.ts +248 -0
- package/src/lib/upstash-config.ts +106 -4
- package/src/services/ai/abort.ts +26 -0
- package/src/services/ai/env.ts +120 -0
- package/src/services/ai/error.ts +64 -0
- package/src/services/ai/index.ts +8 -0
- package/src/services/ai/message-builder.ts +17 -0
- package/src/services/ai/mock.ts +378 -0
- package/src/services/ai/openrouter-client.ts +94 -0
- package/src/services/ai/route.ts +218 -0
- package/src/services/ai/types.ts +131 -0
|
@@ -22,6 +22,30 @@ const setString = (key, value, ttlSec) => tslib.__awaiter(void 0, void 0, void 0
|
|
|
22
22
|
const getString = (key) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
23
23
|
return upstashConfig.withRedis((redis) => redis.get(key));
|
|
24
24
|
});
|
|
25
|
+
/**
|
|
26
|
+
* MGET plain string values. Missing keys are returned as null.
|
|
27
|
+
*/
|
|
28
|
+
const mget = (keys) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
29
|
+
return upstashConfig.withRedis((redis) => {
|
|
30
|
+
if (keys.length === 0) {
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
return redis.mget(...keys);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
/**
|
|
37
|
+
* MSET plain string values.
|
|
38
|
+
*/
|
|
39
|
+
const mset = (entries) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
40
|
+
const keys = Object.keys(entries);
|
|
41
|
+
if (keys.length === 0) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
return upstashConfig.withRedis((redis) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
45
|
+
yield redis.mset(entries);
|
|
46
|
+
return true;
|
|
47
|
+
})).then((result) => result !== null && result !== void 0 ? result : false);
|
|
48
|
+
});
|
|
25
49
|
/**
|
|
26
50
|
* Store an object as JSON string with optional TTL (seconds).
|
|
27
51
|
*/
|
|
@@ -53,6 +77,42 @@ const getJson = (key) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
|
53
77
|
}
|
|
54
78
|
}));
|
|
55
79
|
});
|
|
80
|
+
/**
|
|
81
|
+
* MGET JSON values stored as strings. Missing or invalid values are returned as null.
|
|
82
|
+
*/
|
|
83
|
+
const mgetJson = (keys) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
84
|
+
return upstashConfig.withRedis((redis) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
85
|
+
if (keys.length === 0) {
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
88
|
+
const payloads = yield redis.mget(...keys);
|
|
89
|
+
return payloads.map((payload) => {
|
|
90
|
+
if (!payload) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
return JSON.parse(payload);
|
|
95
|
+
}
|
|
96
|
+
catch (_a) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}));
|
|
101
|
+
});
|
|
102
|
+
/**
|
|
103
|
+
* MSET JSON values as strings.
|
|
104
|
+
*/
|
|
105
|
+
const msetJson = (entries) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
106
|
+
const keys = Object.keys(entries);
|
|
107
|
+
if (keys.length === 0) {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
const payloads = Object.fromEntries(Object.entries(entries).map(([key, value]) => [key, JSON.stringify(value)]));
|
|
111
|
+
return upstashConfig.withRedis((redis) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
112
|
+
yield redis.mset(payloads);
|
|
113
|
+
return true;
|
|
114
|
+
})).then((result) => result !== null && result !== void 0 ? result : false);
|
|
115
|
+
});
|
|
56
116
|
/**
|
|
57
117
|
* Delete a key. Returns false if Redis is unavailable.
|
|
58
118
|
*/
|
|
@@ -63,6 +123,45 @@ const deleteKey = (key) => tslib.__awaiter(void 0, void 0, void 0, function* ()
|
|
|
63
123
|
}));
|
|
64
124
|
return result !== null && result !== void 0 ? result : false;
|
|
65
125
|
});
|
|
126
|
+
/**
|
|
127
|
+
* DEL multiple keys. Returns deleted count, or null if Redis is unavailable.
|
|
128
|
+
*/
|
|
129
|
+
const del = (keys) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
130
|
+
return upstashConfig.withRedis((redis) => {
|
|
131
|
+
if (keys.length === 0) {
|
|
132
|
+
return 0;
|
|
133
|
+
}
|
|
134
|
+
return redis.del(...keys);
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
/**
|
|
138
|
+
* EXISTS a key.
|
|
139
|
+
*/
|
|
140
|
+
const exists = (key) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
141
|
+
return upstashConfig.withRedis((redis) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
142
|
+
const count = yield redis.exists(key);
|
|
143
|
+
return count > 0;
|
|
144
|
+
}));
|
|
145
|
+
});
|
|
146
|
+
/**
|
|
147
|
+
* EXPIRE a key in seconds.
|
|
148
|
+
*/
|
|
149
|
+
const expire = (key, ttlSec) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
150
|
+
if (ttlSec <= 0) {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
const result = yield upstashConfig.withRedis((redis) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
154
|
+
const changed = yield redis.expire(key, ttlSec);
|
|
155
|
+
return changed > 0;
|
|
156
|
+
}));
|
|
157
|
+
return result !== null && result !== void 0 ? result : false;
|
|
158
|
+
});
|
|
159
|
+
/**
|
|
160
|
+
* TTL for a key in seconds. Returns null if Redis is unavailable.
|
|
161
|
+
*/
|
|
162
|
+
const ttl = (key) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
163
|
+
return upstashConfig.withRedis((redis) => redis.ttl(key));
|
|
164
|
+
});
|
|
66
165
|
/**
|
|
67
166
|
* Set a hash field value.
|
|
68
167
|
*/
|
|
@@ -79,6 +178,35 @@ const setHashField = (key, field, value) => tslib.__awaiter(void 0, void 0, void
|
|
|
79
178
|
const getHashField = (key, field) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
80
179
|
return upstashConfig.withRedis((redis) => redis.hget(key, field));
|
|
81
180
|
});
|
|
181
|
+
/**
|
|
182
|
+
* HMSET hash fields.
|
|
183
|
+
*/
|
|
184
|
+
const hmset = (key, values) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
185
|
+
const fields = Object.keys(values);
|
|
186
|
+
if (fields.length === 0) {
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
const result = yield upstashConfig.withRedis((redis) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
190
|
+
yield redis.hset(key, values);
|
|
191
|
+
return true;
|
|
192
|
+
}));
|
|
193
|
+
return result !== null && result !== void 0 ? result : false;
|
|
194
|
+
});
|
|
195
|
+
/**
|
|
196
|
+
* HMGET hash fields.
|
|
197
|
+
*/
|
|
198
|
+
const hmget = (key, fields) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
199
|
+
return upstashConfig.withRedis((redis) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
200
|
+
if (fields.length === 0) {
|
|
201
|
+
return {};
|
|
202
|
+
}
|
|
203
|
+
const result = yield redis.hmget(key, ...fields);
|
|
204
|
+
if (!result) {
|
|
205
|
+
return Object.fromEntries(fields.map((field) => [field, null]));
|
|
206
|
+
}
|
|
207
|
+
return result;
|
|
208
|
+
}));
|
|
209
|
+
});
|
|
82
210
|
/**
|
|
83
211
|
* Store a hash field as JSON string.
|
|
84
212
|
*/
|
|
@@ -116,6 +244,27 @@ const getHashAll = (key) => tslib.__awaiter(void 0, void 0, void 0, function* ()
|
|
|
116
244
|
return result !== null && result !== void 0 ? result : {};
|
|
117
245
|
}));
|
|
118
246
|
});
|
|
247
|
+
/**
|
|
248
|
+
* HEXISTS a hash field.
|
|
249
|
+
*/
|
|
250
|
+
const hexists = (key, field) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
251
|
+
return upstashConfig.withRedis((redis) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
252
|
+
const exists = yield redis.hexists(key, field);
|
|
253
|
+
return exists > 0;
|
|
254
|
+
}));
|
|
255
|
+
});
|
|
256
|
+
/**
|
|
257
|
+
* HKEYS for a hash.
|
|
258
|
+
*/
|
|
259
|
+
const hkeys = (key) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
260
|
+
return upstashConfig.withRedis((redis) => redis.hkeys(key));
|
|
261
|
+
});
|
|
262
|
+
/**
|
|
263
|
+
* HLEN for a hash.
|
|
264
|
+
*/
|
|
265
|
+
const hlen = (key) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
266
|
+
return upstashConfig.withRedis((redis) => redis.hlen(key));
|
|
267
|
+
});
|
|
119
268
|
/**
|
|
120
269
|
* Remove a hash field.
|
|
121
270
|
*/
|
|
@@ -126,6 +275,49 @@ const deleteHashField = (key, field) => tslib.__awaiter(void 0, void 0, void 0,
|
|
|
126
275
|
}));
|
|
127
276
|
return result !== null && result !== void 0 ? result : false;
|
|
128
277
|
});
|
|
278
|
+
/**
|
|
279
|
+
* SADD members to a set. Returns count of newly added members, or null if Redis is unavailable.
|
|
280
|
+
*/
|
|
281
|
+
const sadd = (key, members) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
282
|
+
return upstashConfig.withRedis((redis) => {
|
|
283
|
+
if (members.length === 0) {
|
|
284
|
+
return 0;
|
|
285
|
+
}
|
|
286
|
+
return redis.sadd(key, members[0], ...members.slice(1));
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
/**
|
|
290
|
+
* SREM members from a set. Returns count of removed members, or null if Redis is unavailable.
|
|
291
|
+
*/
|
|
292
|
+
const srem = (key, members) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
293
|
+
return upstashConfig.withRedis((redis) => {
|
|
294
|
+
if (members.length === 0) {
|
|
295
|
+
return 0;
|
|
296
|
+
}
|
|
297
|
+
return redis.srem(key, ...members);
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
/**
|
|
301
|
+
* SISMEMBER for a set member.
|
|
302
|
+
*/
|
|
303
|
+
const sismember = (key, member) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
304
|
+
return upstashConfig.withRedis((redis) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
305
|
+
const exists = yield redis.sismember(key, member);
|
|
306
|
+
return exists > 0;
|
|
307
|
+
}));
|
|
308
|
+
});
|
|
309
|
+
/**
|
|
310
|
+
* SMEMBERS for a set.
|
|
311
|
+
*/
|
|
312
|
+
const smembers = (key) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
313
|
+
return upstashConfig.withRedis((redis) => redis.smembers(key));
|
|
314
|
+
});
|
|
315
|
+
/**
|
|
316
|
+
* SCARD for a set.
|
|
317
|
+
*/
|
|
318
|
+
const scard = (key) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
319
|
+
return upstashConfig.withRedis((redis) => redis.scard(key));
|
|
320
|
+
});
|
|
129
321
|
/**
|
|
130
322
|
* Push values to a list. Returns list length or null if Redis is unavailable.
|
|
131
323
|
*/
|
|
@@ -157,19 +349,47 @@ const rangeList = (key_1, ...args_1) => tslib.__awaiter(void 0, [key_1, ...args_
|
|
|
157
349
|
const listLength = (key) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
158
350
|
return upstashConfig.withRedis((redis) => redis.llen(key));
|
|
159
351
|
});
|
|
352
|
+
/**
|
|
353
|
+
* Execute a Redis pipeline and return the result array from exec().
|
|
354
|
+
*/
|
|
355
|
+
const pipeline = (build) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
356
|
+
return upstashConfig.withRedis((redis) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
357
|
+
const pipeline = redis.pipeline();
|
|
358
|
+
return build(pipeline).exec();
|
|
359
|
+
}));
|
|
360
|
+
});
|
|
160
361
|
|
|
362
|
+
exports.del = del;
|
|
161
363
|
exports.deleteHashField = deleteHashField;
|
|
162
364
|
exports.deleteKey = deleteKey;
|
|
365
|
+
exports.exists = exists;
|
|
366
|
+
exports.expire = expire;
|
|
163
367
|
exports.getHashAll = getHashAll;
|
|
164
368
|
exports.getHashField = getHashField;
|
|
165
369
|
exports.getHashJson = getHashJson;
|
|
166
370
|
exports.getJson = getJson;
|
|
167
371
|
exports.getString = getString;
|
|
372
|
+
exports.hexists = hexists;
|
|
373
|
+
exports.hkeys = hkeys;
|
|
374
|
+
exports.hlen = hlen;
|
|
375
|
+
exports.hmget = hmget;
|
|
376
|
+
exports.hmset = hmset;
|
|
168
377
|
exports.listLength = listLength;
|
|
378
|
+
exports.mget = mget;
|
|
379
|
+
exports.mgetJson = mgetJson;
|
|
380
|
+
exports.mset = mset;
|
|
381
|
+
exports.msetJson = msetJson;
|
|
382
|
+
exports.pipeline = pipeline;
|
|
169
383
|
exports.popList = popList;
|
|
170
384
|
exports.pushList = pushList;
|
|
171
385
|
exports.rangeList = rangeList;
|
|
386
|
+
exports.sadd = sadd;
|
|
387
|
+
exports.scard = scard;
|
|
172
388
|
exports.setHashField = setHashField;
|
|
173
389
|
exports.setHashJson = setHashJson;
|
|
174
390
|
exports.setJson = setJson;
|
|
175
391
|
exports.setString = setString;
|
|
392
|
+
exports.sismember = sismember;
|
|
393
|
+
exports.smembers = smembers;
|
|
394
|
+
exports.srem = srem;
|
|
395
|
+
exports.ttl = ttl;
|
|
@@ -20,6 +20,30 @@ const setString = (key, value, ttlSec) => __awaiter(void 0, void 0, void 0, func
|
|
|
20
20
|
const getString = (key) => __awaiter(void 0, void 0, void 0, function* () {
|
|
21
21
|
return withRedis((redis) => redis.get(key));
|
|
22
22
|
});
|
|
23
|
+
/**
|
|
24
|
+
* MGET plain string values. Missing keys are returned as null.
|
|
25
|
+
*/
|
|
26
|
+
const mget = (keys) => __awaiter(void 0, void 0, void 0, function* () {
|
|
27
|
+
return withRedis((redis) => {
|
|
28
|
+
if (keys.length === 0) {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
return redis.mget(...keys);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
/**
|
|
35
|
+
* MSET plain string values.
|
|
36
|
+
*/
|
|
37
|
+
const mset = (entries) => __awaiter(void 0, void 0, void 0, function* () {
|
|
38
|
+
const keys = Object.keys(entries);
|
|
39
|
+
if (keys.length === 0) {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
return withRedis((redis) => __awaiter(void 0, void 0, void 0, function* () {
|
|
43
|
+
yield redis.mset(entries);
|
|
44
|
+
return true;
|
|
45
|
+
})).then((result) => result !== null && result !== void 0 ? result : false);
|
|
46
|
+
});
|
|
23
47
|
/**
|
|
24
48
|
* Store an object as JSON string with optional TTL (seconds).
|
|
25
49
|
*/
|
|
@@ -51,6 +75,42 @@ const getJson = (key) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
51
75
|
}
|
|
52
76
|
}));
|
|
53
77
|
});
|
|
78
|
+
/**
|
|
79
|
+
* MGET JSON values stored as strings. Missing or invalid values are returned as null.
|
|
80
|
+
*/
|
|
81
|
+
const mgetJson = (keys) => __awaiter(void 0, void 0, void 0, function* () {
|
|
82
|
+
return withRedis((redis) => __awaiter(void 0, void 0, void 0, function* () {
|
|
83
|
+
if (keys.length === 0) {
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
const payloads = yield redis.mget(...keys);
|
|
87
|
+
return payloads.map((payload) => {
|
|
88
|
+
if (!payload) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
try {
|
|
92
|
+
return JSON.parse(payload);
|
|
93
|
+
}
|
|
94
|
+
catch (_a) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
}));
|
|
99
|
+
});
|
|
100
|
+
/**
|
|
101
|
+
* MSET JSON values as strings.
|
|
102
|
+
*/
|
|
103
|
+
const msetJson = (entries) => __awaiter(void 0, void 0, void 0, function* () {
|
|
104
|
+
const keys = Object.keys(entries);
|
|
105
|
+
if (keys.length === 0) {
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
const payloads = Object.fromEntries(Object.entries(entries).map(([key, value]) => [key, JSON.stringify(value)]));
|
|
109
|
+
return withRedis((redis) => __awaiter(void 0, void 0, void 0, function* () {
|
|
110
|
+
yield redis.mset(payloads);
|
|
111
|
+
return true;
|
|
112
|
+
})).then((result) => result !== null && result !== void 0 ? result : false);
|
|
113
|
+
});
|
|
54
114
|
/**
|
|
55
115
|
* Delete a key. Returns false if Redis is unavailable.
|
|
56
116
|
*/
|
|
@@ -61,6 +121,45 @@ const deleteKey = (key) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
61
121
|
}));
|
|
62
122
|
return result !== null && result !== void 0 ? result : false;
|
|
63
123
|
});
|
|
124
|
+
/**
|
|
125
|
+
* DEL multiple keys. Returns deleted count, or null if Redis is unavailable.
|
|
126
|
+
*/
|
|
127
|
+
const del = (keys) => __awaiter(void 0, void 0, void 0, function* () {
|
|
128
|
+
return withRedis((redis) => {
|
|
129
|
+
if (keys.length === 0) {
|
|
130
|
+
return 0;
|
|
131
|
+
}
|
|
132
|
+
return redis.del(...keys);
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
/**
|
|
136
|
+
* EXISTS a key.
|
|
137
|
+
*/
|
|
138
|
+
const exists = (key) => __awaiter(void 0, void 0, void 0, function* () {
|
|
139
|
+
return withRedis((redis) => __awaiter(void 0, void 0, void 0, function* () {
|
|
140
|
+
const count = yield redis.exists(key);
|
|
141
|
+
return count > 0;
|
|
142
|
+
}));
|
|
143
|
+
});
|
|
144
|
+
/**
|
|
145
|
+
* EXPIRE a key in seconds.
|
|
146
|
+
*/
|
|
147
|
+
const expire = (key, ttlSec) => __awaiter(void 0, void 0, void 0, function* () {
|
|
148
|
+
if (ttlSec <= 0) {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
const result = yield withRedis((redis) => __awaiter(void 0, void 0, void 0, function* () {
|
|
152
|
+
const changed = yield redis.expire(key, ttlSec);
|
|
153
|
+
return changed > 0;
|
|
154
|
+
}));
|
|
155
|
+
return result !== null && result !== void 0 ? result : false;
|
|
156
|
+
});
|
|
157
|
+
/**
|
|
158
|
+
* TTL for a key in seconds. Returns null if Redis is unavailable.
|
|
159
|
+
*/
|
|
160
|
+
const ttl = (key) => __awaiter(void 0, void 0, void 0, function* () {
|
|
161
|
+
return withRedis((redis) => redis.ttl(key));
|
|
162
|
+
});
|
|
64
163
|
/**
|
|
65
164
|
* Set a hash field value.
|
|
66
165
|
*/
|
|
@@ -77,6 +176,35 @@ const setHashField = (key, field, value) => __awaiter(void 0, void 0, void 0, fu
|
|
|
77
176
|
const getHashField = (key, field) => __awaiter(void 0, void 0, void 0, function* () {
|
|
78
177
|
return withRedis((redis) => redis.hget(key, field));
|
|
79
178
|
});
|
|
179
|
+
/**
|
|
180
|
+
* HMSET hash fields.
|
|
181
|
+
*/
|
|
182
|
+
const hmset = (key, values) => __awaiter(void 0, void 0, void 0, function* () {
|
|
183
|
+
const fields = Object.keys(values);
|
|
184
|
+
if (fields.length === 0) {
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
const result = yield withRedis((redis) => __awaiter(void 0, void 0, void 0, function* () {
|
|
188
|
+
yield redis.hset(key, values);
|
|
189
|
+
return true;
|
|
190
|
+
}));
|
|
191
|
+
return result !== null && result !== void 0 ? result : false;
|
|
192
|
+
});
|
|
193
|
+
/**
|
|
194
|
+
* HMGET hash fields.
|
|
195
|
+
*/
|
|
196
|
+
const hmget = (key, fields) => __awaiter(void 0, void 0, void 0, function* () {
|
|
197
|
+
return withRedis((redis) => __awaiter(void 0, void 0, void 0, function* () {
|
|
198
|
+
if (fields.length === 0) {
|
|
199
|
+
return {};
|
|
200
|
+
}
|
|
201
|
+
const result = yield redis.hmget(key, ...fields);
|
|
202
|
+
if (!result) {
|
|
203
|
+
return Object.fromEntries(fields.map((field) => [field, null]));
|
|
204
|
+
}
|
|
205
|
+
return result;
|
|
206
|
+
}));
|
|
207
|
+
});
|
|
80
208
|
/**
|
|
81
209
|
* Store a hash field as JSON string.
|
|
82
210
|
*/
|
|
@@ -114,6 +242,27 @@ const getHashAll = (key) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
114
242
|
return result !== null && result !== void 0 ? result : {};
|
|
115
243
|
}));
|
|
116
244
|
});
|
|
245
|
+
/**
|
|
246
|
+
* HEXISTS a hash field.
|
|
247
|
+
*/
|
|
248
|
+
const hexists = (key, field) => __awaiter(void 0, void 0, void 0, function* () {
|
|
249
|
+
return withRedis((redis) => __awaiter(void 0, void 0, void 0, function* () {
|
|
250
|
+
const exists = yield redis.hexists(key, field);
|
|
251
|
+
return exists > 0;
|
|
252
|
+
}));
|
|
253
|
+
});
|
|
254
|
+
/**
|
|
255
|
+
* HKEYS for a hash.
|
|
256
|
+
*/
|
|
257
|
+
const hkeys = (key) => __awaiter(void 0, void 0, void 0, function* () {
|
|
258
|
+
return withRedis((redis) => redis.hkeys(key));
|
|
259
|
+
});
|
|
260
|
+
/**
|
|
261
|
+
* HLEN for a hash.
|
|
262
|
+
*/
|
|
263
|
+
const hlen = (key) => __awaiter(void 0, void 0, void 0, function* () {
|
|
264
|
+
return withRedis((redis) => redis.hlen(key));
|
|
265
|
+
});
|
|
117
266
|
/**
|
|
118
267
|
* Remove a hash field.
|
|
119
268
|
*/
|
|
@@ -124,6 +273,49 @@ const deleteHashField = (key, field) => __awaiter(void 0, void 0, void 0, functi
|
|
|
124
273
|
}));
|
|
125
274
|
return result !== null && result !== void 0 ? result : false;
|
|
126
275
|
});
|
|
276
|
+
/**
|
|
277
|
+
* SADD members to a set. Returns count of newly added members, or null if Redis is unavailable.
|
|
278
|
+
*/
|
|
279
|
+
const sadd = (key, members) => __awaiter(void 0, void 0, void 0, function* () {
|
|
280
|
+
return withRedis((redis) => {
|
|
281
|
+
if (members.length === 0) {
|
|
282
|
+
return 0;
|
|
283
|
+
}
|
|
284
|
+
return redis.sadd(key, members[0], ...members.slice(1));
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
/**
|
|
288
|
+
* SREM members from a set. Returns count of removed members, or null if Redis is unavailable.
|
|
289
|
+
*/
|
|
290
|
+
const srem = (key, members) => __awaiter(void 0, void 0, void 0, function* () {
|
|
291
|
+
return withRedis((redis) => {
|
|
292
|
+
if (members.length === 0) {
|
|
293
|
+
return 0;
|
|
294
|
+
}
|
|
295
|
+
return redis.srem(key, ...members);
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
/**
|
|
299
|
+
* SISMEMBER for a set member.
|
|
300
|
+
*/
|
|
301
|
+
const sismember = (key, member) => __awaiter(void 0, void 0, void 0, function* () {
|
|
302
|
+
return withRedis((redis) => __awaiter(void 0, void 0, void 0, function* () {
|
|
303
|
+
const exists = yield redis.sismember(key, member);
|
|
304
|
+
return exists > 0;
|
|
305
|
+
}));
|
|
306
|
+
});
|
|
307
|
+
/**
|
|
308
|
+
* SMEMBERS for a set.
|
|
309
|
+
*/
|
|
310
|
+
const smembers = (key) => __awaiter(void 0, void 0, void 0, function* () {
|
|
311
|
+
return withRedis((redis) => redis.smembers(key));
|
|
312
|
+
});
|
|
313
|
+
/**
|
|
314
|
+
* SCARD for a set.
|
|
315
|
+
*/
|
|
316
|
+
const scard = (key) => __awaiter(void 0, void 0, void 0, function* () {
|
|
317
|
+
return withRedis((redis) => redis.scard(key));
|
|
318
|
+
});
|
|
127
319
|
/**
|
|
128
320
|
* Push values to a list. Returns list length or null if Redis is unavailable.
|
|
129
321
|
*/
|
|
@@ -155,5 +347,14 @@ const rangeList = (key_1, ...args_1) => __awaiter(void 0, [key_1, ...args_1], vo
|
|
|
155
347
|
const listLength = (key) => __awaiter(void 0, void 0, void 0, function* () {
|
|
156
348
|
return withRedis((redis) => redis.llen(key));
|
|
157
349
|
});
|
|
350
|
+
/**
|
|
351
|
+
* Execute a Redis pipeline and return the result array from exec().
|
|
352
|
+
*/
|
|
353
|
+
const pipeline = (build) => __awaiter(void 0, void 0, void 0, function* () {
|
|
354
|
+
return withRedis((redis) => __awaiter(void 0, void 0, void 0, function* () {
|
|
355
|
+
const pipeline = redis.pipeline();
|
|
356
|
+
return build(pipeline).exec();
|
|
357
|
+
}));
|
|
358
|
+
});
|
|
158
359
|
|
|
159
|
-
export { deleteHashField, deleteKey, getHashAll, getHashField, getHashJson, getJson, getString, listLength, popList, pushList, rangeList, setHashField, setHashJson, setJson, setString };
|
|
360
|
+
export { del, deleteHashField, deleteKey, exists, expire, getHashAll, getHashField, getHashJson, getJson, getString, hexists, hkeys, hlen, hmget, hmset, listLength, mget, mgetJson, mset, msetJson, pipeline, popList, pushList, rangeList, sadd, scard, setHashField, setHashJson, setJson, setString, sismember, smembers, srem, ttl };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upstash-config.d.ts","sourceRoot":"","sources":["../../src/lib/upstash-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"upstash-config.d.ts","sourceRoot":"","sources":["../../src/lib/upstash-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAwOzD;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,QAAO,KAAK,GAAG,IAEnC,CAAC;AAwDF;;;;;GAKG;AACH,eAAO,MAAM,SAAS,QAAO,YAAY,GAAG,IAE3C,CAAC;AAyCF,eAAO,MAAM,SAAS,GAAU,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,KAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAMzF,CAAC;AAEF,eAAO,MAAM,UAAU,GAAU,CAAC,EAChC,IAAI,CAAC,MAAM,EAAE,YAAY,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,KAC3C,OAAO,CAAC,CAAC,GAAG,IAAI,CAMlB,CAAC"}
|
|
@@ -19,6 +19,7 @@ let qstashWarnedHealthCheck = false;
|
|
|
19
19
|
let qstashWarnedHealthSchedule = false;
|
|
20
20
|
let redisHealthTimer = null;
|
|
21
21
|
let qstashHealthTimer = null;
|
|
22
|
+
let cachedRedisPrefixed = null;
|
|
22
23
|
const isNonEmpty = (value) => typeof value === 'string' && value.trim().length > 0;
|
|
23
24
|
const isValidUrl = (value) => {
|
|
24
25
|
try {
|
|
@@ -29,6 +30,75 @@ const isValidUrl = (value) => {
|
|
|
29
30
|
return false;
|
|
30
31
|
}
|
|
31
32
|
};
|
|
33
|
+
const getRequiredRedisAppName = () => {
|
|
34
|
+
const appName = process.env.NEXT_PUBLIC_APP_NAME;
|
|
35
|
+
if (!isNonEmpty(appName)) {
|
|
36
|
+
throw new Error('[Upstash Config] NEXT_PUBLIC_APP_NAME is required for Redis key prefixing and must not be empty');
|
|
37
|
+
}
|
|
38
|
+
const normalized = appName.replace(/\s+/g, '').toLowerCase();
|
|
39
|
+
if (!normalized) {
|
|
40
|
+
throw new Error('[Upstash Config] NEXT_PUBLIC_APP_NAME must contain non-whitespace characters for Redis key prefixing');
|
|
41
|
+
}
|
|
42
|
+
return normalized;
|
|
43
|
+
};
|
|
44
|
+
const getRedisKeyPrefix = () => {
|
|
45
|
+
const envSuffix = process.env.NODE_ENV === 'production' ? 'live' : 'test';
|
|
46
|
+
return `${getRequiredRedisAppName()}_${envSuffix}`;
|
|
47
|
+
};
|
|
48
|
+
const prefixRedisKey = (prefix, key) => `${prefix}:${key}`;
|
|
49
|
+
const prefixRedisKeys = (prefix, keys) => keys.map((key) => prefixRedisKey(prefix, key));
|
|
50
|
+
const prefixFirstStringArg = (args, prefix) => {
|
|
51
|
+
if (typeof args[0] !== 'string') {
|
|
52
|
+
return args;
|
|
53
|
+
}
|
|
54
|
+
const nextArgs = [...args];
|
|
55
|
+
nextArgs[0] = prefixRedisKey(prefix, args[0]);
|
|
56
|
+
return nextArgs;
|
|
57
|
+
};
|
|
58
|
+
const prefixAllStringArgs = (args, prefix) => {
|
|
59
|
+
return args.map((arg) => (typeof arg === 'string' ? prefixRedisKey(prefix, arg) : arg));
|
|
60
|
+
};
|
|
61
|
+
const keyArrayCommands = new Set(['mget', 'del']);
|
|
62
|
+
const allStringKeyCommands = new Set(['exists']);
|
|
63
|
+
const createPrefixedPipeline = (target, prefix) => {
|
|
64
|
+
return new Proxy(target, {
|
|
65
|
+
get(obj, prop, receiver) {
|
|
66
|
+
const value = Reflect.get(obj, prop, receiver);
|
|
67
|
+
if (typeof value !== 'function') {
|
|
68
|
+
return value;
|
|
69
|
+
}
|
|
70
|
+
return (...args) => {
|
|
71
|
+
if (prop === 'eval' || prop === 'evalsha' || prop === 'evalro' || prop === 'evalshaRo') {
|
|
72
|
+
const [script, keys, argv] = args;
|
|
73
|
+
return value.call(obj, script, prefixRedisKeys(prefix, keys), argv);
|
|
74
|
+
}
|
|
75
|
+
if (prop === 'pipeline' || prop === 'multi') {
|
|
76
|
+
const nested = value.call(obj);
|
|
77
|
+
return createPrefixedPipeline(nested, prefix);
|
|
78
|
+
}
|
|
79
|
+
if (typeof prop === 'string' && keyArrayCommands.has(prop)) {
|
|
80
|
+
const nextArgs = prefixAllStringArgs(args, prefix);
|
|
81
|
+
return value.apply(obj, nextArgs);
|
|
82
|
+
}
|
|
83
|
+
if (typeof prop === 'string' && allStringKeyCommands.has(prop)) {
|
|
84
|
+
const nextArgs = prefixAllStringArgs(args, prefix);
|
|
85
|
+
return value.apply(obj, nextArgs);
|
|
86
|
+
}
|
|
87
|
+
if (prop === 'mset') {
|
|
88
|
+
const [entries] = args;
|
|
89
|
+
const prefixedEntries = Object.fromEntries(Object.entries(entries).map(([key, entryValue]) => [prefixRedisKey(prefix, key), entryValue]));
|
|
90
|
+
return value.call(obj, prefixedEntries);
|
|
91
|
+
}
|
|
92
|
+
if (prop === 'hmget') {
|
|
93
|
+
const nextArgs = prefixFirstStringArg(args, prefix);
|
|
94
|
+
return value.apply(obj, nextArgs);
|
|
95
|
+
}
|
|
96
|
+
const nextArgs = prefixFirstStringArg(args, prefix);
|
|
97
|
+
return value.apply(obj, nextArgs);
|
|
98
|
+
};
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
};
|
|
32
102
|
const parseMinutes = (value, fallback) => {
|
|
33
103
|
if (!isNonEmpty(value)) {
|
|
34
104
|
return fallback;
|
|
@@ -131,11 +201,11 @@ const scheduleQstashHealthCheck = (token) => {
|
|
|
131
201
|
* - read-through cached instance only
|
|
132
202
|
*/
|
|
133
203
|
const getRedis = () => {
|
|
134
|
-
return
|
|
204
|
+
return cachedRedisPrefixed;
|
|
135
205
|
};
|
|
136
206
|
const ensureRedis = () => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
137
|
-
if (
|
|
138
|
-
return
|
|
207
|
+
if (cachedRedisPrefixed) {
|
|
208
|
+
return cachedRedisPrefixed;
|
|
139
209
|
}
|
|
140
210
|
if (redisInitPromise) {
|
|
141
211
|
return redisInitPromise;
|
|
@@ -157,14 +227,16 @@ const ensureRedis = () => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
|
157
227
|
return null;
|
|
158
228
|
}
|
|
159
229
|
try {
|
|
230
|
+
const keyPrefix = getRedisKeyPrefix();
|
|
160
231
|
const client = new redis.Redis({
|
|
161
232
|
url: UPSTASH_REDIS_REST_URL,
|
|
162
233
|
token: UPSTASH_REDIS_REST_TOKEN,
|
|
163
234
|
});
|
|
164
235
|
yield client.ping();
|
|
165
236
|
cachedRedis = client;
|
|
237
|
+
cachedRedisPrefixed = createPrefixedPipeline(client, keyPrefix);
|
|
166
238
|
scheduleRedisHealthCheck();
|
|
167
|
-
return
|
|
239
|
+
return cachedRedisPrefixed;
|
|
168
240
|
}
|
|
169
241
|
catch (error) {
|
|
170
242
|
if (!redisWarnedInitError) {
|