limitly 1.0.2 → 3.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 (118) hide show
  1. package/README.md +471 -22
  2. package/dist/algorithms/concurrency.d.ts +11 -0
  3. package/dist/algorithms/concurrency.d.ts.map +1 -0
  4. package/dist/algorithms/concurrency.js +19 -0
  5. package/dist/algorithms/concurrency.js.map +1 -0
  6. package/dist/algorithms/factory.d.ts +3 -2
  7. package/dist/algorithms/factory.d.ts.map +1 -1
  8. package/dist/algorithms/factory.js +9 -3
  9. package/dist/algorithms/factory.js.map +1 -1
  10. package/dist/algorithms/gcra.d.ts +10 -0
  11. package/dist/algorithms/gcra.d.ts.map +1 -0
  12. package/dist/algorithms/gcra.js +15 -0
  13. package/dist/algorithms/gcra.js.map +1 -0
  14. package/dist/algorithms/sliding-window.d.ts +4 -4
  15. package/dist/algorithms/sliding-window.d.ts.map +1 -1
  16. package/dist/algorithms/sliding-window.js +3 -23
  17. package/dist/algorithms/sliding-window.js.map +1 -1
  18. package/dist/algorithms/token-bucket.d.ts +4 -4
  19. package/dist/algorithms/token-bucket.d.ts.map +1 -1
  20. package/dist/algorithms/token-bucket.js +3 -20
  21. package/dist/algorithms/token-bucket.js.map +1 -1
  22. package/dist/index.d.ts +19 -1
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +46 -1
  25. package/dist/index.js.map +1 -1
  26. package/dist/limiter.d.ts +23 -7
  27. package/dist/limiter.d.ts.map +1 -1
  28. package/dist/limiter.js +86 -16
  29. package/dist/limiter.js.map +1 -1
  30. package/dist/middleware/bun.d.ts +9 -0
  31. package/dist/middleware/bun.d.ts.map +1 -0
  32. package/dist/middleware/bun.js +107 -0
  33. package/dist/middleware/bun.js.map +1 -0
  34. package/dist/middleware/express.d.ts.map +1 -1
  35. package/dist/middleware/express.js +30 -14
  36. package/dist/middleware/express.js.map +1 -1
  37. package/dist/middleware/fastify.d.ts +3 -3
  38. package/dist/middleware/fastify.d.ts.map +1 -1
  39. package/dist/middleware/fastify.js +34 -17
  40. package/dist/middleware/fastify.js.map +1 -1
  41. package/dist/middleware/hono.d.ts +5 -0
  42. package/dist/middleware/hono.d.ts.map +1 -0
  43. package/dist/middleware/hono.js +71 -0
  44. package/dist/middleware/hono.js.map +1 -0
  45. package/dist/middleware/koa.d.ts +5 -0
  46. package/dist/middleware/koa.d.ts.map +1 -0
  47. package/dist/middleware/koa.js +65 -0
  48. package/dist/middleware/koa.js.map +1 -0
  49. package/dist/middleware/nest.d.ts +14 -0
  50. package/dist/middleware/nest.d.ts.map +1 -0
  51. package/dist/middleware/nest.js +112 -0
  52. package/dist/middleware/nest.js.map +1 -0
  53. package/dist/observability/index.d.ts +4 -0
  54. package/dist/observability/index.d.ts.map +1 -0
  55. package/dist/observability/index.js +10 -0
  56. package/dist/observability/index.js.map +1 -0
  57. package/dist/observability/opentelemetry.d.ts +28 -0
  58. package/dist/observability/opentelemetry.d.ts.map +1 -0
  59. package/dist/observability/opentelemetry.js +85 -0
  60. package/dist/observability/opentelemetry.js.map +1 -0
  61. package/dist/observability/prometheus.d.ts +27 -0
  62. package/dist/observability/prometheus.d.ts.map +1 -0
  63. package/dist/observability/prometheus.js +88 -0
  64. package/dist/observability/prometheus.js.map +1 -0
  65. package/dist/observability/types.d.ts +9 -0
  66. package/dist/observability/types.d.ts.map +1 -0
  67. package/dist/observability/types.js +3 -0
  68. package/dist/observability/types.js.map +1 -0
  69. package/dist/prometheus.d.ts +3 -0
  70. package/dist/prometheus.d.ts.map +1 -0
  71. package/dist/prometheus.js +9 -0
  72. package/dist/prometheus.js.map +1 -0
  73. package/dist/scripts/concurrencyAcquire.lua +34 -0
  74. package/dist/scripts/concurrencyRelease.lua +9 -0
  75. package/dist/scripts/gcra.lua +38 -0
  76. package/dist/stores/factory.d.ts +5 -0
  77. package/dist/stores/factory.d.ts.map +1 -0
  78. package/dist/stores/factory.js +40 -0
  79. package/dist/stores/factory.js.map +1 -0
  80. package/dist/stores/memcached-store.d.ts +16 -0
  81. package/dist/stores/memcached-store.d.ts.map +1 -0
  82. package/dist/stores/memcached-store.js +211 -0
  83. package/dist/stores/memcached-store.js.map +1 -0
  84. package/dist/stores/redis-store.d.ts +19 -0
  85. package/dist/stores/redis-store.d.ts.map +1 -0
  86. package/dist/stores/redis-store.js +97 -0
  87. package/dist/stores/redis-store.js.map +1 -0
  88. package/dist/stores/types.d.ts +11 -0
  89. package/dist/stores/types.d.ts.map +1 -0
  90. package/dist/stores/types.js +3 -0
  91. package/dist/stores/types.js.map +1 -0
  92. package/dist/types/index.d.ts +94 -5
  93. package/dist/types/index.d.ts.map +1 -1
  94. package/dist/utils/defaults.d.ts +8 -0
  95. package/dist/utils/defaults.d.ts.map +1 -0
  96. package/dist/utils/defaults.js +100 -0
  97. package/dist/utils/defaults.js.map +1 -0
  98. package/dist/utils/limit-execution.d.ts +40 -0
  99. package/dist/utils/limit-execution.d.ts.map +1 -0
  100. package/dist/utils/limit-execution.js +50 -0
  101. package/dist/utils/limit-execution.js.map +1 -0
  102. package/dist/utils/memcached.d.ts +12 -0
  103. package/dist/utils/memcached.d.ts.map +1 -0
  104. package/dist/utils/memcached.js +103 -0
  105. package/dist/utils/memcached.js.map +1 -0
  106. package/dist/utils/metrics.d.ts +21 -0
  107. package/dist/utils/metrics.d.ts.map +1 -0
  108. package/dist/utils/metrics.js +99 -0
  109. package/dist/utils/metrics.js.map +1 -0
  110. package/dist/utils/redis.d.ts +5 -1
  111. package/dist/utils/redis.d.ts.map +1 -1
  112. package/dist/utils/redis.js +38 -3
  113. package/dist/utils/redis.js.map +1 -1
  114. package/dist/utils/scripts.d.ts +16 -2
  115. package/dist/utils/scripts.d.ts.map +1 -1
  116. package/dist/utils/scripts.js +79 -33
  117. package/dist/utils/scripts.js.map +1 -1
  118. package/package.json +86 -3
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createExpressMiddleware = createExpressMiddleware;
4
4
  const headers_1 = require("../utils/headers");
5
+ const limit_execution_1 = require("../utils/limit-execution");
5
6
  const DEFAULT_KEY = (req) => req.ip ?? "unknown";
6
7
  function createExpressMiddleware(limiter) {
7
8
  return function middleware(options) {
@@ -11,29 +12,44 @@ function createExpressMiddleware(limiter) {
11
12
  const failOpen = options.failOpen ?? true;
12
13
  return async (req, res, next) => {
13
14
  const key = keyExtractor(req) ?? "unknown";
14
- let result;
15
- try {
16
- result = await strategy.consume(key);
17
- }
18
- catch {
15
+ const outcome = await (0, limit_execution_1.processLimitRequest)({
16
+ limiter,
17
+ strategy,
18
+ key,
19
+ options,
20
+ failOpen,
21
+ context: req,
22
+ });
23
+ if (outcome.status === "error") {
19
24
  if (failOpen) {
20
25
  return next();
21
26
  }
22
27
  res.status(503).json({ error: "Service Unavailable" });
23
28
  return;
24
29
  }
25
- if (sendHeaders) {
26
- (0, headers_1.setHeaders)(res, (0, headers_1.buildRateLimitHeaders)(result));
27
- }
28
- if (result.allowed) {
29
- next();
30
+ if (outcome.status === "blocked") {
31
+ if (sendHeaders) {
32
+ (0, headers_1.setHeaders)(res, (0, headers_1.buildRateLimitHeaders)(outcome.result));
33
+ }
34
+ if (options.onLimitReached) {
35
+ await options.onLimitReached(req, res);
36
+ return;
37
+ }
38
+ res.status(429).json({ error: "Too Many Requests" });
30
39
  return;
31
40
  }
32
- if (options.onLimitReached) {
33
- await options.onLimitReached(req, res);
34
- return;
41
+ if (sendHeaders) {
42
+ (0, headers_1.setHeaders)(res, (0, headers_1.buildRateLimitHeaders)(outcome.result));
43
+ }
44
+ if (outcome.slotId) {
45
+ (0, limit_execution_1.bindConcurrencyRelease)({
46
+ strategy,
47
+ key,
48
+ slotId: outcome.slotId,
49
+ emitter: res,
50
+ });
35
51
  }
36
- res.status(429).json({ error: "Too Many Requests" });
52
+ next();
37
53
  };
38
54
  };
39
55
  }
@@ -1 +1 @@
1
- {"version":3,"file":"express.js","sourceRoot":"","sources":["../../src/middleware/express.ts"],"names":[],"mappings":";;AAOA,0DA4CC;AAhDD,8CAAqE;AAErE,MAAM,WAAW,GAAG,CAAC,GAAY,EAAU,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,SAAS,CAAC;AAElE,SAAgB,uBAAuB,CAAC,OAAmB;IACzD,OAAO,SAAS,UAAU,CAAC,OAA0B;QACnD,MAAM,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QACjD,MAAM,YAAY,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,WAAW,CAEzB,CAAC;QACxB,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,KAAK,KAAK,CAAC;QAC9C,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC;QAE1C,OAAO,KAAK,EACV,GAAY,EACZ,GAAa,EACb,IAAkB,EACH,EAAE;YACjB,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC;YAE3C,IAAI,MAAM,CAAC;YACX,IAAI,CAAC;gBACH,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACvC,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,QAAQ,EAAE,CAAC;oBACb,OAAO,IAAI,EAAE,CAAC;gBAChB,CAAC;gBACD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC,CAAC;gBACvD,OAAO;YACT,CAAC;YAED,IAAI,WAAW,EAAE,CAAC;gBAChB,IAAA,oBAAU,EAAC,GAAG,EAAE,IAAA,+BAAqB,EAAC,MAAM,CAAC,CAAC,CAAC;YACjD,CAAC;YAED,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,IAAI,EAAE,CAAC;gBACP,OAAO;YACT,CAAC;YAED,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;gBAC3B,MAAM,OAAO,CAAC,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;gBACvC,OAAO;YACT,CAAC;YAED,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;QACvD,CAAC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"express.js","sourceRoot":"","sources":["../../src/middleware/express.ts"],"names":[],"mappings":";;AAWA,0DA8DC;AAtED,8CAAqE;AACrE,8DAGkC;AAElC,MAAM,WAAW,GAAG,CAAC,GAAY,EAAU,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,SAAS,CAAC;AAElE,SAAgB,uBAAuB,CAAC,OAAmB;IACzD,OAAO,SAAS,UAAU,CAAC,OAA0B;QACnD,MAAM,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QACjD,MAAM,YAAY,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,WAAW,CAEzB,CAAC;QACxB,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,KAAK,KAAK,CAAC;QAC9C,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC;QAE1C,OAAO,KAAK,EACV,GAAY,EACZ,GAAa,EACb,IAAkB,EACH,EAAE;YACjB,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC;YAC3C,MAAM,OAAO,GAAG,MAAM,IAAA,qCAAmB,EAAC;gBACxC,OAAO;gBACP,QAAQ;gBACR,GAAG;gBACH,OAAO;gBACP,QAAQ;gBACR,OAAO,EAAE,GAAG;aACb,CAAC,CAAC;YAEH,IAAI,OAAO,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;gBAC/B,IAAI,QAAQ,EAAE,CAAC;oBACb,OAAO,IAAI,EAAE,CAAC;gBAChB,CAAC;gBACD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC,CAAC;gBACvD,OAAO;YACT,CAAC;YAED,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBACjC,IAAI,WAAW,EAAE,CAAC;oBAChB,IAAA,oBAAU,EAAC,GAAG,EAAE,IAAA,+BAAqB,EAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;gBACzD,CAAC;gBAED,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;oBAC3B,MAAM,OAAO,CAAC,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;oBACvC,OAAO;gBACT,CAAC;gBAED,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;gBACrD,OAAO;YACT,CAAC;YAED,IAAI,WAAW,EAAE,CAAC;gBAChB,IAAA,oBAAU,EAAC,GAAG,EAAE,IAAA,+BAAqB,EAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;YACzD,CAAC;YAED,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBACnB,IAAA,wCAAsB,EAAC;oBACrB,QAAQ;oBACR,GAAG;oBACH,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,OAAO,EAAE,GAAG;iBACb,CAAC,CAAC;YACL,CAAC;YAED,IAAI,EAAE,CAAC;QACT,CAAC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
@@ -1,9 +1,9 @@
1
1
  import type { FastifyPluginAsync } from "fastify";
2
2
  import type { RedisLimit } from "../limiter";
3
- import type { MiddlewareOptions } from "../types";
4
- export type FastifyRateLimitOptions = MiddlewareOptions & {
3
+ import type { MiddlewareOptionsInput } from "../types";
4
+ export type FastifyRateLimitOptions = MiddlewareOptionsInput & {
5
5
  limiter: RedisLimit;
6
6
  };
7
- export declare function createFastifyPlugin(limiter: RedisLimit): FastifyPluginAsync<MiddlewareOptions>;
7
+ export declare function createFastifyPlugin(limiter: RedisLimit): FastifyPluginAsync<MiddlewareOptionsInput>;
8
8
  export declare const redisLimitPlugin: FastifyPluginAsync<FastifyRateLimitOptions>;
9
9
  //# sourceMappingURL=fastify.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fastify.d.ts","sourceRoot":"","sources":["../../src/middleware/fastify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAgC,MAAM,SAAS,CAAC;AAChF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAKlD,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,GAAG;IACxD,OAAO,EAAE,UAAU,CAAC;CACrB,CAAC;AAaF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,UAAU,GAAG,kBAAkB,CAAC,iBAAiB,CAAC,CAuC9F;AAED,eAAO,MAAM,gBAAgB,EAAE,kBAAkB,CAAC,uBAAuB,CAOxE,CAAC"}
1
+ {"version":3,"file":"fastify.d.ts","sourceRoot":"","sources":["../../src/middleware/fastify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAgC,MAAM,SAAS,CAAC;AAChF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAqB,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAS1E,MAAM,MAAM,uBAAuB,GAAG,sBAAsB,GAAG;IAC7D,OAAO,EAAE,UAAU,CAAC;CACrB,CAAC;AAaF,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,UAAU,GAClB,kBAAkB,CAAC,sBAAsB,CAAC,CA8D5C;AAED,eAAO,MAAM,gBAAgB,EAAE,kBAAkB,CAAC,uBAAuB,CAMxE,CAAC"}
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.redisLimitPlugin = void 0;
4
4
  exports.createFastifyPlugin = createFastifyPlugin;
5
5
  const headers_1 = require("../utils/headers");
6
+ const limit_execution_1 = require("../utils/limit-execution");
6
7
  const DEFAULT_KEY = (req) => req.ip;
7
8
  function setFastifyHeaders(reply, headers) {
8
9
  for (const [name, value] of Object.entries(headers)) {
@@ -13,32 +14,49 @@ function setFastifyHeaders(reply, headers) {
13
14
  }
14
15
  function createFastifyPlugin(limiter) {
15
16
  const plugin = async (fastify, options) => {
16
- const strategy = limiter.createStrategy(options);
17
- const keyExtractor = (options.key ?? DEFAULT_KEY);
18
- const sendHeaders = options.headers !== false;
19
- const failOpen = options.failOpen ?? true;
17
+ const resolved = limiter.resolveOptions(options);
18
+ const strategy = limiter.createStrategy(resolved);
19
+ const keyExtractor = (resolved.key ?? DEFAULT_KEY);
20
+ const sendHeaders = resolved.headers !== false;
21
+ const failOpen = resolved.failOpen ?? true;
20
22
  fastify.addHook("preHandler", async (request, reply) => {
21
23
  const key = keyExtractor(request) ?? "unknown";
22
- let result;
23
- try {
24
- result = await strategy.consume(key);
25
- }
26
- catch {
24
+ const outcome = await (0, limit_execution_1.processLimitRequest)({
25
+ limiter,
26
+ strategy,
27
+ key,
28
+ options: resolved,
29
+ failOpen,
30
+ context: request,
31
+ });
32
+ if (outcome.status === "error") {
27
33
  if (failOpen) {
28
34
  return;
29
35
  }
30
36
  reply.status(503).send({ error: "Service Unavailable" });
31
37
  return;
32
38
  }
33
- if (sendHeaders) {
34
- setFastifyHeaders(reply, (0, headers_1.buildRateLimitHeaders)(result));
35
- }
36
- if (!result.allowed) {
37
- if (options.onLimitReached) {
38
- await options.onLimitReached(request, reply);
39
+ if (outcome.status === "blocked") {
40
+ if (sendHeaders) {
41
+ setFastifyHeaders(reply, (0, headers_1.buildRateLimitHeaders)(outcome.result));
42
+ }
43
+ if (resolved.onLimitReached) {
44
+ await resolved.onLimitReached(request, reply);
39
45
  return;
40
46
  }
41
47
  reply.status(429).send({ error: "Too Many Requests" });
48
+ return;
49
+ }
50
+ if (sendHeaders) {
51
+ setFastifyHeaders(reply, (0, headers_1.buildRateLimitHeaders)(outcome.result));
52
+ }
53
+ if (outcome.slotId) {
54
+ (0, limit_execution_1.bindConcurrencyRelease)({
55
+ strategy,
56
+ key,
57
+ slotId: outcome.slotId,
58
+ emitter: reply.raw,
59
+ });
42
60
  }
43
61
  });
44
62
  };
@@ -46,8 +64,7 @@ function createFastifyPlugin(limiter) {
46
64
  }
47
65
  const redisLimitPlugin = async (fastify, options) => {
48
66
  const { limiter, ...rest } = options;
49
- const middlewareOptions = rest;
50
- await fastify.register(createFastifyPlugin(limiter), middlewareOptions);
67
+ await fastify.register(createFastifyPlugin(limiter), rest);
51
68
  };
52
69
  exports.redisLimitPlugin = redisLimitPlugin;
53
70
  //# sourceMappingURL=fastify.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fastify.js","sourceRoot":"","sources":["../../src/middleware/fastify.ts"],"names":[],"mappings":";;;AAsBA,kDAuCC;AA1DD,8CAAyD;AAEzD,MAAM,WAAW,GAAG,CAAC,GAAmB,EAAU,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;AAM5D,SAAS,iBAAiB,CACxB,KAAmB,EACnB,OAAiD;IAEjD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACpD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAgB,mBAAmB,CAAC,OAAmB;IACrD,MAAM,MAAM,GAA0C,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;QAC/E,MAAM,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QACjD,MAAM,YAAY,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,WAAW,CAEzB,CAAC;QACxB,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,KAAK,KAAK,CAAC;QAC9C,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC;QAE1C,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;YACrD,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,SAAS,CAAC;YAE/C,IAAI,MAAM,CAAC;YACX,IAAI,CAAC;gBACH,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACvC,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,QAAQ,EAAE,CAAC;oBACb,OAAO;gBACT,CAAC;gBACD,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC,CAAC;gBACzD,OAAO;YACT,CAAC;YAED,IAAI,WAAW,EAAE,CAAC;gBAChB,iBAAiB,CAAC,KAAK,EAAE,IAAA,+BAAqB,EAAC,MAAM,CAAC,CAAC,CAAC;YAC1D,CAAC;YAED,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpB,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;oBAC3B,MAAM,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;oBAC7C,OAAO;gBACT,CAAC;gBAED,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;YACzD,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC;AAEM,MAAM,gBAAgB,GAAgD,KAAK,EAChF,OAAO,EACP,OAAO,EACP,EAAE;IACF,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IACrC,MAAM,iBAAiB,GAAG,IAAyB,CAAC;IACpD,MAAM,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,OAAO,CAAC,EAAE,iBAAiB,CAAC,CAAC;AAC1E,CAAC,CAAC;AAPW,QAAA,gBAAgB,oBAO3B"}
1
+ {"version":3,"file":"fastify.js","sourceRoot":"","sources":["../../src/middleware/fastify.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { Context, Next } from "hono";
2
+ import type { RedisLimit } from "../limiter";
3
+ import type { MiddlewareOptions } from "../types";
4
+ export declare function createHonoMiddleware(limiter: RedisLimit): (options: MiddlewareOptions) => (c: Context, next: Next) => Promise<Response | void>;
5
+ //# sourceMappingURL=hono.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hono.d.ts","sourceRoot":"","sources":["../../src/middleware/hono.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AA0BlD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,UAAU,IAC3B,SAAS,iBAAiB,MAQrC,GAAG,OAAO,EAAE,MAAM,IAAI,KAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAkDlE"}
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createHonoMiddleware = createHonoMiddleware;
4
+ const headers_1 = require("../utils/headers");
5
+ const limit_execution_1 = require("../utils/limit-execution");
6
+ const DEFAULT_KEY = (c) => {
7
+ const forwarded = c.req.header("x-forwarded-for");
8
+ if (forwarded) {
9
+ return forwarded.split(",")[0].trim();
10
+ }
11
+ return c.req.header("x-real-ip") ?? "unknown";
12
+ };
13
+ function setHonoHeaders(c, headers) {
14
+ for (const [name, value] of Object.entries(headers)) {
15
+ if (value !== undefined) {
16
+ c.header(name, value);
17
+ }
18
+ }
19
+ }
20
+ function createHonoMiddleware(limiter) {
21
+ return function middleware(options) {
22
+ const strategy = limiter.createStrategy(options);
23
+ const keyExtractor = (options.key ?? DEFAULT_KEY);
24
+ const sendHeaders = options.headers !== false;
25
+ const failOpen = options.failOpen ?? true;
26
+ return async (c, next) => {
27
+ const key = keyExtractor(c) ?? "unknown";
28
+ const outcome = await (0, limit_execution_1.processLimitRequest)({
29
+ limiter,
30
+ strategy,
31
+ key,
32
+ options,
33
+ failOpen,
34
+ context: c,
35
+ });
36
+ if (outcome.status === "error") {
37
+ if (failOpen) {
38
+ return next();
39
+ }
40
+ return c.json({ error: "Service Unavailable" }, 503);
41
+ }
42
+ if (outcome.status === "blocked") {
43
+ if (sendHeaders) {
44
+ setHonoHeaders(c, (0, headers_1.buildRateLimitHeaders)(outcome.result));
45
+ }
46
+ if (options.onLimitReached) {
47
+ await options.onLimitReached(c.req.raw, c);
48
+ return;
49
+ }
50
+ return c.json({ error: "Too Many Requests" }, 429);
51
+ }
52
+ if (sendHeaders) {
53
+ setHonoHeaders(c, (0, headers_1.buildRateLimitHeaders)(outcome.result));
54
+ }
55
+ if (outcome.slotId) {
56
+ try {
57
+ return await next();
58
+ }
59
+ finally {
60
+ await (0, limit_execution_1.releaseConcurrencySlot)({
61
+ strategy,
62
+ key,
63
+ slotId: outcome.slotId,
64
+ });
65
+ }
66
+ }
67
+ return next();
68
+ };
69
+ };
70
+ }
71
+ //# sourceMappingURL=hono.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hono.js","sourceRoot":"","sources":["../../src/middleware/hono.ts"],"names":[],"mappings":";;AA4BA,oDA2DC;AApFD,8CAAyD;AACzD,8DAGkC;AAElC,MAAM,WAAW,GAAG,CAAC,CAAU,EAAU,EAAE;IACzC,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAClD,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACxC,CAAC;IACD,OAAO,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,SAAS,CAAC;AAChD,CAAC,CAAC;AAEF,SAAS,cAAc,CACrB,CAAU,EACV,OAAiD;IAEjD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACpD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAgB,oBAAoB,CAAC,OAAmB;IACtD,OAAO,SAAS,UAAU,CAAC,OAA0B;QACnD,MAAM,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QACjD,MAAM,YAAY,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,WAAW,CAEzB,CAAC;QACxB,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,KAAK,KAAK,CAAC;QAC9C,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC;QAE1C,OAAO,KAAK,EAAE,CAAU,EAAE,IAAU,EAA4B,EAAE;YAChE,MAAM,GAAG,GAAG,YAAY,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;YACzC,MAAM,OAAO,GAAG,MAAM,IAAA,qCAAmB,EAAC;gBACxC,OAAO;gBACP,QAAQ;gBACR,GAAG;gBACH,OAAO;gBACP,QAAQ;gBACR,OAAO,EAAE,CAAC;aACX,CAAC,CAAC;YAEH,IAAI,OAAO,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;gBAC/B,IAAI,QAAQ,EAAE,CAAC;oBACb,OAAO,IAAI,EAAE,CAAC;gBAChB,CAAC;gBACD,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,EAAE,GAAG,CAAC,CAAC;YACvD,CAAC;YAED,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBACjC,IAAI,WAAW,EAAE,CAAC;oBAChB,cAAc,CAAC,CAAC,EAAE,IAAA,+BAAqB,EAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;gBAC3D,CAAC;gBAED,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;oBAC3B,MAAM,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;oBAC3C,OAAO;gBACT,CAAC;gBAED,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,EAAE,GAAG,CAAC,CAAC;YACrD,CAAC;YAED,IAAI,WAAW,EAAE,CAAC;gBAChB,cAAc,CAAC,CAAC,EAAE,IAAA,+BAAqB,EAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;YAC3D,CAAC;YAED,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBACnB,IAAI,CAAC;oBACH,OAAO,MAAM,IAAI,EAAE,CAAC;gBACtB,CAAC;wBAAS,CAAC;oBACT,MAAM,IAAA,wCAAsB,EAAC;wBAC3B,QAAQ;wBACR,GAAG;wBACH,MAAM,EAAE,OAAO,CAAC,MAAM;qBACvB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAED,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { Context, Next } from "koa";
2
+ import type { RedisLimit } from "../limiter";
3
+ import type { MiddlewareOptions } from "../types";
4
+ export declare function createKoaMiddleware(limiter: RedisLimit): (options: MiddlewareOptions) => (ctx: Context, next: Next) => Promise<void>;
5
+ //# sourceMappingURL=koa.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"koa.d.ts","sourceRoot":"","sources":["../../src/middleware/koa.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAqBlD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,UAAU,IAC1B,SAAS,iBAAiB,MAQrC,KAAK,OAAO,EAAE,MAAM,IAAI,KAAG,OAAO,CAAC,IAAI,CAAC,CAmDzD"}
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createKoaMiddleware = createKoaMiddleware;
4
+ const headers_1 = require("../utils/headers");
5
+ const limit_execution_1 = require("../utils/limit-execution");
6
+ const DEFAULT_KEY = (ctx) => ctx.ip ?? "unknown";
7
+ function setKoaHeaders(ctx, headers) {
8
+ for (const [name, value] of Object.entries(headers)) {
9
+ if (value !== undefined) {
10
+ ctx.set(name, value);
11
+ }
12
+ }
13
+ }
14
+ function createKoaMiddleware(limiter) {
15
+ return function middleware(options) {
16
+ const strategy = limiter.createStrategy(options);
17
+ const keyExtractor = (options.key ?? DEFAULT_KEY);
18
+ const sendHeaders = options.headers !== false;
19
+ const failOpen = options.failOpen ?? true;
20
+ return async (ctx, next) => {
21
+ const key = keyExtractor(ctx) ?? "unknown";
22
+ const outcome = await (0, limit_execution_1.processLimitRequest)({
23
+ limiter,
24
+ strategy,
25
+ key,
26
+ options,
27
+ failOpen,
28
+ context: ctx,
29
+ });
30
+ if (outcome.status === "error") {
31
+ if (failOpen) {
32
+ return next();
33
+ }
34
+ ctx.status = 503;
35
+ ctx.body = { error: "Service Unavailable" };
36
+ return;
37
+ }
38
+ if (outcome.status === "blocked") {
39
+ if (sendHeaders) {
40
+ setKoaHeaders(ctx, (0, headers_1.buildRateLimitHeaders)(outcome.result));
41
+ }
42
+ if (options.onLimitReached) {
43
+ await options.onLimitReached(ctx.request, ctx.response);
44
+ return;
45
+ }
46
+ ctx.status = 429;
47
+ ctx.body = { error: "Too Many Requests" };
48
+ return;
49
+ }
50
+ if (sendHeaders) {
51
+ setKoaHeaders(ctx, (0, headers_1.buildRateLimitHeaders)(outcome.result));
52
+ }
53
+ if (outcome.slotId) {
54
+ (0, limit_execution_1.bindConcurrencyRelease)({
55
+ strategy,
56
+ key,
57
+ slotId: outcome.slotId,
58
+ emitter: ctx.res,
59
+ });
60
+ }
61
+ return next();
62
+ };
63
+ };
64
+ }
65
+ //# sourceMappingURL=koa.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"koa.js","sourceRoot":"","sources":["../../src/middleware/koa.ts"],"names":[],"mappings":";;AAuBA,kDA4DC;AAhFD,8CAAyD;AACzD,8DAIkC;AAElC,MAAM,WAAW,GAAG,CAAC,GAAY,EAAU,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,SAAS,CAAC;AAElE,SAAS,aAAa,CACpB,GAAY,EACZ,OAAiD;IAEjD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACpD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAgB,mBAAmB,CAAC,OAAmB;IACrD,OAAO,SAAS,UAAU,CAAC,OAA0B;QACnD,MAAM,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QACjD,MAAM,YAAY,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,WAAW,CAEzB,CAAC;QACxB,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,KAAK,KAAK,CAAC;QAC9C,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC;QAE1C,OAAO,KAAK,EAAE,GAAY,EAAE,IAAU,EAAiB,EAAE;YACvD,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC;YAC3C,MAAM,OAAO,GAAG,MAAM,IAAA,qCAAmB,EAAC;gBACxC,OAAO;gBACP,QAAQ;gBACR,GAAG;gBACH,OAAO;gBACP,QAAQ;gBACR,OAAO,EAAE,GAAG;aACb,CAAC,CAAC;YAEH,IAAI,OAAO,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;gBAC/B,IAAI,QAAQ,EAAE,CAAC;oBACb,OAAO,IAAI,EAAE,CAAC;gBAChB,CAAC;gBACD,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;gBACjB,GAAG,CAAC,IAAI,GAAG,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC;gBAC5C,OAAO;YACT,CAAC;YAED,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBACjC,IAAI,WAAW,EAAE,CAAC;oBAChB,aAAa,CAAC,GAAG,EAAE,IAAA,+BAAqB,EAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;gBAC5D,CAAC;gBAED,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;oBAC3B,MAAM,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;oBACxD,OAAO;gBACT,CAAC;gBAED,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;gBACjB,GAAG,CAAC,IAAI,GAAG,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC;gBAC1C,OAAO;YACT,CAAC;YAED,IAAI,WAAW,EAAE,CAAC;gBAChB,aAAa,CAAC,GAAG,EAAE,IAAA,+BAAqB,EAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;YAC5D,CAAC;YAED,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBACnB,IAAA,wCAAsB,EAAC;oBACrB,QAAQ;oBACR,GAAG;oBACH,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,OAAO,EAAE,GAAG,CAAC,GAAG;iBACjB,CAAC,CAAC;YACL,CAAC;YAED,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { CanActivate, DynamicModule, type Type } from "@nestjs/common";
2
+ import type { RedisLimit } from "../limiter";
3
+ import type { MiddlewareOptionsInput } from "../types";
4
+ export declare const RATE_LIMIT_KEY = "limitly:rate-limit";
5
+ export declare const RateLimit: (options: MiddlewareOptionsInput) => import("@nestjs/common").CustomDecorator<string>;
6
+ export type NestRateLimitOptions = MiddlewareOptionsInput & {
7
+ limiter: RedisLimit;
8
+ global?: boolean;
9
+ };
10
+ export declare function createNestGuard(limiter: RedisLimit): (defaultOptions?: MiddlewareOptionsInput) => Type<CanActivate>;
11
+ export declare class LimitlyModule {
12
+ }
13
+ export declare function limitlyNestModule(options: NestRateLimitOptions): DynamicModule;
14
+ //# sourceMappingURL=nest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nest.d.ts","sourceRoot":"","sources":["../../src/middleware/nest.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,aAAa,EAQb,KAAK,IAAI,EACV,MAAM,gBAAgB,CAAC;AAGxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AASvD,eAAO,MAAM,cAAc,uBAAuB,CAAC;AAEnD,eAAO,MAAM,SAAS,GAAI,SAAS,sBAAsB,qDACnB,CAAC;AAEvC,MAAM,MAAM,oBAAoB,GAAG,sBAAsB,GAAG;IAC1D,OAAO,EAAE,UAAU,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,IAE/C,iBAAiB,sBAAsB,KACtC,IAAI,CAAC,WAAW,CAAC,CA0FrB;AAED,qBACa,aAAa;CAAG;AAE7B,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,oBAAoB,GAC5B,aAAa,CAUf"}
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.LimitlyModule = exports.RateLimit = exports.RATE_LIMIT_KEY = void 0;
13
+ exports.createNestGuard = createNestGuard;
14
+ exports.limitlyNestModule = limitlyNestModule;
15
+ const common_1 = require("@nestjs/common");
16
+ const core_1 = require("@nestjs/core");
17
+ const headers_1 = require("../utils/headers");
18
+ const limit_execution_1 = require("../utils/limit-execution");
19
+ const DEFAULT_KEY = (req) => req.ip ?? "unknown";
20
+ exports.RATE_LIMIT_KEY = "limitly:rate-limit";
21
+ const RateLimit = (options) => (0, common_1.SetMetadata)(exports.RATE_LIMIT_KEY, options);
22
+ exports.RateLimit = RateLimit;
23
+ function createNestGuard(limiter) {
24
+ return function guard(defaultOptions) {
25
+ let NestGuard = class NestGuard {
26
+ constructor(reflector) {
27
+ this.reflector = reflector;
28
+ }
29
+ async canActivate(context) {
30
+ const metadata = this.reflector.getAllAndOverride(exports.RATE_LIMIT_KEY, [context.getHandler(), context.getClass()]);
31
+ const shouldApply = metadata !== undefined ||
32
+ defaultOptions !== undefined ||
33
+ Object.keys(limiter.getDefaultOptions()).length > 0;
34
+ if (!shouldApply) {
35
+ return true;
36
+ }
37
+ const options = limiter.resolveOptions({
38
+ ...defaultOptions,
39
+ ...metadata,
40
+ });
41
+ const strategy = limiter.createStrategy(options);
42
+ const http = context.switchToHttp();
43
+ const request = http.getRequest();
44
+ const response = http.getResponse();
45
+ const keyExtractor = (options.key ?? DEFAULT_KEY);
46
+ const key = keyExtractor(request) ?? "unknown";
47
+ const sendHeaders = options.headers !== false;
48
+ const failOpen = options.failOpen ?? true;
49
+ const outcome = await (0, limit_execution_1.processLimitRequest)({
50
+ limiter,
51
+ strategy,
52
+ key,
53
+ options,
54
+ failOpen,
55
+ context: context,
56
+ });
57
+ if (outcome.status === "error") {
58
+ if (failOpen) {
59
+ return true;
60
+ }
61
+ throw new common_1.ServiceUnavailableException({
62
+ error: "Service Unavailable",
63
+ });
64
+ }
65
+ if (outcome.status === "blocked") {
66
+ if (sendHeaders) {
67
+ (0, headers_1.setHeaders)(response, (0, headers_1.buildRateLimitHeaders)(outcome.result));
68
+ }
69
+ if (options.onLimitReached) {
70
+ await options.onLimitReached(request, response);
71
+ return false;
72
+ }
73
+ throw new common_1.HttpException({ error: "Too Many Requests" }, common_1.HttpStatus.TOO_MANY_REQUESTS);
74
+ }
75
+ if (sendHeaders) {
76
+ (0, headers_1.setHeaders)(response, (0, headers_1.buildRateLimitHeaders)(outcome.result));
77
+ }
78
+ if (outcome.slotId) {
79
+ (0, limit_execution_1.bindConcurrencyRelease)({
80
+ strategy,
81
+ key,
82
+ slotId: outcome.slotId,
83
+ emitter: response,
84
+ });
85
+ }
86
+ return true;
87
+ }
88
+ };
89
+ NestGuard = __decorate([
90
+ (0, common_1.Injectable)(),
91
+ __metadata("design:paramtypes", [core_1.Reflector])
92
+ ], NestGuard);
93
+ return NestGuard;
94
+ };
95
+ }
96
+ let LimitlyModule = class LimitlyModule {
97
+ };
98
+ exports.LimitlyModule = LimitlyModule;
99
+ exports.LimitlyModule = LimitlyModule = __decorate([
100
+ (0, common_1.Module)({})
101
+ ], LimitlyModule);
102
+ function limitlyNestModule(options) {
103
+ const { limiter, global, ...middlewareOptions } = options;
104
+ const Guard = createNestGuard(limiter)(middlewareOptions);
105
+ return {
106
+ module: LimitlyModule,
107
+ providers: [Guard],
108
+ exports: [Guard],
109
+ global: global ?? false,
110
+ };
111
+ }
112
+ //# sourceMappingURL=nest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nest.js","sourceRoot":"","sources":["../../src/middleware/nest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { createOpenTelemetryInstrumentation, createOpenTelemetryMetricsHook, createOpenTelemetryTracer, DEFAULT_METER_NAME, DEFAULT_TRACER_NAME, } from "./opentelemetry";
2
+ export type { OpenTelemetryInstrumentationOptions, OpenTelemetryMetricsOptions, OpenTelemetryTracerOptions, } from "./opentelemetry";
3
+ export type { RateLimitSpan, RateLimitTracer } from "./types";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/observability/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kCAAkC,EAClC,8BAA8B,EAC9B,yBAAyB,EACzB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,mCAAmC,EACnC,2BAA2B,EAC3B,0BAA0B,GAC3B,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_TRACER_NAME = exports.DEFAULT_METER_NAME = exports.createOpenTelemetryTracer = exports.createOpenTelemetryMetricsHook = exports.createOpenTelemetryInstrumentation = void 0;
4
+ var opentelemetry_1 = require("./opentelemetry");
5
+ Object.defineProperty(exports, "createOpenTelemetryInstrumentation", { enumerable: true, get: function () { return opentelemetry_1.createOpenTelemetryInstrumentation; } });
6
+ Object.defineProperty(exports, "createOpenTelemetryMetricsHook", { enumerable: true, get: function () { return opentelemetry_1.createOpenTelemetryMetricsHook; } });
7
+ Object.defineProperty(exports, "createOpenTelemetryTracer", { enumerable: true, get: function () { return opentelemetry_1.createOpenTelemetryTracer; } });
8
+ Object.defineProperty(exports, "DEFAULT_METER_NAME", { enumerable: true, get: function () { return opentelemetry_1.DEFAULT_METER_NAME; } });
9
+ Object.defineProperty(exports, "DEFAULT_TRACER_NAME", { enumerable: true, get: function () { return opentelemetry_1.DEFAULT_TRACER_NAME; } });
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/observability/index.ts"],"names":[],"mappings":";;;AAAA,iDAMyB;AALvB,mIAAA,kCAAkC,OAAA;AAClC,+HAAA,8BAA8B,OAAA;AAC9B,0HAAA,yBAAyB,OAAA;AACzB,mHAAA,kBAAkB,OAAA;AAClB,oHAAA,mBAAmB,OAAA"}
@@ -0,0 +1,28 @@
1
+ import { type Meter, type Tracer } from "@opentelemetry/api";
2
+ import type { RateLimitMetricsHook } from "../types";
3
+ import type { RateLimitTracer } from "./types";
4
+ export declare const DEFAULT_METER_NAME = "limitly";
5
+ export declare const DEFAULT_TRACER_NAME = "limitly";
6
+ export interface OpenTelemetryMetricsOptions {
7
+ /** OpenTelemetry meter. Defaults to `metrics.getMeter("limitly")`. */
8
+ meter?: Meter;
9
+ /** Meter scope name. Defaults to `"limitly"`. */
10
+ meterName?: string;
11
+ /** Include the rate limit key in metric attributes. Defaults to `false`. */
12
+ includeKey?: boolean;
13
+ }
14
+ export interface OpenTelemetryTracerOptions {
15
+ /** OpenTelemetry tracer. Defaults to `trace.getTracer("limitly")`. */
16
+ tracer?: Tracer;
17
+ /** Tracer scope name. Defaults to `"limitly"`. */
18
+ tracerName?: string;
19
+ }
20
+ export interface OpenTelemetryInstrumentationOptions extends OpenTelemetryMetricsOptions, OpenTelemetryTracerOptions {
21
+ }
22
+ export declare function createOpenTelemetryMetricsHook(options?: OpenTelemetryMetricsOptions): RateLimitMetricsHook;
23
+ export declare function createOpenTelemetryTracer(options?: OpenTelemetryTracerOptions): RateLimitTracer;
24
+ export declare function createOpenTelemetryInstrumentation(options?: OpenTelemetryInstrumentationOptions): {
25
+ tracer: RateLimitTracer;
26
+ onMetrics: RateLimitMetricsHook;
27
+ };
28
+ //# sourceMappingURL=opentelemetry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opentelemetry.d.ts","sourceRoot":"","sources":["../../src/observability/opentelemetry.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,KAAK,EACV,KAAK,MAAM,EACZ,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAEV,oBAAoB,EACrB,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,eAAO,MAAM,kBAAkB,YAAY,CAAC;AAC5C,eAAO,MAAM,mBAAmB,YAAY,CAAC;AAE7C,MAAM,WAAW,2BAA2B;IAC1C,sEAAsE;IACtE,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,0BAA0B;IACzC,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mCACf,SAAQ,2BAA2B,EACjC,0BAA0B;CAAG;AAoDjC,wBAAgB,8BAA8B,CAC5C,OAAO,GAAE,2BAAgC,GACxC,oBAAoB,CAWtB;AAED,wBAAgB,yBAAyB,CACvC,OAAO,GAAE,0BAA+B,GACvC,eAAe,CA6BjB;AAED,wBAAgB,kCAAkC,CAChD,OAAO,GAAE,mCAAwC,GAChD;IACD,MAAM,EAAE,eAAe,CAAC;IACxB,SAAS,EAAE,oBAAoB,CAAC;CACjC,CAKA"}