@kanjijs/throttler 0.2.0-beta.11 → 0.2.0-beta.13

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kanjijs/throttler",
3
- "version": "0.2.0-beta.11",
3
+ "version": "0.2.0-beta.13",
4
4
  "type": "module",
5
5
  "main": "./src/index.ts",
6
6
  "dependencies": {
@@ -8,7 +8,7 @@
8
8
  "reflect-metadata": "^0.2.0"
9
9
  },
10
10
  "peerDependencies": {
11
- "@kanjijs/core": "^0.2.0-beta.11"
11
+ "@kanjijs/core": "^0.2.0-beta.13"
12
12
  },
13
13
  "scripts": {
14
14
  "build": "bun build ./src/index.ts --outdir ./dist --target bun"
@@ -10,7 +10,7 @@ export interface ThrottlerOptions {
10
10
  export function Throttle(options: ThrottlerOptions) {
11
11
  return Use(async (c: Context, next: Next) => {
12
12
  // Resolve singleton
13
- const throttler = KanjijsIoC.resolve(ThrottlerService);
13
+ const throttler = KanjijsIoC.resolve(ThrottlerService) as ThrottlerService | undefined;
14
14
 
15
15
  if (throttler) {
16
16
  // Use specific options from decorator
@@ -1,85 +1,25 @@
1
1
  import { Inject, Injectable, GLOBAL_MIDDLEWARE_TOKEN } from "@kanjijs/core";
2
- import { type Context, type Next } from "hono";
3
- import { ThrottlerInMemoryStorage, type ThrottlerStorage } from "./throttler.storage";
4
- import { THROTTLER_LIMIT, THROTTLER_TTL } from "./throttler.decorator";
5
-
6
- export interface ThrottlerModuleOptions {
7
- limit?: number;
8
- ttl?: number;
9
- storage?: ThrottlerStorage;
10
- }
11
-
12
- export const THROTTLER_OPTIONS = "THROTTLER_OPTIONS";
2
+ import { type Context, type Handler, type Next } from "hono";
3
+ import { type ThrottlerModuleOptions, THROTTLER_OPTIONS, ThrottlerService } from "./throttler.service";
13
4
 
14
5
  @Injectable()
15
6
  export class ThrottlerGuard {
16
- private storage: ThrottlerStorage;
17
- private defaultLimit: number;
18
- private defaultTtl: number;
19
-
20
- constructor(@Inject(THROTTLER_OPTIONS) private options: ThrottlerModuleOptions) {
21
- this.storage = options.storage || new ThrottlerInMemoryStorage();
22
- this.defaultLimit = options.limit || 10;
23
- this.defaultTtl = options.ttl || 60;
24
- }
7
+ constructor(
8
+ @Inject(ThrottlerService) private throttler: ThrottlerService
9
+ ) {}
25
10
 
26
11
  // This will be registered as a Global Middleware in KanjijsAdapter if provided
27
12
  async handle(c: Context, next: Next) {
28
- // 1. Identify Client (IP)
29
- // Hono "conn" info or header
30
- /*
31
- NOTE: In Bun/Hono, getting IP can be platform specific.
32
- We will trust X-Forwarded-For or use a fallback.
33
- */
34
- const ip = c.req.header("x-forwarded-for") || "unknown";
35
- const key = `throttler:${ip}:${c.req.path}`; // Limit by IP + Path (or just IP?) -> Usually just IP for global
36
-
37
- // 2. Resolve Metadata (Limit/TTL)
38
- // KanjijsAdapter doesn't expose the "Current Handler" to global middleware easily yet in the context.
39
- // LIMITATION: Global Middleware runs BEFORE routing in Hono standard app.use('*').
40
- // To support @Throttle decorators, we need to run THIS check inside the route handler wrapper OR
41
- // we need to access the route handler metadata here.
42
-
43
- // CURRENT STRATEGY:
44
- // Global Config applies to ALL routes globally (Middleware style).
45
- // @Throttle decorator support requires Per-Route logic.
46
- // Since KanjijsAdapter registers routes, we should probably implement this as a specific middleware wrapper there,
47
- // OR we rely on Hono context to pass handler info? No standard way.
48
-
49
- // REVISED PLAN:
50
- // We will implement `ThrottlerGuard` but we cannot easily use it as a simple `app.use('*')`
51
- // IF we want to support @Throttle decorators overriding it properly *per route* efficiently without finding the route match twice.
52
-
53
- // HOWEVER, for MVP:
54
- // 1. Global Throttling: Runs on `*`, uses default limit.
55
- // 2. Decorator Throttling: The adapter needs to know about it.
56
-
57
- // BUT the user asked for: "rate limit haz que tambien se pueda configurar desde main y no solo usando el decorador"
58
-
59
- // Let's stick to the plan:
60
- // If we use Global Middleware, we enforce global limit.
61
- // If we want specific limits, we need `KanjijsAdapter` to help us OR we attach `ThrottlerGuard` to the route in the Adapter.
62
-
63
- // DECISION:
64
- // This `handle` method will apply the DEFAULT global limit if installed globally.
65
- // For Decorator support, `KanjijsAdapter` needs to look for `@Throttle` metadata and add THIS middleware (configured differently) to that route.
66
-
67
- const limit = this.defaultLimit;
68
- const ttl = this.defaultTtl;
13
+ // Override global options? For now, simply use global defaults.
14
+ const { limit, ttl } = this.throttler.getGlobalOptions();
69
15
 
70
- const { total, timeToExpire } = await this.storage.increment(key, ttl);
16
+ const allowed = await this.throttler.handleRequest(c, limit, ttl);
71
17
 
72
- if (total > limit) {
73
- return c.text(`Too Many Requests`, 429, {
74
- "Retry-After": timeToExpire.toString()
75
- });
18
+ if (!allowed) {
19
+ // Response is already handled by service (429)
20
+ return;
76
21
  }
77
22
 
78
- // Headers
79
- c.header("X-RateLimit-Limit", limit.toString());
80
- c.header("X-RateLimit-Remaining", Math.max(0, limit - total).toString());
81
- c.header("X-RateLimit-Reset", timeToExpire.toString());
82
-
83
23
  await next();
84
24
  }
85
25
  }
@@ -17,7 +17,7 @@ export class ThrottlerModule {
17
17
  provide: GLOBAL_MIDDLEWARE_TOKEN,
18
18
  useValue: async (c: Context, next: Next) => {
19
19
  // console.log("Throttler Middleware Executing via Global Token");
20
- const throttler = KanjijsIoC.resolve(ThrottlerService);
20
+ const throttler = KanjijsIoC.resolve(ThrottlerService) as ThrottlerService | undefined;
21
21
  if (throttler) {
22
22
  const { limit, ttl } = throttler.getGlobalOptions();
23
23
  const allowed = await throttler.handleRequest(c, limit, ttl);
package/tsconfig.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "declaration": true,
6
+ "emitDeclarationOnly": true,
7
+ "noEmit": false
8
+ },
9
+ "include": ["src/**/*"]
10
+ }