@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,78 @@
1
+ import { type RedisCodec } from "../core/codec.js";
2
+ import type { RedisExecutor } from "../core/executor.js";
3
+ export type QueueJob<T> = Readonly<{
4
+ id: string;
5
+ data: T;
6
+ attempts: number;
7
+ enqueuedAt: number;
8
+ }>;
9
+ export type EnqueueOptions = Readonly<{
10
+ delayMs?: number;
11
+ jobId?: string;
12
+ }>;
13
+ export type QueueOptions<T> = Readonly<{
14
+ redis: RedisExecutor;
15
+ /** JSON is used by default. Provide a codec for binary or schema-validated jobs. */
16
+ codec?: RedisCodec<T>;
17
+ name: string;
18
+ prefix?: string;
19
+ maxAttempts?: number;
20
+ visibilityTimeoutMs?: number;
21
+ }>;
22
+ export type QueueWorkerOptions = Readonly<{
23
+ group?: string;
24
+ consumer?: string;
25
+ blockMs?: number;
26
+ concurrency?: number;
27
+ }>;
28
+ export interface JobQueue<T> {
29
+ enqueue(data: T, options?: EnqueueOptions): Promise<string>;
30
+ worker(handler: (job: QueueJob<T>) => Promise<void>, options?: QueueWorkerOptions): QueueWorker;
31
+ close?(): Promise<void>;
32
+ }
33
+ export interface QueueWorker {
34
+ start(): Promise<void>;
35
+ close(): Promise<void>;
36
+ }
37
+ export declare class RedisQueue<T> implements JobQueue<T> {
38
+ private readonly options;
39
+ private readonly prefix;
40
+ private readonly valueCodec;
41
+ private readonly maxAttempts;
42
+ private readonly visibilityTimeoutMs;
43
+ constructor(options: QueueOptions<T>);
44
+ enqueue(data: T, enqueueOptions?: EnqueueOptions): Promise<string>;
45
+ worker(handler: (job: QueueJob<T>) => Promise<void>, workerOptions?: QueueWorkerOptions): RedisQueueWorker<T>;
46
+ get streamKey(): string;
47
+ get delayedKey(): string;
48
+ get deadLetterKey(): string;
49
+ get codec(): RedisCodec<T>;
50
+ get redis(): RedisExecutor;
51
+ get attempts(): number;
52
+ get visibilityTimeout(): number;
53
+ private encode;
54
+ decode(value: string): QueueJob<T>;
55
+ }
56
+ export declare class RedisQueueWorker<T> implements QueueWorker {
57
+ private readonly queue;
58
+ private readonly handler;
59
+ private readonly group;
60
+ private readonly consumer;
61
+ private readonly blockMs;
62
+ private readonly concurrency;
63
+ private stopping;
64
+ private running;
65
+ constructor(queue: RedisQueue<T>, handler: (job: QueueJob<T>) => Promise<void>, options: QueueWorkerOptions);
66
+ start(): Promise<void>;
67
+ close(): Promise<void>;
68
+ private run;
69
+ private ensureGroup;
70
+ private promoteDue;
71
+ private recoverPending;
72
+ private process;
73
+ private encodeRetry;
74
+ }
75
+ export declare function createQueue<T>(options: QueueOptions<T>): RedisQueue<T>;
76
+ /** A discoverable alias for applications that prefer Redis-prefixed factory names. */
77
+ export declare const createRedisQueue: typeof createQueue;
78
+ //# sourceMappingURL=queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../src/queue/queue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,260 @@
1
+ import { jsonCodec } from "../core/codec.js";
2
+ import { RedisQueueError } from "../core/errors.js";
3
+ export class RedisQueue {
4
+ options;
5
+ prefix;
6
+ valueCodec;
7
+ maxAttempts;
8
+ visibilityTimeoutMs;
9
+ constructor(options) {
10
+ this.options = options;
11
+ if (!options.name.trim())
12
+ throw new RedisQueueError("Queue name is required");
13
+ this.prefix = options.prefix ?? "mhbdev:queue";
14
+ this.valueCodec = options.codec ?? jsonCodec();
15
+ this.maxAttempts = options.maxAttempts ?? 3;
16
+ this.visibilityTimeoutMs = options.visibilityTimeoutMs ?? 30_000;
17
+ if (!Number.isSafeInteger(this.maxAttempts) || this.maxAttempts <= 0)
18
+ throw new RedisQueueError("Queue max attempts must be positive");
19
+ }
20
+ async enqueue(data, enqueueOptions = {}) {
21
+ const id = enqueueOptions.jobId ?? crypto.randomUUID();
22
+ const job = { id, data, attempts: 0, enqueuedAt: Date.now() };
23
+ const encoded = this.encode(job);
24
+ if ((enqueueOptions.delayMs ?? 0) > 0) {
25
+ await this.options.redis.execute([
26
+ "ZADD",
27
+ this.delayedKey,
28
+ String(Date.now() + (enqueueOptions.delayMs ?? 0)),
29
+ encoded,
30
+ ]);
31
+ }
32
+ else {
33
+ await this.options.redis.execute(["XADD", this.streamKey, "*", "payload", encoded]);
34
+ }
35
+ return id;
36
+ }
37
+ worker(handler, workerOptions = {}) {
38
+ return new RedisQueueWorker(this, handler, workerOptions);
39
+ }
40
+ get streamKey() {
41
+ return `${this.prefix}:${this.options.name}:stream`;
42
+ }
43
+ get delayedKey() {
44
+ return `${this.prefix}:${this.options.name}:delayed`;
45
+ }
46
+ get deadLetterKey() {
47
+ return `${this.prefix}:${this.options.name}:dead-letter`;
48
+ }
49
+ get codec() {
50
+ return this.valueCodec;
51
+ }
52
+ get redis() {
53
+ return this.options.redis;
54
+ }
55
+ get attempts() {
56
+ return this.maxAttempts;
57
+ }
58
+ get visibilityTimeout() {
59
+ return this.visibilityTimeoutMs;
60
+ }
61
+ encode(job) {
62
+ return JSON.stringify({
63
+ id: job.id,
64
+ data: this.valueCodec.encode(job.data),
65
+ attempts: job.attempts,
66
+ enqueuedAt: job.enqueuedAt,
67
+ });
68
+ }
69
+ decode(value) {
70
+ try {
71
+ const parsed = JSON.parse(value);
72
+ return {
73
+ id: parsed.id,
74
+ data: this.valueCodec.decode(parsed.data),
75
+ attempts: parsed.attempts,
76
+ enqueuedAt: parsed.enqueuedAt,
77
+ };
78
+ }
79
+ catch (error) {
80
+ throw new RedisQueueError("Unable to decode Redis queue job", error);
81
+ }
82
+ }
83
+ }
84
+ export class RedisQueueWorker {
85
+ queue;
86
+ handler;
87
+ group;
88
+ consumer;
89
+ blockMs;
90
+ concurrency;
91
+ stopping = false;
92
+ running = null;
93
+ constructor(queue, handler, options) {
94
+ this.queue = queue;
95
+ this.handler = handler;
96
+ this.group = options.group ?? "default";
97
+ this.consumer = options.consumer ?? crypto.randomUUID();
98
+ this.blockMs = options.blockMs ?? 1_000;
99
+ this.concurrency = options.concurrency ?? 1;
100
+ if (!Number.isSafeInteger(this.concurrency) || this.concurrency <= 0)
101
+ throw new RedisQueueError("Queue concurrency must be positive");
102
+ }
103
+ async start() {
104
+ if (this.running)
105
+ return this.running;
106
+ this.stopping = false;
107
+ this.running = this.run().finally(() => {
108
+ this.running = null;
109
+ });
110
+ return this.running;
111
+ }
112
+ async close() {
113
+ this.stopping = true;
114
+ await this.running;
115
+ }
116
+ async run() {
117
+ await this.ensureGroup();
118
+ while (!this.stopping) {
119
+ await this.promoteDue();
120
+ const recovered = await this.recoverPending();
121
+ if (recovered.length) {
122
+ await Promise.all(recovered.map((entry) => this.process(entry)));
123
+ continue;
124
+ }
125
+ const response = await this.queue.redis.execute([
126
+ "XREADGROUP",
127
+ "GROUP",
128
+ this.group,
129
+ this.consumer,
130
+ "COUNT",
131
+ String(this.concurrency),
132
+ "BLOCK",
133
+ String(this.blockMs),
134
+ "STREAMS",
135
+ this.queue.streamKey,
136
+ ">",
137
+ ]);
138
+ const entries = parseStreamResponse(response);
139
+ await Promise.all(entries.map((entry) => this.process(entry)));
140
+ }
141
+ }
142
+ async ensureGroup() {
143
+ await this.queue.redis.eval(ENSURE_GROUP_SCRIPT, {
144
+ keys: [this.queue.streamKey],
145
+ arguments: [this.group],
146
+ });
147
+ }
148
+ async promoteDue() {
149
+ const due = await this.queue.redis.execute([
150
+ "ZRANGEBYSCORE",
151
+ this.queue.delayedKey,
152
+ "-inf",
153
+ String(Date.now()),
154
+ "LIMIT",
155
+ "0",
156
+ "100",
157
+ ]);
158
+ for (const encoded of due ?? []) {
159
+ await this.queue.redis.execute(["ZREM", this.queue.delayedKey, encoded]);
160
+ await this.queue.redis.execute([
161
+ "XADD",
162
+ this.queue.streamKey,
163
+ "*",
164
+ "payload",
165
+ encoded,
166
+ ]);
167
+ }
168
+ }
169
+ async recoverPending() {
170
+ const response = await this.queue.redis.execute([
171
+ "XAUTOCLAIM",
172
+ this.queue.streamKey,
173
+ this.group,
174
+ this.consumer,
175
+ String(this.queue.visibilityTimeout),
176
+ "0-0",
177
+ "COUNT",
178
+ String(this.concurrency),
179
+ ]);
180
+ return parseAutoClaimResponse(response);
181
+ }
182
+ async process(entry) {
183
+ const job = this.queue.decode(entry.payload);
184
+ try {
185
+ await this.handler(job);
186
+ await this.queue.redis.execute([
187
+ "XACK",
188
+ this.queue.streamKey,
189
+ this.group,
190
+ entry.id,
191
+ ]);
192
+ }
193
+ catch (_error) {
194
+ await this.queue.redis.execute([
195
+ "XACK",
196
+ this.queue.streamKey,
197
+ this.group,
198
+ entry.id,
199
+ ]);
200
+ if (job.attempts + 1 >= this.queue.attempts) {
201
+ await this.queue.redis.execute([
202
+ "XADD",
203
+ this.queue.deadLetterKey,
204
+ "*",
205
+ "payload",
206
+ this.encodeRetry(job),
207
+ ]);
208
+ return;
209
+ }
210
+ const retry = { ...job, attempts: job.attempts + 1 };
211
+ await this.queue.redis.execute([
212
+ "XADD",
213
+ this.queue.streamKey,
214
+ "*",
215
+ "payload",
216
+ this.encodeRetry(retry),
217
+ ]);
218
+ }
219
+ }
220
+ encodeRetry(job) {
221
+ return JSON.stringify({
222
+ id: job.id,
223
+ data: this.queue.codec.encode(job.data),
224
+ attempts: job.attempts,
225
+ enqueuedAt: job.enqueuedAt,
226
+ });
227
+ }
228
+ }
229
+ const ENSURE_GROUP_SCRIPT = `local groups = redis.pcall("XINFO", "GROUPS", KEYS[1]) if type(groups) == "table" then for _, group in ipairs(groups) do if group[2] == ARGV[1] then return 0 end end end local result = redis.pcall("XGROUP", "CREATE", KEYS[1], ARGV[1], "0-0", "MKSTREAM") if type(result) == "table" then return 1 end local groupsAfter = redis.pcall("XINFO", "GROUPS", KEYS[1]) if type(groupsAfter) == "table" then for _, group in ipairs(groupsAfter) do if group[2] == ARGV[1] then return 0 end end end return redis.error_reply("Redis consumer group creation failed")`;
230
+ function parseStreamResponse(value) {
231
+ if (!Array.isArray(value) || value.length === 0)
232
+ return [];
233
+ const streams = value[0];
234
+ if (!Array.isArray(streams) || !Array.isArray(streams[1]))
235
+ return [];
236
+ const result = [];
237
+ for (const rawEntry of streams[1]) {
238
+ if (!Array.isArray(rawEntry) ||
239
+ typeof rawEntry[0] !== "string" ||
240
+ !Array.isArray(rawEntry[1]))
241
+ continue;
242
+ const fields = rawEntry[1];
243
+ const payloadIndex = fields.indexOf("payload");
244
+ const payload = payloadIndex >= 0 ? fields[payloadIndex + 1] : undefined;
245
+ if (typeof payload === "string")
246
+ result.push({ id: rawEntry[0], payload });
247
+ }
248
+ return result;
249
+ }
250
+ function parseAutoClaimResponse(value) {
251
+ if (!Array.isArray(value) || !Array.isArray(value[1]))
252
+ return [];
253
+ return parseStreamResponse([["recovered", value[1]]]);
254
+ }
255
+ export function createQueue(options) {
256
+ return new RedisQueue(options);
257
+ }
258
+ /** A discoverable alias for applications that prefer Redis-prefixed factory names. */
259
+ export const createRedisQueue = createQueue;
260
+ //# sourceMappingURL=queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/queue/queue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,93 @@
1
+ import { type RedisExecutor } from "../core/executor.js";
2
+ export type RateLimitFailureMode = "open" | "closed";
3
+ export type RateLimitReason = "limit" | "cache" | "timeout" | "redis" | "success";
4
+ export type RateLimitAlgorithm = Readonly<{
5
+ kind: "fixed-window" | "sliding-window" | "token-bucket";
6
+ limit: number;
7
+ windowMs: number;
8
+ maxTokens?: number;
9
+ refillRate?: number;
10
+ }>;
11
+ export type RateLimitPolicy = Readonly<{
12
+ name: string;
13
+ maxRequests: number;
14
+ windowMs: number;
15
+ failureMode: RateLimitFailureMode;
16
+ }>;
17
+ export type RateLimitRequest = Readonly<{
18
+ rate?: number;
19
+ }>;
20
+ export type RateLimitResponse = Readonly<{
21
+ success: boolean;
22
+ allowed: boolean;
23
+ limit: number;
24
+ remaining: number;
25
+ reset: number;
26
+ resetAt: Date;
27
+ retryAfterMs: number;
28
+ reason: RateLimitReason;
29
+ pending: Promise<void>;
30
+ }>;
31
+ export type RateLimitResult = Readonly<{
32
+ allowed: boolean;
33
+ limit: number;
34
+ remaining: number;
35
+ resetAt: Date;
36
+ }>;
37
+ export type RateLimitAnalyticsEvent = Readonly<{
38
+ identifier: string;
39
+ algorithm: RateLimitAlgorithm["kind"];
40
+ allowed: boolean;
41
+ limit: number;
42
+ remaining: number;
43
+ timestamp: number;
44
+ }>;
45
+ export interface RateLimitAnalyticsSink {
46
+ record(event: RateLimitAnalyticsEvent): void | Promise<void>;
47
+ }
48
+ export type RateLimiterOptions = Readonly<{
49
+ redis: RedisExecutor;
50
+ prefix?: string;
51
+ timeoutMs?: number;
52
+ failureMode?: RateLimitFailureMode;
53
+ ephemeralCache?: boolean | Map<string, number>;
54
+ analytics?: RateLimitAnalyticsSink;
55
+ dynamicLimits?: boolean;
56
+ now?: () => number;
57
+ }>;
58
+ export interface RateLimiter {
59
+ limit(identifier: string, request?: RateLimitRequest): Promise<RateLimitResponse>;
60
+ check(identity: string, policy: RateLimitPolicy): Promise<RateLimitResult>;
61
+ getRemaining(identifier: string): Promise<Pick<RateLimitResponse, "remaining" | "reset" | "resetAt">>;
62
+ reset(identifier: string): Promise<void>;
63
+ blockUntilReady(identifier: string, timeoutMs: number, request?: RateLimitRequest): Promise<RateLimitResponse>;
64
+ setDynamicLimit(limit: number | false): Promise<void>;
65
+ getDynamicLimit(): Promise<number | null>;
66
+ }
67
+ export declare function fixedWindow(limit: number, windowMs: number): RateLimitAlgorithm;
68
+ export declare function slidingWindow(limit: number, windowMs: number): RateLimitAlgorithm;
69
+ export declare function tokenBucket(refillRate: number, windowMs: number, maxTokens: number): RateLimitAlgorithm;
70
+ export declare function createRateLimiter(algorithm: RateLimitAlgorithm, options: RateLimiterOptions): RateLimiter;
71
+ /** A discoverable alias for applications that prefer Redis-prefixed factory names. */
72
+ export declare const createRedisRateLimiter: typeof createRateLimiter;
73
+ export declare class RedisRateLimiter implements RateLimiter {
74
+ private readonly algorithm;
75
+ private readonly options;
76
+ private readonly prefix;
77
+ private readonly timeoutMs;
78
+ private readonly failureMode;
79
+ private readonly cache;
80
+ private readonly now;
81
+ constructor(algorithm: RateLimitAlgorithm, options: RateLimiterOptions);
82
+ limit(identifier: string, request?: RateLimitRequest): Promise<RateLimitResponse>;
83
+ check(identity: string, policy: RateLimitPolicy): Promise<RateLimitResult>;
84
+ getRemaining(identifier: string): Promise<Pick<RateLimitResponse, "remaining" | "reset" | "resetAt">>;
85
+ reset(identifier: string): Promise<void>;
86
+ blockUntilReady(identifier: string, timeoutMs: number, request?: RateLimitRequest): Promise<RateLimitResponse>;
87
+ setDynamicLimit(limit: number | false): Promise<void>;
88
+ getDynamicLimit(): Promise<number | null>;
89
+ private runAlgorithm;
90
+ private keysFor;
91
+ private response;
92
+ }
93
+ //# sourceMappingURL=contracts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../src/rate-limit/contracts.ts"],"names":[],"mappings":"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"}