@zeitar/throttle 1.0.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 (163) hide show
  1. package/LICENSE.md +24 -0
  2. package/README.md +204 -0
  3. package/dist/CompoundLimiter.d.ts +33 -0
  4. package/dist/CompoundLimiter.d.ts.map +1 -0
  5. package/dist/CompoundLimiter.js +62 -0
  6. package/dist/CompoundLimiter.js.map +1 -0
  7. package/dist/CompoundRateLimiterFactory.d.ts +19 -0
  8. package/dist/CompoundRateLimiterFactory.d.ts.map +1 -0
  9. package/dist/CompoundRateLimiterFactory.js +29 -0
  10. package/dist/CompoundRateLimiterFactory.js.map +1 -0
  11. package/dist/LimiterInterface.d.ts +32 -0
  12. package/dist/LimiterInterface.d.ts.map +1 -0
  13. package/dist/LimiterInterface.js +3 -0
  14. package/dist/LimiterInterface.js.map +1 -0
  15. package/dist/LimiterStateInterface.d.ts +16 -0
  16. package/dist/LimiterStateInterface.d.ts.map +1 -0
  17. package/dist/LimiterStateInterface.js +3 -0
  18. package/dist/LimiterStateInterface.js.map +1 -0
  19. package/dist/RateLimit.d.ts +43 -0
  20. package/dist/RateLimit.d.ts.map +1 -0
  21. package/dist/RateLimit.js +68 -0
  22. package/dist/RateLimit.js.map +1 -0
  23. package/dist/RateLimiterFactory.d.ts +83 -0
  24. package/dist/RateLimiterFactory.d.ts.map +1 -0
  25. package/dist/RateLimiterFactory.js +115 -0
  26. package/dist/RateLimiterFactory.js.map +1 -0
  27. package/dist/RateLimiterFactoryInterface.d.ts +17 -0
  28. package/dist/RateLimiterFactoryInterface.d.ts.map +1 -0
  29. package/dist/RateLimiterFactoryInterface.js +3 -0
  30. package/dist/RateLimiterFactoryInterface.js.map +1 -0
  31. package/dist/Reservation.d.ts +29 -0
  32. package/dist/Reservation.d.ts.map +1 -0
  33. package/dist/Reservation.js +44 -0
  34. package/dist/Reservation.js.map +1 -0
  35. package/dist/__tests__/CompoundLimiter.test.d.ts +2 -0
  36. package/dist/__tests__/CompoundLimiter.test.d.ts.map +1 -0
  37. package/dist/__tests__/CompoundLimiter.test.js +231 -0
  38. package/dist/__tests__/CompoundLimiter.test.js.map +1 -0
  39. package/dist/__tests__/CompoundRateLimiterFactory.test.d.ts +2 -0
  40. package/dist/__tests__/CompoundRateLimiterFactory.test.d.ts.map +1 -0
  41. package/dist/__tests__/CompoundRateLimiterFactory.test.js +213 -0
  42. package/dist/__tests__/CompoundRateLimiterFactory.test.js.map +1 -0
  43. package/dist/__tests__/RateLimit.test.d.ts +2 -0
  44. package/dist/__tests__/RateLimit.test.d.ts.map +1 -0
  45. package/dist/__tests__/RateLimit.test.js +108 -0
  46. package/dist/__tests__/RateLimit.test.js.map +1 -0
  47. package/dist/__tests__/RateLimiterFactory.test.d.ts +2 -0
  48. package/dist/__tests__/RateLimiterFactory.test.d.ts.map +1 -0
  49. package/dist/__tests__/RateLimiterFactory.test.js +323 -0
  50. package/dist/__tests__/RateLimiterFactory.test.js.map +1 -0
  51. package/dist/__tests__/Reservation.test.d.ts +2 -0
  52. package/dist/__tests__/Reservation.test.d.ts.map +1 -0
  53. package/dist/__tests__/Reservation.test.js +110 -0
  54. package/dist/__tests__/Reservation.test.js.map +1 -0
  55. package/dist/errors/InvalidIntervalError.d.ts +10 -0
  56. package/dist/errors/InvalidIntervalError.d.ts.map +1 -0
  57. package/dist/errors/InvalidIntervalError.js +18 -0
  58. package/dist/errors/InvalidIntervalError.js.map +1 -0
  59. package/dist/errors/MaxWaitDurationExceededError.d.ts +15 -0
  60. package/dist/errors/MaxWaitDurationExceededError.d.ts.map +1 -0
  61. package/dist/errors/MaxWaitDurationExceededError.js +24 -0
  62. package/dist/errors/MaxWaitDurationExceededError.js.map +1 -0
  63. package/dist/errors/RateLimitExceededError.d.ts +27 -0
  64. package/dist/errors/RateLimitExceededError.d.ts.map +1 -0
  65. package/dist/errors/RateLimitExceededError.js +42 -0
  66. package/dist/errors/RateLimitExceededError.js.map +1 -0
  67. package/dist/errors/ReserveNotSupportedError.d.ts +10 -0
  68. package/dist/errors/ReserveNotSupportedError.d.ts.map +1 -0
  69. package/dist/errors/ReserveNotSupportedError.js +18 -0
  70. package/dist/errors/ReserveNotSupportedError.js.map +1 -0
  71. package/dist/index.d.ts +35 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +58 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/policy/FixedWindowLimiter.d.ts +36 -0
  76. package/dist/policy/FixedWindowLimiter.d.ts.map +1 -0
  77. package/dist/policy/FixedWindowLimiter.js +105 -0
  78. package/dist/policy/FixedWindowLimiter.js.map +1 -0
  79. package/dist/policy/NoLimiter.d.ts +23 -0
  80. package/dist/policy/NoLimiter.d.ts.map +1 -0
  81. package/dist/policy/NoLimiter.js +34 -0
  82. package/dist/policy/NoLimiter.js.map +1 -0
  83. package/dist/policy/Rate.d.ts +69 -0
  84. package/dist/policy/Rate.d.ts.map +1 -0
  85. package/dist/policy/Rate.js +121 -0
  86. package/dist/policy/Rate.js.map +1 -0
  87. package/dist/policy/SlidingWindow.d.ts +74 -0
  88. package/dist/policy/SlidingWindow.d.ts.map +1 -0
  89. package/dist/policy/SlidingWindow.js +130 -0
  90. package/dist/policy/SlidingWindow.js.map +1 -0
  91. package/dist/policy/SlidingWindowLimiter.d.ts +41 -0
  92. package/dist/policy/SlidingWindowLimiter.d.ts.map +1 -0
  93. package/dist/policy/SlidingWindowLimiter.js +127 -0
  94. package/dist/policy/SlidingWindowLimiter.js.map +1 -0
  95. package/dist/policy/TokenBucket.d.ts +63 -0
  96. package/dist/policy/TokenBucket.d.ts.map +1 -0
  97. package/dist/policy/TokenBucket.js +92 -0
  98. package/dist/policy/TokenBucket.js.map +1 -0
  99. package/dist/policy/TokenBucketLimiter.d.ts +38 -0
  100. package/dist/policy/TokenBucketLimiter.d.ts.map +1 -0
  101. package/dist/policy/TokenBucketLimiter.js +114 -0
  102. package/dist/policy/TokenBucketLimiter.js.map +1 -0
  103. package/dist/policy/Window.d.ts +58 -0
  104. package/dist/policy/Window.d.ts.map +1 -0
  105. package/dist/policy/Window.js +105 -0
  106. package/dist/policy/Window.js.map +1 -0
  107. package/dist/policy/__tests__/FixedWindowLimiter.test.d.ts +2 -0
  108. package/dist/policy/__tests__/FixedWindowLimiter.test.d.ts.map +1 -0
  109. package/dist/policy/__tests__/FixedWindowLimiter.test.js +180 -0
  110. package/dist/policy/__tests__/FixedWindowLimiter.test.js.map +1 -0
  111. package/dist/policy/__tests__/NoLimiter.test.d.ts +2 -0
  112. package/dist/policy/__tests__/NoLimiter.test.d.ts.map +1 -0
  113. package/dist/policy/__tests__/NoLimiter.test.js +40 -0
  114. package/dist/policy/__tests__/NoLimiter.test.js.map +1 -0
  115. package/dist/policy/__tests__/Rate.test.d.ts +2 -0
  116. package/dist/policy/__tests__/Rate.test.d.ts.map +1 -0
  117. package/dist/policy/__tests__/Rate.test.js +162 -0
  118. package/dist/policy/__tests__/Rate.test.js.map +1 -0
  119. package/dist/policy/__tests__/SlidingWindow.test.d.ts +2 -0
  120. package/dist/policy/__tests__/SlidingWindow.test.d.ts.map +1 -0
  121. package/dist/policy/__tests__/SlidingWindow.test.js +257 -0
  122. package/dist/policy/__tests__/SlidingWindow.test.js.map +1 -0
  123. package/dist/policy/__tests__/SlidingWindowLimiter.test.d.ts +2 -0
  124. package/dist/policy/__tests__/SlidingWindowLimiter.test.d.ts.map +1 -0
  125. package/dist/policy/__tests__/SlidingWindowLimiter.test.js +201 -0
  126. package/dist/policy/__tests__/SlidingWindowLimiter.test.js.map +1 -0
  127. package/dist/policy/__tests__/TokenBucket.test.d.ts +2 -0
  128. package/dist/policy/__tests__/TokenBucket.test.d.ts.map +1 -0
  129. package/dist/policy/__tests__/TokenBucket.test.js +171 -0
  130. package/dist/policy/__tests__/TokenBucket.test.js.map +1 -0
  131. package/dist/policy/__tests__/TokenBucketLimiter.test.d.ts +2 -0
  132. package/dist/policy/__tests__/TokenBucketLimiter.test.d.ts.map +1 -0
  133. package/dist/policy/__tests__/TokenBucketLimiter.test.js +175 -0
  134. package/dist/policy/__tests__/TokenBucketLimiter.test.js.map +1 -0
  135. package/dist/policy/__tests__/Window.test.d.ts +2 -0
  136. package/dist/policy/__tests__/Window.test.d.ts.map +1 -0
  137. package/dist/policy/__tests__/Window.test.js +193 -0
  138. package/dist/policy/__tests__/Window.test.js.map +1 -0
  139. package/dist/storage/InMemoryStorage.d.ts +34 -0
  140. package/dist/storage/InMemoryStorage.d.ts.map +1 -0
  141. package/dist/storage/InMemoryStorage.js +62 -0
  142. package/dist/storage/InMemoryStorage.js.map +1 -0
  143. package/dist/storage/LockInterface.d.ts +41 -0
  144. package/dist/storage/LockInterface.d.ts.map +1 -0
  145. package/dist/storage/LockInterface.js +19 -0
  146. package/dist/storage/LockInterface.js.map +1 -0
  147. package/dist/storage/StorageInterface.d.ts +29 -0
  148. package/dist/storage/StorageInterface.d.ts.map +1 -0
  149. package/dist/storage/StorageInterface.js +3 -0
  150. package/dist/storage/StorageInterface.js.map +1 -0
  151. package/dist/storage/__tests__/InMemoryStorage.test.d.ts +2 -0
  152. package/dist/storage/__tests__/InMemoryStorage.test.d.ts.map +1 -0
  153. package/dist/storage/__tests__/InMemoryStorage.test.js +154 -0
  154. package/dist/storage/__tests__/InMemoryStorage.test.js.map +1 -0
  155. package/dist/util/TimeUtil.d.ts +35 -0
  156. package/dist/util/TimeUtil.d.ts.map +1 -0
  157. package/dist/util/TimeUtil.js +87 -0
  158. package/dist/util/TimeUtil.js.map +1 -0
  159. package/dist/util/__tests__/TimeUtil.test.d.ts +2 -0
  160. package/dist/util/__tests__/TimeUtil.test.d.ts.map +1 -0
  161. package/dist/util/__tests__/TimeUtil.test.js +132 -0
  162. package/dist/util/__tests__/TimeUtil.test.js.map +1 -0
  163. package/package.json +59 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReserveNotSupportedError.d.ts","sourceRoot":"","sources":["../../src/errors/ReserveNotSupportedError.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;gBACrC,OAAO,EAAE,MAAM;CAK5B"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ReserveNotSupportedError = void 0;
4
+ /**
5
+ * Thrown when reserve() is called on a limiter that doesn't support reservations.
6
+ *
7
+ * Some limiters (like CompoundLimiter) don't support the reserve pattern and will
8
+ * throw this exception if reserve() is called.
9
+ */
10
+ class ReserveNotSupportedError extends Error {
11
+ constructor(message) {
12
+ super(message);
13
+ this.name = 'ReserveNotSupportedError';
14
+ Object.setPrototypeOf(this, ReserveNotSupportedError.prototype);
15
+ }
16
+ }
17
+ exports.ReserveNotSupportedError = ReserveNotSupportedError;
18
+ //# sourceMappingURL=ReserveNotSupportedError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReserveNotSupportedError.js","sourceRoot":"","sources":["../../src/errors/ReserveNotSupportedError.ts"],"names":[],"mappings":";;;AAAA;;;;;GAKG;AACH,MAAa,wBAAyB,SAAQ,KAAK;IACjD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;QACvC,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,wBAAwB,CAAC,SAAS,CAAC,CAAC;IAClE,CAAC;CACF;AAND,4DAMC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * @throttle - TypeScript Rate Limiter Library
3
+ *
4
+ * A production-ready rate limiting library supporting multiple algorithms:
5
+ * - Token Bucket: Allows bursts with steady refill rate
6
+ * - Fixed Window: Simple window-based limiting
7
+ * - Sliding Window: Smoothed rate limiting across window boundaries
8
+ * - No Limit: Pass-through for testing/conditional scenarios
9
+ */
10
+ export type { LimiterInterface } from './LimiterInterface';
11
+ export type { LimiterStateInterface } from './LimiterStateInterface';
12
+ export type { RateLimiterFactoryInterface } from './RateLimiterFactoryInterface';
13
+ export { RateLimit } from './RateLimit';
14
+ export { Reservation } from './Reservation';
15
+ export { RateLimiterFactory, type RateLimiterConfig, type TokenBucketConfig, type FixedWindowConfig, type SlidingWindowConfig, type NoLimitConfig, } from './RateLimiterFactory';
16
+ export { CompoundRateLimiterFactory } from './CompoundRateLimiterFactory';
17
+ export { CompoundLimiter } from './CompoundLimiter';
18
+ export type { StorageInterface } from './storage/StorageInterface';
19
+ export { InMemoryStorage } from './storage/InMemoryStorage';
20
+ export type { LockInterface } from './storage/LockInterface';
21
+ export { NoLock } from './storage/LockInterface';
22
+ export { Rate } from './policy/Rate';
23
+ export { TokenBucket } from './policy/TokenBucket';
24
+ export { TokenBucketLimiter } from './policy/TokenBucketLimiter';
25
+ export { Window } from './policy/Window';
26
+ export { FixedWindowLimiter } from './policy/FixedWindowLimiter';
27
+ export { SlidingWindow } from './policy/SlidingWindow';
28
+ export { SlidingWindowLimiter } from './policy/SlidingWindowLimiter';
29
+ export { NoLimiter } from './policy/NoLimiter';
30
+ export { InvalidIntervalError } from './errors/InvalidIntervalError';
31
+ export { MaxWaitDurationExceededError } from './errors/MaxWaitDurationExceededError';
32
+ export { RateLimitExceededError } from './errors/RateLimitExceededError';
33
+ export { ReserveNotSupportedError } from './errors/ReserveNotSupportedError';
34
+ export { TimeUtil } from './util/TimeUtil';
35
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,YAAY,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACrE,YAAY,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAGjF,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,OAAO,EACL,kBAAkB,EAClB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,aAAa,GACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGpD,YAAY,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,YAAY,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAGjD,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAG/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,4BAA4B,EAAE,MAAM,uCAAuC,CAAC;AACrF,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AAG7E,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ /**
3
+ * @throttle - TypeScript Rate Limiter Library
4
+ *
5
+ * A production-ready rate limiting library supporting multiple algorithms:
6
+ * - Token Bucket: Allows bursts with steady refill rate
7
+ * - Fixed Window: Simple window-based limiting
8
+ * - Sliding Window: Smoothed rate limiting across window boundaries
9
+ * - No Limit: Pass-through for testing/conditional scenarios
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.TimeUtil = exports.ReserveNotSupportedError = exports.RateLimitExceededError = exports.MaxWaitDurationExceededError = exports.InvalidIntervalError = exports.NoLimiter = exports.SlidingWindowLimiter = exports.SlidingWindow = exports.FixedWindowLimiter = exports.Window = exports.TokenBucketLimiter = exports.TokenBucket = exports.Rate = exports.NoLock = exports.InMemoryStorage = exports.CompoundLimiter = exports.CompoundRateLimiterFactory = exports.RateLimiterFactory = exports.Reservation = exports.RateLimit = void 0;
13
+ // Core classes
14
+ var RateLimit_1 = require("./RateLimit");
15
+ Object.defineProperty(exports, "RateLimit", { enumerable: true, get: function () { return RateLimit_1.RateLimit; } });
16
+ var Reservation_1 = require("./Reservation");
17
+ Object.defineProperty(exports, "Reservation", { enumerable: true, get: function () { return Reservation_1.Reservation; } });
18
+ // Factories
19
+ var RateLimiterFactory_1 = require("./RateLimiterFactory");
20
+ Object.defineProperty(exports, "RateLimiterFactory", { enumerable: true, get: function () { return RateLimiterFactory_1.RateLimiterFactory; } });
21
+ var CompoundRateLimiterFactory_1 = require("./CompoundRateLimiterFactory");
22
+ Object.defineProperty(exports, "CompoundRateLimiterFactory", { enumerable: true, get: function () { return CompoundRateLimiterFactory_1.CompoundRateLimiterFactory; } });
23
+ var CompoundLimiter_1 = require("./CompoundLimiter");
24
+ Object.defineProperty(exports, "CompoundLimiter", { enumerable: true, get: function () { return CompoundLimiter_1.CompoundLimiter; } });
25
+ var InMemoryStorage_1 = require("./storage/InMemoryStorage");
26
+ Object.defineProperty(exports, "InMemoryStorage", { enumerable: true, get: function () { return InMemoryStorage_1.InMemoryStorage; } });
27
+ var LockInterface_1 = require("./storage/LockInterface");
28
+ Object.defineProperty(exports, "NoLock", { enumerable: true, get: function () { return LockInterface_1.NoLock; } });
29
+ // Policy implementations
30
+ var Rate_1 = require("./policy/Rate");
31
+ Object.defineProperty(exports, "Rate", { enumerable: true, get: function () { return Rate_1.Rate; } });
32
+ var TokenBucket_1 = require("./policy/TokenBucket");
33
+ Object.defineProperty(exports, "TokenBucket", { enumerable: true, get: function () { return TokenBucket_1.TokenBucket; } });
34
+ var TokenBucketLimiter_1 = require("./policy/TokenBucketLimiter");
35
+ Object.defineProperty(exports, "TokenBucketLimiter", { enumerable: true, get: function () { return TokenBucketLimiter_1.TokenBucketLimiter; } });
36
+ var Window_1 = require("./policy/Window");
37
+ Object.defineProperty(exports, "Window", { enumerable: true, get: function () { return Window_1.Window; } });
38
+ var FixedWindowLimiter_1 = require("./policy/FixedWindowLimiter");
39
+ Object.defineProperty(exports, "FixedWindowLimiter", { enumerable: true, get: function () { return FixedWindowLimiter_1.FixedWindowLimiter; } });
40
+ var SlidingWindow_1 = require("./policy/SlidingWindow");
41
+ Object.defineProperty(exports, "SlidingWindow", { enumerable: true, get: function () { return SlidingWindow_1.SlidingWindow; } });
42
+ var SlidingWindowLimiter_1 = require("./policy/SlidingWindowLimiter");
43
+ Object.defineProperty(exports, "SlidingWindowLimiter", { enumerable: true, get: function () { return SlidingWindowLimiter_1.SlidingWindowLimiter; } });
44
+ var NoLimiter_1 = require("./policy/NoLimiter");
45
+ Object.defineProperty(exports, "NoLimiter", { enumerable: true, get: function () { return NoLimiter_1.NoLimiter; } });
46
+ // Exceptions
47
+ var InvalidIntervalError_1 = require("./errors/InvalidIntervalError");
48
+ Object.defineProperty(exports, "InvalidIntervalError", { enumerable: true, get: function () { return InvalidIntervalError_1.InvalidIntervalError; } });
49
+ var MaxWaitDurationExceededError_1 = require("./errors/MaxWaitDurationExceededError");
50
+ Object.defineProperty(exports, "MaxWaitDurationExceededError", { enumerable: true, get: function () { return MaxWaitDurationExceededError_1.MaxWaitDurationExceededError; } });
51
+ var RateLimitExceededError_1 = require("./errors/RateLimitExceededError");
52
+ Object.defineProperty(exports, "RateLimitExceededError", { enumerable: true, get: function () { return RateLimitExceededError_1.RateLimitExceededError; } });
53
+ var ReserveNotSupportedError_1 = require("./errors/ReserveNotSupportedError");
54
+ Object.defineProperty(exports, "ReserveNotSupportedError", { enumerable: true, get: function () { return ReserveNotSupportedError_1.ReserveNotSupportedError; } });
55
+ // Utilities
56
+ var TimeUtil_1 = require("./util/TimeUtil");
57
+ Object.defineProperty(exports, "TimeUtil", { enumerable: true, get: function () { return TimeUtil_1.TimeUtil; } });
58
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAOH,eAAe;AACf,yCAAwC;AAA/B,sGAAA,SAAS,OAAA;AAClB,6CAA4C;AAAnC,0GAAA,WAAW,OAAA;AAEpB,YAAY;AACZ,2DAO8B;AAN5B,wHAAA,kBAAkB,OAAA;AAOpB,2EAA0E;AAAjE,wIAAA,0BAA0B,OAAA;AACnC,qDAAoD;AAA3C,kHAAA,eAAe,OAAA;AAIxB,6DAA4D;AAAnD,kHAAA,eAAe,OAAA;AAExB,yDAAiD;AAAxC,uGAAA,MAAM,OAAA;AAEf,yBAAyB;AACzB,sCAAqC;AAA5B,4FAAA,IAAI,OAAA;AACb,oDAAmD;AAA1C,0GAAA,WAAW,OAAA;AACpB,kEAAiE;AAAxD,wHAAA,kBAAkB,OAAA;AAC3B,0CAAyC;AAAhC,gGAAA,MAAM,OAAA;AACf,kEAAiE;AAAxD,wHAAA,kBAAkB,OAAA;AAC3B,wDAAuD;AAA9C,8GAAA,aAAa,OAAA;AACtB,sEAAqE;AAA5D,4HAAA,oBAAoB,OAAA;AAC7B,gDAA+C;AAAtC,sGAAA,SAAS,OAAA;AAElB,aAAa;AACb,sEAAqE;AAA5D,4HAAA,oBAAoB,OAAA;AAC7B,sFAAqF;AAA5E,4IAAA,4BAA4B,OAAA;AACrC,0EAAyE;AAAhE,gIAAA,sBAAsB,OAAA;AAC/B,8EAA6E;AAApE,oIAAA,wBAAwB,OAAA;AAEjC,YAAY;AACZ,4CAA2C;AAAlC,oGAAA,QAAQ,OAAA"}
@@ -0,0 +1,36 @@
1
+ import type { LimiterInterface } from '../LimiterInterface';
2
+ import type { StorageInterface } from '../storage/StorageInterface';
3
+ import type { LockInterface } from '../storage/LockInterface';
4
+ import { RateLimit } from '../RateLimit';
5
+ import { Reservation } from '../Reservation';
6
+ /**
7
+ * Fixed window rate limiter implementation.
8
+ *
9
+ * Divides time into fixed windows and counts hits within each window.
10
+ * Simple and efficient, but can allow bursts at window boundaries.
11
+ */
12
+ export declare class FixedWindowLimiter implements LimiterInterface {
13
+ private readonly id;
14
+ private readonly limit;
15
+ private readonly intervalInSeconds;
16
+ private readonly storage;
17
+ private readonly lock;
18
+ constructor(id: string, limit: number, intervalInSeconds: number, storage: StorageInterface, lock?: LockInterface);
19
+ /**
20
+ * Reserve tokens with optional maximum wait time.
21
+ */
22
+ reserve(tokens?: number, maxTime?: number | null): Promise<Reservation>;
23
+ /**
24
+ * Try to consume tokens immediately.
25
+ */
26
+ consume(tokens?: number): Promise<RateLimit>;
27
+ /**
28
+ * Reset the rate limiter state.
29
+ */
30
+ reset(): Promise<void>;
31
+ /**
32
+ * Get existing window or create a new one.
33
+ */
34
+ private getOrCreateWindow;
35
+ }
36
+ //# sourceMappingURL=FixedWindowLimiter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FixedWindowLimiter.d.ts","sourceRoot":"","sources":["../../src/policy/FixedWindowLimiter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAM7C;;;;;GAKG;AACH,qBAAa,kBAAmB,YAAW,gBAAgB;IACzD,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAC3C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;gBAGnC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,iBAAiB,EAAE,MAAM,EACzB,OAAO,EAAE,gBAAgB,EACzB,IAAI,CAAC,EAAE,aAAa;IAStB;;OAEG;IACG,OAAO,CAAC,MAAM,GAAE,MAAU,EAAE,OAAO,GAAE,MAAM,GAAG,IAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IAoDtF;;OAEG;IACG,OAAO,CAAC,MAAM,GAAE,MAAU,GAAG,OAAO,CAAC,SAAS,CAAC;IA4BrD;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAM5B;;OAEG;YACW,iBAAiB;CAWhC"}
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FixedWindowLimiter = void 0;
4
+ const RateLimit_1 = require("../RateLimit");
5
+ const Reservation_1 = require("../Reservation");
6
+ const MaxWaitDurationExceededError_1 = require("../errors/MaxWaitDurationExceededError");
7
+ const Window_1 = require("./Window");
8
+ const TimeUtil_1 = require("../util/TimeUtil");
9
+ const LockInterface_1 = require("../storage/LockInterface");
10
+ /**
11
+ * Fixed window rate limiter implementation.
12
+ *
13
+ * Divides time into fixed windows and counts hits within each window.
14
+ * Simple and efficient, but can allow bursts at window boundaries.
15
+ */
16
+ class FixedWindowLimiter {
17
+ constructor(id, limit, intervalInSeconds, storage, lock) {
18
+ this.id = id;
19
+ this.limit = limit;
20
+ this.intervalInSeconds = intervalInSeconds;
21
+ this.storage = storage;
22
+ this.lock = lock ?? new LockInterface_1.NoLock();
23
+ }
24
+ /**
25
+ * Reserve tokens with optional maximum wait time.
26
+ */
27
+ async reserve(tokens = 1, maxTime = null) {
28
+ return this.lock.withLock(this.id, async () => {
29
+ const now = TimeUtil_1.TimeUtil.now();
30
+ const window = await this.getOrCreateWindow(now);
31
+ const availableTokens = window.getAvailableTokens(now);
32
+ if (tokens > this.limit) {
33
+ throw new Error(`Cannot reserve ${tokens} tokens, limit is ${this.limit}`);
34
+ }
35
+ let timeToAct;
36
+ let waitTime;
37
+ if (availableTokens >= tokens) {
38
+ // Tokens available now
39
+ timeToAct = now;
40
+ waitTime = 0;
41
+ window.add(tokens, now);
42
+ }
43
+ else {
44
+ // Need to wait for next window
45
+ const windowEnd = window.getTimer() + this.intervalInSeconds;
46
+ waitTime = windowEnd - now;
47
+ timeToAct = windowEnd;
48
+ }
49
+ // Check max wait time
50
+ if (maxTime !== null && waitTime > maxTime) {
51
+ const retryAfter = new Date((now + waitTime) * 1000);
52
+ const rateLimit = new RateLimit_1.RateLimit(availableTokens, retryAfter, false, this.limit);
53
+ throw new MaxWaitDurationExceededError_1.MaxWaitDurationExceededError(`Cannot reserve ${tokens} tokens within ${maxTime} seconds`, rateLimit);
54
+ }
55
+ await this.storage.save(window);
56
+ const retryAfter = new Date(timeToAct * 1000);
57
+ const rateLimit = new RateLimit_1.RateLimit(Math.max(0, availableTokens - tokens), retryAfter, true, this.limit);
58
+ return new Reservation_1.Reservation(timeToAct * 1000, rateLimit); // Convert to ms
59
+ });
60
+ }
61
+ /**
62
+ * Try to consume tokens immediately.
63
+ */
64
+ async consume(tokens = 1) {
65
+ return this.lock.withLock(this.id, async () => {
66
+ const now = TimeUtil_1.TimeUtil.now();
67
+ const window = await this.getOrCreateWindow(now);
68
+ const availableTokens = window.getAvailableTokens(now);
69
+ if (availableTokens >= tokens) {
70
+ // Success
71
+ window.add(tokens, now);
72
+ await this.storage.save(window);
73
+ return new RateLimit_1.RateLimit(availableTokens - tokens, new Date(now * 1000), true, this.limit);
74
+ }
75
+ else {
76
+ // Rate limit exceeded - need to wait for next window
77
+ const waitTime = window.calculateTimeForTokens(tokens, now);
78
+ const retryAfter = new Date((now + waitTime) * 1000);
79
+ return new RateLimit_1.RateLimit(availableTokens, retryAfter, false, this.limit);
80
+ }
81
+ });
82
+ }
83
+ /**
84
+ * Reset the rate limiter state.
85
+ */
86
+ async reset() {
87
+ await this.lock.withLock(this.id, async () => {
88
+ await this.storage.delete(this.id);
89
+ });
90
+ }
91
+ /**
92
+ * Get existing window or create a new one.
93
+ */
94
+ async getOrCreateWindow(now) {
95
+ const state = await this.storage.fetch(this.id);
96
+ if (state instanceof Window_1.Window) {
97
+ return state;
98
+ }
99
+ // Create new window aligned to interval boundary
100
+ const windowStart = Math.floor(now / this.intervalInSeconds) * this.intervalInSeconds;
101
+ return new Window_1.Window(this.id, this.intervalInSeconds, this.limit, 0, windowStart);
102
+ }
103
+ }
104
+ exports.FixedWindowLimiter = FixedWindowLimiter;
105
+ //# sourceMappingURL=FixedWindowLimiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FixedWindowLimiter.js","sourceRoot":"","sources":["../../src/policy/FixedWindowLimiter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { LimiterInterface } from '../LimiterInterface';
2
+ import { RateLimit } from '../RateLimit';
3
+ import { Reservation } from '../Reservation';
4
+ /**
5
+ * No-op rate limiter that always accepts requests.
6
+ *
7
+ * Useful for testing, feature flags, or conditional rate limiting scenarios.
8
+ */
9
+ export declare class NoLimiter implements LimiterInterface {
10
+ /**
11
+ * Always returns an immediate reservation with maximum tokens.
12
+ */
13
+ reserve(_tokens?: number, _maxTime?: number | null): Promise<Reservation>;
14
+ /**
15
+ * Always returns an accepted rate limit with maximum tokens.
16
+ */
17
+ consume(_tokens?: number): Promise<RateLimit>;
18
+ /**
19
+ * No-op reset (nothing to reset).
20
+ */
21
+ reset(): Promise<void>;
22
+ }
23
+ //# sourceMappingURL=NoLimiter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NoLimiter.d.ts","sourceRoot":"","sources":["../../src/policy/NoLimiter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C;;;;GAIG;AACH,qBAAa,SAAU,YAAW,gBAAgB;IAChD;;OAEG;IACG,OAAO,CAAC,OAAO,GAAE,MAAU,EAAE,QAAQ,GAAE,MAAM,GAAG,IAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IAWxF;;OAEG;IACG,OAAO,CAAC,OAAO,GAAE,MAAU,GAAG,OAAO,CAAC,SAAS,CAAC;IAStD;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NoLimiter = void 0;
4
+ const RateLimit_1 = require("../RateLimit");
5
+ const Reservation_1 = require("../Reservation");
6
+ /**
7
+ * No-op rate limiter that always accepts requests.
8
+ *
9
+ * Useful for testing, feature flags, or conditional rate limiting scenarios.
10
+ */
11
+ class NoLimiter {
12
+ /**
13
+ * Always returns an immediate reservation with maximum tokens.
14
+ */
15
+ async reserve(_tokens = 1, _maxTime = null) {
16
+ const now = Date.now();
17
+ const rateLimit = new RateLimit_1.RateLimit(Number.MAX_SAFE_INTEGER, new Date(now), true, Number.MAX_SAFE_INTEGER);
18
+ return new Reservation_1.Reservation(now, rateLimit);
19
+ }
20
+ /**
21
+ * Always returns an accepted rate limit with maximum tokens.
22
+ */
23
+ async consume(_tokens = 1) {
24
+ return new RateLimit_1.RateLimit(Number.MAX_SAFE_INTEGER, new Date(), true, Number.MAX_SAFE_INTEGER);
25
+ }
26
+ /**
27
+ * No-op reset (nothing to reset).
28
+ */
29
+ async reset() {
30
+ // No-op
31
+ }
32
+ }
33
+ exports.NoLimiter = NoLimiter;
34
+ //# sourceMappingURL=NoLimiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NoLimiter.js","sourceRoot":"","sources":["../../src/policy/NoLimiter.ts"],"names":[],"mappings":";;;AACA,4CAAyC;AACzC,gDAA6C;AAE7C;;;;GAIG;AACH,MAAa,SAAS;IACpB;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,UAAkB,CAAC,EAAE,WAA0B,IAAI;QAC/D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,IAAI,qBAAS,CAC7B,MAAM,CAAC,gBAAgB,EACvB,IAAI,IAAI,CAAC,GAAG,CAAC,EACb,IAAI,EACJ,MAAM,CAAC,gBAAgB,CACxB,CAAC;QACF,OAAO,IAAI,yBAAW,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,UAAkB,CAAC;QAC/B,OAAO,IAAI,qBAAS,CAClB,MAAM,CAAC,gBAAgB,EACvB,IAAI,IAAI,EAAE,EACV,IAAI,EACJ,MAAM,CAAC,gBAAgB,CACxB,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAK;QACT,QAAQ;IACV,CAAC;CACF;AAjCD,8BAiCC"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Configuration object for token bucket refill rates.
3
+ *
4
+ * Defines how many tokens are added per time interval.
5
+ */
6
+ export declare class Rate {
7
+ private readonly intervalInSeconds;
8
+ private readonly amount;
9
+ constructor(intervalInSeconds: number, amount: number);
10
+ /**
11
+ * Get the interval in seconds.
12
+ */
13
+ getInterval(): number;
14
+ /**
15
+ * Get the amount of tokens per interval.
16
+ */
17
+ getAmount(): number;
18
+ /**
19
+ * Create a rate of N tokens per second.
20
+ */
21
+ static perSecond(amount: number): Rate;
22
+ /**
23
+ * Create a rate of N tokens per minute.
24
+ */
25
+ static perMinute(amount: number): Rate;
26
+ /**
27
+ * Create a rate of N tokens per hour.
28
+ */
29
+ static perHour(amount: number): Rate;
30
+ /**
31
+ * Create a rate of N tokens per day.
32
+ */
33
+ static perDay(amount: number): Rate;
34
+ /**
35
+ * Create a rate of N tokens per week.
36
+ */
37
+ static perWeek(amount: number): Rate;
38
+ /**
39
+ * Create a rate of N tokens per month (30 days).
40
+ */
41
+ static perMonth(amount: number): Rate;
42
+ /**
43
+ * Create a rate of N tokens per year (365 days).
44
+ */
45
+ static perYear(amount: number): Rate;
46
+ /**
47
+ * Create a rate from a string like "1 hour-100" or "60 seconds-5".
48
+ *
49
+ * Format: "{interval}-{amount}" where interval is a duration string.
50
+ */
51
+ static fromString(rateString: string): Rate;
52
+ /**
53
+ * Calculate the time (in seconds) needed to accumulate N tokens.
54
+ */
55
+ calculateTimeForTokens(tokens: number): number;
56
+ /**
57
+ * Calculate when the next token will be available.
58
+ */
59
+ calculateNextTokenAvailability(now?: number): Date;
60
+ /**
61
+ * Calculate how many new tokens are added during a given duration.
62
+ */
63
+ calculateNewTokensDuringInterval(durationInSeconds: number): number;
64
+ /**
65
+ * Calculate the refill interval (time per token in seconds).
66
+ */
67
+ getRefillInterval(): number;
68
+ }
69
+ //# sourceMappingURL=Rate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Rate.d.ts","sourceRoot":"","sources":["../../src/policy/Rate.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,qBAAa,IAAI;IACf,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,iBAAiB,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAiBrD;;OAEG;IACH,WAAW,IAAI,MAAM;IAIrB;;OAEG;IACH,SAAS,IAAI,MAAM;IAInB;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAItC;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAItC;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAIpC;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAInC;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAIpC;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAIrC;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAIpC;;;;OAIG;IACH,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAmB3C;;OAEG;IACH,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAI9C;;OAEG;IACH,8BAA8B,CAAC,GAAG,GAAE,MAAuB,GAAG,IAAI;IAKlE;;OAEG;IACH,gCAAgC,CAAC,iBAAiB,EAAE,MAAM,GAAG,MAAM;IAInE;;OAEG;IACH,iBAAiB,IAAI,MAAM;CAG5B"}
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Rate = void 0;
4
+ const InvalidIntervalError_1 = require("../errors/InvalidIntervalError");
5
+ const TimeUtil_1 = require("../util/TimeUtil");
6
+ /**
7
+ * Configuration object for token bucket refill rates.
8
+ *
9
+ * Defines how many tokens are added per time interval.
10
+ */
11
+ class Rate {
12
+ constructor(intervalInSeconds, amount) {
13
+ if (intervalInSeconds < 1) {
14
+ throw new InvalidIntervalError_1.InvalidIntervalError(`Interval must be at least 1 second, got ${intervalInSeconds}`);
15
+ }
16
+ if (amount < 1) {
17
+ throw new InvalidIntervalError_1.InvalidIntervalError(`Amount must be at least 1, got ${amount}`);
18
+ }
19
+ this.intervalInSeconds = intervalInSeconds;
20
+ this.amount = amount;
21
+ }
22
+ /**
23
+ * Get the interval in seconds.
24
+ */
25
+ getInterval() {
26
+ return this.intervalInSeconds;
27
+ }
28
+ /**
29
+ * Get the amount of tokens per interval.
30
+ */
31
+ getAmount() {
32
+ return this.amount;
33
+ }
34
+ /**
35
+ * Create a rate of N tokens per second.
36
+ */
37
+ static perSecond(amount) {
38
+ return new Rate(1, amount);
39
+ }
40
+ /**
41
+ * Create a rate of N tokens per minute.
42
+ */
43
+ static perMinute(amount) {
44
+ return new Rate(60, amount);
45
+ }
46
+ /**
47
+ * Create a rate of N tokens per hour.
48
+ */
49
+ static perHour(amount) {
50
+ return new Rate(3600, amount);
51
+ }
52
+ /**
53
+ * Create a rate of N tokens per day.
54
+ */
55
+ static perDay(amount) {
56
+ return new Rate(86400, amount);
57
+ }
58
+ /**
59
+ * Create a rate of N tokens per week.
60
+ */
61
+ static perWeek(amount) {
62
+ return new Rate(604800, amount);
63
+ }
64
+ /**
65
+ * Create a rate of N tokens per month (30 days).
66
+ */
67
+ static perMonth(amount) {
68
+ return new Rate(2592000, amount);
69
+ }
70
+ /**
71
+ * Create a rate of N tokens per year (365 days).
72
+ */
73
+ static perYear(amount) {
74
+ return new Rate(31536000, amount);
75
+ }
76
+ /**
77
+ * Create a rate from a string like "1 hour-100" or "60 seconds-5".
78
+ *
79
+ * Format: "{interval}-{amount}" where interval is a duration string.
80
+ */
81
+ static fromString(rateString) {
82
+ const parts = rateString.split('-');
83
+ if (parts.length !== 2) {
84
+ throw new Error(`Invalid rate format: ${rateString}. Expected format: "interval-amount"`);
85
+ }
86
+ const [intervalStr, amountStr] = parts;
87
+ const interval = TimeUtil_1.TimeUtil.durationToSeconds(intervalStr.trim());
88
+ const amount = parseInt(amountStr.trim(), 10);
89
+ if (isNaN(amount)) {
90
+ throw new Error(`Invalid amount in rate string: ${amountStr}`);
91
+ }
92
+ return new Rate(interval, amount);
93
+ }
94
+ /**
95
+ * Calculate the time (in seconds) needed to accumulate N tokens.
96
+ */
97
+ calculateTimeForTokens(tokens) {
98
+ return Math.ceil((tokens * this.intervalInSeconds) / this.amount);
99
+ }
100
+ /**
101
+ * Calculate when the next token will be available.
102
+ */
103
+ calculateNextTokenAvailability(now = TimeUtil_1.TimeUtil.now()) {
104
+ const secondsToWait = this.intervalInSeconds / this.amount;
105
+ return new Date((now + secondsToWait) * 1000);
106
+ }
107
+ /**
108
+ * Calculate how many new tokens are added during a given duration.
109
+ */
110
+ calculateNewTokensDuringInterval(durationInSeconds) {
111
+ return Math.floor((durationInSeconds * this.amount) / this.intervalInSeconds);
112
+ }
113
+ /**
114
+ * Calculate the refill interval (time per token in seconds).
115
+ */
116
+ getRefillInterval() {
117
+ return this.intervalInSeconds / this.amount;
118
+ }
119
+ }
120
+ exports.Rate = Rate;
121
+ //# sourceMappingURL=Rate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Rate.js","sourceRoot":"","sources":["../../src/policy/Rate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ import type { LimiterStateInterface } from '../LimiterStateInterface';
2
+ /**
3
+ * Serializable state for SlidingWindowLimiter.
4
+ *
5
+ * Tracks hit counts across current and previous windows to implement
6
+ * a sliding window algorithm.
7
+ */
8
+ export declare class SlidingWindow implements LimiterStateInterface {
9
+ private readonly id;
10
+ private hitCount;
11
+ private hitCountForLastWindow;
12
+ private windowEndAt;
13
+ private readonly intervalInSeconds;
14
+ constructor(id: string, intervalInSeconds: number, hitCount?: number, hitCountForLastWindow?: number, windowEndAt?: number);
15
+ getId(): string;
16
+ /**
17
+ * Get the expiration time in seconds since epoch.
18
+ */
19
+ getExpirationTime(): number;
20
+ /**
21
+ * Create a new window from a previous window (window transition).
22
+ */
23
+ static createFromPreviousWindow(id: string, intervalInSeconds: number, previousWindow: SlidingWindow, now: number): SlidingWindow;
24
+ /**
25
+ * Check if the window has expired.
26
+ */
27
+ isExpired(now?: number): boolean;
28
+ /**
29
+ * Add hits to the current window.
30
+ */
31
+ add(hits: number): void;
32
+ /**
33
+ * Get the sliding window hit count at a given time.
34
+ *
35
+ * Uses the formula:
36
+ * (previousWindowHits * (1 - percentIntoCurrentWindow)) + currentWindowHits
37
+ */
38
+ getHitCount(now?: number): number;
39
+ /**
40
+ * Get the current window's hit count (not sliding).
41
+ */
42
+ getCurrentWindowHitCount(): number;
43
+ /**
44
+ * Get the previous window's hit count.
45
+ */
46
+ getPreviousWindowHitCount(): number;
47
+ /**
48
+ * Get when the current window ends.
49
+ */
50
+ getWindowEndAt(): number;
51
+ /**
52
+ * Get the interval in seconds.
53
+ */
54
+ getInterval(): number;
55
+ /**
56
+ * Calculate time needed for N tokens to become available.
57
+ */
58
+ calculateTimeForTokens(maxSize: number, tokens: number, now?: number): number;
59
+ /**
60
+ * Convert to JSON for serialization.
61
+ */
62
+ toJSON(): Record<string, unknown>;
63
+ /**
64
+ * Create from JSON.
65
+ */
66
+ static fromJSON(data: {
67
+ id: string;
68
+ hitCount: number;
69
+ hitCountForLastWindow: number;
70
+ windowEndAt: number;
71
+ intervalInSeconds: number;
72
+ }): SlidingWindow;
73
+ }
74
+ //# sourceMappingURL=SlidingWindow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SlidingWindow.d.ts","sourceRoot":"","sources":["../../src/policy/SlidingWindow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAGtE;;;;;GAKG;AACH,qBAAa,aAAc,YAAW,qBAAqB;IACzD,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,qBAAqB,CAAS;IACtC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;gBAGzC,EAAE,EAAE,MAAM,EACV,iBAAiB,EAAE,MAAM,EACzB,QAAQ,CAAC,EAAE,MAAM,EACjB,qBAAqB,CAAC,EAAE,MAAM,EAC9B,WAAW,CAAC,EAAE,MAAM;IAStB,KAAK,IAAI,MAAM;IAIf;;OAEG;IACH,iBAAiB,IAAI,MAAM;IAK3B;;OAEG;IACH,MAAM,CAAC,wBAAwB,CAC7B,EAAE,EAAE,MAAM,EACV,iBAAiB,EAAE,MAAM,EACzB,cAAc,EAAE,aAAa,EAC7B,GAAG,EAAE,MAAM,GACV,aAAa;IAYhB;;OAEG;IACH,SAAS,CAAC,GAAG,GAAE,MAAuB,GAAG,OAAO;IAIhD;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIvB;;;;;OAKG;IACH,WAAW,CAAC,GAAG,GAAE,MAAuB,GAAG,MAAM;IAmBjD;;OAEG;IACH,wBAAwB,IAAI,MAAM;IAIlC;;OAEG;IACH,yBAAyB,IAAI,MAAM;IAInC;;OAEG;IACH,cAAc,IAAI,MAAM;IAIxB;;OAEG;IACH,WAAW,IAAI,MAAM;IAIrB;;OAEG;IACH,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAE,MAAuB,GAAG,MAAM;IAgB7F;;OAEG;IACH,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAUjC;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE;QACpB,EAAE,EAAE,MAAM,CAAC;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,qBAAqB,EAAE,MAAM,CAAC;QAC9B,WAAW,EAAE,MAAM,CAAC;QACpB,iBAAiB,EAAE,MAAM,CAAC;KAC3B,GAAG,aAAa;CASlB"}