ioredis-toolkit 0.0.9 → 0.5.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.
Files changed (267) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/LICENSE +1 -1
  3. package/README.md +68 -1058
  4. package/dist/cache/cache.d.ts +30 -0
  5. package/dist/cache/cache.d.ts.map +1 -0
  6. package/dist/cache/cache.js +59 -0
  7. package/dist/cache/cache.js.map +1 -0
  8. package/dist/cache/config.d.ts +12 -0
  9. package/dist/cache/config.d.ts.map +1 -0
  10. package/dist/cache/config.js +13 -0
  11. package/dist/cache/config.js.map +1 -0
  12. package/dist/cache/types.d.ts +32 -0
  13. package/dist/cache/types.d.ts.map +1 -0
  14. package/dist/cache/types.js +5 -0
  15. package/dist/cache/types.js.map +1 -0
  16. package/dist/index.d.ts +43 -51
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +32 -44
  19. package/dist/index.js.map +1 -0
  20. package/dist/lock/config.d.ts +12 -0
  21. package/dist/lock/config.d.ts.map +1 -0
  22. package/dist/lock/config.js +8 -0
  23. package/dist/lock/config.js.map +1 -0
  24. package/dist/lock/lock.d.ts +20 -0
  25. package/dist/lock/lock.d.ts.map +1 -0
  26. package/dist/lock/lock.js +44 -0
  27. package/dist/lock/lock.js.map +1 -0
  28. package/dist/lock/types.d.ts +19 -0
  29. package/dist/lock/types.d.ts.map +1 -0
  30. package/dist/lock/types.js +2 -0
  31. package/dist/lock/types.js.map +1 -0
  32. package/dist/modules-config.d.ts +3 -0
  33. package/dist/modules-config.d.ts.map +1 -0
  34. package/dist/modules-config.js +2 -0
  35. package/dist/modules-config.js.map +1 -0
  36. package/dist/pubsub/config.d.ts +11 -0
  37. package/dist/pubsub/config.d.ts.map +1 -0
  38. package/dist/pubsub/config.js +6 -0
  39. package/dist/pubsub/config.js.map +1 -0
  40. package/dist/pubsub/pubsub.d.ts +20 -0
  41. package/dist/pubsub/pubsub.d.ts.map +1 -0
  42. package/dist/pubsub/pubsub.js +54 -0
  43. package/dist/pubsub/pubsub.js.map +1 -0
  44. package/dist/pubsub/types.d.ts +24 -0
  45. package/dist/pubsub/types.d.ts.map +1 -0
  46. package/dist/pubsub/types.js +2 -0
  47. package/dist/pubsub/types.js.map +1 -0
  48. package/dist/rate-limit/config.d.ts +12 -0
  49. package/dist/rate-limit/config.d.ts.map +1 -0
  50. package/dist/rate-limit/config.js +6 -0
  51. package/dist/rate-limit/config.js.map +1 -0
  52. package/dist/rate-limit/rate-limiter.d.ts +18 -0
  53. package/dist/rate-limit/rate-limiter.d.ts.map +1 -0
  54. package/dist/rate-limit/rate-limiter.js +37 -0
  55. package/dist/rate-limit/rate-limiter.js.map +1 -0
  56. package/dist/rate-limit/types.d.ts +27 -0
  57. package/dist/rate-limit/types.d.ts.map +1 -0
  58. package/dist/rate-limit/types.js +2 -0
  59. package/dist/rate-limit/types.js.map +1 -0
  60. package/dist/redis/client-facade.d.ts +77 -0
  61. package/dist/redis/client-facade.d.ts.map +1 -0
  62. package/dist/redis/client-facade.js +102 -0
  63. package/dist/redis/client-facade.js.map +1 -0
  64. package/dist/redis/client.d.ts +10 -0
  65. package/dist/redis/client.d.ts.map +1 -0
  66. package/dist/redis/client.js +29 -0
  67. package/dist/redis/client.js.map +1 -0
  68. package/dist/redis/cluster.d.ts +7 -0
  69. package/dist/redis/cluster.d.ts.map +1 -0
  70. package/dist/redis/cluster.js +47 -0
  71. package/dist/redis/cluster.js.map +1 -0
  72. package/dist/redis/config.d.ts +39 -0
  73. package/dist/redis/config.d.ts.map +1 -0
  74. package/dist/redis/config.js +52 -0
  75. package/dist/redis/config.js.map +1 -0
  76. package/dist/redis/errors.d.ts +5 -0
  77. package/dist/redis/errors.d.ts.map +1 -0
  78. package/dist/redis/errors.js +5 -0
  79. package/dist/redis/errors.js.map +1 -0
  80. package/dist/redis/types.d.ts +135 -0
  81. package/dist/redis/types.d.ts.map +1 -0
  82. package/dist/redis/types.js +2 -0
  83. package/dist/redis/types.js.map +1 -0
  84. package/dist/redis/wrapper.d.ts +88 -0
  85. package/dist/redis/wrapper.d.ts.map +1 -0
  86. package/dist/redis/wrapper.js +206 -0
  87. package/dist/redis/wrapper.js.map +1 -0
  88. package/dist/session/config.d.ts +47 -0
  89. package/dist/session/config.d.ts.map +1 -0
  90. package/dist/session/config.js +101 -0
  91. package/dist/session/config.js.map +1 -0
  92. package/dist/session/cookie.d.ts +16 -0
  93. package/dist/session/cookie.d.ts.map +1 -0
  94. package/dist/session/cookie.js +28 -0
  95. package/dist/session/cookie.js.map +1 -0
  96. package/dist/session/errors.d.ts +56 -0
  97. package/dist/session/errors.d.ts.map +1 -0
  98. package/dist/session/errors.js +58 -0
  99. package/dist/session/errors.js.map +1 -0
  100. package/dist/session/factory.d.ts +21 -0
  101. package/dist/session/factory.d.ts.map +1 -0
  102. package/dist/session/factory.js +30 -0
  103. package/dist/session/factory.js.map +1 -0
  104. package/dist/session/health.d.ts +12 -0
  105. package/dist/session/health.d.ts.map +1 -0
  106. package/dist/session/health.js +23 -0
  107. package/dist/session/health.js.map +1 -0
  108. package/dist/session/keys.d.ts +23 -0
  109. package/dist/session/keys.d.ts.map +1 -0
  110. package/dist/session/keys.js +27 -0
  111. package/dist/session/keys.js.map +1 -0
  112. package/dist/session/manager.d.ts +34 -0
  113. package/dist/session/manager.d.ts.map +1 -0
  114. package/dist/session/manager.js +31 -0
  115. package/dist/session/manager.js.map +1 -0
  116. package/dist/session/metrics.d.ts +11 -0
  117. package/dist/session/metrics.d.ts.map +1 -0
  118. package/dist/session/metrics.js +10 -0
  119. package/dist/session/metrics.js.map +1 -0
  120. package/dist/session/repository.d.ts +49 -0
  121. package/dist/session/repository.d.ts.map +1 -0
  122. package/dist/session/repository.js +203 -0
  123. package/dist/session/repository.js.map +1 -0
  124. package/dist/session/revocation.d.ts +22 -0
  125. package/dist/session/revocation.d.ts.map +1 -0
  126. package/dist/session/revocation.js +41 -0
  127. package/dist/session/revocation.js.map +1 -0
  128. package/dist/session/script-sources.d.ts +11 -0
  129. package/dist/session/script-sources.d.ts.map +1 -0
  130. package/dist/session/script-sources.js +140 -0
  131. package/dist/session/script-sources.js.map +1 -0
  132. package/dist/session/scripts.d.ts +15 -0
  133. package/dist/session/scripts.d.ts.map +1 -0
  134. package/dist/session/scripts.js +41 -0
  135. package/dist/session/scripts.js.map +1 -0
  136. package/dist/session/serializer.d.ts +12 -0
  137. package/dist/session/serializer.d.ts.map +1 -0
  138. package/dist/session/serializer.js +77 -0
  139. package/dist/session/serializer.js.map +1 -0
  140. package/dist/session/service.d.ts +48 -0
  141. package/dist/session/service.d.ts.map +1 -0
  142. package/dist/session/service.js +235 -0
  143. package/dist/session/service.js.map +1 -0
  144. package/dist/session/token.d.ts +16 -0
  145. package/dist/session/token.d.ts.map +1 -0
  146. package/dist/session/token.js +32 -0
  147. package/dist/session/token.js.map +1 -0
  148. package/dist/session/types.d.ts +134 -0
  149. package/dist/session/types.d.ts.map +1 -0
  150. package/dist/session/types.js +2 -0
  151. package/dist/session/types.js.map +1 -0
  152. package/dist/streams/config.d.ts +12 -0
  153. package/dist/streams/config.d.ts.map +1 -0
  154. package/dist/streams/config.js +6 -0
  155. package/dist/streams/config.js.map +1 -0
  156. package/dist/streams/streams.d.ts +24 -0
  157. package/dist/streams/streams.d.ts.map +1 -0
  158. package/dist/streams/streams.js +55 -0
  159. package/dist/streams/streams.js.map +1 -0
  160. package/dist/streams/types.d.ts +32 -0
  161. package/dist/streams/types.d.ts.map +1 -0
  162. package/dist/streams/types.js +2 -0
  163. package/dist/streams/types.js.map +1 -0
  164. package/docs/ACCEPTANCE-REPORT.md +70 -0
  165. package/docs/ARCHITECTURE.md +61 -0
  166. package/docs/CAPACITY.md +33 -0
  167. package/docs/DEPLOYMENT.md +22 -0
  168. package/docs/README-API.md +15 -0
  169. package/docs/STATE-MACHINE.md +38 -0
  170. package/docs/TESTING.md +37 -0
  171. package/docs/THREAT-MODEL.md +23 -0
  172. package/docs/TYPE-SAFETY.md +34 -0
  173. package/docs/modules/cache/README.md +7 -0
  174. package/docs/modules/cache/usage.md +156 -0
  175. package/docs/modules/lock/README.md +7 -0
  176. package/docs/modules/lock/usage.md +105 -0
  177. package/docs/modules/pubsub/README.md +7 -0
  178. package/docs/modules/pubsub/usage.md +106 -0
  179. package/docs/modules/rate-limit/README.md +7 -0
  180. package/docs/modules/rate-limit/usage.md +100 -0
  181. package/docs/modules/sessions/README.md +7 -0
  182. package/docs/modules/sessions/usage.md +262 -0
  183. package/docs/modules/streams/README.md +7 -0
  184. package/docs/modules/streams/usage.md +141 -0
  185. package/package.json +50 -60
  186. package/src/scripts/cleanup-index.lua +4 -0
  187. package/src/scripts/conditional-update.lua +21 -0
  188. package/src/scripts/consume-session.lua +21 -0
  189. package/src/scripts/create-session.lua +28 -0
  190. package/src/scripts/delete.lua +2 -0
  191. package/src/scripts/destroy-user.lua +13 -0
  192. package/src/scripts/enforce-limit.lua +17 -0
  193. package/src/scripts/revoke-session.lua +13 -0
  194. package/src/scripts/rotate.lua +24 -0
  195. package/src/scripts/touch-session.lua +28 -0
  196. package/src/scripts/update-session.lua +18 -0
  197. package/dist/cache.d.ts +0 -796
  198. package/dist/cache.js +0 -1120
  199. package/dist/client.d.ts +0 -284
  200. package/dist/client.js +0 -1114
  201. package/dist/cluster-slot.d.ts +0 -4
  202. package/dist/cluster-slot.js +0 -31
  203. package/dist/cluster.d.ts +0 -79
  204. package/dist/cluster.js +0 -156
  205. package/dist/errors.d.ts +0 -30
  206. package/dist/errors.js +0 -63
  207. package/dist/health.d.ts +0 -180
  208. package/dist/health.js +0 -239
  209. package/dist/lock.d.ts +0 -248
  210. package/dist/lock.js +0 -397
  211. package/dist/logger.d.ts +0 -12
  212. package/dist/logger.js +0 -40
  213. package/dist/pubsub.d.ts +0 -423
  214. package/dist/pubsub.js +0 -537
  215. package/dist/ratelimiter.d.ts +0 -441
  216. package/dist/ratelimiter.js +0 -539
  217. package/dist/session/index.d.ts +0 -23
  218. package/dist/session/index.js +0 -16
  219. package/dist/session/revocation-store.d.ts +0 -176
  220. package/dist/session/revocation-store.js +0 -318
  221. package/dist/session/scripts/cleanup-index.lua +0 -21
  222. package/dist/session/scripts/conditional-update-encrypted.lua +0 -60
  223. package/dist/session/scripts/conditional-update.lua +0 -63
  224. package/dist/session/scripts/create.lua +0 -83
  225. package/dist/session/scripts/delete-by-user.lua +0 -29
  226. package/dist/session/scripts/delete.lua +0 -15
  227. package/dist/session/scripts/enforce-limit.lua +0 -38
  228. package/dist/session/scripts/revoke.lua +0 -61
  229. package/dist/session/scripts/rotate-encrypted.lua +0 -110
  230. package/dist/session/scripts/rotate.lua +0 -122
  231. package/dist/session/scripts/touch-encrypted.lua +0 -89
  232. package/dist/session/scripts/touch.lua +0 -72
  233. package/dist/session/scripts/validate.lua +0 -90
  234. package/dist/session/session-circuit-breaker.d.ts +0 -42
  235. package/dist/session/session-circuit-breaker.js +0 -129
  236. package/dist/session/session-config.d.ts +0 -335
  237. package/dist/session/session-config.js +0 -162
  238. package/dist/session/session-cookie.d.ts +0 -72
  239. package/dist/session/session-cookie.js +0 -101
  240. package/dist/session/session-encryption.d.ts +0 -87
  241. package/dist/session/session-encryption.js +0 -139
  242. package/dist/session/session-errors.d.ts +0 -85
  243. package/dist/session/session-errors.js +0 -145
  244. package/dist/session/session-health.d.ts +0 -38
  245. package/dist/session/session-health.js +0 -60
  246. package/dist/session/session-keys.d.ts +0 -51
  247. package/dist/session/session-keys.js +0 -113
  248. package/dist/session/session-manager.d.ts +0 -73
  249. package/dist/session/session-manager.js +0 -94
  250. package/dist/session/session-metrics.d.ts +0 -33
  251. package/dist/session/session-metrics.js +0 -112
  252. package/dist/session/session-repository.d.ts +0 -161
  253. package/dist/session/session-repository.js +0 -683
  254. package/dist/session/session-scripts.d.ts +0 -36
  255. package/dist/session/session-scripts.js +0 -130
  256. package/dist/session/session-serializer.d.ts +0 -42
  257. package/dist/session/session-serializer.js +0 -248
  258. package/dist/session/session-service.d.ts +0 -104
  259. package/dist/session/session-service.js +0 -611
  260. package/dist/session/session-token.d.ts +0 -38
  261. package/dist/session/session-token.js +0 -86
  262. package/dist/session/session-types.d.ts +0 -253
  263. package/dist/session/session-types.js +0 -16
  264. package/dist/types.d.ts +0 -924
  265. package/dist/types.js +0 -151
  266. package/dist/utils/deepmerge.d.ts +0 -9
  267. package/dist/utils/deepmerge.js +0 -61
@@ -0,0 +1,54 @@
1
+ import { Cluster } from 'ioredis';
2
+ /** JSON Pub/Sub abstraction using a dedicated subscriber connection. */
3
+ export class RedisPubSub {
4
+ redis;
5
+ config;
6
+ subscriber;
7
+ handlers = new Map();
8
+ /** Creates a Pub/Sub module using the same connection configuration as the shared client. */
9
+ constructor(redis, config) {
10
+ this.redis = redis;
11
+ this.config = config;
12
+ this.subscriber = redis.duplicateConnection();
13
+ this.subscriber.on('error', () => { });
14
+ this.subscriber.on('message', (channel, message) => this.handlers.get(channel)?.forEach(handler => handler(message)));
15
+ }
16
+ /** Publishes a JSON value to a namespaced channel and returns subscriber count. */
17
+ async publish(channel, value) {
18
+ const encoded = JSON.stringify(value);
19
+ if (encoded === undefined)
20
+ throw new TypeError('Pub/Sub values must be JSON-serializable');
21
+ if (Buffer.byteLength(encoded, 'utf8') > this.config.maxMessageBytes)
22
+ throw new RangeError('Pub/Sub message exceeds maxMessageBytes');
23
+ return this.redis.publish(this.fullChannel(channel), encoded);
24
+ }
25
+ /** Subscribes to a namespaced channel and parses each JSON message. */
26
+ async subscribe(channel, handler) {
27
+ const full = this.fullChannel(channel);
28
+ const wrapped = (raw) => {
29
+ let value;
30
+ try {
31
+ value = JSON.parse(raw);
32
+ }
33
+ catch {
34
+ return;
35
+ }
36
+ handler({ channel, value });
37
+ };
38
+ const existing = this.handlers.get(full);
39
+ const set = existing ?? new Set();
40
+ set.add(wrapped);
41
+ this.handlers.set(full, set);
42
+ if (!existing)
43
+ await this.subscriber.subscribe(full);
44
+ return { channel, unsubscribe: async () => { set.delete(wrapped); if (set.size === 0) {
45
+ this.handlers.delete(full);
46
+ await this.subscriber.unsubscribe(full);
47
+ } } };
48
+ }
49
+ /** Closes the dedicated subscriber connection. */
50
+ async close() { await this.subscriber.quit(); this.handlers.clear(); }
51
+ /** Returns the physical namespaced channel. */
52
+ fullChannel(channel) { return `${this.config.channelPrefix}:${channel}`; }
53
+ }
54
+ //# sourceMappingURL=pubsub.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pubsub.js","sourceRoot":"","sources":["../../src/pubsub/pubsub.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /** Normalized configuration for {@link RedisPubSub}. */
2
+ export interface PubSubConfig {
3
+ /** Whether the application has enabled the module. The class remains directly constructible when false; {@link RedisClient}'s `pubsub` getter throws when disabled. */
4
+ enabled: boolean;
5
+ /** Prefix used for physical Redis channel names. */
6
+ channelPrefix: string;
7
+ /** Maximum UTF-8 encoded JSON message size. */
8
+ maxMessageBytes: number;
9
+ }
10
+ /** Handle returned by a Pub/Sub subscription. */
11
+ export interface Subscription {
12
+ /** Logical, unprefixed channel name. */
13
+ readonly channel: string;
14
+ /** Removes this subscription and unsubscribes the physical channel when no handlers remain. */
15
+ unsubscribe(): Promise<void>;
16
+ }
17
+ /** Decoded Pub/Sub message delivered to a subscriber callback. */
18
+ export interface PubSubMessage<T = unknown> {
19
+ /** Logical, unprefixed channel name. */
20
+ channel: string;
21
+ /** Application payload decoded from JSON. */
22
+ value: T;
23
+ }
24
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/pubsub/types.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,MAAM,WAAW,YAAY;IAC3B,uKAAuK;IACvK,OAAO,EAAE,OAAO,CAAC;IACjB,oDAAoD;IACpD,aAAa,EAAE,MAAM,CAAC;IACtB,+CAA+C;IAC/C,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,iDAAiD;AACjD,MAAM,WAAW,YAAY;IAC3B,wCAAwC;IACxC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,+FAA+F;IAC/F,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,kEAAkE;AAClE,MAAM,WAAW,aAAa,CAAC,CAAC,GAAG,OAAO;IACxC,wCAAwC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,KAAK,EAAE,CAAC,CAAC;CACV"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/pubsub/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ import { z } from 'zod';
2
+ import type { RateLimitConfig } from './types.js';
3
+ /** Runtime schema for rate-limiter configuration. */
4
+ export declare const RateLimitConfigSchema: z.ZodObject<{
5
+ enabled: z.ZodDefault<z.ZodBoolean>;
6
+ namespace: z.ZodDefault<z.ZodString>;
7
+ windowSeconds: z.ZodDefault<z.ZodNumber>;
8
+ maxRequests: z.ZodDefault<z.ZodNumber>;
9
+ }, z.core.$strip>;
10
+ /** Validates and normalizes rate-limiter configuration. */
11
+ export declare function parseRateLimitConfig(input: unknown): RateLimitConfig;
12
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/rate-limit/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,qDAAqD;AACrD,eAAO,MAAM,qBAAqB;;;;;iBAA2P,CAAC;AAC9R,2DAA2D;AAC3D,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CAAwE"}
@@ -0,0 +1,6 @@
1
+ import { z } from 'zod';
2
+ /** Runtime schema for rate-limiter configuration. */
3
+ export const RateLimitConfigSchema = z.object({ enabled: z.boolean().default(false), namespace: z.string().min(1).max(128).default('rate-limit'), windowSeconds: z.number().int().positive().max(86400).default(60), maxRequests: z.number().int().positive().max(10_000_000).default(100) });
4
+ /** Validates and normalizes rate-limiter configuration. */
5
+ export function parseRateLimitConfig(input) { return RateLimitConfigSchema.parse(input ?? {}); }
6
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/rate-limit/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,qDAAqD;AACrD,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAC9R,2DAA2D;AAC3D,MAAM,UAAU,oBAAoB,CAAC,KAAc,IAAqB,OAAO,qBAAqB,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAoB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { RedisClientWrapper } from '../redis/wrapper.js';
2
+ import type { RateLimitConfig, RateLimitResult } from './types.js';
3
+ /** Fixed-window Redis rate limiter with atomic increment-and-expire behavior. */
4
+ export declare class RedisRateLimiter {
5
+ private readonly redis;
6
+ private readonly config;
7
+ /** Creates a rate limiter bound to the shared Redis client. */
8
+ constructor(redis: RedisClientWrapper, config: RateLimitConfig);
9
+ /** Builds the physical key for a subject and current time window. */
10
+ key(subject: string, nowSeconds?: number): string;
11
+ /** Consumes one request from the configured fixed window. */
12
+ consume(subject: string, cost?: number, nowSeconds?: number): Promise<RateLimitResult>;
13
+ /** Checks the current window without consuming a request. */
14
+ check(subject: string, nowSeconds?: number): Promise<RateLimitResult>;
15
+ /** Resets the current fixed-window counter for a subject. */
16
+ reset(subject: string, nowSeconds?: number): Promise<boolean>;
17
+ }
18
+ //# sourceMappingURL=rate-limiter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../src/rate-limit/rate-limiter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAInE,iFAAiF;AACjF,qBAAa,gBAAgB;IAEf,OAAO,CAAC,QAAQ,CAAC,KAAK;IAAsB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAD/E,+DAA+D;gBAClC,KAAK,EAAE,kBAAkB,EAAmB,MAAM,EAAE,eAAe;IAEhG,qEAAqE;IACrE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,SAAgC,GAAG,MAAM;IAExE,6DAA6D;IACvD,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,SAAI,EAAE,UAAU,SAAgC,GAAG,OAAO,CAAC,eAAe,CAAC;IAW9G,6DAA6D;IACvD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,SAAgC,GAAG,OAAO,CAAC,eAAe,CAAC;IAKlG,6DAA6D;IACvD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,SAAgC,GAAG,OAAO,CAAC,OAAO,CAAC;CAC3F"}
@@ -0,0 +1,37 @@
1
+ const SCRIPT = `local c=redis.call('INCRBY',KEYS[1],ARGV[2]); if c==1 then redis.call('EXPIRE',KEYS[1],ARGV[1]) end; local ttl=redis.call('TTL',KEYS[1]); return {c,ttl}`;
2
+ /** Fixed-window Redis rate limiter with atomic increment-and-expire behavior. */
3
+ export class RedisRateLimiter {
4
+ redis;
5
+ config;
6
+ /** Creates a rate limiter bound to the shared Redis client. */
7
+ constructor(redis, config) {
8
+ this.redis = redis;
9
+ this.config = config;
10
+ }
11
+ /** Builds the physical key for a subject and current time window. */
12
+ key(subject, nowSeconds = Math.floor(Date.now() / 1000)) { return `${this.config.namespace}:${subject}:${Math.floor(nowSeconds / this.config.windowSeconds)}`; }
13
+ /** Consumes one request from the configured fixed window. */
14
+ async consume(subject, cost = 1, nowSeconds = Math.floor(Date.now() / 1000)) {
15
+ if (!Number.isSafeInteger(nowSeconds) || nowSeconds < 0)
16
+ throw new RangeError('nowSeconds must be a non-negative safe integer');
17
+ if (!Number.isInteger(cost) || cost <= 0)
18
+ throw new RangeError('Rate-limit cost must be a positive integer');
19
+ const key = this.key(subject, nowSeconds);
20
+ const raw = await this.redis.eval(SCRIPT, 1, key, String(this.config.windowSeconds), String(cost));
21
+ const [countRaw, ttlRaw] = raw;
22
+ const count = Number(countRaw);
23
+ const ttl = Math.max(0, Number(ttlRaw));
24
+ const resetAt = nowSeconds + ttl;
25
+ return { allowed: count <= this.config.maxRequests, limit: this.config.maxRequests, remaining: Math.max(0, this.config.maxRequests - count), resetAt, retryAfterSeconds: count > this.config.maxRequests ? ttl : 0, count };
26
+ }
27
+ /** Checks the current window without consuming a request. */
28
+ async check(subject, nowSeconds = Math.floor(Date.now() / 1000)) {
29
+ const key = this.key(subject, nowSeconds);
30
+ const count = Number((await this.redis.get(key)) ?? 0);
31
+ const ttl = Math.max(0, await this.redis.ttl(key));
32
+ return { allowed: count < this.config.maxRequests, limit: this.config.maxRequests, remaining: Math.max(0, this.config.maxRequests - count), resetAt: nowSeconds + ttl, retryAfterSeconds: count >= this.config.maxRequests ? ttl : 0, count };
33
+ }
34
+ /** Resets the current fixed-window counter for a subject. */
35
+ async reset(subject, nowSeconds = Math.floor(Date.now() / 1000)) { return (await this.redis.del(this.key(subject, nowSeconds))) > 0; }
36
+ }
37
+ //# sourceMappingURL=rate-limiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/rate-limit/rate-limiter.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,GAAG,0JAA0J,CAAC;AAE1K,iFAAiF;AACjF,MAAM,OAAO,gBAAgB;IAEE;IAA4C;IADzE,+DAA+D;IAC/D,YAA6B,KAAyB,EAAmB,MAAuB;QAAnE,UAAK,GAAL,KAAK,CAAoB;QAAmB,WAAM,GAAN,MAAM,CAAiB;IAAG,CAAC;IAEpG,qEAAqE;IACrE,GAAG,CAAC,OAAe,EAAE,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,IAAY,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC;IAEhL,6DAA6D;IAC7D,KAAK,CAAC,OAAO,CAAC,OAAe,EAAE,IAAI,GAAG,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;QACjF,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC;YAAE,MAAM,IAAI,UAAU,CAAC,gDAAgD,CAAC,CAAC;QAChI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;YAAE,MAAM,IAAI,UAAU,CAAC,4CAA4C,CAAC,CAAC;QAC7G,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC1C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QACnG,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,GAAyC,CAAC;QACrE,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;QAAC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QACxE,MAAM,OAAO,GAAG,UAAU,GAAG,GAAG,CAAC;QACjC,OAAO,EAAE,OAAO,EAAE,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC,EAAE,OAAO,EAAE,iBAAiB,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;IAC9N,CAAC;IAED,6DAA6D;IAC7D,KAAK,CAAC,KAAK,CAAC,OAAe,EAAE,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;QACrE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAAC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAAC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;QACtJ,OAAO,EAAE,OAAO,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC,EAAE,OAAO,EAAE,UAAU,GAAG,GAAG,EAAE,iBAAiB,EAAE,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;IAChP,CAAC;IAED,6DAA6D;IAC7D,KAAK,CAAC,KAAK,CAAC,OAAe,EAAE,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,IAAsB,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CACjK"}
@@ -0,0 +1,27 @@
1
+ /** Normalized configuration for the fixed-window rate limiter. */
2
+ export interface RateLimitConfig {
3
+ /** Whether the application has enabled the module. The class remains directly constructible when false; {@link RedisClient}'s `rateLimiter` getter throws when disabled. */
4
+ enabled: boolean;
5
+ /** Prefix used for counter keys. */
6
+ namespace: string;
7
+ /** Length of each fixed window in seconds. */
8
+ windowSeconds: number;
9
+ /** Maximum consumed units permitted during one window. */
10
+ maxRequests: number;
11
+ }
12
+ /** Result returned by a rate-limit check or consumption operation. */
13
+ export interface RateLimitResult {
14
+ /** Whether the attempted cost is within the configured limit. */
15
+ allowed: boolean;
16
+ /** Configured maximum number of units. */
17
+ limit: number;
18
+ /** Remaining units after the operation. */
19
+ remaining: number;
20
+ /** Approximate Unix timestamp at which the current fixed window expires. */
21
+ resetAt: number;
22
+ /** Seconds until the counter resets when the request is denied; otherwise zero. */
23
+ retryAfterSeconds: number;
24
+ /** Current counter value after the operation, or current value for `check()`. */
25
+ count: number;
26
+ }
27
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/rate-limit/types.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,MAAM,WAAW,eAAe;IAC9B,4KAA4K;IAC5K,OAAO,EAAE,OAAO,CAAC;IACjB,oCAAoC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,aAAa,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,sEAAsE;AACtE,MAAM,WAAW,eAAe;IAC9B,iEAAiE;IACjE,OAAO,EAAE,OAAO,CAAC;IACjB,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;IAChB,mFAAmF;IACnF,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAC;CACf"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/rate-limit/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,77 @@
1
+ import type { RedisConfig } from './types.js';
2
+ import { createRedisConnection } from './client.js';
3
+ import { RedisClientWrapper } from './wrapper.js';
4
+ import { RedisCache } from '../cache/cache.js';
5
+ import type { CacheConfig } from '../cache/types.js';
6
+ import { RedisLock } from '../lock/lock.js';
7
+ import type { LockConfig } from '../lock/types.js';
8
+ import { RedisRateLimiter } from '../rate-limit/rate-limiter.js';
9
+ import type { RateLimitConfig } from '../rate-limit/types.js';
10
+ import { RedisPubSub } from '../pubsub/pubsub.js';
11
+ import type { PubSubConfig } from '../pubsub/types.js';
12
+ import { RedisStreams } from '../streams/streams.js';
13
+ import type { StreamsConfig } from '../streams/types.js';
14
+ import { type SessionConfig } from '../session/config.js';
15
+ import type { KeyManager, SessionMetrics } from '../session/types.js';
16
+ import type { SessionManager } from '../session/manager.js';
17
+ import type { ModuleConfigMode } from '../modules-config.js';
18
+ /** Complete package configuration. Module sections are optional and disabled by default. */
19
+ export type RedisClientConfig = RedisConfig & {
20
+ cache?: Partial<CacheConfig>;
21
+ lock?: Partial<LockConfig>;
22
+ rateLimit?: Partial<RateLimitConfig>;
23
+ pubsub?: Partial<PubSubConfig>;
24
+ streams?: Partial<StreamsConfig>;
25
+ sessions?: Partial<SessionConfig>;
26
+ };
27
+ /** Optional dependencies for the session module: a key manager when encryption is enabled, and/or a metrics sink. */
28
+ export interface RedisClientDependencies {
29
+ encryptionKeyManager?: KeyManager;
30
+ metrics?: SessionMetrics;
31
+ }
32
+ /** Shared Redis client facade exposing all package modules through one connection/configuration boundary. */
33
+ export declare class RedisClient extends RedisClientWrapper {
34
+ private cacheModule?;
35
+ private lockModule?;
36
+ private rateLimitModule?;
37
+ private pubsubModule;
38
+ private streamsModule?;
39
+ private sessionModule;
40
+ private readonly moduleConfig;
41
+ private readonly dependencies;
42
+ /** Creates the shared Redis facade and normalizes every module's global configuration. */
43
+ constructor(connection: ReturnType<typeof createRedisConnection>, config: RedisClientConfig, dependencies?: RedisClientDependencies);
44
+ /** Returns the configured cache module, creating it lazily. Throws if the module is disabled. */
45
+ get cache(): RedisCache;
46
+ /** Returns the configured distributed-lock module, creating it lazily. Throws if the module is disabled. */
47
+ get lock(): RedisLock;
48
+ /** Returns the configured rate-limiter module, creating it lazily. Throws if the module is disabled. */
49
+ get rateLimiter(): RedisRateLimiter;
50
+ /** Returns the configured Pub/Sub module, creating it lazily. Throws if the module is disabled. */
51
+ get pubsub(): RedisPubSub;
52
+ /** Returns the configured Streams module, creating it lazily. Throws if the module is disabled. */
53
+ get streams(): RedisStreams;
54
+ /** Returns the configured session manager, creating it lazily. */
55
+ get sessions(): SessionManager;
56
+ /** Merges or replaces the global cache configuration and returns this client for fluent chaining. */
57
+ withCache(options?: Partial<CacheConfig>, mode?: ModuleConfigMode): this;
58
+ /** Merges or replaces the global lock configuration and returns this client for fluent chaining. */
59
+ withLock(options?: Partial<LockConfig>, mode?: ModuleConfigMode): this;
60
+ /** Alias for withLock for codebases that prefer lowercase module naming. */
61
+ withlock(options?: Partial<LockConfig>, mode?: ModuleConfigMode): this;
62
+ /** Merges or replaces the global rate-limit configuration and returns this client for fluent chaining. */
63
+ withRateLimit(options?: Partial<RateLimitConfig>, mode?: ModuleConfigMode): this;
64
+ /** Merges or replaces the global Pub/Sub configuration and returns this client for fluent chaining. */
65
+ withPubSub(options?: Partial<PubSubConfig>, mode?: ModuleConfigMode): this;
66
+ /** Merges or replaces the global Streams configuration and returns this client for fluent chaining. */
67
+ withStreams(options?: Partial<StreamsConfig>, mode?: ModuleConfigMode): this;
68
+ /** Merges or replaces the global session configuration and returns this client for fluent chaining. */
69
+ withSessions(options?: Partial<SessionConfig>, mode?: ModuleConfigMode): this;
70
+ /** Alias for withSession for singular naming. */
71
+ withSession(options?: Partial<SessionConfig>, mode?: ModuleConfigMode): this;
72
+ /** Returns a snapshot of normalized global module configuration. */
73
+ get config(): Readonly<typeof this.moduleConfig>;
74
+ }
75
+ /** Creates a single shared Redis client with all optional modules configured from one object. */
76
+ export declare function createRedisClient(config: RedisClientConfig, dependencies?: RedisClientDependencies): RedisClient;
77
+ //# sourceMappingURL=client-facade.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-facade.d.ts","sourceRoot":"","sources":["../../src/redis/client-facade.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,102 @@
1
+ import { createRedisConnection } from './client.js';
2
+ import { RedisClientWrapper } from './wrapper.js';
3
+ import { RedisConfigurationError } from './errors.js';
4
+ import { parseCacheConfig } from '../cache/config.js';
5
+ import { RedisCache } from '../cache/cache.js';
6
+ import { parseLockConfig } from '../lock/config.js';
7
+ import { RedisLock } from '../lock/lock.js';
8
+ import { parseRateLimitConfig } from '../rate-limit/config.js';
9
+ import { RedisRateLimiter } from '../rate-limit/rate-limiter.js';
10
+ import { parsePubSubConfig } from '../pubsub/config.js';
11
+ import { RedisPubSub } from '../pubsub/pubsub.js';
12
+ import { parseStreamsConfig } from '../streams/config.js';
13
+ import { RedisStreams } from '../streams/streams.js';
14
+ import { parseSessionConfig } from '../session/config.js';
15
+ import { createSessionManager } from '../session/factory.js';
16
+ /** Shared Redis client facade exposing all package modules through one connection/configuration boundary. */
17
+ export class RedisClient extends RedisClientWrapper {
18
+ cacheModule;
19
+ lockModule;
20
+ rateLimitModule;
21
+ pubsubModule;
22
+ streamsModule;
23
+ sessionModule;
24
+ moduleConfig;
25
+ dependencies;
26
+ /** Creates the shared Redis facade and normalizes every module's global configuration. */
27
+ constructor(connection, config, dependencies = {}) {
28
+ super(connection);
29
+ this.dependencies = dependencies;
30
+ this.moduleConfig = {
31
+ cache: parseCacheConfig(config.cache), lock: parseLockConfig(config.lock), rateLimit: parseRateLimitConfig(config.rateLimit), pubsub: parsePubSubConfig(config.pubsub), streams: parseStreamsConfig(config.streams), sessions: parseSessionConfig(config.sessions),
32
+ };
33
+ }
34
+ /** Returns the configured cache module, creating it lazily. Throws if the module is disabled. */
35
+ get cache() {
36
+ if (!this.moduleConfig.cache.enabled)
37
+ throw new RedisConfigurationError('Cache module is disabled');
38
+ return this.cacheModule ??= new RedisCache(this, this.moduleConfig.cache);
39
+ }
40
+ /** Returns the configured distributed-lock module, creating it lazily. Throws if the module is disabled. */
41
+ get lock() {
42
+ if (!this.moduleConfig.lock.enabled)
43
+ throw new RedisConfigurationError('Lock module is disabled');
44
+ return this.lockModule ??= new RedisLock(this, this.moduleConfig.lock);
45
+ }
46
+ /** Returns the configured rate-limiter module, creating it lazily. Throws if the module is disabled. */
47
+ get rateLimiter() {
48
+ if (!this.moduleConfig.rateLimit.enabled)
49
+ throw new RedisConfigurationError('Rate-limit module is disabled');
50
+ return this.rateLimitModule ??= new RedisRateLimiter(this, this.moduleConfig.rateLimit);
51
+ }
52
+ /** Returns the configured Pub/Sub module, creating it lazily. Throws if the module is disabled. */
53
+ get pubsub() {
54
+ if (!this.moduleConfig.pubsub.enabled)
55
+ throw new RedisConfigurationError('Pub/Sub module is disabled');
56
+ return this.pubsubModule ??= new RedisPubSub(this, this.moduleConfig.pubsub);
57
+ }
58
+ /** Returns the configured Streams module, creating it lazily. Throws if the module is disabled. */
59
+ get streams() {
60
+ if (!this.moduleConfig.streams.enabled)
61
+ throw new RedisConfigurationError('Streams module is disabled');
62
+ return this.streamsModule ??= new RedisStreams(this, this.moduleConfig.streams);
63
+ }
64
+ /** Returns the configured session manager, creating it lazily. */
65
+ get sessions() {
66
+ if (!this.sessionModule) {
67
+ const options = { redis: this, config: this.moduleConfig.sessions, ...(this.dependencies.encryptionKeyManager ? { encryptionKeyManager: this.dependencies.encryptionKeyManager } : {}), ...(this.dependencies.metrics ? { metrics: this.dependencies.metrics } : {}) };
68
+ this.sessionModule = createSessionManager(options);
69
+ }
70
+ return this.sessionModule;
71
+ }
72
+ /** Merges or replaces the global cache configuration and returns this client for fluent chaining. */
73
+ withCache(options = {}, mode = 'merge') { this.moduleConfig.cache = parseCacheConfig(mode === 'merge' ? { ...this.moduleConfig.cache, ...options } : options); this.cacheModule = new RedisCache(this, this.moduleConfig.cache); return this; }
74
+ /** Merges or replaces the global lock configuration and returns this client for fluent chaining. */
75
+ withLock(options = {}, mode = 'merge') { this.moduleConfig.lock = parseLockConfig(mode === 'merge' ? { ...this.moduleConfig.lock, ...options } : options); this.lockModule = new RedisLock(this, this.moduleConfig.lock); return this; }
76
+ /** Alias for withLock for codebases that prefer lowercase module naming. */
77
+ withlock(options = {}, mode = 'merge') { return this.withLock(options, mode); }
78
+ /** Merges or replaces the global rate-limit configuration and returns this client for fluent chaining. */
79
+ withRateLimit(options = {}, mode = 'merge') { this.moduleConfig.rateLimit = parseRateLimitConfig(mode === 'merge' ? { ...this.moduleConfig.rateLimit, ...options } : options); this.rateLimitModule = new RedisRateLimiter(this, this.moduleConfig.rateLimit); return this; }
80
+ /** Merges or replaces the global Pub/Sub configuration and returns this client for fluent chaining. */
81
+ withPubSub(options = {}, mode = 'merge') { void this.pubsubModule?.close().catch(() => undefined); this.pubsubModule = undefined; this.moduleConfig.pubsub = parsePubSubConfig(mode === 'merge' ? { ...this.moduleConfig.pubsub, ...options } : options); this.pubsubModule = new RedisPubSub(this, this.moduleConfig.pubsub); return this; }
82
+ /** Merges or replaces the global Streams configuration and returns this client for fluent chaining. */
83
+ withStreams(options = {}, mode = 'merge') { this.moduleConfig.streams = parseStreamsConfig(mode === 'merge' ? { ...this.moduleConfig.streams, ...options } : options); this.streamsModule = new RedisStreams(this, this.moduleConfig.streams); return this; }
84
+ /** Merges or replaces the global session configuration and returns this client for fluent chaining. */
85
+ withSessions(options = {}, mode = 'merge') { this.moduleConfig.sessions = parseSessionConfig(mode === 'merge' ? { ...this.moduleConfig.sessions, ...options } : options); this.sessionModule = undefined; return this; }
86
+ /** Alias for withSession for singular naming. */
87
+ withSession(options = {}, mode = 'merge') { return this.withSessions(options, mode); }
88
+ /** Returns a snapshot of normalized global module configuration. */
89
+ get config() { return this.moduleConfig; }
90
+ }
91
+ /** Creates a single shared Redis client with all optional modules configured from one object. */
92
+ export function createRedisClient(config, dependencies = {}) {
93
+ const { cache: _cache, lock: _lock, rateLimit: _rateLimit, pubsub: _pubsub, streams: _streams, sessions: _sessions, ...redisConfig } = config;
94
+ void _cache;
95
+ void _lock;
96
+ void _rateLimit;
97
+ void _pubsub;
98
+ void _streams;
99
+ void _sessions;
100
+ return new RedisClient(createRedisConnection(redisConfig), config, dependencies);
101
+ }
102
+ //# sourceMappingURL=client-facade.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-facade.js","sourceRoot":"","sources":["../../src/redis/client-facade.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { RedisConfig, RedisConnection } from './types.js';
2
+ /**
3
+ * Creates a topology-appropriate ioredis connection. Always attaches a no-op
4
+ * `'error'` listener: ioredis (like every Node `EventEmitter`) throws an uncaught
5
+ * exception and crashes the process when an `'error'` event fires with zero
6
+ * listeners. Attaching this default does not prevent callers from adding their
7
+ * own listener on the returned connection for real observability/alerting.
8
+ */
9
+ export declare function createRedisConnection(config: RedisConfig): RedisConnection;
10
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/redis/client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAkB/D;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,WAAW,GAAG,eAAe,CAI1E"}
@@ -0,0 +1,29 @@
1
+ import Redis, { Cluster } from 'ioredis';
2
+ function buildConnection(config) {
3
+ if (config.mode === "cluster") {
4
+ const { mode: _mode, nodes, ...options } = config;
5
+ void _mode;
6
+ return new Cluster(nodes, options);
7
+ }
8
+ if (config.mode === "sentinel") {
9
+ const { mode: _mode, sentinels, name, ...options } = config;
10
+ void _mode;
11
+ return new Redis.Redis({ ...options, sentinels, name });
12
+ }
13
+ const { mode: _mode, ...options } = config;
14
+ void _mode;
15
+ return new Redis.Redis(options);
16
+ }
17
+ /**
18
+ * Creates a topology-appropriate ioredis connection. Always attaches a no-op
19
+ * `'error'` listener: ioredis (like every Node `EventEmitter`) throws an uncaught
20
+ * exception and crashes the process when an `'error'` event fires with zero
21
+ * listeners. Attaching this default does not prevent callers from adding their
22
+ * own listener on the returned connection for real observability/alerting.
23
+ */
24
+ export function createRedisConnection(config) {
25
+ const connection = buildConnection(config);
26
+ connection.on('error', () => { });
27
+ return connection;
28
+ }
29
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/redis/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGzC,SAAS,eAAe,CAAC,MAAmB;IAC1C,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,OAAO,EAAE,GAAG,MAAM,CAAC;QAClD,KAAK,KAAK,CAAC;QACX,OAAO,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC/B,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,GAAG,MAAM,CAAC;QAC5D,KAAK,KAAK,CAAC;QACX,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,CAAC;IACD,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,OAAO,EAAE,GAAG,MAAM,CAAC;IAC3C,KAAK,KAAK,CAAC;IACX,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAmB;IACvD,MAAM,UAAU,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAC3C,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAA2F,CAAC,CAAC,CAAC;IAC1H,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /** Calculates the Redis Cluster hash slot (0-16383), honoring the first valid hash tag. */
2
+ export declare function redisHashSlot(key: string): number;
3
+ /** Derives a fixed-length SHA-256 user tag safe for Redis Cluster hash-tagging. */
4
+ export declare function safeUserTag(userId: string): string;
5
+ /** Throws when two or more keys do not resolve to the same Redis Cluster slot. */
6
+ export declare function assertSameSlot(keys: readonly string[]): void;
7
+ //# sourceMappingURL=cluster.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cluster.d.ts","sourceRoot":"","sources":["../../src/redis/cluster.ts"],"names":[],"mappings":"AAyBA,2FAA2F;AAC3F,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKjD;AAED,mFAAmF;AACnF,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,kFAAkF;AAClF,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAM5D"}
@@ -0,0 +1,47 @@
1
+ import { createHash } from 'node:crypto';
2
+ const SLOT_COUNT = 16_384;
3
+ const CRC16_TABLE = (() => {
4
+ const table = new Uint16Array(256);
5
+ for (let i = 0; i < 256; i += 1) {
6
+ let crc = i << 8;
7
+ for (let j = 0; j < 8; j += 1) {
8
+ crc = (crc & 0x8000) !== 0 ? ((crc << 1) ^ 0x1021) & 0xffff : (crc << 1) & 0xffff;
9
+ }
10
+ table[i] = crc;
11
+ }
12
+ return table;
13
+ })();
14
+ function hashInput(key) {
15
+ const first = key.indexOf('{');
16
+ if (first !== -1) {
17
+ const second = key.indexOf('}', first + 1);
18
+ if (second !== -1 && second > first + 1)
19
+ return Buffer.from(key.slice(first + 1, second));
20
+ }
21
+ return Buffer.from(key);
22
+ }
23
+ /** Calculates the Redis Cluster hash slot (0-16383), honoring the first valid hash tag. */
24
+ export function redisHashSlot(key) {
25
+ const input = hashInput(key);
26
+ let crc = 0;
27
+ for (const byte of input) {
28
+ const index = ((crc >>> 8) ^ byte) & 0xff;
29
+ crc = ((crc << 8) ^ CRC16_TABLE[index]) & 0xffff;
30
+ }
31
+ return crc % SLOT_COUNT;
32
+ }
33
+ /** Derives a fixed-length SHA-256 user tag safe for Redis Cluster hash-tagging. */
34
+ export function safeUserTag(userId) {
35
+ return createHash('sha256').update(userId, 'utf8').digest('hex');
36
+ }
37
+ /** Throws when two or more keys do not resolve to the same Redis Cluster slot. */
38
+ export function assertSameSlot(keys) {
39
+ if (keys.length < 2)
40
+ return;
41
+ const slot = redisHashSlot(keys[0]);
42
+ for (const key of keys.slice(1)) {
43
+ if (redisHashSlot(key) !== slot)
44
+ throw new Error('Redis keys do not share a hash slot');
45
+ }
46
+ }
47
+ //# sourceMappingURL=cluster.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cluster.js","sourceRoot":"","sources":["../../src/redis/cluster.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,UAAU,GAAG,MAAM,CAAC;AAE1B,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE;IACxB,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC;IACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAChC,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;QACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,GAAG,GAAG,CAAC,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC;QACpF,CAAC;QACD,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;IACjB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC,EAAE,CAAC;AAEL,SAAS,SAAS,CAAC,GAAW;IAC5B,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;QACjB,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;QAC3C,IAAI,MAAM,KAAK,CAAC,CAAC,IAAI,MAAM,GAAG,KAAK,GAAG,CAAC;YAAE,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5F,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC1B,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAAC,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;QAAC,GAAG,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,WAAW,CAAC,KAAK,CAAE,CAAC,GAAG,MAAM,CAAC;IAAC,CAAC;IAC3H,OAAO,GAAG,GAAG,UAAU,CAAC;AAC1B,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACnE,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,cAAc,CAAC,IAAuB;IACpD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO;IAC5B,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC;IACrC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAChC,IAAI,aAAa,CAAC,GAAG,CAAC,KAAK,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IAC1F,CAAC;AACH,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { z } from 'zod';
2
+ import type { RedisConfig } from './types.js';
3
+ /** Runtime schema for the standalone Redis connection subset accepted by this package. */
4
+ export declare const RedisConnectionConfigSchema: z.ZodPreprocess<z.ZodDiscriminatedUnion<[z.ZodObject<{
5
+ mode: z.ZodLiteral<"standalone">;
6
+ host: z.ZodDefault<z.ZodString>;
7
+ port: z.ZodDefault<z.ZodNumber>;
8
+ password: z.ZodOptional<z.ZodString>;
9
+ username: z.ZodOptional<z.ZodString>;
10
+ db: z.ZodDefault<z.ZodNumber>;
11
+ tls: z.ZodOptional<z.ZodUnknown>;
12
+ }, z.core.$loose>, z.ZodObject<{
13
+ mode: z.ZodLiteral<"sentinel">;
14
+ sentinels: z.ZodArray<z.ZodObject<{
15
+ host: z.ZodString;
16
+ port: z.ZodNumber;
17
+ }, z.core.$strip>>;
18
+ name: z.ZodString;
19
+ username: z.ZodOptional<z.ZodString>;
20
+ password: z.ZodOptional<z.ZodString>;
21
+ db: z.ZodDefault<z.ZodNumber>;
22
+ tls: z.ZodOptional<z.ZodUnknown>;
23
+ }, z.core.$loose>, z.ZodObject<{
24
+ mode: z.ZodLiteral<"cluster">;
25
+ nodes: z.ZodArray<z.ZodObject<{
26
+ host: z.ZodString;
27
+ port: z.ZodNumber;
28
+ }, z.core.$strip>>;
29
+ redisOptions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
30
+ }, z.core.$loose>], "mode">, unknown>;
31
+ /**
32
+ * Validates the public Redis connection configuration and returns it in the
33
+ * package's topology-independent shape. Unsupported extra ioredis options are
34
+ * preserved so advanced users can still configure retries, TLS, timeouts, and
35
+ * other supported client features. `mode` may be omitted for standalone Redis,
36
+ * matching {@link StandaloneRedisConfig}'s optional `mode` field.
37
+ */
38
+ export declare function parseRedisConnectionConfig(input: unknown): RedisConfig;
39
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/redis/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAO9C,0FAA0F;AAC1F,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;qCAgCvC,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAMtE"}