ai.matey.http.core 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cjs/auth.js +173 -0
  3. package/dist/cjs/auth.js.map +1 -0
  4. package/dist/cjs/cors.js +140 -0
  5. package/dist/cjs/cors.js.map +1 -0
  6. package/dist/cjs/error-handler.js +147 -0
  7. package/dist/cjs/error-handler.js.map +1 -0
  8. package/dist/cjs/handler.js +335 -0
  9. package/dist/cjs/handler.js.map +1 -0
  10. package/dist/cjs/health.js +218 -0
  11. package/dist/cjs/health.js.map +1 -0
  12. package/dist/cjs/index.js +83 -0
  13. package/dist/cjs/index.js.map +1 -0
  14. package/dist/cjs/rate-limiter.js +163 -0
  15. package/dist/cjs/rate-limiter.js.map +1 -0
  16. package/dist/cjs/request-parser.js +141 -0
  17. package/dist/cjs/request-parser.js.map +1 -0
  18. package/dist/cjs/response-formatter.js +218 -0
  19. package/dist/cjs/response-formatter.js.map +1 -0
  20. package/dist/cjs/route-matcher.js +178 -0
  21. package/dist/cjs/route-matcher.js.map +1 -0
  22. package/dist/cjs/streaming-handler.js +120 -0
  23. package/dist/cjs/streaming-handler.js.map +1 -0
  24. package/dist/cjs/types.js +11 -0
  25. package/dist/cjs/types.js.map +1 -0
  26. package/dist/esm/auth.js +163 -0
  27. package/dist/esm/auth.js.map +1 -0
  28. package/dist/esm/cors.js +134 -0
  29. package/dist/esm/cors.js.map +1 -0
  30. package/dist/esm/error-handler.js +137 -0
  31. package/dist/esm/error-handler.js.map +1 -0
  32. package/dist/esm/handler.js +331 -0
  33. package/dist/esm/handler.js.map +1 -0
  34. package/dist/esm/health.js +210 -0
  35. package/dist/esm/health.js.map +1 -0
  36. package/dist/esm/index.js +30 -0
  37. package/dist/esm/index.js.map +1 -0
  38. package/dist/esm/rate-limiter.js +156 -0
  39. package/dist/esm/rate-limiter.js.map +1 -0
  40. package/dist/esm/request-parser.js +136 -0
  41. package/dist/esm/request-parser.js.map +1 -0
  42. package/dist/esm/response-formatter.js +206 -0
  43. package/dist/esm/response-formatter.js.map +1 -0
  44. package/dist/esm/route-matcher.js +171 -0
  45. package/dist/esm/route-matcher.js.map +1 -0
  46. package/dist/esm/streaming-handler.js +112 -0
  47. package/dist/esm/streaming-handler.js.map +1 -0
  48. package/dist/esm/types.js +10 -0
  49. package/dist/esm/types.js.map +1 -0
  50. package/dist/types/auth.d.ts +37 -0
  51. package/dist/types/auth.d.ts.map +1 -0
  52. package/dist/types/cors.d.ts +26 -0
  53. package/dist/types/cors.d.ts.map +1 -0
  54. package/dist/types/error-handler.d.ts +38 -0
  55. package/dist/types/error-handler.d.ts.map +1 -0
  56. package/dist/types/handler.d.ts +45 -0
  57. package/dist/types/handler.d.ts.map +1 -0
  58. package/dist/types/health.d.ts +164 -0
  59. package/dist/types/health.d.ts.map +1 -0
  60. package/dist/types/index.d.ts +21 -0
  61. package/dist/types/index.d.ts.map +1 -0
  62. package/dist/types/rate-limiter.d.ts +56 -0
  63. package/dist/types/rate-limiter.d.ts.map +1 -0
  64. package/dist/types/request-parser.d.ts +22 -0
  65. package/dist/types/request-parser.d.ts.map +1 -0
  66. package/dist/types/response-formatter.d.ts +49 -0
  67. package/dist/types/response-formatter.d.ts.map +1 -0
  68. package/dist/types/route-matcher.d.ts +45 -0
  69. package/dist/types/route-matcher.d.ts.map +1 -0
  70. package/dist/types/streaming-handler.d.ts +40 -0
  71. package/dist/types/streaming-handler.d.ts.map +1 -0
  72. package/dist/types/types.d.ts +398 -0
  73. package/dist/types/types.d.ts.map +1 -0
  74. package/package.json +73 -0
  75. package/readme.md +60 -0
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Health Check Utilities
3
+ *
4
+ * Health check endpoint for monitoring and load balancers.
5
+ *
6
+ * @module
7
+ */
8
+ /**
9
+ * Health check handler
10
+ */
11
+ export class HealthCheck {
12
+ config;
13
+ customChecks;
14
+ metadata;
15
+ startTime;
16
+ router;
17
+ constructor(bridgeOrRouter, config = {}) {
18
+ this.config = {
19
+ serviceName: 'ai.matey',
20
+ version: '1.0.0',
21
+ includeUptime: true,
22
+ includeChecks: true,
23
+ checkBackends: true,
24
+ ...config,
25
+ };
26
+ this.customChecks = config.customChecks || {};
27
+ this.metadata = config.metadata || {};
28
+ this.startTime = Date.now();
29
+ // Detect if bridge or router
30
+ if ('getBackends' in bridgeOrRouter) {
31
+ this.router = bridgeOrRouter;
32
+ }
33
+ // Bridge support can be added in the future
34
+ }
35
+ /**
36
+ * Perform health check
37
+ */
38
+ async check() {
39
+ const checks = {};
40
+ // Basic system check
41
+ if (this.config.includeChecks) {
42
+ checks.system = {
43
+ status: 'healthy',
44
+ message: 'System operational',
45
+ };
46
+ // Check backend health (router only)
47
+ if (this.router && this.config.checkBackends) {
48
+ try {
49
+ // For now, assume healthy if router exists
50
+ // In the future, we can add a getBackends() method to Router
51
+ checks.backends = {
52
+ status: 'healthy',
53
+ message: 'Router operational',
54
+ };
55
+ }
56
+ catch (error) {
57
+ checks.backends = {
58
+ status: 'unhealthy',
59
+ message: 'Unable to check backends',
60
+ details: { error: error.message },
61
+ };
62
+ }
63
+ }
64
+ // Run custom checks
65
+ for (const [name, checkFn] of Object.entries(this.customChecks)) {
66
+ try {
67
+ checks[name] = await checkFn();
68
+ }
69
+ catch (error) {
70
+ checks[name] = {
71
+ status: 'unhealthy',
72
+ message: `Check failed: ${error.message}`,
73
+ };
74
+ }
75
+ }
76
+ }
77
+ // Determine overall status
78
+ const statuses = Object.values(checks).map((c) => c.status);
79
+ let overallStatus = 'healthy';
80
+ if (statuses.includes('unhealthy')) {
81
+ overallStatus = 'unhealthy';
82
+ }
83
+ else if (statuses.includes('degraded')) {
84
+ overallStatus = 'degraded';
85
+ }
86
+ const result = {
87
+ status: overallStatus,
88
+ timestamp: new Date().toISOString(),
89
+ service: this.config.serviceName,
90
+ version: this.config.version,
91
+ };
92
+ if (this.config.includeUptime) {
93
+ result.uptime = Date.now() - this.startTime;
94
+ }
95
+ if (this.config.includeChecks && Object.keys(checks).length > 0) {
96
+ result.checks = checks;
97
+ }
98
+ if (Object.keys(this.metadata).length > 0) {
99
+ result.metadata = this.metadata;
100
+ }
101
+ return result;
102
+ }
103
+ /**
104
+ * Handle health check request
105
+ */
106
+ async handle(_req, res) {
107
+ const result = await this.check();
108
+ // Set status code based on health
109
+ const statusCode = result.status === 'healthy' ? 200 : result.status === 'degraded' ? 200 : 503;
110
+ res.status(statusCode);
111
+ res.header('Content-Type', 'application/json');
112
+ res.header('Cache-Control', 'no-cache, no-store, must-revalidate');
113
+ res.send(result);
114
+ }
115
+ }
116
+ /**
117
+ * Create health check handler
118
+ *
119
+ * @param bridgeOrRouter - Bridge or Router instance
120
+ * @param config - Health check configuration
121
+ * @returns Health check handler
122
+ *
123
+ * @example
124
+ * ```typescript
125
+ * import { createHealthCheck } from 'ai.matey.http';
126
+ *
127
+ * const healthCheck = createHealthCheck(bridge, {
128
+ * serviceName: 'my-ai-service',
129
+ * version: '1.0.0',
130
+ * });
131
+ *
132
+ * // In your HTTP server:
133
+ * if (req.url === '/health') {
134
+ * await healthCheck.handle(req, res);
135
+ * }
136
+ * ```
137
+ */
138
+ export function createHealthCheck(bridgeOrRouter, config) {
139
+ return new HealthCheck(bridgeOrRouter, config);
140
+ }
141
+ /**
142
+ * Create simple health check middleware
143
+ *
144
+ * @param bridgeOrRouter - Bridge or Router instance
145
+ * @param path - Health check path (default: '/health')
146
+ * @param config - Health check configuration
147
+ * @returns Middleware function
148
+ *
149
+ * @example
150
+ * ```typescript
151
+ * import { createHealthCheckMiddleware } from 'ai.matey.http';
152
+ *
153
+ * const healthMiddleware = createHealthCheckMiddleware(bridge);
154
+ *
155
+ * // Use in HTTP server
156
+ * app.use(healthMiddleware);
157
+ * ```
158
+ */
159
+ export function createHealthCheckMiddleware(bridgeOrRouter, path = '/health', config) {
160
+ const healthCheck = new HealthCheck(bridgeOrRouter, config);
161
+ return async (req, res) => {
162
+ if (req.url === path || req.url?.startsWith(`${path}?`)) {
163
+ await healthCheck.handle(req, res);
164
+ return true; // Handled
165
+ }
166
+ return false; // Not handled
167
+ };
168
+ }
169
+ /**
170
+ * Readiness check (for Kubernetes)
171
+ *
172
+ * Returns 200 when service is ready to accept traffic.
173
+ */
174
+ export function createReadinessCheck(bridgeOrRouter) {
175
+ const healthCheck = new HealthCheck(bridgeOrRouter, {
176
+ includeUptime: false,
177
+ includeChecks: true,
178
+ checkBackends: true,
179
+ });
180
+ return async (_req, res) => {
181
+ const result = await healthCheck.check();
182
+ // Only ready if all checks are healthy
183
+ const isReady = result.status === 'healthy';
184
+ res.status(isReady ? 200 : 503);
185
+ res.header('Content-Type', 'application/json');
186
+ res.send({
187
+ ready: isReady,
188
+ timestamp: result.timestamp,
189
+ checks: result.checks,
190
+ });
191
+ };
192
+ }
193
+ /**
194
+ * Liveness check (for Kubernetes)
195
+ *
196
+ * Returns 200 if service is alive (even if degraded).
197
+ */
198
+ export function createLivenessCheck() {
199
+ const startTime = Date.now();
200
+ return (_req, res) => {
201
+ res.status(200);
202
+ res.header('Content-Type', 'application/json');
203
+ res.send({
204
+ alive: true,
205
+ timestamp: new Date().toISOString(),
206
+ uptime: Date.now() - startTime,
207
+ });
208
+ };
209
+ }
210
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/health.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAqGH;;GAEG;AACH,MAAM,OAAO,WAAW;IACd,MAAM,CAAiE;IACvE,YAAY,CAAiD;IAC7D,QAAQ,CAA0B;IAClC,SAAS,CAAS;IAClB,MAAM,CAAU;IAExB,YAAY,cAA+B,EAAE,SAA4B,EAAE;QACzE,IAAI,CAAC,MAAM,GAAG;YACZ,WAAW,EAAE,UAAU;YACvB,OAAO,EAAE,OAAO;YAChB,aAAa,EAAE,IAAI;YACnB,aAAa,EAAE,IAAI;YACnB,aAAa,EAAE,IAAI;YACnB,GAAG,MAAM;SACV,CAAC;QAEF,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,EAAE,CAAC;QAC9C,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;QACtC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE5B,6BAA6B;QAC7B,IAAI,aAAa,IAAI,cAAc,EAAE,CAAC;YACpC,IAAI,CAAC,MAAM,GAAG,cAAwB,CAAC;QACzC,CAAC;QACD,4CAA4C;IAC9C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAK;QACT,MAAM,MAAM,GAAoC,EAAE,CAAC;QAEnD,qBAAqB;QACrB,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;YAC9B,MAAM,CAAC,MAAM,GAAG;gBACd,MAAM,EAAE,SAAS;gBACjB,OAAO,EAAE,oBAAoB;aAC9B,CAAC;YAEF,qCAAqC;YACrC,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;gBAC7C,IAAI,CAAC;oBACH,2CAA2C;oBAC3C,6DAA6D;oBAC7D,MAAM,CAAC,QAAQ,GAAG;wBAChB,MAAM,EAAE,SAAS;wBACjB,OAAO,EAAE,oBAAoB;qBAC9B,CAAC;gBACJ,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,MAAM,CAAC,QAAQ,GAAG;wBAChB,MAAM,EAAE,WAAW;wBACnB,OAAO,EAAE,0BAA0B;wBACnC,OAAO,EAAE,EAAE,KAAK,EAAG,KAAe,CAAC,OAAO,EAAE;qBAC7C,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,oBAAoB;YACpB,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;gBAChE,IAAI,CAAC;oBACH,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,OAAO,EAAE,CAAC;gBACjC,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,MAAM,CAAC,IAAI,CAAC,GAAG;wBACb,MAAM,EAAE,WAAW;wBACnB,OAAO,EAAE,iBAAkB,KAAe,CAAC,OAAO,EAAE;qBACrD,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,2BAA2B;QAC3B,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QAC5D,IAAI,aAAa,GAAiB,SAAS,CAAC;QAE5C,IAAI,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YACnC,aAAa,GAAG,WAAW,CAAC;QAC9B,CAAC;aAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YACzC,aAAa,GAAG,UAAU,CAAC;QAC7B,CAAC;QAED,MAAM,MAAM,GAAsB;YAChC,MAAM,EAAE,aAAa;YACrB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW;YAChC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO;SAC7B,CAAC;QAEF,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;YAC9B,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC;QAC9C,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChE,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;QACzB,CAAC;QAED,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1C,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAClC,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAM,CAAC,IAAoB,EAAE,GAAoB;QACrD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QAElC,kCAAkC;QAClC,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QAEhG,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACvB,GAAG,CAAC,MAAM,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;QAC/C,GAAG,CAAC,MAAM,CAAC,eAAe,EAAE,qCAAqC,CAAC,CAAC;QACnE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACnB,CAAC;CACF;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,iBAAiB,CAC/B,cAA+B,EAC/B,MAA0B;IAE1B,OAAO,IAAI,WAAW,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;AACjD,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,2BAA2B,CACzC,cAA+B,EAC/B,OAAe,SAAS,EACxB,MAA0B;IAE1B,MAAM,WAAW,GAAG,IAAI,WAAW,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IAE5D,OAAO,KAAK,EAAE,GAAmB,EAAE,GAAoB,EAAoB,EAAE;QAC3E,IAAI,GAAG,CAAC,GAAG,KAAK,IAAI,IAAI,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC;YACxD,MAAM,WAAW,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACnC,OAAO,IAAI,CAAC,CAAC,UAAU;QACzB,CAAC;QACD,OAAO,KAAK,CAAC,CAAC,cAAc;IAC9B,CAAC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,cAA+B;IAE/B,MAAM,WAAW,GAAG,IAAI,WAAW,CAAC,cAAc,EAAE;QAClD,aAAa,EAAE,KAAK;QACpB,aAAa,EAAE,IAAI;QACnB,aAAa,EAAE,IAAI;KACpB,CAAC,CAAC;IAEH,OAAO,KAAK,EAAE,IAAoB,EAAE,GAAoB,EAAiB,EAAE;QACzE,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,CAAC;QAEzC,uCAAuC;QACvC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC;QAE5C,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAChC,GAAG,CAAC,MAAM,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;QAC/C,GAAG,CAAC,IAAI,CAAC;YACP,KAAK,EAAE,OAAO;YACd,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,MAAM,EAAE,MAAM,CAAC,MAAM;SACtB,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB;IACjC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,OAAO,CAAC,IAAoB,EAAE,GAAoB,EAAQ,EAAE;QAC1D,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAChB,GAAG,CAAC,MAAM,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;QAC/C,GAAG,CAAC,IAAI,CAAC;YACP,KAAK,EAAE,IAAI;YACX,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;SAC/B,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * HTTP Core Module
3
+ *
4
+ * Framework-agnostic HTTP utilities for the Universal AI Adapter System.
5
+ * This package provides the core logic for HTTP request handling that can
6
+ * be adapted to any HTTP framework.
7
+ *
8
+ * @module
9
+ */
10
+ // Core handler
11
+ export { CoreHTTPHandler } from './handler.js';
12
+ // Request parsing
13
+ export { parseRequest, extractBearerToken, getClientIP } from './request-parser.js';
14
+ // Response formatting
15
+ export { sendJSON, sendError, sendSSEHeaders, sendSSEChunk, sendSSEEvent, sendSSEDone, sendSSEError, sendText, sendNoContent, detectProviderFormat, } from './response-formatter.js';
16
+ // CORS
17
+ export { normalizeCORSOptions, handleCORS, handlePreflight, isPreflight } from './cors.js';
18
+ // Authentication
19
+ export { defaultAuthValidator, createBearerTokenValidator, createAPIKeyValidator, createBasicAuthValidator, combineAuthValidators, requireAllAuth, skipAuthForPaths, } from './auth.js';
20
+ // Rate limiting
21
+ export { RateLimiter, userIDKeyGenerator, tokenKeyGenerator, combineKeyGenerators, } from './rate-limiter.js';
22
+ // Error handling
23
+ export { defaultErrorHandler, createLoggingErrorHandler, createReportingErrorHandler, wrapErrorHandler, isRetryableError, isClientError, isServerError, } from './error-handler.js';
24
+ // Streaming
25
+ export { handleStreamingRequest, SSEKeepAlive, onClientDisconnect, supportsStreaming, createAbortController, } from './streaming-handler.js';
26
+ // Routing
27
+ export { RouteMatcher, createDefaultRoutes, normalizePath, applyPathPrefix, } from './route-matcher.js';
28
+ // Health checks
29
+ export { HealthCheck, createHealthCheck, createHealthCheckMiddleware, createReadinessCheck, createLivenessCheck, } from './health.js';
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAe;AACf,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AA2B/C,kBAAkB;AAClB,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEpF,sBAAsB;AACtB,OAAO,EACL,QAAQ,EACR,SAAS,EACT,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,oBAAoB,GACrB,MAAM,yBAAyB,CAAC;AAEjC,OAAO;AACP,OAAO,EAAE,oBAAoB,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE3F,iBAAiB;AACjB,OAAO,EACL,oBAAoB,EACpB,0BAA0B,EAC1B,qBAAqB,EACrB,wBAAwB,EACxB,qBAAqB,EACrB,cAAc,EACd,gBAAgB,GACjB,MAAM,WAAW,CAAC;AAEnB,gBAAgB;AAChB,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAE3B,iBAAiB;AACjB,OAAO,EACL,mBAAmB,EACnB,yBAAyB,EACzB,2BAA2B,EAC3B,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,aAAa,GACd,MAAM,oBAAoB,CAAC;AAE5B,YAAY;AACZ,OAAO,EACL,sBAAsB,EACtB,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAEhC,UAAU;AACV,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,aAAa,EACb,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAE5B,gBAAgB;AAChB,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,2BAA2B,EAC3B,oBAAoB,EACpB,mBAAmB,GAKpB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Rate Limiter
3
+ *
4
+ * Implements rate limiting for HTTP requests using a sliding window algorithm.
5
+ *
6
+ * @module
7
+ */
8
+ import { getClientIP } from './request-parser.js';
9
+ import { sendJSON } from './response-formatter.js';
10
+ /**
11
+ * Rate limiter class
12
+ */
13
+ export class RateLimiter {
14
+ options;
15
+ store;
16
+ cleanupIntervalId;
17
+ constructor(options) {
18
+ this.options = {
19
+ max: options.max,
20
+ windowMs: options.windowMs ?? 60000, // 1 minute default
21
+ keyGenerator: options.keyGenerator ?? defaultKeyGenerator,
22
+ handler: options.handler ?? defaultRateLimitHandler,
23
+ skip: options.skip ?? (() => false),
24
+ headers: options.headers ?? true,
25
+ };
26
+ this.store = new Map();
27
+ // Cleanup old entries periodically
28
+ this.cleanupIntervalId = setInterval(() => this.cleanup(), this.options.windowMs);
29
+ }
30
+ /**
31
+ * Dispose of the rate limiter and clean up resources.
32
+ * Call this when the rate limiter is no longer needed to prevent memory leaks.
33
+ */
34
+ dispose() {
35
+ if (this.cleanupIntervalId) {
36
+ clearInterval(this.cleanupIntervalId);
37
+ this.cleanupIntervalId = undefined;
38
+ }
39
+ this.store.clear();
40
+ }
41
+ /**
42
+ * Check if request should be rate limited
43
+ */
44
+ async check(req, res) {
45
+ // Check if rate limiting should be skipped
46
+ if (await this.options.skip(req)) {
47
+ return false;
48
+ }
49
+ const key = this.options.keyGenerator(req);
50
+ const now = Date.now();
51
+ // Get or create state for this key
52
+ let state = this.store.get(key);
53
+ if (!state || now >= state.resetTime) {
54
+ // Create new window
55
+ state = {
56
+ count: 0,
57
+ resetTime: now + this.options.windowMs,
58
+ };
59
+ this.store.set(key, state);
60
+ }
61
+ // Increment request count
62
+ state.count++;
63
+ // Add rate limit headers
64
+ if (this.options.headers) {
65
+ res.setHeader('X-RateLimit-Limit', String(this.options.max));
66
+ res.setHeader('X-RateLimit-Remaining', String(Math.max(0, this.options.max - state.count)));
67
+ res.setHeader('X-RateLimit-Reset', String(Math.ceil(state.resetTime / 1000)));
68
+ }
69
+ // Check if limit exceeded
70
+ if (state.count > this.options.max) {
71
+ const retryAfter = Math.ceil((state.resetTime - now) / 1000);
72
+ if (this.options.headers) {
73
+ res.setHeader('Retry-After', String(retryAfter));
74
+ }
75
+ // Call custom handler
76
+ await this.options.handler(req, res, retryAfter);
77
+ return true; // Rate limited
78
+ }
79
+ return false; // Not rate limited
80
+ }
81
+ /**
82
+ * Clean up expired entries
83
+ */
84
+ cleanup() {
85
+ const now = Date.now();
86
+ for (const [key, state] of this.store.entries()) {
87
+ if (now >= state.resetTime) {
88
+ this.store.delete(key);
89
+ }
90
+ }
91
+ }
92
+ /**
93
+ * Reset rate limit for a specific key
94
+ */
95
+ reset(key) {
96
+ this.store.delete(key);
97
+ }
98
+ /**
99
+ * Reset all rate limits
100
+ */
101
+ resetAll() {
102
+ this.store.clear();
103
+ }
104
+ /**
105
+ * Get current state for a key
106
+ */
107
+ getState(key) {
108
+ return this.store.get(key);
109
+ }
110
+ }
111
+ /**
112
+ * Default key generator (uses IP address)
113
+ */
114
+ function defaultKeyGenerator(req) {
115
+ return getClientIP(req);
116
+ }
117
+ /**
118
+ * Default rate limit handler
119
+ */
120
+ function defaultRateLimitHandler(_req, res, retryAfter) {
121
+ sendJSON(res, {
122
+ error: {
123
+ message: 'Too many requests, please try again later.',
124
+ type: 'rate_limit_exceeded',
125
+ retryAfter,
126
+ },
127
+ }, 429);
128
+ }
129
+ /**
130
+ * Create key generator from user ID in request body
131
+ */
132
+ export function userIDKeyGenerator(req) {
133
+ // This would need to be called after body parsing
134
+ // For now, fall back to IP
135
+ return getClientIP(req);
136
+ }
137
+ /**
138
+ * Create key generator from authorization token
139
+ */
140
+ export function tokenKeyGenerator(req) {
141
+ const auth = req.headers.authorization;
142
+ if (auth) {
143
+ return auth;
144
+ }
145
+ return getClientIP(req);
146
+ }
147
+ /**
148
+ * Create key generator that combines multiple factors
149
+ */
150
+ export function combineKeyGenerators(...generators) {
151
+ return (req) => {
152
+ const parts = generators.map((gen) => gen(req));
153
+ return parts.join(':');
154
+ };
155
+ }
156
+ //# sourceMappingURL=rate-limiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/rate-limiter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * HTTP Request Parser
3
+ *
4
+ * Parses incoming HTTP requests into a standardized format for processing.
5
+ *
6
+ * @module
7
+ */
8
+ /**
9
+ * Parse incoming HTTP request
10
+ */
11
+ export async function parseRequest(req, maxBodySize = 10 * 1024 * 1024 // 10MB default
12
+ ) {
13
+ // Parse URL
14
+ const url = new URL(req.url || '/', `http://${req.headers.host || 'localhost'}`);
15
+ const path = url.pathname;
16
+ const method = req.method?.toUpperCase() || 'GET';
17
+ // Parse query parameters
18
+ const query = {};
19
+ url.searchParams.forEach((value, key) => {
20
+ query[key] = value;
21
+ });
22
+ // Normalize headers
23
+ const headers = {};
24
+ for (const [key, value] of Object.entries(req.headers)) {
25
+ if (typeof value === 'string') {
26
+ headers[key.toLowerCase()] = value;
27
+ }
28
+ else if (Array.isArray(value)) {
29
+ headers[key.toLowerCase()] = value[0] || '';
30
+ }
31
+ }
32
+ // Parse body (if present)
33
+ let body = null;
34
+ if (method === 'POST' || method === 'PUT' || method === 'PATCH') {
35
+ const rawBody = await readBody(req, maxBodySize);
36
+ if (rawBody) {
37
+ const contentType = headers['content-type'] || '';
38
+ if (contentType.includes('application/json')) {
39
+ try {
40
+ body = JSON.parse(rawBody);
41
+ }
42
+ catch (error) {
43
+ throw new Error(`Invalid JSON body: ${error instanceof Error ? error.message : String(error)}`);
44
+ }
45
+ }
46
+ else if (contentType.includes('application/x-www-form-urlencoded')) {
47
+ body = parseFormData(rawBody);
48
+ }
49
+ else {
50
+ // Unknown content type, try JSON anyway
51
+ try {
52
+ body = JSON.parse(rawBody);
53
+ }
54
+ catch {
55
+ body = rawBody;
56
+ }
57
+ }
58
+ }
59
+ }
60
+ // Detect streaming request
61
+ const stream = body?.stream === true || headers['accept'] === 'text/event-stream';
62
+ return {
63
+ body,
64
+ headers,
65
+ path,
66
+ method,
67
+ query,
68
+ stream,
69
+ };
70
+ }
71
+ /**
72
+ * Read request body as string
73
+ */
74
+ function readBody(req, maxSize) {
75
+ return new Promise((resolve, reject) => {
76
+ const chunks = [];
77
+ let totalSize = 0;
78
+ req.on('data', (chunk) => {
79
+ totalSize += chunk.length;
80
+ if (totalSize > maxSize) {
81
+ // Destroy the stream to stop receiving data and free resources
82
+ req.destroy();
83
+ reject(new Error(`Request body too large (max ${maxSize} bytes)`));
84
+ return;
85
+ }
86
+ chunks.push(chunk);
87
+ });
88
+ req.on('end', () => {
89
+ const body = Buffer.concat(chunks).toString('utf-8');
90
+ resolve(body);
91
+ });
92
+ req.on('error', (error) => {
93
+ reject(error);
94
+ });
95
+ });
96
+ }
97
+ /**
98
+ * Parse form-encoded data
99
+ */
100
+ function parseFormData(data) {
101
+ const params = new URLSearchParams(data);
102
+ const result = {};
103
+ params.forEach((value, key) => {
104
+ result[key] = value;
105
+ });
106
+ return result;
107
+ }
108
+ /**
109
+ * Extract bearer token from Authorization header
110
+ */
111
+ export function extractBearerToken(req) {
112
+ const auth = req.headers.authorization;
113
+ if (!auth) {
114
+ return null;
115
+ }
116
+ const match = auth.match(/^Bearer\s+(.+)$/i);
117
+ return match ? match[1] || null : null;
118
+ }
119
+ /**
120
+ * Get client IP address from request
121
+ */
122
+ export function getClientIP(req) {
123
+ // Check common proxy headers
124
+ const forwarded = req.headers['x-forwarded-for'];
125
+ if (forwarded) {
126
+ const ips = typeof forwarded === 'string' ? forwarded.split(',') : forwarded;
127
+ return ips[0]?.trim() || 'unknown';
128
+ }
129
+ const realIP = req.headers['x-real-ip'];
130
+ if (realIP && typeof realIP === 'string') {
131
+ return realIP;
132
+ }
133
+ // Fallback to socket address
134
+ return req.socket.remoteAddress || 'unknown';
135
+ }
136
+ //# sourceMappingURL=request-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-parser.js","sourceRoot":"","sources":["../../src/request-parser.ts"],"names":[],"mappings":"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"}