@mhbdev/redis 0.2.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 (123) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE +21 -0
  3. package/README.md +173 -0
  4. package/dist/bullmq/adapter.d.ts +49 -0
  5. package/dist/bullmq/adapter.d.ts.map +1 -0
  6. package/dist/bullmq/adapter.js +56 -0
  7. package/dist/bullmq/adapter.js.map +1 -0
  8. package/dist/bullmq/index.d.ts +3 -0
  9. package/dist/bullmq/index.d.ts.map +1 -0
  10. package/dist/bullmq/index.js +2 -0
  11. package/dist/bullmq/index.js.map +1 -0
  12. package/dist/cache/cache.d.ts +31 -0
  13. package/dist/cache/cache.d.ts.map +1 -0
  14. package/dist/cache/cache.js +78 -0
  15. package/dist/cache/cache.js.map +1 -0
  16. package/dist/cache/index.d.ts +3 -0
  17. package/dist/cache/index.d.ts.map +1 -0
  18. package/dist/cache/index.js +2 -0
  19. package/dist/cache/index.js.map +1 -0
  20. package/dist/core/codec.d.ts +7 -0
  21. package/dist/core/codec.d.ts.map +1 -0
  22. package/dist/core/codec.js +24 -0
  23. package/dist/core/codec.js.map +1 -0
  24. package/dist/core/errors.d.ts +43 -0
  25. package/dist/core/errors.d.ts.map +1 -0
  26. package/dist/core/errors.js +84 -0
  27. package/dist/core/errors.js.map +1 -0
  28. package/dist/core/executor.d.ts +28 -0
  29. package/dist/core/executor.d.ts.map +1 -0
  30. package/dist/core/executor.js +27 -0
  31. package/dist/core/executor.js.map +1 -0
  32. package/dist/core/keys.d.ts +4 -0
  33. package/dist/core/keys.d.ts.map +1 -0
  34. package/dist/core/keys.js +15 -0
  35. package/dist/core/keys.js.map +1 -0
  36. package/dist/index.d.ts +15 -0
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +11 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/ioredis/executor.d.ts +30 -0
  41. package/dist/ioredis/executor.d.ts.map +1 -0
  42. package/dist/ioredis/executor.js +52 -0
  43. package/dist/ioredis/executor.js.map +1 -0
  44. package/dist/ioredis/index.d.ts +5 -0
  45. package/dist/ioredis/index.d.ts.map +1 -0
  46. package/dist/ioredis/index.js +3 -0
  47. package/dist/ioredis/index.js.map +1 -0
  48. package/dist/ioredis/pubsub.d.ts +16 -0
  49. package/dist/ioredis/pubsub.d.ts.map +1 -0
  50. package/dist/ioredis/pubsub.js +42 -0
  51. package/dist/ioredis/pubsub.js.map +1 -0
  52. package/dist/locks/index.d.ts +3 -0
  53. package/dist/locks/index.d.ts.map +1 -0
  54. package/dist/locks/index.js +2 -0
  55. package/dist/locks/index.js.map +1 -0
  56. package/dist/locks/locks.d.ts +25 -0
  57. package/dist/locks/locks.d.ts.map +1 -0
  58. package/dist/locks/locks.js +77 -0
  59. package/dist/locks/locks.js.map +1 -0
  60. package/dist/node/client.d.ts +47 -0
  61. package/dist/node/client.d.ts.map +1 -0
  62. package/dist/node/client.js +155 -0
  63. package/dist/node/client.js.map +1 -0
  64. package/dist/node/errors.d.ts +3 -0
  65. package/dist/node/errors.d.ts.map +1 -0
  66. package/dist/node/errors.js +16 -0
  67. package/dist/node/errors.js.map +1 -0
  68. package/dist/node/index.d.ts +6 -0
  69. package/dist/node/index.d.ts.map +1 -0
  70. package/dist/node/index.js +4 -0
  71. package/dist/node/index.js.map +1 -0
  72. package/dist/node/pool.d.ts +31 -0
  73. package/dist/node/pool.d.ts.map +1 -0
  74. package/dist/node/pool.js +131 -0
  75. package/dist/node/pool.js.map +1 -0
  76. package/dist/node/pubsub.d.ts +16 -0
  77. package/dist/node/pubsub.d.ts.map +1 -0
  78. package/dist/node/pubsub.js +41 -0
  79. package/dist/node/pubsub.js.map +1 -0
  80. package/dist/pubsub/contracts.d.ts +6 -0
  81. package/dist/pubsub/contracts.d.ts.map +1 -0
  82. package/dist/pubsub/contracts.js +2 -0
  83. package/dist/pubsub/contracts.js.map +1 -0
  84. package/dist/pubsub/index.d.ts +3 -0
  85. package/dist/pubsub/index.d.ts.map +1 -0
  86. package/dist/pubsub/index.js +2 -0
  87. package/dist/pubsub/index.js.map +1 -0
  88. package/dist/pubsub/pubsub.d.ts +15 -0
  89. package/dist/pubsub/pubsub.d.ts.map +1 -0
  90. package/dist/pubsub/pubsub.js +62 -0
  91. package/dist/pubsub/pubsub.js.map +1 -0
  92. package/dist/queue/index.d.ts +3 -0
  93. package/dist/queue/index.d.ts.map +1 -0
  94. package/dist/queue/index.js +2 -0
  95. package/dist/queue/index.js.map +1 -0
  96. package/dist/queue/queue.d.ts +78 -0
  97. package/dist/queue/queue.d.ts.map +1 -0
  98. package/dist/queue/queue.js +260 -0
  99. package/dist/queue/queue.js.map +1 -0
  100. package/dist/rate-limit/contracts.d.ts +93 -0
  101. package/dist/rate-limit/contracts.d.ts.map +1 -0
  102. package/dist/rate-limit/contracts.js +304 -0
  103. package/dist/rate-limit/contracts.js.map +1 -0
  104. package/dist/rate-limit/index.d.ts +3 -0
  105. package/dist/rate-limit/index.d.ts.map +1 -0
  106. package/dist/rate-limit/index.js +2 -0
  107. package/dist/rate-limit/index.js.map +1 -0
  108. package/dist/testing/fake-executor.d.ts +9 -0
  109. package/dist/testing/fake-executor.d.ts.map +1 -0
  110. package/dist/testing/fake-executor.js +15 -0
  111. package/dist/testing/fake-executor.js.map +1 -0
  112. package/dist/testing/index.d.ts +2 -0
  113. package/dist/testing/index.d.ts.map +1 -0
  114. package/dist/testing/index.js +2 -0
  115. package/dist/testing/index.js.map +1 -0
  116. package/docs/adapters.md +41 -0
  117. package/docs/architecture.md +41 -0
  118. package/docs/errors.md +27 -0
  119. package/docs/migration.md +21 -0
  120. package/docs/queues.md +13 -0
  121. package/docs/rate-limiting.md +23 -0
  122. package/docs/releasing.md +45 -0
  123. package/package.json +135 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ export type RedisCommand = readonly string[];
2
+ export type RedisCommandOptions = Readonly<{
3
+ signal?: AbortSignal;
4
+ }>;
5
+ export type RedisScriptOptions = Readonly<{
6
+ keys?: readonly string[];
7
+ arguments?: readonly string[];
8
+ }>;
9
+ export interface RedisExecutor {
10
+ execute<T = unknown>(command: RedisCommand, options?: RedisCommandOptions): Promise<T>;
11
+ eval<T = unknown>(script: string, options: RedisScriptOptions, request?: RedisCommandOptions): Promise<T>;
12
+ }
13
+ export interface RedisConnection extends RedisExecutor {
14
+ connect(): Promise<void>;
15
+ close(): Promise<void>;
16
+ ping(): Promise<void>;
17
+ readonly isReady: boolean;
18
+ }
19
+ export type RedisHooks = Readonly<{
20
+ onCommandStart?: (command: RedisCommand) => void;
21
+ onCommandEnd?: (command: RedisCommand, durationMs: number) => void;
22
+ onError?: (error: Error) => void;
23
+ onStateChange?: (state: RedisConnectionState) => void;
24
+ }>;
25
+ export type RedisConnectionState = "idle" | "connecting" | "ready" | "closed" | "error";
26
+ export declare function assertPositiveInteger(value: number, name: string): void;
27
+ export declare function withTimeout<T>(operation: (signal: AbortSignal) => Promise<T>, timeoutMs: number, message?: string): Promise<T>;
28
+ //# sourceMappingURL=executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/core/executor.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,YAAY,GAAG,SAAS,MAAM,EAAE,CAAC;AAC7C,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IAAE,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,CAAC,CAAC;AACrE,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC;IACzC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B,CAAC,CAAC;AAEH,MAAM,WAAW,aAAa;IAC7B,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACvF,IAAI,CAAC,CAAC,GAAG,OAAO,EACf,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,mBAAmB,GAC3B,OAAO,CAAC,CAAC,CAAC,CAAC;CACd;AAED,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACrD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IACjC,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;IACjD,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IACnE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAC;CACtD,CAAC,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,YAAY,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAExF,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAIvE;AAED,wBAAsB,WAAW,CAAC,CAAC,EAClC,SAAS,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,EAC9C,SAAS,EAAE,MAAM,EACjB,OAAO,SAA8B,GACnC,OAAO,CAAC,CAAC,CAAC,CAiBZ"}
@@ -0,0 +1,27 @@
1
+ import { RedisConfigurationError, RedisTimeoutError } from "./errors.js";
2
+ export function assertPositiveInteger(value, name) {
3
+ if (!Number.isSafeInteger(value) || value <= 0) {
4
+ throw new RedisConfigurationError(`${name} must be a positive integer`);
5
+ }
6
+ }
7
+ export async function withTimeout(operation, timeoutMs, message = "Redis operation timed out") {
8
+ assertPositiveInteger(timeoutMs, "Redis timeout");
9
+ const controller = new AbortController();
10
+ let timer;
11
+ try {
12
+ return await Promise.race([
13
+ operation(controller.signal),
14
+ new Promise((_, reject) => {
15
+ timer = setTimeout(() => {
16
+ controller.abort();
17
+ reject(new RedisTimeoutError(message));
18
+ }, timeoutMs);
19
+ }),
20
+ ]);
21
+ }
22
+ finally {
23
+ if (timer)
24
+ clearTimeout(timer);
25
+ }
26
+ }
27
+ //# sourceMappingURL=executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/core/executor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAkCzE,MAAM,UAAU,qBAAqB,CAAC,KAAa,EAAE,IAAY;IAChE,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,uBAAuB,CAAC,GAAG,IAAI,6BAA6B,CAAC,CAAC;IACzE,CAAC;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAChC,SAA8C,EAC9C,SAAiB,EACjB,OAAO,GAAG,2BAA2B;IAErC,qBAAqB,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;IAClD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,IAAI,KAAgD,CAAC;IACrD,IAAI,CAAC;QACJ,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC;YACzB,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC;YAC5B,IAAI,OAAO,CAAI,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;gBAC5B,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;oBACvB,UAAU,CAAC,KAAK,EAAE,CAAC;oBACnB,MAAM,CAAC,IAAI,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC;gBACxC,CAAC,EAAE,SAAS,CAAC,CAAC;YACf,CAAC,CAAC;SACF,CAAC,CAAC;IACJ,CAAC;YAAS,CAAC;QACV,IAAI,KAAK;YAAE,YAAY,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;AACF,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function hashIdentifier(value: string): Promise<string>;
2
+ export declare function namespacedKey(prefix: string, ...parts: string[]): string;
3
+ export declare function assertKeyPart(value: string, name: string): void;
4
+ //# sourceMappingURL=keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../src/core/keys.ts"],"names":[],"mappings":"AAIA,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAKnE;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAExE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAM/D"}
@@ -0,0 +1,15 @@
1
+ import { RedisConfigurationError } from "./errors.js";
2
+ const encoder = new TextEncoder();
3
+ export async function hashIdentifier(value) {
4
+ const digest = await crypto.subtle.digest("SHA-256", encoder.encode(value));
5
+ return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
6
+ }
7
+ export function namespacedKey(prefix, ...parts) {
8
+ return [prefix, ...parts].join(":");
9
+ }
10
+ export function assertKeyPart(value, name) {
11
+ if (!value.trim() || value.length > 256 || value.includes("\n")) {
12
+ throw new RedisConfigurationError(`${name} must be a non-empty value of at most 256 characters`);
13
+ }
14
+ }
15
+ //# sourceMappingURL=keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.js","sourceRoot":"","sources":["../../src/core/keys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAEtD,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAElC,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAa;IACjD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5E,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAClD,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAClC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAc,EAAE,GAAG,KAAe;IAC/D,OAAO,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,IAAY;IACxD,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,uBAAuB,CAChC,GAAG,IAAI,sDAAsD,CAC7D,CAAC;IACH,CAAC;AACF,CAAC"}
@@ -0,0 +1,15 @@
1
+ export * from "./bullmq/index.js";
2
+ export * from "./cache/index.js";
3
+ export type { RedisCodec } from "./core/codec.js";
4
+ export { jsonCodec, stringCodec } from "./core/codec.js";
5
+ export type { RedisErrorCode } from "./core/errors.js";
6
+ export { asError, isRedisError, isRedisErrorCode, RedisClientStateError, RedisConfigurationError, RedisConnectionError, RedisError, RedisLockError, RedisProtocolError, RedisQueueError, RedisRequestAbortedError, RedisSerializationError, RedisTimeoutError, RedisUnavailableError, } from "./core/errors.js";
7
+ export type { RedisCommand, RedisCommandOptions, RedisConnection, RedisConnectionState, RedisExecutor, RedisHooks, RedisScriptOptions, } from "./core/executor.js";
8
+ export * from "./ioredis/index.js";
9
+ export * from "./locks/index.js";
10
+ export type { RedisClientOptions, RedisPoolOptions, } from "./node/index.js";
11
+ export { createRedisClient, createRedisPool, RedisClient, RedisPool, withRedisClient, withRedisPool, } from "./node/index.js";
12
+ export * from "./pubsub/index.js";
13
+ export * from "./queue/index.js";
14
+ export * from "./rate-limit/index.js";
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACzD,YAAY,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EACN,OAAO,EACP,YAAY,EACZ,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,EACpB,UAAU,EACV,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,wBAAwB,EACxB,uBAAuB,EACvB,iBAAiB,EACjB,qBAAqB,GACrB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACX,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,oBAAoB,EACpB,aAAa,EACb,UAAU,EACV,kBAAkB,GAClB,MAAM,oBAAoB,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,YAAY,EACX,kBAAkB,EAClB,gBAAgB,GAChB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACN,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,SAAS,EACT,eAAe,EACf,aAAa,GACb,MAAM,iBAAiB,CAAC;AACzB,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ export * from "./bullmq/index.js";
2
+ export * from "./cache/index.js";
3
+ export { jsonCodec, stringCodec } from "./core/codec.js";
4
+ export { asError, isRedisError, isRedisErrorCode, RedisClientStateError, RedisConfigurationError, RedisConnectionError, RedisError, RedisLockError, RedisProtocolError, RedisQueueError, RedisRequestAbortedError, RedisSerializationError, RedisTimeoutError, RedisUnavailableError, } from "./core/errors.js";
5
+ export * from "./ioredis/index.js";
6
+ export * from "./locks/index.js";
7
+ export { createRedisClient, createRedisPool, RedisClient, RedisPool, withRedisClient, withRedisPool, } from "./node/index.js";
8
+ export * from "./pubsub/index.js";
9
+ export * from "./queue/index.js";
10
+ export * from "./rate-limit/index.js";
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AAEjC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEzD,OAAO,EACN,OAAO,EACP,YAAY,EACZ,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,EACpB,UAAU,EACV,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,wBAAwB,EACxB,uBAAuB,EACvB,iBAAiB,EACjB,qBAAqB,GACrB,MAAM,kBAAkB,CAAC;AAU1B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AAKjC,OAAO,EACN,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,SAAS,EACT,eAAe,EACf,aAAa,GACb,MAAM,iBAAiB,CAAC;AACzB,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { RedisError } from "../core/errors.js";
2
+ import type { RedisCommand, RedisCommandOptions, RedisConnection, RedisScriptOptions } from "../core/executor.js";
3
+ export interface IoredisClientLike {
4
+ call(command: string, ...arguments_: string[]): Promise<unknown>;
5
+ eval(script: string, numberOfKeys: number, ...arguments_: string[]): Promise<unknown>;
6
+ ping(): Promise<unknown>;
7
+ quit?(): Promise<unknown>;
8
+ disconnect?(): void;
9
+ readonly status?: string;
10
+ }
11
+ export type IoredisExecutorOptions = Readonly<{
12
+ commandTimeoutMs?: number;
13
+ /** Map known ioredis/plugin error classes without inspecting error messages. */
14
+ normalizeError?: (error: unknown) => RedisError | undefined;
15
+ }>;
16
+ export declare class IoredisExecutor implements RedisConnection {
17
+ private readonly client;
18
+ private readonly options;
19
+ private readonly commandTimeoutMs;
20
+ constructor(client: IoredisClientLike, options?: IoredisExecutorOptions);
21
+ get isReady(): boolean;
22
+ connect(): Promise<void>;
23
+ execute<T = unknown>(command: RedisCommand, _options?: RedisCommandOptions): Promise<T>;
24
+ eval<T = unknown>(script: string, options: RedisScriptOptions, _options?: RedisCommandOptions): Promise<T>;
25
+ ping(): Promise<void>;
26
+ close(): Promise<void>;
27
+ private run;
28
+ }
29
+ export declare function createIoredisExecutor(client: IoredisClientLike, options?: IoredisExecutorOptions): IoredisExecutor;
30
+ //# sourceMappingURL=executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/ioredis/executor.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,UAAU,EAEV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EACX,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,kBAAkB,EAClB,MAAM,qBAAqB,CAAC;AAG7B,MAAM,WAAW,iBAAiB;IACjC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACjE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtF,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACzB,IAAI,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1B,UAAU,CAAC,IAAI,IAAI,CAAC;IACpB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAC7C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gFAAgF;IAChF,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,UAAU,GAAG,SAAS,CAAC;CAC5D,CAAC,CAAC;AAEH,qBAAa,eAAgB,YAAW,eAAe;IAIrD,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJzB,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAE1C,YACkB,MAAM,EAAE,iBAAiB,EACzB,OAAO,GAAE,sBAA2B,EAGrD;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAEK,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAI7B;IAEK,OAAO,CAAC,CAAC,GAAG,OAAO,EACxB,OAAO,EAAE,YAAY,EACrB,QAAQ,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,CAAC,CAAC,CAIZ;IAEK,IAAI,CAAC,CAAC,GAAG,OAAO,EACrB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,kBAAkB,EAC3B,QAAQ,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,CAAC,CAAC,CAUZ;IAEK,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAE1B;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAG3B;YAEa,GAAG;CAUjB;AAED,wBAAgB,qBAAqB,CACpC,MAAM,EAAE,iBAAiB,EACzB,OAAO,CAAC,EAAE,sBAAsB,GAC9B,eAAe,CAEjB"}
@@ -0,0 +1,52 @@
1
+ import { RedisClientStateError, RedisError, RedisUnavailableError, } from "../core/errors.js";
2
+ import { withTimeout } from "../core/executor.js";
3
+ export class IoredisExecutor {
4
+ client;
5
+ options;
6
+ commandTimeoutMs;
7
+ constructor(client, options = {}) {
8
+ this.client = client;
9
+ this.options = options;
10
+ this.commandTimeoutMs = options.commandTimeoutMs ?? 3_000;
11
+ }
12
+ get isReady() {
13
+ return this.client.status === undefined || this.client.status === "ready";
14
+ }
15
+ async connect() {
16
+ if (!this.isReady && this.client.status === "end")
17
+ throw new RedisClientStateError("The ioredis client has ended");
18
+ await this.run(() => this.client.ping());
19
+ }
20
+ async execute(command, _options) {
21
+ return this.run(() => this.client.call(command[0] ?? "", ...command.slice(1)));
22
+ }
23
+ async eval(script, options, _options) {
24
+ return this.run(() => this.client.eval(script, options.keys?.length ?? 0, ...(options.keys ?? []), ...(options.arguments ?? [])));
25
+ }
26
+ async ping() {
27
+ await this.run(() => this.client.ping());
28
+ }
29
+ async close() {
30
+ if (this.client.quit)
31
+ await this.client.quit();
32
+ else
33
+ this.client.disconnect?.();
34
+ }
35
+ async run(operation) {
36
+ try {
37
+ return await withTimeout(operation, this.commandTimeoutMs);
38
+ }
39
+ catch (error) {
40
+ const normalized = this.options.normalizeError?.(error);
41
+ if (normalized)
42
+ throw normalized;
43
+ if (error instanceof RedisError)
44
+ throw error;
45
+ throw new RedisUnavailableError(error);
46
+ }
47
+ }
48
+ }
49
+ export function createIoredisExecutor(client, options) {
50
+ return new IoredisExecutor(client, options);
51
+ }
52
+ //# sourceMappingURL=executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/ioredis/executor.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,qBAAqB,EACrB,UAAU,EACV,qBAAqB,GACrB,MAAM,mBAAmB,CAAC;AAO3B,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAiBlD,MAAM,OAAO,eAAe;IAIT,MAAM;IACN,OAAO;IAJR,gBAAgB,CAAS;IAE1C,YACkB,MAAyB,EACzB,OAAO,GAA2B,EAAE;sBADpC,MAAM;uBACN,OAAO;QAExB,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,KAAK,CAAC;IAC3D,CAAC;IAED,IAAI,OAAO;QACV,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,OAAO,CAAC;IAC3E,CAAC;IAED,KAAK,CAAC,OAAO;QACZ,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,KAAK;YAChD,MAAM,IAAI,qBAAqB,CAAC,8BAA8B,CAAC,CAAC;QACjE,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,OAAO,CACZ,OAAqB,EACrB,QAA8B;QAE9B,OAAO,IAAI,CAAC,GAAG,CACd,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAe,CAC3E,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CACT,MAAc,EACd,OAA2B,EAC3B,QAA8B;QAE9B,OAAO,IAAI,CAAC,GAAG,CACd,GAAG,EAAE,CACJ,IAAI,CAAC,MAAM,CAAC,IAAI,CACf,MAAM,EACN,OAAO,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,EACzB,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,EACvB,GAAG,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CACd,CAChB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI;QACT,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,KAAK;QACV,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI;YAAE,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;;YAC1C,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,CAAC;IACjC,CAAC;IAEO,KAAK,CAAC,GAAG,CAAI,SAA2B;QAC/C,IAAI,CAAC;YACJ,OAAO,MAAM,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC5D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,KAAK,CAAC,CAAC;YACxD,IAAI,UAAU;gBAAE,MAAM,UAAU,CAAC;YACjC,IAAI,KAAK,YAAY,UAAU;gBAAE,MAAM,KAAK,CAAC;YAC7C,MAAM,IAAI,qBAAqB,CAAC,KAAK,CAAC,CAAC;QACxC,CAAC;IACF,CAAC;CACD;AAED,MAAM,UAAU,qBAAqB,CACpC,MAAyB,EACzB,OAAgC;IAEhC,OAAO,IAAI,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,5 @@
1
+ export type { IoredisClientLike, IoredisExecutorOptions } from "./executor.js";
2
+ export { createIoredisExecutor, IoredisExecutor } from "./executor.js";
3
+ export type { IoredisPubSubClientLike } from "./pubsub.js";
4
+ export { createIoredisPubSubTransport } from "./pubsub.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ioredis/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACvE,YAAY,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { createIoredisExecutor, IoredisExecutor } from "./executor.js";
2
+ export { createIoredisPubSubTransport } from "./pubsub.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ioredis/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEvE,OAAO,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { RedisSubscriptionTransport } from "../pubsub/contracts.js";
2
+ export interface IoredisPubSubClientLike {
3
+ publish(channel: string, message: string): Promise<number>;
4
+ subscribe(channel: string): Promise<unknown>;
5
+ unsubscribe(channel: string): Promise<unknown>;
6
+ on(event: "message", listener: (channel: string, message: string) => void): this;
7
+ off?(event: "message", listener: (channel: string, message: string) => void): this;
8
+ duplicate?(): IoredisPubSubClientLike;
9
+ quit?(): Promise<unknown>;
10
+ disconnect?(): void;
11
+ }
12
+ export declare function createIoredisPubSubTransport(options: Readonly<{
13
+ publisher: IoredisPubSubClientLike;
14
+ subscriber?: IoredisPubSubClientLike;
15
+ }>): RedisSubscriptionTransport;
16
+ //# sourceMappingURL=pubsub.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pubsub.d.ts","sourceRoot":"","sources":["../../src/ioredis/pubsub.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAEzE,MAAM,WAAW,uBAAuB;IACvC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3D,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IACjF,GAAG,CAAC,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IACnF,SAAS,CAAC,IAAI,uBAAuB,CAAC;IACtC,IAAI,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1B,UAAU,CAAC,IAAI,IAAI,CAAC;CACpB;AAED,wBAAgB,4BAA4B,CAC3C,OAAO,EAAE,QAAQ,CAAC;IACjB,SAAS,EAAE,uBAAuB,CAAC;IACnC,UAAU,CAAC,EAAE,uBAAuB,CAAC;CACrC,CAAC,GACA,0BAA0B,CAoC5B"}
@@ -0,0 +1,42 @@
1
+ import { RedisConfigurationError } from "../core/errors.js";
2
+ export function createIoredisPubSubTransport(options) {
3
+ const subscriber = options.subscriber ?? options.publisher.duplicate?.();
4
+ if (!subscriber)
5
+ throw new RedisConfigurationError("An ioredis subscriber or duplicate() method is required");
6
+ const listeners = new Map();
7
+ const onMessage = (channel, message) => {
8
+ for (const listener of listeners.get(channel) ?? [])
9
+ void listener(message);
10
+ };
11
+ subscriber.on("message", onMessage);
12
+ return {
13
+ publish: (channel, message) => options.publisher.publish(channel, message),
14
+ async subscribe(channel, handler) {
15
+ let channelListeners = listeners.get(channel);
16
+ if (!channelListeners) {
17
+ channelListeners = new Set();
18
+ listeners.set(channel, channelListeners);
19
+ await subscriber.subscribe(channel);
20
+ }
21
+ channelListeners.add(handler);
22
+ return async () => {
23
+ channelListeners?.delete(handler);
24
+ if (channelListeners?.size === 0) {
25
+ listeners.delete(channel);
26
+ await subscriber.unsubscribe(channel);
27
+ }
28
+ };
29
+ },
30
+ async close() {
31
+ if (subscriber.quit)
32
+ await subscriber.quit();
33
+ else
34
+ subscriber.disconnect?.();
35
+ if (options.publisher.quit)
36
+ await options.publisher.quit();
37
+ else
38
+ options.publisher.disconnect?.();
39
+ },
40
+ };
41
+ }
42
+ //# sourceMappingURL=pubsub.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pubsub.js","sourceRoot":"","sources":["../../src/ioredis/pubsub.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAc5D,MAAM,UAAU,4BAA4B,CAC3C,OAGE;IAEF,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,CAAC;IACzE,IAAI,CAAC,UAAU;QACd,MAAM,IAAI,uBAAuB,CAChC,yDAAyD,CACzD,CAAC;IACH,MAAM,SAAS,GAAG,IAAI,GAAG,EAA0D,CAAC;IACpF,MAAM,SAAS,GAAG,CAAC,OAAe,EAAE,OAAe,EAAE,EAAE;QACtD,KAAK,MAAM,QAAQ,IAAI,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE;YAAE,KAAK,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC7E,CAAC,CAAC;IACF,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACpC,OAAO;QACN,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC;QAC1E,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO;YAC/B,IAAI,gBAAgB,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC9C,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACvB,gBAAgB,GAAG,IAAI,GAAG,EAAE,CAAC;gBAC7B,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;gBACzC,MAAM,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACrC,CAAC;YACD,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC9B,OAAO,KAAK,IAAI,EAAE;gBACjB,gBAAgB,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;gBAClC,IAAI,gBAAgB,EAAE,IAAI,KAAK,CAAC,EAAE,CAAC;oBAClC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;oBAC1B,MAAM,UAAU,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;gBACvC,CAAC;YACF,CAAC,CAAC;QACH,CAAC;QACD,KAAK,CAAC,KAAK;YACV,IAAI,UAAU,CAAC,IAAI;gBAAE,MAAM,UAAU,CAAC,IAAI,EAAE,CAAC;;gBACxC,UAAU,CAAC,UAAU,EAAE,EAAE,CAAC;YAC/B,IAAI,OAAO,CAAC,SAAS,CAAC,IAAI;gBAAE,MAAM,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;;gBACtD,OAAO,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,CAAC;QACvC,CAAC;KACD,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ export type { RedisLockLease, RedisLockOptions } from "./locks.js";
2
+ export { createLockManager, createRedisLockManager, RedisLockManager } from "./locks.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/locks/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { createLockManager, createRedisLockManager, RedisLockManager } from "./locks.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/locks/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { RedisExecutor } from "../core/executor.js";
2
+ export type RedisLockOptions = Readonly<{
3
+ redis: RedisExecutor;
4
+ prefix?: string;
5
+ defaultTtlMs?: number;
6
+ }>;
7
+ export interface RedisLockLease {
8
+ readonly key: string;
9
+ readonly token: string;
10
+ readonly expiresAt: number;
11
+ release(): Promise<boolean>;
12
+ extend(ttlMs: number): Promise<boolean>;
13
+ }
14
+ export declare class RedisLockManager {
15
+ private readonly options;
16
+ private readonly prefix;
17
+ private readonly defaultTtlMs;
18
+ constructor(options: RedisLockOptions);
19
+ acquire(name: string, ttlMs?: number): Promise<RedisLockLease | null>;
20
+ withLock<T>(name: string, operation: (lease: RedisLockLease) => Promise<T>, ttlMs?: number): Promise<T>;
21
+ }
22
+ export declare function createLockManager(options: RedisLockOptions): RedisLockManager;
23
+ /** A discoverable alias for applications that prefer Redis-prefixed factory names. */
24
+ export declare const createRedisLockManager: typeof createLockManager;
25
+ //# sourceMappingURL=locks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locks.d.ts","sourceRoot":"","sources":["../../src/locks/locks.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACvC,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC,CAAC;AAEH,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5B,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACxC;AAED,qBAAa,gBAAgB;IAIhB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IAEtC,YAA6B,OAAO,EAAE,gBAAgB,EAGrD;IAEK,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAoB,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAyCrF;IAEK,QAAQ,CAAC,CAAC,EACf,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,OAAO,CAAC,CAAC,CAAC,EAChD,KAAK,SAAoB,GACvB,OAAO,CAAC,CAAC,CAAC,CAQZ;CACD;AAKD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,GAAG,gBAAgB,CAE7E;AAED,sFAAsF;AACtF,eAAO,MAAM,sBAAsB,0BAAoB,CAAC"}
@@ -0,0 +1,77 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { RedisLockError } from "../core/errors.js";
3
+ export class RedisLockManager {
4
+ options;
5
+ prefix;
6
+ defaultTtlMs;
7
+ constructor(options) {
8
+ this.options = options;
9
+ this.prefix = options.prefix ?? "mhbdev:lock";
10
+ this.defaultTtlMs = options.defaultTtlMs ?? 30_000;
11
+ }
12
+ async acquire(name, ttlMs = this.defaultTtlMs) {
13
+ if (!name.trim())
14
+ throw new RedisLockError("Lock name is required");
15
+ if (!Number.isSafeInteger(ttlMs) || ttlMs <= 0)
16
+ throw new RedisLockError("Lock TTL must be positive");
17
+ const key = `${this.prefix}:${name}`;
18
+ const token = randomBytes(32).toString("hex");
19
+ const result = await this.options.redis.execute([
20
+ "SET",
21
+ key,
22
+ token,
23
+ "NX",
24
+ "PX",
25
+ String(ttlMs),
26
+ ]);
27
+ if (result !== "OK")
28
+ return null;
29
+ const createdAt = Date.now();
30
+ let released = false;
31
+ return {
32
+ key,
33
+ token,
34
+ expiresAt: createdAt + ttlMs,
35
+ release: async () => {
36
+ if (released)
37
+ return false;
38
+ const result = await this.options.redis.eval(RELEASE_SCRIPT, {
39
+ keys: [key],
40
+ arguments: [token],
41
+ });
42
+ released = result === 1;
43
+ return released;
44
+ },
45
+ extend: async (nextTtlMs) => {
46
+ if (released)
47
+ return false;
48
+ if (!Number.isSafeInteger(nextTtlMs) || nextTtlMs <= 0)
49
+ throw new RedisLockError("Lock TTL must be positive");
50
+ const result = await this.options.redis.eval(EXTEND_SCRIPT, {
51
+ keys: [key],
52
+ arguments: [token, String(nextTtlMs)],
53
+ });
54
+ return result === 1;
55
+ },
56
+ };
57
+ }
58
+ async withLock(name, operation, ttlMs = this.defaultTtlMs) {
59
+ const lease = await this.acquire(name, ttlMs);
60
+ if (!lease)
61
+ throw new RedisLockError("Unable to acquire Redis lock");
62
+ try {
63
+ return await operation(lease);
64
+ }
65
+ finally {
66
+ await lease.release();
67
+ }
68
+ }
69
+ }
70
+ const RELEASE_SCRIPT = `if redis.call("GET", KEYS[1]) == ARGV[1] then return redis.call("DEL", KEYS[1]) else return 0 end`;
71
+ const EXTEND_SCRIPT = `if redis.call("GET", KEYS[1]) == ARGV[1] then return redis.call("PEXPIRE", KEYS[1], ARGV[2]) else return 0 end`;
72
+ export function createLockManager(options) {
73
+ return new RedisLockManager(options);
74
+ }
75
+ /** A discoverable alias for applications that prefer Redis-prefixed factory names. */
76
+ export const createRedisLockManager = createLockManager;
77
+ //# sourceMappingURL=locks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locks.js","sourceRoot":"","sources":["../../src/locks/locks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import { type RedisClientOptions as NodeRedisOptions, type RedisClientType } from "redis";
2
+ import { type RedisCommand, type RedisConnection, type RedisHooks, type RedisScriptOptions } from "../core/executor.js";
3
+ type EmptyModule = Record<never, never>;
4
+ export type NodeRedisClient = RedisClientType<EmptyModule, EmptyModule, EmptyModule, 3, EmptyModule>;
5
+ export type RedisClientOptions = Readonly<{
6
+ url: string;
7
+ connectTimeoutMs?: number;
8
+ commandTimeoutMs?: number;
9
+ maxReconnectAttempts?: number;
10
+ reconnectBaseDelayMs?: number;
11
+ reconnectMaxDelayMs?: number;
12
+ disableOfflineQueue?: boolean;
13
+ clientOptions?: Omit<NodeRedisOptions, "url" | "disableOfflineQueue">;
14
+ onError?: (error: Error) => void;
15
+ hooks?: RedisHooks;
16
+ }>;
17
+ export declare class RedisClient implements RedisConnection {
18
+ private client;
19
+ private readonly options;
20
+ private connecting;
21
+ private closing;
22
+ private closed;
23
+ constructor(options: RedisClientOptions);
24
+ get isReady(): boolean;
25
+ get isOpen(): boolean;
26
+ private createClient;
27
+ private replaceClient;
28
+ connect(): Promise<void>;
29
+ execute<T = unknown>(command: RedisCommand, options?: {
30
+ signal?: AbortSignal;
31
+ }): Promise<T>;
32
+ private sendCommand;
33
+ eval<T = unknown>(script: string, options: RedisScriptOptions, request?: {
34
+ signal?: AbortSignal;
35
+ }): Promise<T>;
36
+ ping(): Promise<void>;
37
+ raw(): NodeRedisClient;
38
+ close(): Promise<void>;
39
+ }
40
+ export declare function createRedisClient(options: RedisClientOptions): RedisClient;
41
+ /**
42
+ * Creates, connects, and closes a managed client around one operation.
43
+ * This is useful for scripts, jobs, and request-scoped composition tests.
44
+ */
45
+ export declare function withRedisClient<T>(options: RedisClientOptions, operation: (redis: RedisClient) => Promise<T>): Promise<T>;
46
+ export {};
47
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/node/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,kBAAkB,IAAI,gBAAgB,EAC3C,KAAK,eAAe,EACpB,MAAM,OAAO,CAAC;AAGf,OAAO,EAEN,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,UAAU,EACf,KAAK,kBAAkB,EAEvB,MAAM,qBAAqB,CAAC;AAG7B,KAAK,WAAW,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AACxC,MAAM,MAAM,eAAe,GAAG,eAAe,CAC5C,WAAW,EACX,WAAW,EACX,WAAW,EACX,CAAC,EACD,WAAW,CACX,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,aAAa,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,KAAK,GAAG,qBAAqB,CAAC,CAAC;IACtE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,KAAK,CAAC,EAAE,UAAU,CAAC;CACnB,CAAC,CAAC;AAEH,qBAAa,WAAY,YAAW,eAAe;IAClD,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAmBrB;IACH,OAAO,CAAC,UAAU,CAA8B;IAChD,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,MAAM,CAAS;IAEvB,YAAY,OAAO,EAAE,kBAAkB,EActC;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,OAAO,CAAC,YAAY;IA4BpB,OAAO,CAAC,aAAa;IAMf,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CA0B7B;IAEK,OAAO,CAAC,CAAC,GAAG,OAAO,EACxB,OAAO,EAAE,YAAY,EACrB,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAO,GACpC,OAAO,CAAC,CAAC,CAAC,CAYZ;YAEa,WAAW;IAanB,IAAI,CAAC,CAAC,GAAG,OAAO,EACrB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,kBAAkB,EAC3B,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAO,GACpC,OAAO,CAAC,CAAC,CAAC,CASZ;IAEK,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAE1B;IAED,GAAG,IAAI,eAAe,CAErB;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAQ3B;CACD;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,WAAW,CAE1E;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,CAAC,EACtC,OAAO,EAAE,kBAAkB,EAC3B,SAAS,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GAC3C,OAAO,CAAC,CAAC,CAAC,CAQZ"}