@joint-ops/hitlimit 1.0.6 → 1.1.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.
package/README.md CHANGED
@@ -17,7 +17,7 @@
17
17
  - **Blazing Fast** - 2,450,000+ ops/sec with memory store (multi-IP scenarios), ~7% HTTP overhead
18
18
  - **Zero Config** - Works out of the box with sensible defaults
19
19
  - **Tiny Footprint** - Only ~7KB core, zero runtime dependencies
20
- - **Framework Agnostic** - Express, NestJS, Fastify, native HTTP
20
+ - **Framework Agnostic** - Express, Fastify, Hono, NestJS, native HTTP
21
21
  - **Multiple Stores** - Memory, Redis, SQLite for distributed systems
22
22
  - **TypeScript First** - Full type safety and IntelliSense support
23
23
  - **Flexible Keys** - Rate limit by IP, user ID, API key, or custom logic
@@ -124,6 +124,24 @@ app.get('/api', () => ({ status: 'ok' }))
124
124
  await app.listen({ port: 3000 })
125
125
  ```
126
126
 
127
+ ### Hono Rate Limiting
128
+
129
+ ```typescript
130
+ import { Hono } from 'hono'
131
+ import { serve } from '@hono/node-server'
132
+ import { hitlimit } from '@joint-ops/hitlimit/hono'
133
+
134
+ const app = new Hono()
135
+
136
+ app.use(hitlimit({
137
+ limit: 100,
138
+ window: '1m'
139
+ }))
140
+
141
+ app.get('/api', (c) => c.json({ status: 'ok' }))
142
+ serve({ fetch: app.fetch, port: 3000 })
143
+ ```
144
+
127
145
  ### NestJS Rate Limiting
128
146
 
129
147
  ```typescript
package/dist/hono.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import type { Context } from 'hono';
2
+ import type { HitLimitOptions } from '@joint-ops/hitlimit-types';
3
+ export declare function hitlimit(options?: HitLimitOptions<Context>): import("hono").MiddlewareHandler<any, string, {}, Response | (Response & import("hono").TypedResponse<{
4
+ [x: string]: any;
5
+ }, 429, "json">)>;
6
+ //# sourceMappingURL=hono.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hono.d.ts","sourceRoot":"","sources":["../src/hono.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AACnC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAahE,wBAAgB,QAAQ,CAAC,OAAO,GAAE,eAAe,CAAC,OAAO,CAAM;;kBAmC9D"}
package/dist/hono.js ADDED
@@ -0,0 +1,44 @@
1
+ import { createMiddleware } from 'hono/factory';
2
+ import { resolveConfig } from './core/config.js';
3
+ import { checkLimit } from './core/limiter.js';
4
+ import { memoryStore } from './stores/memory.js';
5
+ function getDefaultKey(c) {
6
+ // Hono doesn't expose raw IP — it's runtime-dependent
7
+ // Use standard proxy headers as fallback
8
+ return c.req.header('x-forwarded-for')?.split(',')[0]?.trim()
9
+ || c.req.header('x-real-ip')
10
+ || 'unknown';
11
+ }
12
+ export function hitlimit(options = {}) {
13
+ const store = options.store ?? memoryStore();
14
+ const config = resolveConfig(options, store, getDefaultKey);
15
+ return createMiddleware(async (c, next) => {
16
+ // Skip check
17
+ if (config.skip) {
18
+ const shouldSkip = await config.skip(c);
19
+ if (shouldSkip) {
20
+ await next();
21
+ return;
22
+ }
23
+ }
24
+ try {
25
+ const result = await checkLimit(config, c);
26
+ // Set all rate limit headers
27
+ for (const [key, value] of Object.entries(result.headers)) {
28
+ c.header(key, value);
29
+ }
30
+ // Block if not allowed
31
+ if (!result.allowed) {
32
+ return c.json(result.body, 429);
33
+ }
34
+ }
35
+ catch (error) {
36
+ const action = await config.onStoreError(error, c);
37
+ if (action === 'deny') {
38
+ return c.json({ hitlimit: true, message: 'Rate limit error' }, 429);
39
+ }
40
+ }
41
+ await next();
42
+ });
43
+ }
44
+ //# sourceMappingURL=hono.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hono.js","sourceRoot":"","sources":["../src/hono.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAG/C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAEhD,SAAS,aAAa,CAAC,CAAU;IAC/B,sDAAsD;IACtD,yCAAyC;IACzC,OAAO,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE;WACxD,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC;WACzB,SAAS,CAAA;AAChB,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,UAAoC,EAAE;IAC7D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,WAAW,EAAE,CAAA;IAC5C,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,EAAE,KAAK,EAAE,aAAa,CAAC,CAAA;IAE3D,OAAO,gBAAgB,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QACxC,aAAa;QACb,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YAChB,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACvC,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,IAAI,EAAE,CAAA;gBACZ,OAAM;YACR,CAAC;QACH,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;YAE1C,6BAA6B;YAC7B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC1D,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;YACtB,CAAC;YAED,uBAAuB;YACvB,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpB,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;YACjC,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,KAAc,EAAE,CAAC,CAAC,CAAA;YAC3D,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;gBACtB,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,kBAAkB,EAAE,EAAE,GAAG,CAAC,CAAA;YACrE,CAAC;QACH,CAAC;QAED,MAAM,IAAI,EAAE,CAAA;IACd,CAAC,CAAC,CAAA;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@joint-ops/hitlimit",
3
- "version": "1.0.6",
3
+ "version": "1.1.0",
4
4
  "description": "Fast rate limiting middleware for Express, Fastify, NestJS & Node.js - API throttling, brute force protection, request limiting",
5
5
  "author": {
6
6
  "name": "Shayan M Hussain",
@@ -93,6 +93,10 @@
93
93
  "types": "./dist/fastify.d.ts",
94
94
  "import": "./dist/fastify.js"
95
95
  },
96
+ "./hono": {
97
+ "types": "./dist/hono.d.ts",
98
+ "import": "./dist/hono.js"
99
+ },
96
100
  "./stores/memory": {
97
101
  "types": "./dist/stores/memory.d.ts",
98
102
  "import": "./dist/stores/memory.js"
@@ -129,14 +133,15 @@
129
133
  "test:watch": "vitest"
130
134
  },
131
135
  "dependencies": {
132
- "@joint-ops/hitlimit-types": "1.0.6"
136
+ "@joint-ops/hitlimit-types": "1.1.0"
133
137
  },
134
138
  "peerDependencies": {
135
139
  "@nestjs/common": ">=8.0.0",
136
140
  "@nestjs/core": ">=8.0.0",
141
+ "better-sqlite3": ">=9.0.0",
137
142
  "fastify": ">=4.0.0",
138
143
  "fastify-plugin": ">=4.0.0",
139
- "better-sqlite3": ">=9.0.0",
144
+ "hono": ">=4.0.0",
140
145
  "ioredis": ">=5.0.0",
141
146
  "pino": ">=8.0.0",
142
147
  "winston": ">=3.0.0"
@@ -154,6 +159,9 @@
154
159
  "fastify-plugin": {
155
160
  "optional": true
156
161
  },
162
+ "hono": {
163
+ "optional": true
164
+ },
157
165
  "better-sqlite3": {
158
166
  "optional": true
159
167
  },
@@ -168,6 +176,7 @@
168
176
  }
169
177
  },
170
178
  "devDependencies": {
179
+ "@hono/node-server": "^1.19.9",
171
180
  "@nestjs/common": "^10.0.0",
172
181
  "@nestjs/core": "^10.0.0",
173
182
  "@nestjs/platform-express": "^10.0.0",
@@ -180,6 +189,7 @@
180
189
  "express": "^4.18.0",
181
190
  "fastify": "^5.7.4",
182
191
  "fastify-plugin": "^5.1.0",
192
+ "hono": "^4.11.9",
183
193
  "ioredis": "^5.3.0",
184
194
  "pino": "^10.3.0",
185
195
  "reflect-metadata": "^0.2.0",