@ionite/redis 0.0.24-beta.20260907.2 → 0.0.24-beta.20260907.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +248 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1 +1,248 @@
|
|
|
1
|
-
|
|
1
|
+
// packages/redis/src/index.ts
|
|
2
|
+
import {
|
|
3
|
+
createReactiveRedis as createReactiveRedis2,
|
|
4
|
+
createRedisLfvTransport,
|
|
5
|
+
getKeyPrefix,
|
|
6
|
+
getLogger,
|
|
7
|
+
prefixedKey,
|
|
8
|
+
RedisAccessAssignmentStore,
|
|
9
|
+
RedisAccessCatalogStore,
|
|
10
|
+
RedisAccessIndex,
|
|
11
|
+
RedisCustomerStore,
|
|
12
|
+
RedisMagicLinkStore,
|
|
13
|
+
RedisResourceStore,
|
|
14
|
+
RedisSessionStore,
|
|
15
|
+
RedisTenantStore,
|
|
16
|
+
RedisUserStore,
|
|
17
|
+
RedisWorkloadIdentityStore,
|
|
18
|
+
RedisWorkloadTokenStore
|
|
19
|
+
} from "@ionite/redis-core";
|
|
20
|
+
import { createClient as createClient3 } from "redis";
|
|
21
|
+
|
|
22
|
+
// packages/redis/src/adapter.ts
|
|
23
|
+
import { chunkedMget, createEvalshaRunner } from "@ionite/redis-core";
|
|
24
|
+
function createRedisAdapter(client) {
|
|
25
|
+
const runScript = createEvalshaRunner({
|
|
26
|
+
eval: (script, keys, args) => client.eval(script, { keys, arguments: args }),
|
|
27
|
+
evalsha: (sha, keys, args) => client.evalSha(sha, { keys, arguments: args })
|
|
28
|
+
});
|
|
29
|
+
let subscriber;
|
|
30
|
+
let subscriberPromise;
|
|
31
|
+
const channelListeners = new Map;
|
|
32
|
+
const getSubscriber = async () => {
|
|
33
|
+
if (subscriber)
|
|
34
|
+
return subscriber;
|
|
35
|
+
if (subscriberPromise)
|
|
36
|
+
return subscriberPromise;
|
|
37
|
+
subscriberPromise = (async () => {
|
|
38
|
+
const next = client.duplicate?.();
|
|
39
|
+
if (!next?.subscribe || !next.unsubscribe) {
|
|
40
|
+
throw new Error("node-redis adapter requires client.duplicate() with subscribe/unsubscribe for Pub/Sub");
|
|
41
|
+
}
|
|
42
|
+
await next.connect?.();
|
|
43
|
+
subscriber = next;
|
|
44
|
+
return next;
|
|
45
|
+
})().finally(() => {
|
|
46
|
+
subscriberPromise = undefined;
|
|
47
|
+
});
|
|
48
|
+
return subscriberPromise;
|
|
49
|
+
};
|
|
50
|
+
return {
|
|
51
|
+
async get(key) {
|
|
52
|
+
return client.get(key);
|
|
53
|
+
},
|
|
54
|
+
async set(key, value) {
|
|
55
|
+
await client.set(key, value);
|
|
56
|
+
},
|
|
57
|
+
async setex(key, seconds, value) {
|
|
58
|
+
await client.setEx(key, seconds, value);
|
|
59
|
+
},
|
|
60
|
+
async del(key) {
|
|
61
|
+
await client.del(key);
|
|
62
|
+
},
|
|
63
|
+
async ttl(key) {
|
|
64
|
+
return client.ttl(key);
|
|
65
|
+
},
|
|
66
|
+
async getdel(key) {
|
|
67
|
+
return client.getDel(key);
|
|
68
|
+
},
|
|
69
|
+
async sadd(key, ...members) {
|
|
70
|
+
if (members.length > 0)
|
|
71
|
+
await client.sAdd(key, members);
|
|
72
|
+
},
|
|
73
|
+
async srem(key, ...members) {
|
|
74
|
+
if (members.length > 0)
|
|
75
|
+
await client.sRem(key, members);
|
|
76
|
+
},
|
|
77
|
+
async smembers(key) {
|
|
78
|
+
const arr = await client.sMembers(key);
|
|
79
|
+
return Array.from(arr);
|
|
80
|
+
},
|
|
81
|
+
async mget(keys) {
|
|
82
|
+
return chunkedMget(keys, (chunk) => client.mGet(chunk));
|
|
83
|
+
},
|
|
84
|
+
...client.publish ? {
|
|
85
|
+
async publish(channel, message) {
|
|
86
|
+
await client.publish?.(channel, message);
|
|
87
|
+
},
|
|
88
|
+
async subscribeChannel(channel, listener) {
|
|
89
|
+
const active = await getSubscriber();
|
|
90
|
+
const listeners = channelListeners.get(channel) ?? new Set;
|
|
91
|
+
const isFirst = listeners.size === 0;
|
|
92
|
+
listeners.add(listener);
|
|
93
|
+
channelListeners.set(channel, listeners);
|
|
94
|
+
if (isFirst) {
|
|
95
|
+
try {
|
|
96
|
+
await active.subscribe?.(channel, (message) => {
|
|
97
|
+
for (const current of channelListeners.get(channel) ?? [])
|
|
98
|
+
current(message);
|
|
99
|
+
});
|
|
100
|
+
} catch (error) {
|
|
101
|
+
listeners.delete(listener);
|
|
102
|
+
if (listeners.size === 0)
|
|
103
|
+
channelListeners.delete(channel);
|
|
104
|
+
if (channelListeners.size === 0 && subscriber === active) {
|
|
105
|
+
subscriber = undefined;
|
|
106
|
+
await active.disconnect?.();
|
|
107
|
+
}
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
let subscribed = true;
|
|
112
|
+
return async () => {
|
|
113
|
+
if (!subscribed)
|
|
114
|
+
return;
|
|
115
|
+
subscribed = false;
|
|
116
|
+
const current = channelListeners.get(channel);
|
|
117
|
+
current?.delete(listener);
|
|
118
|
+
if (current && current.size === 0) {
|
|
119
|
+
channelListeners.delete(channel);
|
|
120
|
+
await active.unsubscribe?.(channel);
|
|
121
|
+
}
|
|
122
|
+
if (channelListeners.size === 0 && subscriber === active) {
|
|
123
|
+
subscriber = undefined;
|
|
124
|
+
await active.disconnect?.();
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
} : {},
|
|
129
|
+
runScript
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
var createRedisAdapterV4 = createRedisAdapter;
|
|
133
|
+
// packages/redis/src/ion-redis.ts
|
|
134
|
+
import {
|
|
135
|
+
createReactiveRedis,
|
|
136
|
+
splitIonRedisSecret
|
|
137
|
+
} from "@ionite/redis-core";
|
|
138
|
+
import { createClient } from "redis";
|
|
139
|
+
function normalizeClientOptions(secret) {
|
|
140
|
+
const { redisUrl, clientOptions } = splitIonRedisSecret(secret);
|
|
141
|
+
if (redisUrl) {
|
|
142
|
+
clientOptions.url = redisUrl;
|
|
143
|
+
}
|
|
144
|
+
return clientOptions;
|
|
145
|
+
}
|
|
146
|
+
function endpointSignature(secret) {
|
|
147
|
+
const options = normalizeClientOptions(secret);
|
|
148
|
+
if (typeof options.url === "string" && options.url)
|
|
149
|
+
return options.url;
|
|
150
|
+
const socket = options.socket;
|
|
151
|
+
if (socket?.path)
|
|
152
|
+
return socket.path;
|
|
153
|
+
if (socket?.host)
|
|
154
|
+
return `${socket.host}:${socket.port ?? 6379}`;
|
|
155
|
+
return "";
|
|
156
|
+
}
|
|
157
|
+
async function closeClient(client) {
|
|
158
|
+
if (typeof client.quit === "function") {
|
|
159
|
+
await client.quit();
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
if (typeof client.disconnect === "function") {
|
|
163
|
+
await client.disconnect();
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
client.destroy?.();
|
|
167
|
+
}
|
|
168
|
+
function ionRedis(source, path, options = {}) {
|
|
169
|
+
return createReactiveRedis({
|
|
170
|
+
source,
|
|
171
|
+
path,
|
|
172
|
+
sourceName: options.sourceName,
|
|
173
|
+
logger: options.logger,
|
|
174
|
+
secretOptions: options.secretOptions,
|
|
175
|
+
subscription: options.subscription,
|
|
176
|
+
endpointOf: (secret) => endpointSignature(secret.data),
|
|
177
|
+
async createClient(secret) {
|
|
178
|
+
const client = createClient(normalizeClientOptions(secret.data));
|
|
179
|
+
client.on?.("error", (error) => {
|
|
180
|
+
options.logger?.warn?.("Reactive node-redis client error", {
|
|
181
|
+
path,
|
|
182
|
+
sourceName: options.sourceName ?? "redis",
|
|
183
|
+
error: error.message
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
await client.connect();
|
|
187
|
+
return {
|
|
188
|
+
adapter: createRedisAdapter(client),
|
|
189
|
+
dispose: async () => {
|
|
190
|
+
await closeClient(client);
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
// packages/redis/src/shared-adapter.ts
|
|
197
|
+
import { createClient as createClient2 } from "redis";
|
|
198
|
+
var sharedRedisAdapterPromise;
|
|
199
|
+
var sharedClient;
|
|
200
|
+
async function getSharedRedisAdapter() {
|
|
201
|
+
sharedRedisAdapterPromise ??= (async () => {
|
|
202
|
+
const url = process.env.REDIS_URL?.trim() || "redis://localhost:3503";
|
|
203
|
+
const client = createClient2({ url });
|
|
204
|
+
await client.connect();
|
|
205
|
+
sharedClient = client;
|
|
206
|
+
return createRedisAdapter(client);
|
|
207
|
+
})();
|
|
208
|
+
return sharedRedisAdapterPromise;
|
|
209
|
+
}
|
|
210
|
+
async function closeSharedRedisAdapter() {
|
|
211
|
+
const promise = sharedRedisAdapterPromise;
|
|
212
|
+
sharedRedisAdapterPromise = undefined;
|
|
213
|
+
const client = sharedClient;
|
|
214
|
+
sharedClient = undefined;
|
|
215
|
+
if (promise)
|
|
216
|
+
await promise.catch(() => {});
|
|
217
|
+
if (!client)
|
|
218
|
+
return;
|
|
219
|
+
try {
|
|
220
|
+
await client.quit();
|
|
221
|
+
} catch {
|
|
222
|
+
client.destroy?.();
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
export {
|
|
226
|
+
prefixedKey,
|
|
227
|
+
ionRedis,
|
|
228
|
+
getSharedRedisAdapter,
|
|
229
|
+
getLogger,
|
|
230
|
+
getKeyPrefix,
|
|
231
|
+
createRedisLfvTransport,
|
|
232
|
+
createRedisAdapterV4,
|
|
233
|
+
createRedisAdapter,
|
|
234
|
+
createReactiveRedis2 as createReactiveRedis,
|
|
235
|
+
createClient3 as createClient,
|
|
236
|
+
closeSharedRedisAdapter,
|
|
237
|
+
RedisWorkloadTokenStore,
|
|
238
|
+
RedisWorkloadIdentityStore,
|
|
239
|
+
RedisUserStore,
|
|
240
|
+
RedisTenantStore,
|
|
241
|
+
RedisSessionStore,
|
|
242
|
+
RedisResourceStore,
|
|
243
|
+
RedisMagicLinkStore,
|
|
244
|
+
RedisCustomerStore,
|
|
245
|
+
RedisAccessIndex,
|
|
246
|
+
RedisAccessCatalogStore,
|
|
247
|
+
RedisAccessAssignmentStore
|
|
248
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ionite/redis",
|
|
3
|
-
"version": "0.0.24-beta.20260907.
|
|
3
|
+
"version": "0.0.24-beta.20260907.3",
|
|
4
4
|
"description": "redis (node-redis) adapter and Redis stores for ionite. Includes createRedisAdapter (v6) and createRedisAdapterV4 (v4). Install this; redis is included.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"author": "ionite",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"./package.json": "./package.json"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@ionite/redis-core": "0.0.24-beta.20260907.
|
|
27
|
+
"@ionite/redis-core": "0.0.24-beta.20260907.3",
|
|
28
28
|
"redis": "^6.1.0"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|