@nexusts/redis 0.7.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/README.md +45 -0
- package/dist/index.js +440 -0
- package/dist/index.js.map +15 -0
- package/package.json +39 -0
package/README.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# @nexusts/redis
|
|
2
|
+
|
|
3
|
+
> **NexusTS** — Bun-native fullstack framework
|
|
4
|
+
|
|
5
|
+
## Description
|
|
6
|
+
|
|
7
|
+
Runtime-aware Redis client (Bun / Node / Workers).
|
|
8
|
+
|
|
9
|
+
One client, three runtimes. Powers the Drizzle-backend session, cache, and limiter stores.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
This module is part of the NexusTS monorepo. Each module is published as its own npm package under the `@nexusts/` scope.
|
|
14
|
+
|
|
15
|
+
Most apps start with just the core:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
bun add @nexusts/core reflect-metadata zod hono
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Then add this module only if you need it:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
bun add @nexusts/redis
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Peer dependencies
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
bun add ioredis
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Required by this module. Without them the module loads but its public methods throw a clear error pointing to this install command on first call.
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { /* public API */ } from "@nexusts/redis";
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
See the [user guide](../../docs/user-guide/redis.md) and the [example app](../../examples/) for a working demo.
|
|
42
|
+
|
|
43
|
+
## License
|
|
44
|
+
|
|
45
|
+
MIT — see the root [LICENSE](../../LICENSE).
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
8
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
9
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
10
|
+
for (let key of __getOwnPropNames(mod))
|
|
11
|
+
if (!__hasOwnProp.call(to, key))
|
|
12
|
+
__defProp(to, key, {
|
|
13
|
+
get: () => mod[key],
|
|
14
|
+
enumerable: true
|
|
15
|
+
});
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __legacyDecorateClassTS = function(decorators, target, key, desc) {
|
|
19
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
20
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
21
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
22
|
+
else
|
|
23
|
+
for (var i = decorators.length - 1;i >= 0; i--)
|
|
24
|
+
if (d = decorators[i])
|
|
25
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
26
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
27
|
+
};
|
|
28
|
+
var __require = import.meta.require;
|
|
29
|
+
|
|
30
|
+
// packages/redis/src/adapters/bun.ts
|
|
31
|
+
class BunRedisAdapter {
|
|
32
|
+
adapter = "bun";
|
|
33
|
+
client = null;
|
|
34
|
+
url;
|
|
35
|
+
keyPrefix;
|
|
36
|
+
defaultTtlSeconds;
|
|
37
|
+
constructor(config = {}) {
|
|
38
|
+
this.url = config.url ?? process.env["REDIS_URL"] ?? "redis://localhost:6379";
|
|
39
|
+
this.keyPrefix = config.keyPrefix ?? "";
|
|
40
|
+
this.defaultTtlSeconds = config.defaultTtlSeconds ?? 0;
|
|
41
|
+
}
|
|
42
|
+
getClient() {
|
|
43
|
+
if (this.client)
|
|
44
|
+
return this.client;
|
|
45
|
+
const bun = globalThis.Bun;
|
|
46
|
+
if (!bun || typeof bun.redis !== "function") {
|
|
47
|
+
throw new Error("BunRedisAdapter can only be used in a Bun runtime. " + "On Node, use NodeRedisAdapter (install ioredis).");
|
|
48
|
+
}
|
|
49
|
+
this.client = bun.redis(this.url);
|
|
50
|
+
return this.client;
|
|
51
|
+
}
|
|
52
|
+
k(key) {
|
|
53
|
+
return this.keyPrefix + key;
|
|
54
|
+
}
|
|
55
|
+
async get(key) {
|
|
56
|
+
return this.getClient().get(this.k(key));
|
|
57
|
+
}
|
|
58
|
+
async set(key, value, options) {
|
|
59
|
+
const ex = options?.ex ?? this.defaultTtlSeconds ?? undefined;
|
|
60
|
+
const px = options?.px ?? undefined;
|
|
61
|
+
const bunOpts = {};
|
|
62
|
+
if (ex)
|
|
63
|
+
bunOpts.EX = ex;
|
|
64
|
+
if (px)
|
|
65
|
+
bunOpts.PX = px;
|
|
66
|
+
if (options?.nx)
|
|
67
|
+
bunOpts.NX = true;
|
|
68
|
+
if (options?.xx)
|
|
69
|
+
bunOpts.XX = true;
|
|
70
|
+
await this.getClient().set(this.k(key), value, bunOpts);
|
|
71
|
+
}
|
|
72
|
+
async del(key) {
|
|
73
|
+
return this.getClient().del(this.k(key));
|
|
74
|
+
}
|
|
75
|
+
async exists(key) {
|
|
76
|
+
return await this.getClient().exists(this.k(key)) > 0;
|
|
77
|
+
}
|
|
78
|
+
async incr(key, by = 1, options) {
|
|
79
|
+
const fullKey = this.k(key);
|
|
80
|
+
const client = this.getClient();
|
|
81
|
+
const value = await client.incr(fullKey);
|
|
82
|
+
if (options?.ex && value === by) {
|
|
83
|
+
await client.set(fullKey, String(value), { EX: options.ex });
|
|
84
|
+
}
|
|
85
|
+
return value;
|
|
86
|
+
}
|
|
87
|
+
async scan(options = {}) {
|
|
88
|
+
const cursor = typeof options.cursor === "number" ? options.cursor : 0;
|
|
89
|
+
const res = await this.getClient().scan(cursor, {
|
|
90
|
+
MATCH: options.match ?? "*",
|
|
91
|
+
COUNT: options.count ?? 100
|
|
92
|
+
});
|
|
93
|
+
return {
|
|
94
|
+
cursor: res.cursor,
|
|
95
|
+
keys: (res.keys ?? []).map((k) => this.keyPrefix && k.startsWith(this.keyPrefix) ? k.slice(this.keyPrefix.length) : k)
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
async close() {
|
|
99
|
+
if (this.client) {
|
|
100
|
+
await this.client.close();
|
|
101
|
+
this.client = null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// packages/redis/src/adapters/cloudflare.ts
|
|
107
|
+
class CloudflareKVAdapter {
|
|
108
|
+
adapter = "cloudflare";
|
|
109
|
+
kv = null;
|
|
110
|
+
keyPrefix;
|
|
111
|
+
defaultTtlSeconds;
|
|
112
|
+
constructor(config = {}) {
|
|
113
|
+
this.keyPrefix = config.keyPrefix ?? "";
|
|
114
|
+
this.defaultTtlSeconds = config.defaultTtlSeconds ?? 0;
|
|
115
|
+
if (config.kv)
|
|
116
|
+
this.kv = config.kv;
|
|
117
|
+
}
|
|
118
|
+
getKV() {
|
|
119
|
+
if (this.kv)
|
|
120
|
+
return this.kv;
|
|
121
|
+
const env = globalThis.env;
|
|
122
|
+
if (env?.KV) {
|
|
123
|
+
this.kv = env.KV;
|
|
124
|
+
return this.kv;
|
|
125
|
+
}
|
|
126
|
+
throw new Error("CloudflareKVAdapter could not find a KV binding. " + "Pass it explicitly via RedisConfig({ kv }) or run inside a " + "Workers request handler where `c.env.KV` is available.");
|
|
127
|
+
}
|
|
128
|
+
k(key) {
|
|
129
|
+
return this.keyPrefix + key;
|
|
130
|
+
}
|
|
131
|
+
stripPrefix(key) {
|
|
132
|
+
return this.keyPrefix && key.startsWith(this.keyPrefix) ? key.slice(this.keyPrefix.length) : key;
|
|
133
|
+
}
|
|
134
|
+
async get(key) {
|
|
135
|
+
return this.getKV().get(this.k(key));
|
|
136
|
+
}
|
|
137
|
+
async set(key, value, options) {
|
|
138
|
+
const ex = options?.ex ?? this.defaultTtlSeconds ?? undefined;
|
|
139
|
+
if (ex && ex > 0) {
|
|
140
|
+
await this.getKV().put(this.k(key), value, { expirationTtl: ex });
|
|
141
|
+
} else {
|
|
142
|
+
await this.getKV().put(this.k(key), value);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
async del(key) {
|
|
146
|
+
const existed = await this.getKV().get(this.k(key)) !== null;
|
|
147
|
+
await this.getKV().delete(this.k(key));
|
|
148
|
+
return existed ? 1 : 0;
|
|
149
|
+
}
|
|
150
|
+
async exists(key) {
|
|
151
|
+
return await this.getKV().get(this.k(key)) !== null;
|
|
152
|
+
}
|
|
153
|
+
async incr(key, by = 1, options) {
|
|
154
|
+
const fullKey = this.k(key);
|
|
155
|
+
const raw = await this.getKV().get(fullKey);
|
|
156
|
+
const current = raw ? Number.parseInt(raw, 10) || 0 : 0;
|
|
157
|
+
const next = current + by;
|
|
158
|
+
const ex = options?.ex ?? this.defaultTtlSeconds ?? undefined;
|
|
159
|
+
if (ex && ex > 0) {
|
|
160
|
+
await this.getKV().put(fullKey, String(next), { expirationTtl: ex });
|
|
161
|
+
} else {
|
|
162
|
+
await this.getKV().put(fullKey, String(next));
|
|
163
|
+
}
|
|
164
|
+
return next;
|
|
165
|
+
}
|
|
166
|
+
async scan(options = {}) {
|
|
167
|
+
const match = options.match ?? "*";
|
|
168
|
+
const prefix = globToPrefix(match, this.keyPrefix);
|
|
169
|
+
const res = await this.getKV().list({
|
|
170
|
+
prefix,
|
|
171
|
+
limit: options.count ?? 100,
|
|
172
|
+
cursor: typeof options.cursor === "string" ? options.cursor : undefined
|
|
173
|
+
});
|
|
174
|
+
return {
|
|
175
|
+
cursor: res.cursor,
|
|
176
|
+
keys: (res.keys ?? []).map((k) => this.stripPrefix(k.name))
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
async close() {}
|
|
180
|
+
}
|
|
181
|
+
function globToPrefix(glob, keyPrefix) {
|
|
182
|
+
const meta = /[*?\[]/.exec(glob);
|
|
183
|
+
const base = meta ? glob.slice(0, meta.index) : glob;
|
|
184
|
+
return (keyPrefix ?? "") + base;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// packages/redis/src/adapters/memory.ts
|
|
188
|
+
class MemoryRedisAdapter {
|
|
189
|
+
adapter = "memory";
|
|
190
|
+
data = new Map;
|
|
191
|
+
keyPrefix;
|
|
192
|
+
defaultTtlSeconds;
|
|
193
|
+
constructor(config = {}) {
|
|
194
|
+
this.keyPrefix = config.keyPrefix ?? "";
|
|
195
|
+
this.defaultTtlSeconds = config.defaultTtlSeconds ?? 0;
|
|
196
|
+
}
|
|
197
|
+
k(key) {
|
|
198
|
+
return this.keyPrefix + key;
|
|
199
|
+
}
|
|
200
|
+
stripPrefix(key) {
|
|
201
|
+
return this.keyPrefix && key.startsWith(this.keyPrefix) ? key.slice(this.keyPrefix.length) : key;
|
|
202
|
+
}
|
|
203
|
+
isExpired(e) {
|
|
204
|
+
return !e || e.expiresAt !== null && e.expiresAt < Date.now();
|
|
205
|
+
}
|
|
206
|
+
purge(key) {
|
|
207
|
+
const e = this.data.get(key);
|
|
208
|
+
if (this.isExpired(e))
|
|
209
|
+
this.data.delete(key);
|
|
210
|
+
}
|
|
211
|
+
async get(key) {
|
|
212
|
+
const k = this.k(key);
|
|
213
|
+
this.purge(k);
|
|
214
|
+
const e = this.data.get(k);
|
|
215
|
+
return e ? e.value : null;
|
|
216
|
+
}
|
|
217
|
+
async set(key, value, options) {
|
|
218
|
+
const k = this.k(key);
|
|
219
|
+
const ttl = options?.ex !== undefined ? options.ex : options?.px !== undefined ? options.px / 1000 : this.defaultTtlSeconds;
|
|
220
|
+
const expiresAt = ttl && ttl > 0 ? Date.now() + ttl * 1000 : null;
|
|
221
|
+
if (options?.nx && !this.isExpired(this.data.get(k)))
|
|
222
|
+
return;
|
|
223
|
+
if (options?.xx && this.isExpired(this.data.get(k)))
|
|
224
|
+
return;
|
|
225
|
+
this.data.set(k, { value, expiresAt });
|
|
226
|
+
}
|
|
227
|
+
async del(key) {
|
|
228
|
+
const k = this.k(key);
|
|
229
|
+
const existed = this.data.delete(k);
|
|
230
|
+
return existed ? 1 : 0;
|
|
231
|
+
}
|
|
232
|
+
async exists(key) {
|
|
233
|
+
const k = this.k(key);
|
|
234
|
+
this.purge(k);
|
|
235
|
+
return this.data.has(k);
|
|
236
|
+
}
|
|
237
|
+
async incr(key, by = 1, options) {
|
|
238
|
+
const k = this.k(key);
|
|
239
|
+
this.purge(k);
|
|
240
|
+
const e = this.data.get(k);
|
|
241
|
+
const current = e ? Number.parseInt(e.value, 10) || 0 : 0;
|
|
242
|
+
const next = current + by;
|
|
243
|
+
const ttl = options?.ex ?? this.defaultTtlSeconds ?? undefined;
|
|
244
|
+
const expiresAt = ttl && ttl > 0 ? Date.now() + ttl * 1000 : null;
|
|
245
|
+
this.data.set(k, { value: String(next), expiresAt });
|
|
246
|
+
return next;
|
|
247
|
+
}
|
|
248
|
+
async scan(options = {}) {
|
|
249
|
+
const match = options.match ?? "*";
|
|
250
|
+
const re = globToRegex(match);
|
|
251
|
+
const keys = [];
|
|
252
|
+
for (const k of this.data.keys()) {
|
|
253
|
+
if (this.keyPrefix && !k.startsWith(this.keyPrefix))
|
|
254
|
+
continue;
|
|
255
|
+
if (re.test(k))
|
|
256
|
+
keys.push(this.stripPrefix(k));
|
|
257
|
+
}
|
|
258
|
+
return { cursor: "0", keys };
|
|
259
|
+
}
|
|
260
|
+
async close() {
|
|
261
|
+
this.data.clear();
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
function globToRegex(glob) {
|
|
265
|
+
const escaped = glob.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
|
|
266
|
+
return new RegExp("^" + escaped + "$");
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// packages/redis/src/adapters/node.ts
|
|
270
|
+
class NodeRedisAdapter {
|
|
271
|
+
adapter = "node";
|
|
272
|
+
client = null;
|
|
273
|
+
url;
|
|
274
|
+
keyPrefix;
|
|
275
|
+
defaultTtlSeconds;
|
|
276
|
+
nodeOptions;
|
|
277
|
+
constructor(config = {}) {
|
|
278
|
+
this.url = config.url ?? process.env["REDIS_URL"] ?? "redis://localhost:6379";
|
|
279
|
+
this.keyPrefix = config.keyPrefix ?? "";
|
|
280
|
+
this.defaultTtlSeconds = config.defaultTtlSeconds ?? 0;
|
|
281
|
+
this.nodeOptions = config.nodeOptions ?? {};
|
|
282
|
+
}
|
|
283
|
+
async getClient() {
|
|
284
|
+
if (this.client)
|
|
285
|
+
return this.client;
|
|
286
|
+
try {
|
|
287
|
+
const mod = await import("ioredis");
|
|
288
|
+
const Ctor = mod.default ?? mod;
|
|
289
|
+
if (typeof Ctor !== "function") {
|
|
290
|
+
throw new Error("ioredis module did not export a constructor");
|
|
291
|
+
}
|
|
292
|
+
this.client = new Ctor(this.url, this.nodeOptions);
|
|
293
|
+
} catch (err) {
|
|
294
|
+
throw new Error("NodeRedisAdapter requires the `ioredis` package. Install with: bun add ioredis");
|
|
295
|
+
}
|
|
296
|
+
return this.client;
|
|
297
|
+
}
|
|
298
|
+
k(key) {
|
|
299
|
+
return this.keyPrefix + key;
|
|
300
|
+
}
|
|
301
|
+
stripPrefix(key) {
|
|
302
|
+
return this.keyPrefix && key.startsWith(this.keyPrefix) ? key.slice(this.keyPrefix.length) : key;
|
|
303
|
+
}
|
|
304
|
+
async get(key) {
|
|
305
|
+
return (await this.getClient()).get(this.k(key));
|
|
306
|
+
}
|
|
307
|
+
async set(key, value, options) {
|
|
308
|
+
const ex = options?.ex ?? this.defaultTtlSeconds ?? undefined;
|
|
309
|
+
const c = await this.getClient();
|
|
310
|
+
const fullKey = this.k(key);
|
|
311
|
+
if (options?.nx) {
|
|
312
|
+
await c.set(fullKey, value, "EX", ex ?? 0, "NX");
|
|
313
|
+
} else if (options?.xx) {
|
|
314
|
+
await c.set(fullKey, value, "EX", ex ?? 0, "XX");
|
|
315
|
+
} else if (ex) {
|
|
316
|
+
await c.set(fullKey, value, "EX", ex);
|
|
317
|
+
} else {
|
|
318
|
+
await c.set(fullKey, value);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
async del(key) {
|
|
322
|
+
return (await this.getClient()).del(this.k(key));
|
|
323
|
+
}
|
|
324
|
+
async exists(key) {
|
|
325
|
+
const n = await (await this.getClient()).exists(this.k(key));
|
|
326
|
+
return n > 0;
|
|
327
|
+
}
|
|
328
|
+
async incr(key, by = 1, options) {
|
|
329
|
+
const fullKey = this.k(key);
|
|
330
|
+
const c = await this.getClient();
|
|
331
|
+
let value;
|
|
332
|
+
if (by === 1) {
|
|
333
|
+
value = await c.incr(fullKey);
|
|
334
|
+
} else {
|
|
335
|
+
value = await c.incrby(fullKey, by);
|
|
336
|
+
}
|
|
337
|
+
if (options?.ex && value === by) {
|
|
338
|
+
await c.expire(fullKey, options.ex);
|
|
339
|
+
}
|
|
340
|
+
return value;
|
|
341
|
+
}
|
|
342
|
+
async scan(options = {}) {
|
|
343
|
+
const cursor = typeof options.cursor === "number" || typeof options.cursor === "string" ? options.cursor : 0;
|
|
344
|
+
const [next, keys] = await (await this.getClient()).scan(cursor, options.match ?? "*", options.count ?? 100);
|
|
345
|
+
return {
|
|
346
|
+
cursor: next,
|
|
347
|
+
keys: (keys ?? []).map((k) => this.stripPrefix(k))
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
async close() {
|
|
351
|
+
if (this.client) {
|
|
352
|
+
try {
|
|
353
|
+
await this.client.quit();
|
|
354
|
+
} catch {
|
|
355
|
+
this.client.disconnect();
|
|
356
|
+
}
|
|
357
|
+
this.client = null;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// packages/redis/src/adapters/index.ts
|
|
363
|
+
function detectRedisRuntime() {
|
|
364
|
+
if (typeof globalThis.caches !== "undefined" && typeof globalThis.WebSocketPair !== "undefined") {
|
|
365
|
+
return "cloudflare";
|
|
366
|
+
}
|
|
367
|
+
if (typeof globalThis.Bun !== "undefined")
|
|
368
|
+
return "bun";
|
|
369
|
+
if (typeof process !== "undefined" && process.versions?.node)
|
|
370
|
+
return "node";
|
|
371
|
+
return "memory";
|
|
372
|
+
}
|
|
373
|
+
function createRedisClient(config = {}) {
|
|
374
|
+
const adapter = config.adapter ?? detectRedisRuntime();
|
|
375
|
+
switch (adapter) {
|
|
376
|
+
case "bun":
|
|
377
|
+
return new BunRedisAdapter(config);
|
|
378
|
+
case "node":
|
|
379
|
+
return new NodeRedisAdapter(config);
|
|
380
|
+
case "cloudflare":
|
|
381
|
+
return new CloudflareKVAdapter(config);
|
|
382
|
+
case "memory":
|
|
383
|
+
return new MemoryRedisAdapter(config);
|
|
384
|
+
default: {
|
|
385
|
+
const _exhaustive = adapter;
|
|
386
|
+
throw new Error(`unknown redis adapter: ${_exhaustive}`);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
// packages/redis/src/module.ts
|
|
391
|
+
import { Module } from "@nexusts/core/decorators/index.js";
|
|
392
|
+
var REDIS_CLIENT_TOKEN = Symbol.for("nexus:RedisClient");
|
|
393
|
+
|
|
394
|
+
class RedisModule {
|
|
395
|
+
static forRoot(config = {}) {
|
|
396
|
+
|
|
397
|
+
class ConfiguredRedisModule {
|
|
398
|
+
}
|
|
399
|
+
ConfiguredRedisModule = __legacyDecorateClassTS([
|
|
400
|
+
Module({
|
|
401
|
+
providers: [
|
|
402
|
+
{
|
|
403
|
+
provide: REDIS_CLIENT_TOKEN,
|
|
404
|
+
useFactory: () => createRedisClient(config)
|
|
405
|
+
},
|
|
406
|
+
{ provide: "REDIS_CONFIG", useValue: config }
|
|
407
|
+
],
|
|
408
|
+
exports: [REDIS_CLIENT_TOKEN, "REDIS_CONFIG"]
|
|
409
|
+
})
|
|
410
|
+
], ConfiguredRedisModule);
|
|
411
|
+
Object.defineProperty(ConfiguredRedisModule, "name", {
|
|
412
|
+
value: "ConfiguredRedisModule"
|
|
413
|
+
});
|
|
414
|
+
return ConfiguredRedisModule;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
RedisModule = __legacyDecorateClassTS([
|
|
418
|
+
Module({
|
|
419
|
+
providers: [
|
|
420
|
+
{
|
|
421
|
+
provide: REDIS_CLIENT_TOKEN,
|
|
422
|
+
useFactory: () => createRedisClient()
|
|
423
|
+
}
|
|
424
|
+
],
|
|
425
|
+
exports: [REDIS_CLIENT_TOKEN]
|
|
426
|
+
})
|
|
427
|
+
], RedisModule);
|
|
428
|
+
export {
|
|
429
|
+
detectRedisRuntime,
|
|
430
|
+
createRedisClient,
|
|
431
|
+
RedisModule,
|
|
432
|
+
REDIS_CLIENT_TOKEN,
|
|
433
|
+
NodeRedisAdapter,
|
|
434
|
+
MemoryRedisAdapter,
|
|
435
|
+
CloudflareKVAdapter,
|
|
436
|
+
BunRedisAdapter
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
//# debugId=0BCE9406D8DDE88C64756E2164756E21
|
|
440
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/adapters/bun.ts", "../src/adapters/cloudflare.ts", "../src/adapters/memory.ts", "../src/adapters/node.ts", "../src/adapters/index.ts", "../src/module.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * Bun runtime adapter for `nexusjs/redis`.\n *\n * Uses the built-in `Bun.redis` client. No extra package needed.\n * The client is lazily opened on first use.\n */\n\nimport type {\n\tRedisClient,\n\tRedisConfig,\n\tRedisScanOptions,\n\tRedisScanResult,\n\tRedisSetOptions,\n\tRedisValue,\n} from \"../types.js\";\n\n/** The shape we need from `Bun.redis()`. */\ninterface BunRedisClient {\n\tget(key: string): Promise<string | null>;\n\tset(\n\t\tkey: string,\n\t\tvalue: string,\n\t\toptions?: { EX?: number; PX?: number; NX?: boolean; XX?: boolean },\n\t): Promise<\"OK\" | null>;\n\tdel(key: string): Promise<number>;\n\texists(key: string): Promise<number>;\n\tincr(key: string): Promise<number>;\n\tscan(cursor: number, options?: { MATCH?: string; COUNT?: number }): Promise<{\n\t\tcursor: number;\n\t\tkeys: string[];\n\t}>;\n\tclose(): void | Promise<void>;\n}\n\nexport class BunRedisAdapter implements RedisClient {\n\treadonly adapter = \"bun\" as const;\n\tprivate client: BunRedisClient | null = null;\n\tprivate readonly url: string;\n\tprivate readonly keyPrefix: string;\n\tprivate readonly defaultTtlSeconds: number;\n\n\tconstructor(config: RedisConfig = {}) {\n\t\tthis.url = config.url ?? process.env[\"REDIS_URL\"] ?? \"redis://localhost:6379\";\n\t\tthis.keyPrefix = config.keyPrefix ?? \"\";\n\t\tthis.defaultTtlSeconds = config.defaultTtlSeconds ?? 0;\n\t}\n\n\tprivate getClient(): BunRedisClient {\n\t\tif (this.client) return this.client;\n\t\t// Bun.redis is a global; cast through unknown so we can compile\n\t\t// in environments that don't have Bun's lib.d.ts loaded.\n\t\tconst bun = (globalThis as unknown as { Bun?: { redis: (url: string) => BunRedisClient } }).Bun;\n\t\tif (!bun || typeof bun.redis !== \"function\") {\n\t\t\tthrow new Error(\n\t\t\t\t\"BunRedisAdapter can only be used in a Bun runtime. \" +\n\t\t\t\t\t\"On Node, use NodeRedisAdapter (install ioredis).\",\n\t\t\t);\n\t\t}\n\t\tthis.client = bun.redis(this.url);\n\t\treturn this.client!;\n\t}\n\n\tprivate k(key: string): string {\n\t\treturn this.keyPrefix + key;\n\t}\n\n\tasync get(key: string): Promise<RedisValue> {\n\t\treturn this.getClient().get(this.k(key));\n\t}\n\n\tasync set(key: string, value: string, options?: RedisSetOptions): Promise<void> {\n\t\tconst ex = options?.ex ?? this.defaultTtlSeconds ?? undefined;\n\t\tconst px = options?.px ?? undefined;\n\t\tconst bunOpts: { EX?: number; PX?: number; NX?: boolean; XX?: boolean } = {};\n\t\tif (ex) bunOpts.EX = ex;\n\t\tif (px) bunOpts.PX = px;\n\t\tif (options?.nx) bunOpts.NX = true;\n\t\tif (options?.xx) bunOpts.XX = true;\n\t\tawait this.getClient().set(this.k(key), value, bunOpts);\n\t}\n\n\tasync del(key: string): Promise<number> {\n\t\treturn this.getClient().del(this.k(key));\n\t}\n\n\tasync exists(key: string): Promise<boolean> {\n\t\treturn (await this.getClient().exists(this.k(key))) > 0;\n\t}\n\n\tasync incr(key: string, by = 1, options?: { ex?: number }): Promise<number> {\n\t\tconst fullKey = this.k(key);\n\t\tconst client = this.getClient();\n\t\tconst value = await client.incr(fullKey);\n\t\t// On the first increment (value === 1), apply the TTL if requested.\n\t\tif (options?.ex && value === by) {\n\t\t\tawait client.set(fullKey, String(value), { EX: options.ex });\n\t\t}\n\t\treturn value;\n\t}\n\n\tasync scan(options: RedisScanOptions = {}): Promise<RedisScanResult> {\n\t\tconst cursor = typeof options.cursor === \"number\" ? options.cursor : 0;\n\t\tconst res = await this.getClient().scan(cursor, {\n\t\t\tMATCH: options.match ?? \"*\",\n\t\t\tCOUNT: options.count ?? 100,\n\t\t});\n\t\treturn {\n\t\t\tcursor: res.cursor,\n\t\t\tkeys: (res.keys ?? []).map((k) =>\n\t\t\t\tthis.keyPrefix && k.startsWith(this.keyPrefix)\n\t\t\t\t\t? k.slice(this.keyPrefix.length)\n\t\t\t\t\t: k,\n\t\t\t),\n\t\t};\n\t}\n\n\tasync close(): Promise<void> {\n\t\tif (this.client) {\n\t\t\tawait this.client.close();\n\t\t\tthis.client = null;\n\t\t}\n\t}\n}\n",
|
|
6
|
+
"/**\n * Cloudflare Workers KV adapter for `nexusjs/redis`.\n *\n * Workers KV is **not** Redis, but the surface is close enough\n * that the same `RedisClient` API can sit on top of it. The\n * adapter:\n *\n * - Maps `set(key, value, { ex })` to `KVNamespace.put()` with\n * `expirationTtl` (seconds).\n * - Maps `scan({ match })` to `KVNamespace.list({ prefix })`,\n * which is the closest thing KV offers to Redis `SCAN MATCH`.\n * The `cursor` field is a Cloudflare opaque string.\n * - `del` uses `KVNamespace.delete()`.\n * - `incr` falls back to a small read-modify-write: get the\n * value, parse as int, add, put back. (KV doesn't have\n * atomic INCR.) Use with care — concurrent writes can lose\n * updates. For high-contention counters use a real Redis.\n *\n * Cloudflare imposes a 25 MB value limit per key and a global\n * 100k reads / 1000 writes per second per KV namespace. Don't\n * store large objects in KV.\n *\n * To use:\n *\n * // In a Worker request handler:\n * const client = createRedisClient({\n * adapter: \"cloudflare\",\n * kv: c.env.SESSIONS, // KVNamespace binding from wrangler.toml\n * });\n */\n\nimport type {\n\tKVNamespaceLike,\n\tRedisClient,\n\tRedisConfig,\n\tRedisScanOptions,\n\tRedisScanResult,\n\tRedisSetOptions,\n\tRedisValue,\n} from \"../types.js\";\n\nexport class CloudflareKVAdapter implements RedisClient {\n\treadonly adapter = \"cloudflare\" as const;\n\tprivate kv: KVNamespaceLike | null = null;\n\tprivate readonly keyPrefix: string;\n\tprivate readonly defaultTtlSeconds: number;\n\n\tconstructor(config: RedisConfig = {}) {\n\t\tthis.keyPrefix = config.keyPrefix ?? \"\";\n\t\tthis.defaultTtlSeconds = config.defaultTtlSeconds ?? 0;\n\t\tif (config.kv) this.kv = config.kv;\n\t}\n\n\tprivate getKV(): KVNamespaceLike {\n\t\tif (this.kv) return this.kv;\n\t\t// Auto-detect from `globalThis.env` (Workers context).\n\t\tconst env = (globalThis as unknown as { env?: { KV?: KVNamespaceLike } }).env;\n\t\tif (env?.KV) {\n\t\t\tthis.kv = env.KV;\n\t\t\treturn this.kv;\n\t\t}\n\t\tthrow new Error(\n\t\t\t\"CloudflareKVAdapter could not find a KV binding. \" +\n\t\t\t\t\"Pass it explicitly via RedisConfig({ kv }) or run inside a \" +\n\t\t\t\t\"Workers request handler where `c.env.KV` is available.\",\n\t\t);\n\t}\n\n\tprivate k(key: string): string {\n\t\treturn this.keyPrefix + key;\n\t}\n\n\tprivate stripPrefix(key: string): string {\n\t\treturn this.keyPrefix && key.startsWith(this.keyPrefix)\n\t\t\t? key.slice(this.keyPrefix.length)\n\t\t\t: key;\n\t}\n\n\tasync get(key: string): Promise<RedisValue> {\n\t\treturn this.getKV().get(this.k(key));\n\t}\n\n\tasync set(key: string, value: string, options?: RedisSetOptions): Promise<void> {\n\t\tconst ex = options?.ex ?? this.defaultTtlSeconds ?? undefined;\n\t\tif (ex && ex > 0) {\n\t\t\tawait this.getKV().put(this.k(key), value, { expirationTtl: ex });\n\t\t} else {\n\t\t\tawait this.getKV().put(this.k(key), value);\n\t\t}\n\t}\n\n\tasync del(key: string): Promise<number> {\n\t\t// KV.delete returns void; we conservatively return 1 if a value\n\t\t// existed before, 0 otherwise.\n\t\tconst existed = (await this.getKV().get(this.k(key))) !== null;\n\t\tawait this.getKV().delete(this.k(key));\n\t\treturn existed ? 1 : 0;\n\t}\n\n\tasync exists(key: string): Promise<boolean> {\n\t\treturn (await this.getKV().get(this.k(key))) !== null;\n\t}\n\n\tasync incr(key: string, by = 1, options?: { ex?: number }): Promise<number> {\n\t\t// Naive read-modify-write. KV doesn't have atomic INCR. Don't\n\t\t// use this for high-contention counters.\n\t\tconst fullKey = this.k(key);\n\t\tconst raw = await this.getKV().get(fullKey);\n\t\tconst current = raw ? Number.parseInt(raw, 10) || 0 : 0;\n\t\tconst next = current + by;\n\t\tconst ex = options?.ex ?? this.defaultTtlSeconds ?? undefined;\n\t\tif (ex && ex > 0) {\n\t\t\tawait this.getKV().put(fullKey, String(next), { expirationTtl: ex });\n\t\t} else {\n\t\t\tawait this.getKV().put(fullKey, String(next));\n\t\t}\n\t\treturn next;\n\t}\n\n\tasync scan(options: RedisScanOptions = {}): Promise<RedisScanResult> {\n\t\t// KV.list() supports `prefix` only — convert a `match` glob\n\t\t// to a prefix. Full glob support would require client-side\n\t\t// filtering. The cursor is a Cloudflare opaque string.\n\t\tconst match = options.match ?? \"*\";\n\t\tconst prefix = globToPrefix(match, this.keyPrefix);\n\t\tconst res = await this.getKV().list({\n\t\t\tprefix,\n\t\t\tlimit: options.count ?? 100,\n\t\t\tcursor: typeof options.cursor === \"string\" ? options.cursor : undefined,\n\t\t});\n\t\treturn {\n\t\t\tcursor: res.cursor,\n\t\t\tkeys: (res.keys ?? []).map((k) => this.stripPrefix(k.name)),\n\t\t};\n\t}\n\n\tasync close(): Promise<void> {\n\t\t// KV has no client to close.\n\t}\n}\n\n/** Convert a Redis-style glob (`*`, `?`, `[abc]`) to a KV prefix. */\nfunction globToPrefix(glob: string, keyPrefix: string): string {\n\t// Everything up to the first glob meta-character.\n\tconst meta = /[*?\\[]/.exec(glob);\n\tconst base = meta ? glob.slice(0, meta.index) : glob;\n\treturn (keyPrefix ?? \"\") + base;\n}\n",
|
|
7
|
+
"/**\n * In-memory adapter for `nexusjs/redis`.\n *\n * Used for tests and single-process dev. Not cluster-safe; values\n * don't survive process restart.\n */\n\nimport type {\n\tRedisClient,\n\tRedisConfig,\n\tRedisScanOptions,\n\tRedisScanResult,\n\tRedisSetOptions,\n\tRedisValue,\n} from \"../types.js\";\n\ninterface Entry {\n\tvalue: string;\n\texpiresAt: number | null; // ms epoch; null = no expiry\n}\n\nexport class MemoryRedisAdapter implements RedisClient {\n\treadonly adapter = \"memory\" as const;\n\tprivate data = new Map<string, Entry>();\n\tprivate readonly keyPrefix: string;\n\tprivate readonly defaultTtlSeconds: number;\n\n\tconstructor(config: RedisConfig = {}) {\n\t\tthis.keyPrefix = config.keyPrefix ?? \"\";\n\t\tthis.defaultTtlSeconds = config.defaultTtlSeconds ?? 0;\n\t}\n\n\tprivate k(key: string): string {\n\t\treturn this.keyPrefix + key;\n\t}\n\n\tprivate stripPrefix(key: string): string {\n\t\treturn this.keyPrefix && key.startsWith(this.keyPrefix)\n\t\t\t? key.slice(this.keyPrefix.length)\n\t\t\t: key;\n\t}\n\n\tprivate isExpired(e: Entry | undefined): e is undefined {\n\t\treturn !e || (e.expiresAt !== null && e.expiresAt < Date.now());\n\t}\n\n\tprivate purge(key: string): void {\n\t\tconst e = this.data.get(key);\n\t\tif (this.isExpired(e)) this.data.delete(key);\n\t}\n\n\tasync get(key: string): Promise<RedisValue> {\n\t\tconst k = this.k(key);\n\t\tthis.purge(k);\n\t\tconst e = this.data.get(k);\n\t\treturn e ? e.value : null;\n\t}\n\n\tasync set(key: string, value: string, options?: RedisSetOptions): Promise<void> {\n\t\tconst k = this.k(key);\n\t\tconst ttl =\n\t\t\toptions?.ex !== undefined\n\t\t\t\t? options.ex\n\t\t\t\t: options?.px !== undefined\n\t\t\t\t\t? options.px / 1000\n\t\t\t\t\t: this.defaultTtlSeconds;\n\t\tconst expiresAt = ttl && ttl > 0 ? Date.now() + ttl * 1000 : null;\n\t\tif (options?.nx && !this.isExpired(this.data.get(k))) return; // NX semantics\n\t\tif (options?.xx && this.isExpired(this.data.get(k))) return; // XX semantics\n\t\tthis.data.set(k, { value, expiresAt });\n\t}\n\n\tasync del(key: string): Promise<number> {\n\t\tconst k = this.k(key);\n\t\tconst existed = this.data.delete(k);\n\t\treturn existed ? 1 : 0;\n\t}\n\n\tasync exists(key: string): Promise<boolean> {\n\t\tconst k = this.k(key);\n\t\tthis.purge(k);\n\t\treturn this.data.has(k);\n\t}\n\n\tasync incr(key: string, by = 1, options?: { ex?: number }): Promise<number> {\n\t\tconst k = this.k(key);\n\t\tthis.purge(k);\n\t\tconst e = this.data.get(k);\n\t\tconst current = e ? Number.parseInt(e.value, 10) || 0 : 0;\n\t\tconst next = current + by;\n\t\tconst ttl = options?.ex ?? this.defaultTtlSeconds ?? undefined;\n\t\tconst expiresAt = ttl && ttl > 0 ? Date.now() + ttl * 1000 : null;\n\t\tthis.data.set(k, { value: String(next), expiresAt });\n\t\treturn next;\n\t}\n\n\tasync scan(options: RedisScanOptions = {}): Promise<RedisScanResult> {\n\t\tconst match = options.match ?? \"*\";\n\t\t// The match pattern is matched against the full key (with\n\t\t// prefix included). Callers should write patterns that\n\t\t// include the prefix.\n\t\tconst re = globToRegex(match);\n\t\tconst keys: string[] = [];\n\t\tfor (const k of this.data.keys()) {\n\t\t\tif (this.keyPrefix && !k.startsWith(this.keyPrefix)) continue;\n\t\t\tif (re.test(k)) keys.push(this.stripPrefix(k));\n\t\t}\n\t\treturn { cursor: \"0\", keys };\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.data.clear();\n\t}\n}\n\nfunction globToRegex(glob: string): RegExp {\n\tconst escaped = glob\n\t\t.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n\t\t.replace(/\\*/g, \".*\")\n\t\t.replace(/\\?/g, \".\");\n\treturn new RegExp(\"^\" + escaped + \"$\");\n}\n",
|
|
8
|
+
"/**\n * Node.js runtime adapter for `nexusjs/redis`.\n *\n * Uses the `ioredis` package. The package is an **optional**\n * peer dependency of `nexusjs` — install it only when targeting\n * Node:\n *\n * bun add ioredis\n *\n * The adapter opens a single shared client per `RedisConfig` and\n * reuses it across `get` / `set` / `del` / `scan` calls. Use\n * `await client.close()` to release the connection.\n */\n\nimport type {\n\tRedisClient,\n\tRedisConfig,\n\tRedisScanOptions,\n\tRedisScanResult,\n\tRedisSetOptions,\n\tRedisValue,\n} from \"../types.js\";\n\n/** The shape we need from `ioredis`. We don't depend on the\n * package at the type level so users who don't install it\n * still type-check. */\ninterface IORedisLike {\n\tget(key: string): Promise<string | null>;\n\tset(\n\t\tkey: string,\n\t\tvalue: string,\n\t\tmodeOrEx?: string | number,\n\t\tduration?: number,\n\t\tflag?: \"NX\" | \"XX\",\n\t): Promise<\"OK\" | null>;\n\tdel(key: string | string[]): Promise<number>;\n\texists(key: string): Promise<number>;\n\tincr(key: string): Promise<number>;\n\texpire(key: string, seconds: number): Promise<number>;\n\tscan(\n\t\tcursor: number | string,\n\t\tmatch: string,\n\t\tcount: number,\n\t): Promise<[string | number, string[]]>;\n\tquit(): Promise<\"OK\">;\n\tdisconnect(): void;\n}\n\nexport class NodeRedisAdapter implements RedisClient {\n\treadonly adapter = \"node\" as const;\n\tprivate client: IORedisLike | null = null;\n\tprivate readonly url: string;\n\tprivate readonly keyPrefix: string;\n\tprivate readonly defaultTtlSeconds: number;\n\tprivate readonly nodeOptions: Record<string, unknown>;\n\n\tconstructor(config: RedisConfig = {}) {\n\t\tthis.url = config.url ?? process.env[\"REDIS_URL\"] ?? \"redis://localhost:6379\";\n\t\tthis.keyPrefix = config.keyPrefix ?? \"\";\n\t\tthis.defaultTtlSeconds = config.defaultTtlSeconds ?? 0;\n\t\tthis.nodeOptions = config.nodeOptions ?? {};\n\t}\n\n\tprivate async getClient(): Promise<IORedisLike> {\n\t\tif (this.client) return this.client;\n\t\ttry {\n\t\t\t// @ts-ignore - optional peer dep\n\t\t\tconst mod = await import(\"ioredis\");\n\t\t\tconst Ctor = (mod as any).default ?? (mod as any);\n\t\t\tif (typeof Ctor !== \"function\") {\n\t\t\t\tthrow new Error(\"ioredis module did not export a constructor\");\n\t\t\t}\n\t\t\tthis.client = new Ctor(this.url, this.nodeOptions) as IORedisLike;\n\t\t} catch (err) {\n\t\t\tthrow new Error(\n\t\t\t\t\"NodeRedisAdapter requires the `ioredis` package. \" +\n\t\t\t\t\t\"Install with: bun add ioredis\",\n\t\t\t);\n\t\t}\n\t\treturn this.client!;\n\t}\n\n\tprivate k(key: string): string {\n\t\treturn this.keyPrefix + key;\n\t}\n\n\tprivate stripPrefix(key: string): string {\n\t\treturn this.keyPrefix && key.startsWith(this.keyPrefix)\n\t\t\t? key.slice(this.keyPrefix.length)\n\t\t\t: key;\n\t}\n\n\tasync get(key: string): Promise<RedisValue> {\n\t\treturn (await this.getClient()).get(this.k(key));\n\t}\n\n\tasync set(key: string, value: string, options?: RedisSetOptions): Promise<void> {\n\t\tconst ex = options?.ex ?? this.defaultTtlSeconds ?? undefined;\n\t\tconst c = await this.getClient();\n\t\tconst fullKey = this.k(key);\n\t\t// ioredis set signature: set(key, value, EX, seconds, NX|XX) or\n\t\t// set(key, value, NX|XX). We dispatch on the combination of\n\t\t// flags.\n\t\tif (options?.nx) {\n\t\t\tawait c.set(fullKey, value, \"EX\", ex ?? 0, \"NX\");\n\t\t} else if (options?.xx) {\n\t\t\tawait c.set(fullKey, value, \"EX\", ex ?? 0, \"XX\");\n\t\t} else if (ex) {\n\t\t\tawait c.set(fullKey, value, \"EX\", ex);\n\t\t} else {\n\t\t\tawait c.set(fullKey, value);\n\t\t}\n\t}\n\n\tasync del(key: string): Promise<number> {\n\t\treturn (await this.getClient()).del(this.k(key));\n\t}\n\n\tasync exists(key: string): Promise<boolean> {\n\t\tconst n = await (await this.getClient()).exists(this.k(key));\n\t\treturn n > 0;\n\t}\n\n\tasync incr(key: string, by = 1, options?: { ex?: number }): Promise<number> {\n\t\tconst fullKey = this.k(key);\n\t\tconst c = await this.getClient();\n\t\tlet value: number;\n\t\tif (by === 1) {\n\t\t\tvalue = await c.incr(fullKey);\n\t\t} else {\n\t\t\t// ioredis doesn't have incrby with delta? It does — use\n\t\t\t// the multi-step: `incrby` is the ioredis method. Patch\n\t\t\t// the IORedisLike to include it.\n\t\t\tvalue = await (c as unknown as { incrby: (k: string, n: number) => Promise<number> }).incrby(fullKey, by);\n\t\t}\n\t\tif (options?.ex && value === by) {\n\t\t\tawait c.expire(fullKey, options.ex);\n\t\t}\n\t\treturn value;\n\t}\n\n\tasync scan(options: RedisScanOptions = {}): Promise<RedisScanResult> {\n\t\tconst cursor = typeof options.cursor === \"number\" || typeof options.cursor === \"string\"\n\t\t\t? options.cursor\n\t\t\t: 0;\n\t\tconst [next, keys] = await (await this.getClient()).scan(\n\t\t\tcursor,\n\t\t\toptions.match ?? \"*\",\n\t\t\toptions.count ?? 100,\n\t\t);\n\t\treturn {\n\t\t\tcursor: next,\n\t\t\tkeys: (keys ?? []).map((k) => this.stripPrefix(k)),\n\t\t};\n\t}\n\n\tasync close(): Promise<void> {\n\t\tif (this.client) {\n\t\t\ttry {\n\t\t\t\tawait this.client.quit();\n\t\t\t} catch {\n\t\t\t\tthis.client.disconnect();\n\t\t\t}\n\t\t\tthis.client = null;\n\t\t}\n\t}\n}\n",
|
|
9
|
+
"/**\n * Runtime detection and factory for `nexusjs/redis` adapters.\n *\n * - `Bun` → `BunRedisAdapter` (built-in `Bun.redis`, no extra package).\n * - `node` → `NodeRedisAdapter` (uses `ioredis` — install separately).\n * - `cloudflare` (Workers / Pages) → `CloudflareKVAdapter` (Workers KV).\n * - `memory` → `MemoryRedisAdapter` (always available, no external dep).\n *\n * The factory `createRedisClient(config)` auto-detects when\n * `config.adapter` is omitted.\n */\n\nimport type { RedisAdapterKind, RedisClient, RedisConfig } from \"../types.js\";\nimport { BunRedisAdapter } from \"./bun.js\";\nimport { CloudflareKVAdapter } from \"./cloudflare.js\";\nimport { MemoryRedisAdapter } from \"./memory.js\";\nimport { NodeRedisAdapter } from \"./node.js\";\n\n/** Detect the active runtime. */\nexport function detectRedisRuntime(): RedisAdapterKind {\n\t// Cloudflare Workers — most specific first.\n\tif (\n\t\ttypeof (globalThis as { caches?: unknown }).caches !== \"undefined\" &&\n\t\ttypeof (globalThis as { WebSocketPair?: unknown }).WebSocketPair !== \"undefined\"\n\t) {\n\t\treturn \"cloudflare\";\n\t}\n\tif (typeof (globalThis as { Bun?: unknown }).Bun !== \"undefined\") return \"bun\";\n\tif (typeof process !== \"undefined\" && process.versions?.node) return \"node\";\n\treturn \"memory\";\n}\n\n/**\n * Create a Redis client with the configured (or auto-detected)\n * adapter.\n *\n * const client = createRedisClient({ adapter: \"bun\", url: \"redis://localhost:6379\" });\n * await client.set(\"hello\", \"world\", { ex: 60 });\n * console.log(await client.get(\"hello\")); // → \"world\"\n */\nexport function createRedisClient(config: RedisConfig = {}): RedisClient {\n\tconst adapter = config.adapter ?? detectRedisRuntime();\n\tswitch (adapter) {\n\t\tcase \"bun\":\n\t\t\treturn new BunRedisAdapter(config);\n\t\tcase \"node\":\n\t\t\treturn new NodeRedisAdapter(config);\n\t\tcase \"cloudflare\":\n\t\t\treturn new CloudflareKVAdapter(config);\n\t\tcase \"memory\":\n\t\t\treturn new MemoryRedisAdapter(config);\n\t\tdefault: {\n\t\t\tconst _exhaustive: never = adapter;\n\t\t\tthrow new Error(`unknown redis adapter: ${_exhaustive as string}`);\n\t\t}\n\t}\n}\n\nexport {\n\tBunRedisAdapter,\n\tCloudflareKVAdapter,\n\tMemoryRedisAdapter,\n\tNodeRedisAdapter,\n};",
|
|
10
|
+
"/**\n * `RedisModule` — wires `RedisClient` into the DI container.\n *\n * @Module({\n * imports: [\n * RedisModule.forRoot({\n * adapter: \"bun\", // or \"node\" | \"cloudflare\" | \"memory\"\n * url: \"redis://localhost:6379\",\n * keyPrefix: \"myapp:\",\n * }),\n * ],\n * })\n * class AppModule {}\n *\n * @Injectable()\n * class UserService {\n * constructor(@Inject(REDIS_CLIENT_TOKEN) private redis: RedisClient) {}\n * async countVisits(userId: string) {\n * return this.redis.incr(`visits:${userId}`, 1, { ex: 60 * 60 });\n * }\n * }\n *\n * Most users won't import `RedisModule` directly — the\n * `SessionModule` and `CacheModule` use it under the hood when\n * the user configures a `redis` / `cloudflare-kv` backend.\n */\n\nimport { Module } from \"@nexusts/core/decorators/index.js\";\nimport { createRedisClient } from \"./adapters/index.js\";\nimport type { RedisClient, RedisConfig } from \"./types.js\";\n\nexport const REDIS_CLIENT_TOKEN = Symbol.for(\"nexus:RedisClient\");\n\n@Module({\n\tproviders: [\n\t\t{\n\t\t\tprovide: REDIS_CLIENT_TOKEN,\n\t\t\tuseFactory: () => createRedisClient(),\n\t\t},\n\t],\n\texports: [REDIS_CLIENT_TOKEN],\n})\nexport class RedisModule {\n\tstatic forRoot(config: RedisConfig = {}) {\n\t\t@Module({\n\t\t\tproviders: [\n\t\t\t\t{\n\t\t\t\t\tprovide: REDIS_CLIENT_TOKEN,\n\t\t\t\t\tuseFactory: () => createRedisClient(config),\n\t\t\t\t},\n\t\t\t\t{ provide: \"REDIS_CONFIG\", useValue: config },\n\t\t\t],\n\t\t\texports: [REDIS_CLIENT_TOKEN, \"REDIS_CONFIG\"],\n\t\t})\n\t\tclass ConfiguredRedisModule {}\n\t\tObject.defineProperty(ConfiguredRedisModule, \"name\", {\n\t\t\tvalue: \"ConfiguredRedisModule\",\n\t\t});\n\t\treturn ConfiguredRedisModule as unknown as typeof RedisModule;\n\t}\n}\n"
|
|
11
|
+
],
|
|
12
|
+
"mappings": "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",
|
|
13
|
+
"debugId": "0BCE9406D8DDE88C64756E2164756E21",
|
|
14
|
+
"names": []
|
|
15
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nexusts/redis",
|
|
3
|
+
"version": "0.7.0",
|
|
4
|
+
"description": "Runtime-aware Redis client (Bun / Node / Workers)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "bun run ../../build.ts"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"nexusts",
|
|
24
|
+
"framework",
|
|
25
|
+
"bun"
|
|
26
|
+
],
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"ioredis": "^5.11.1"
|
|
30
|
+
},
|
|
31
|
+
"peerDependenciesMeta": {
|
|
32
|
+
"ioredis": {
|
|
33
|
+
"optional": true
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@nexusts/core": "^0.7.0"
|
|
38
|
+
}
|
|
39
|
+
}
|