@morojs/moro 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.
- package/LICENSE +21 -0
- package/README.md +233 -0
- package/dist/core/config/index.d.ts +19 -0
- package/dist/core/config/index.js +59 -0
- package/dist/core/config/index.js.map +1 -0
- package/dist/core/config/loader.d.ts +6 -0
- package/dist/core/config/loader.js +288 -0
- package/dist/core/config/loader.js.map +1 -0
- package/dist/core/config/schema.d.ts +335 -0
- package/dist/core/config/schema.js +286 -0
- package/dist/core/config/schema.js.map +1 -0
- package/dist/core/config/utils.d.ts +50 -0
- package/dist/core/config/utils.js +185 -0
- package/dist/core/config/utils.js.map +1 -0
- package/dist/core/database/adapters/drizzle.d.ts +29 -0
- package/dist/core/database/adapters/drizzle.js +366 -0
- package/dist/core/database/adapters/drizzle.js.map +1 -0
- package/dist/core/database/adapters/index.d.ts +8 -0
- package/dist/core/database/adapters/index.js +48 -0
- package/dist/core/database/adapters/index.js.map +1 -0
- package/dist/core/database/adapters/mongodb.d.ts +35 -0
- package/dist/core/database/adapters/mongodb.js +215 -0
- package/dist/core/database/adapters/mongodb.js.map +1 -0
- package/dist/core/database/adapters/mysql.d.ts +23 -0
- package/dist/core/database/adapters/mysql.js +149 -0
- package/dist/core/database/adapters/mysql.js.map +1 -0
- package/dist/core/database/adapters/postgresql.d.ts +24 -0
- package/dist/core/database/adapters/postgresql.js +160 -0
- package/dist/core/database/adapters/postgresql.js.map +1 -0
- package/dist/core/database/adapters/redis.d.ts +50 -0
- package/dist/core/database/adapters/redis.js +266 -0
- package/dist/core/database/adapters/redis.js.map +1 -0
- package/dist/core/database/adapters/sqlite.d.ts +23 -0
- package/dist/core/database/adapters/sqlite.js +194 -0
- package/dist/core/database/adapters/sqlite.js.map +1 -0
- package/dist/core/database/index.d.ts +2 -0
- package/dist/core/database/index.js +20 -0
- package/dist/core/database/index.js.map +1 -0
- package/dist/core/docs/index.d.ts +63 -0
- package/dist/core/docs/index.js +170 -0
- package/dist/core/docs/index.js.map +1 -0
- package/dist/core/docs/openapi-generator.d.ts +124 -0
- package/dist/core/docs/openapi-generator.js +413 -0
- package/dist/core/docs/openapi-generator.js.map +1 -0
- package/dist/core/docs/simple-docs.d.ts +21 -0
- package/dist/core/docs/simple-docs.js +268 -0
- package/dist/core/docs/simple-docs.js.map +1 -0
- package/dist/core/docs/swagger-ui.d.ts +28 -0
- package/dist/core/docs/swagger-ui.js +317 -0
- package/dist/core/docs/swagger-ui.js.map +1 -0
- package/dist/core/docs/zod-to-openapi.d.ts +29 -0
- package/dist/core/docs/zod-to-openapi.js +414 -0
- package/dist/core/docs/zod-to-openapi.js.map +1 -0
- package/dist/core/events/event-bus.d.ts +27 -0
- package/dist/core/events/event-bus.js +193 -0
- package/dist/core/events/event-bus.js.map +1 -0
- package/dist/core/events/index.d.ts +2 -0
- package/dist/core/events/index.js +7 -0
- package/dist/core/events/index.js.map +1 -0
- package/dist/core/framework.d.ts +57 -0
- package/dist/core/framework.js +432 -0
- package/dist/core/framework.js.map +1 -0
- package/dist/core/http/http-server.d.ts +114 -0
- package/dist/core/http/http-server.js +1154 -0
- package/dist/core/http/http-server.js.map +1 -0
- package/dist/core/http/index.d.ts +3 -0
- package/dist/core/http/index.js +10 -0
- package/dist/core/http/index.js.map +1 -0
- package/dist/core/http/router.d.ts +14 -0
- package/dist/core/http/router.js +113 -0
- package/dist/core/http/router.js.map +1 -0
- package/dist/core/logger/filters.d.ts +9 -0
- package/dist/core/logger/filters.js +134 -0
- package/dist/core/logger/filters.js.map +1 -0
- package/dist/core/logger/index.d.ts +3 -0
- package/dist/core/logger/index.js +26 -0
- package/dist/core/logger/index.js.map +1 -0
- package/dist/core/logger/logger.d.ts +49 -0
- package/dist/core/logger/logger.js +332 -0
- package/dist/core/logger/logger.js.map +1 -0
- package/dist/core/logger/outputs.d.ts +42 -0
- package/dist/core/logger/outputs.js +110 -0
- package/dist/core/logger/outputs.js.map +1 -0
- package/dist/core/middleware/built-in/adapters/cache/file.d.ts +15 -0
- package/dist/core/middleware/built-in/adapters/cache/file.js +128 -0
- package/dist/core/middleware/built-in/adapters/cache/file.js.map +1 -0
- package/dist/core/middleware/built-in/adapters/cache/index.d.ts +5 -0
- package/dist/core/middleware/built-in/adapters/cache/index.js +28 -0
- package/dist/core/middleware/built-in/adapters/cache/index.js.map +1 -0
- package/dist/core/middleware/built-in/adapters/cache/memory.d.ts +11 -0
- package/dist/core/middleware/built-in/adapters/cache/memory.js +65 -0
- package/dist/core/middleware/built-in/adapters/cache/memory.js.map +1 -0
- package/dist/core/middleware/built-in/adapters/cache/redis.d.ts +17 -0
- package/dist/core/middleware/built-in/adapters/cache/redis.js +91 -0
- package/dist/core/middleware/built-in/adapters/cache/redis.js.map +1 -0
- package/dist/core/middleware/built-in/adapters/cdn/azure.d.ts +21 -0
- package/dist/core/middleware/built-in/adapters/cdn/azure.js +40 -0
- package/dist/core/middleware/built-in/adapters/cdn/azure.js.map +1 -0
- package/dist/core/middleware/built-in/adapters/cdn/cloudflare.d.ts +14 -0
- package/dist/core/middleware/built-in/adapters/cdn/cloudflare.js +77 -0
- package/dist/core/middleware/built-in/adapters/cdn/cloudflare.js.map +1 -0
- package/dist/core/middleware/built-in/adapters/cdn/cloudfront.d.ts +15 -0
- package/dist/core/middleware/built-in/adapters/cdn/cloudfront.js +73 -0
- package/dist/core/middleware/built-in/adapters/cdn/cloudfront.js.map +1 -0
- package/dist/core/middleware/built-in/adapters/cdn/index.d.ts +5 -0
- package/dist/core/middleware/built-in/adapters/cdn/index.js +28 -0
- package/dist/core/middleware/built-in/adapters/cdn/index.js.map +1 -0
- package/dist/core/middleware/built-in/adapters/index.d.ts +4 -0
- package/dist/core/middleware/built-in/adapters/index.js +26 -0
- package/dist/core/middleware/built-in/adapters/index.js.map +1 -0
- package/dist/core/middleware/built-in/auth.d.ts +2 -0
- package/dist/core/middleware/built-in/auth.js +38 -0
- package/dist/core/middleware/built-in/auth.js.map +1 -0
- package/dist/core/middleware/built-in/cache.d.ts +3 -0
- package/dist/core/middleware/built-in/cache.js +188 -0
- package/dist/core/middleware/built-in/cache.js.map +1 -0
- package/dist/core/middleware/built-in/cdn.d.ts +3 -0
- package/dist/core/middleware/built-in/cdn.js +115 -0
- package/dist/core/middleware/built-in/cdn.js.map +1 -0
- package/dist/core/middleware/built-in/cookie.d.ts +14 -0
- package/dist/core/middleware/built-in/cookie.js +68 -0
- package/dist/core/middleware/built-in/cookie.js.map +1 -0
- package/dist/core/middleware/built-in/cors.d.ts +2 -0
- package/dist/core/middleware/built-in/cors.js +29 -0
- package/dist/core/middleware/built-in/cors.js.map +1 -0
- package/dist/core/middleware/built-in/csp.d.ts +22 -0
- package/dist/core/middleware/built-in/csp.js +74 -0
- package/dist/core/middleware/built-in/csp.js.map +1 -0
- package/dist/core/middleware/built-in/csrf.d.ts +9 -0
- package/dist/core/middleware/built-in/csrf.js +66 -0
- package/dist/core/middleware/built-in/csrf.js.map +1 -0
- package/dist/core/middleware/built-in/error-tracker.d.ts +1 -0
- package/dist/core/middleware/built-in/error-tracker.js +19 -0
- package/dist/core/middleware/built-in/error-tracker.js.map +1 -0
- package/dist/core/middleware/built-in/index.d.ts +70 -0
- package/dist/core/middleware/built-in/index.js +70 -0
- package/dist/core/middleware/built-in/index.js.map +1 -0
- package/dist/core/middleware/built-in/performance-monitor.d.ts +1 -0
- package/dist/core/middleware/built-in/performance-monitor.js +22 -0
- package/dist/core/middleware/built-in/performance-monitor.js.map +1 -0
- package/dist/core/middleware/built-in/rate-limit.d.ts +6 -0
- package/dist/core/middleware/built-in/rate-limit.js +47 -0
- package/dist/core/middleware/built-in/rate-limit.js.map +1 -0
- package/dist/core/middleware/built-in/request-logger.d.ts +1 -0
- package/dist/core/middleware/built-in/request-logger.js +15 -0
- package/dist/core/middleware/built-in/request-logger.js.map +1 -0
- package/dist/core/middleware/built-in/session.d.ts +41 -0
- package/dist/core/middleware/built-in/session.js +209 -0
- package/dist/core/middleware/built-in/session.js.map +1 -0
- package/dist/core/middleware/built-in/sse.d.ts +6 -0
- package/dist/core/middleware/built-in/sse.js +73 -0
- package/dist/core/middleware/built-in/sse.js.map +1 -0
- package/dist/core/middleware/built-in/validation.d.ts +2 -0
- package/dist/core/middleware/built-in/validation.js +31 -0
- package/dist/core/middleware/built-in/validation.js.map +1 -0
- package/dist/core/middleware/index.d.ts +21 -0
- package/dist/core/middleware/index.js +152 -0
- package/dist/core/middleware/index.js.map +1 -0
- package/dist/core/modules/auto-discovery.d.ts +27 -0
- package/dist/core/modules/auto-discovery.js +255 -0
- package/dist/core/modules/auto-discovery.js.map +1 -0
- package/dist/core/modules/index.d.ts +2 -0
- package/dist/core/modules/index.js +11 -0
- package/dist/core/modules/index.js.map +1 -0
- package/dist/core/modules/modules.d.ts +10 -0
- package/dist/core/modules/modules.js +137 -0
- package/dist/core/modules/modules.js.map +1 -0
- package/dist/core/networking/index.d.ts +2 -0
- package/dist/core/networking/index.js +9 -0
- package/dist/core/networking/index.js.map +1 -0
- package/dist/core/networking/service-discovery.d.ts +38 -0
- package/dist/core/networking/service-discovery.js +233 -0
- package/dist/core/networking/service-discovery.js.map +1 -0
- package/dist/core/networking/websocket-manager.d.ts +27 -0
- package/dist/core/networking/websocket-manager.js +211 -0
- package/dist/core/networking/websocket-manager.js.map +1 -0
- package/dist/core/routing/app-integration.d.ts +42 -0
- package/dist/core/routing/app-integration.js +152 -0
- package/dist/core/routing/app-integration.js.map +1 -0
- package/dist/core/routing/index.d.ts +106 -0
- package/dist/core/routing/index.js +343 -0
- package/dist/core/routing/index.js.map +1 -0
- package/dist/core/runtime/aws-lambda-adapter.d.ts +43 -0
- package/dist/core/runtime/aws-lambda-adapter.js +108 -0
- package/dist/core/runtime/aws-lambda-adapter.js.map +1 -0
- package/dist/core/runtime/base-adapter.d.ts +16 -0
- package/dist/core/runtime/base-adapter.js +105 -0
- package/dist/core/runtime/base-adapter.js.map +1 -0
- package/dist/core/runtime/cloudflare-workers-adapter.d.ts +18 -0
- package/dist/core/runtime/cloudflare-workers-adapter.js +131 -0
- package/dist/core/runtime/cloudflare-workers-adapter.js.map +1 -0
- package/dist/core/runtime/index.d.ts +14 -0
- package/dist/core/runtime/index.js +56 -0
- package/dist/core/runtime/index.js.map +1 -0
- package/dist/core/runtime/node-adapter.d.ts +15 -0
- package/dist/core/runtime/node-adapter.js +204 -0
- package/dist/core/runtime/node-adapter.js.map +1 -0
- package/dist/core/runtime/vercel-edge-adapter.d.ts +10 -0
- package/dist/core/runtime/vercel-edge-adapter.js +106 -0
- package/dist/core/runtime/vercel-edge-adapter.js.map +1 -0
- package/dist/core/utilities/circuit-breaker.d.ts +14 -0
- package/dist/core/utilities/circuit-breaker.js +42 -0
- package/dist/core/utilities/circuit-breaker.js.map +1 -0
- package/dist/core/utilities/container.d.ts +116 -0
- package/dist/core/utilities/container.js +529 -0
- package/dist/core/utilities/container.js.map +1 -0
- package/dist/core/utilities/hooks.d.ts +24 -0
- package/dist/core/utilities/hooks.js +131 -0
- package/dist/core/utilities/hooks.js.map +1 -0
- package/dist/core/utilities/index.d.ts +4 -0
- package/dist/core/utilities/index.js +22 -0
- package/dist/core/utilities/index.js.map +1 -0
- package/dist/core/validation/index.d.ts +30 -0
- package/dist/core/validation/index.js +144 -0
- package/dist/core/validation/index.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.js +72 -0
- package/dist/index.js.map +1 -0
- package/dist/moro.d.ts +82 -0
- package/dist/moro.js +679 -0
- package/dist/moro.js.map +1 -0
- package/dist/types/cache.d.ts +34 -0
- package/dist/types/cache.js +3 -0
- package/dist/types/cache.js.map +1 -0
- package/dist/types/cdn.d.ts +19 -0
- package/dist/types/cdn.js +3 -0
- package/dist/types/cdn.js.map +1 -0
- package/dist/types/core.d.ts +13 -0
- package/dist/types/core.js +3 -0
- package/dist/types/core.js.map +1 -0
- package/dist/types/database.d.ts +29 -0
- package/dist/types/database.js +3 -0
- package/dist/types/database.js.map +1 -0
- package/dist/types/discovery.d.ts +6 -0
- package/dist/types/discovery.js +3 -0
- package/dist/types/discovery.js.map +1 -0
- package/dist/types/events.d.ts +116 -0
- package/dist/types/events.js +3 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/hooks.d.ts +38 -0
- package/dist/types/hooks.js +3 -0
- package/dist/types/hooks.js.map +1 -0
- package/dist/types/http.d.ts +51 -0
- package/dist/types/http.js +3 -0
- package/dist/types/http.js.map +1 -0
- package/dist/types/logger.d.ts +77 -0
- package/dist/types/logger.js +3 -0
- package/dist/types/logger.js.map +1 -0
- package/dist/types/module.d.ts +91 -0
- package/dist/types/module.js +3 -0
- package/dist/types/module.js.map +1 -0
- package/dist/types/runtime.d.ts +48 -0
- package/dist/types/runtime.js +3 -0
- package/dist/types/runtime.js.map +1 -0
- package/dist/types/session.d.ts +66 -0
- package/dist/types/session.js +3 -0
- package/dist/types/session.js.map +1 -0
- package/package.json +176 -0
- package/src/core/config/index.ts +47 -0
- package/src/core/config/loader.ts +366 -0
- package/src/core/config/schema.ts +346 -0
- package/src/core/config/utils.ts +220 -0
- package/src/core/database/README.md +228 -0
- package/src/core/database/adapters/drizzle.ts +425 -0
- package/src/core/database/adapters/index.ts +45 -0
- package/src/core/database/adapters/mongodb.ts +292 -0
- package/src/core/database/adapters/mysql.ts +217 -0
- package/src/core/database/adapters/postgresql.ts +211 -0
- package/src/core/database/adapters/redis.ts +331 -0
- package/src/core/database/adapters/sqlite.ts +255 -0
- package/src/core/database/index.ts +3 -0
- package/src/core/docs/index.ts +245 -0
- package/src/core/docs/openapi-generator.ts +588 -0
- package/src/core/docs/simple-docs.ts +305 -0
- package/src/core/docs/swagger-ui.ts +370 -0
- package/src/core/docs/zod-to-openapi.ts +532 -0
- package/src/core/events/event-bus.ts +249 -0
- package/src/core/events/index.ts +12 -0
- package/src/core/framework.ts +621 -0
- package/src/core/http/http-server.ts +1421 -0
- package/src/core/http/index.ts +11 -0
- package/src/core/http/router.ts +153 -0
- package/src/core/logger/filters.ts +148 -0
- package/src/core/logger/index.ts +20 -0
- package/src/core/logger/logger.ts +434 -0
- package/src/core/logger/outputs.ts +136 -0
- package/src/core/middleware/built-in/adapters/cache/file.ts +106 -0
- package/src/core/middleware/built-in/adapters/cache/index.ts +26 -0
- package/src/core/middleware/built-in/adapters/cache/memory.ts +73 -0
- package/src/core/middleware/built-in/adapters/cache/redis.ts +103 -0
- package/src/core/middleware/built-in/adapters/cdn/azure.ts +68 -0
- package/src/core/middleware/built-in/adapters/cdn/cloudflare.ts +100 -0
- package/src/core/middleware/built-in/adapters/cdn/cloudfront.ts +92 -0
- package/src/core/middleware/built-in/adapters/cdn/index.ts +23 -0
- package/src/core/middleware/built-in/adapters/index.ts +7 -0
- package/src/core/middleware/built-in/auth.ts +39 -0
- package/src/core/middleware/built-in/cache.ts +228 -0
- package/src/core/middleware/built-in/cdn.ts +151 -0
- package/src/core/middleware/built-in/cookie.ts +90 -0
- package/src/core/middleware/built-in/cors.ts +38 -0
- package/src/core/middleware/built-in/csp.ts +107 -0
- package/src/core/middleware/built-in/csrf.ts +87 -0
- package/src/core/middleware/built-in/error-tracker.ts +16 -0
- package/src/core/middleware/built-in/index.ts +57 -0
- package/src/core/middleware/built-in/performance-monitor.ts +25 -0
- package/src/core/middleware/built-in/rate-limit.ts +60 -0
- package/src/core/middleware/built-in/request-logger.ts +14 -0
- package/src/core/middleware/built-in/session.ts +311 -0
- package/src/core/middleware/built-in/sse.ts +91 -0
- package/src/core/middleware/built-in/validation.ts +33 -0
- package/src/core/middleware/index.ts +188 -0
- package/src/core/modules/auto-discovery.ts +265 -0
- package/src/core/modules/index.ts +6 -0
- package/src/core/modules/modules.ts +125 -0
- package/src/core/networking/index.ts +7 -0
- package/src/core/networking/service-discovery.ts +309 -0
- package/src/core/networking/websocket-manager.ts +259 -0
- package/src/core/routing/app-integration.ts +229 -0
- package/src/core/routing/index.ts +519 -0
- package/src/core/runtime/aws-lambda-adapter.ts +157 -0
- package/src/core/runtime/base-adapter.ts +140 -0
- package/src/core/runtime/cloudflare-workers-adapter.ts +166 -0
- package/src/core/runtime/index.ts +74 -0
- package/src/core/runtime/node-adapter.ts +210 -0
- package/src/core/runtime/vercel-edge-adapter.ts +125 -0
- package/src/core/utilities/circuit-breaker.ts +46 -0
- package/src/core/utilities/container.ts +760 -0
- package/src/core/utilities/hooks.ts +148 -0
- package/src/core/utilities/index.ts +16 -0
- package/src/core/validation/index.ts +216 -0
- package/src/index.ts +120 -0
- package/src/moro.ts +842 -0
- package/src/types/cache.ts +38 -0
- package/src/types/cdn.ts +22 -0
- package/src/types/core.ts +17 -0
- package/src/types/database.ts +40 -0
- package/src/types/discovery.ts +7 -0
- package/src/types/events.ts +90 -0
- package/src/types/hooks.ts +47 -0
- package/src/types/http.ts +70 -0
- package/src/types/logger.ts +109 -0
- package/src/types/module.ts +87 -0
- package/src/types/runtime.ts +91 -0
- package/src/types/session.ts +89 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
// Intelligent Routing System for Moro Framework
|
|
2
|
+
// Schema-first with automatic middleware ordering and chainable API
|
|
3
|
+
|
|
4
|
+
import { z, ZodSchema } from "zod";
|
|
5
|
+
import { HttpRequest, HttpResponse } from "../http";
|
|
6
|
+
import { createFrameworkLogger } from "../logger";
|
|
7
|
+
|
|
8
|
+
const logger = createFrameworkLogger("IntelligentRouting");
|
|
9
|
+
|
|
10
|
+
// Core types
|
|
11
|
+
export type HttpMethod =
|
|
12
|
+
| "GET"
|
|
13
|
+
| "POST"
|
|
14
|
+
| "PUT"
|
|
15
|
+
| "DELETE"
|
|
16
|
+
| "PATCH"
|
|
17
|
+
| "HEAD"
|
|
18
|
+
| "OPTIONS";
|
|
19
|
+
export type RouteHandler<T = any> = (
|
|
20
|
+
req: HttpRequest,
|
|
21
|
+
res: HttpResponse,
|
|
22
|
+
) => T | Promise<T>;
|
|
23
|
+
export type Middleware = (
|
|
24
|
+
req: HttpRequest,
|
|
25
|
+
res: HttpResponse,
|
|
26
|
+
next: () => void,
|
|
27
|
+
) => void | Promise<void>;
|
|
28
|
+
|
|
29
|
+
// Configuration interfaces
|
|
30
|
+
export interface ValidationConfig {
|
|
31
|
+
body?: ZodSchema;
|
|
32
|
+
query?: ZodSchema;
|
|
33
|
+
params?: ZodSchema;
|
|
34
|
+
headers?: ZodSchema;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface AuthConfig {
|
|
38
|
+
roles?: string[];
|
|
39
|
+
permissions?: string[];
|
|
40
|
+
optional?: boolean;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface RateLimitConfig {
|
|
44
|
+
requests: number;
|
|
45
|
+
window: number;
|
|
46
|
+
skipSuccessfulRequests?: boolean;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface CacheConfig {
|
|
50
|
+
ttl: number;
|
|
51
|
+
key?: string;
|
|
52
|
+
tags?: string[];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Middleware phases for intelligent ordering
|
|
56
|
+
export interface MiddlewarePhases {
|
|
57
|
+
before?: Middleware[]; // Before auth/validation
|
|
58
|
+
after?: Middleware[]; // After validation, before handler
|
|
59
|
+
transform?: Middleware[]; // Data transformation phase
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Core route schema
|
|
63
|
+
export interface RouteSchema {
|
|
64
|
+
method: HttpMethod;
|
|
65
|
+
path: string;
|
|
66
|
+
handler: RouteHandler;
|
|
67
|
+
|
|
68
|
+
// Framework-managed (order-independent)
|
|
69
|
+
validation?: ValidationConfig;
|
|
70
|
+
auth?: AuthConfig;
|
|
71
|
+
rateLimit?: RateLimitConfig;
|
|
72
|
+
cache?: CacheConfig;
|
|
73
|
+
|
|
74
|
+
// Custom middleware with phase hints
|
|
75
|
+
middleware?: MiddlewarePhases;
|
|
76
|
+
|
|
77
|
+
// Metadata
|
|
78
|
+
description?: string;
|
|
79
|
+
tags?: string[];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Execution phases in optimal order
|
|
83
|
+
export const EXECUTION_PHASES = [
|
|
84
|
+
"security", // CORS, Helmet (framework-managed)
|
|
85
|
+
"parsing", // Body/query parsing (framework-managed)
|
|
86
|
+
"rateLimit", // Rate limiting (early protection)
|
|
87
|
+
"before", // Custom pre-processing middleware
|
|
88
|
+
"auth", // Authentication/authorization
|
|
89
|
+
"validation", // Request validation
|
|
90
|
+
"transform", // Data transformation middleware
|
|
91
|
+
"cache", // Caching logic
|
|
92
|
+
"after", // Custom post-processing middleware
|
|
93
|
+
"handler", // Route handler (always last)
|
|
94
|
+
] as const;
|
|
95
|
+
|
|
96
|
+
export type ExecutionPhase = (typeof EXECUTION_PHASES)[number];
|
|
97
|
+
|
|
98
|
+
// Enhanced request with validation results
|
|
99
|
+
export interface ValidatedRequest<T = any> extends HttpRequest {
|
|
100
|
+
validatedBody?: T;
|
|
101
|
+
validatedQuery?: any;
|
|
102
|
+
validatedParams?: any;
|
|
103
|
+
validatedHeaders?: any;
|
|
104
|
+
user?: any; // Added by auth middleware
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Route builder for chainable API
|
|
108
|
+
export interface RouteBuilder {
|
|
109
|
+
// Validation methods
|
|
110
|
+
validate(config: ValidationConfig): RouteBuilder;
|
|
111
|
+
body<T>(schema: ZodSchema<T>): RouteBuilder;
|
|
112
|
+
query<T>(schema: ZodSchema<T>): RouteBuilder;
|
|
113
|
+
params<T>(schema: ZodSchema<T>): RouteBuilder;
|
|
114
|
+
headers<T>(schema: ZodSchema<T>): RouteBuilder;
|
|
115
|
+
|
|
116
|
+
// Security/Auth methods
|
|
117
|
+
auth(config: AuthConfig): RouteBuilder;
|
|
118
|
+
rateLimit(config: RateLimitConfig): RouteBuilder;
|
|
119
|
+
|
|
120
|
+
// Caching
|
|
121
|
+
cache(config: CacheConfig): RouteBuilder;
|
|
122
|
+
|
|
123
|
+
// Custom middleware with phase control
|
|
124
|
+
before(...middleware: Middleware[]): RouteBuilder;
|
|
125
|
+
after(...middleware: Middleware[]): RouteBuilder;
|
|
126
|
+
transform(...middleware: Middleware[]): RouteBuilder;
|
|
127
|
+
use(...middleware: Middleware[]): RouteBuilder; // Alias for 'after'
|
|
128
|
+
|
|
129
|
+
// Metadata
|
|
130
|
+
describe(description: string): RouteBuilder;
|
|
131
|
+
tag(...tags: string[]): RouteBuilder;
|
|
132
|
+
|
|
133
|
+
// Terminal method
|
|
134
|
+
handler<T>(handler: RouteHandler<T>): CompiledRoute;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Compiled route ready for execution
|
|
138
|
+
export interface CompiledRoute {
|
|
139
|
+
schema: RouteSchema;
|
|
140
|
+
execute(req: HttpRequest, res: HttpResponse): Promise<void>;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Route builder implementation
|
|
144
|
+
export class IntelligentRouteBuilder implements RouteBuilder {
|
|
145
|
+
private schema: Partial<RouteSchema>;
|
|
146
|
+
|
|
147
|
+
constructor(method: HttpMethod, path: string) {
|
|
148
|
+
this.schema = {
|
|
149
|
+
method,
|
|
150
|
+
path,
|
|
151
|
+
middleware: {},
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Validation methods
|
|
156
|
+
validate(config: ValidationConfig): RouteBuilder {
|
|
157
|
+
this.schema.validation = { ...this.schema.validation, ...config };
|
|
158
|
+
return this;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
body<T>(schema: ZodSchema<T>): RouteBuilder {
|
|
162
|
+
if (!this.schema.validation) this.schema.validation = {};
|
|
163
|
+
this.schema.validation.body = schema;
|
|
164
|
+
return this;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
query<T>(schema: ZodSchema<T>): RouteBuilder {
|
|
168
|
+
if (!this.schema.validation) this.schema.validation = {};
|
|
169
|
+
this.schema.validation.query = schema;
|
|
170
|
+
return this;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
params<T>(schema: ZodSchema<T>): RouteBuilder {
|
|
174
|
+
if (!this.schema.validation) this.schema.validation = {};
|
|
175
|
+
this.schema.validation.params = schema;
|
|
176
|
+
return this;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
headers<T>(schema: ZodSchema<T>): RouteBuilder {
|
|
180
|
+
if (!this.schema.validation) this.schema.validation = {};
|
|
181
|
+
this.schema.validation.headers = schema;
|
|
182
|
+
return this;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Security methods
|
|
186
|
+
auth(config: AuthConfig): RouteBuilder {
|
|
187
|
+
this.schema.auth = config;
|
|
188
|
+
return this;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
rateLimit(config: RateLimitConfig): RouteBuilder {
|
|
192
|
+
this.schema.rateLimit = config;
|
|
193
|
+
return this;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Caching
|
|
197
|
+
cache(config: CacheConfig): RouteBuilder {
|
|
198
|
+
this.schema.cache = config;
|
|
199
|
+
return this;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Custom middleware
|
|
203
|
+
before(...middleware: Middleware[]): RouteBuilder {
|
|
204
|
+
if (!this.schema.middleware) this.schema.middleware = {};
|
|
205
|
+
this.schema.middleware.before = [
|
|
206
|
+
...(this.schema.middleware.before || []),
|
|
207
|
+
...middleware,
|
|
208
|
+
];
|
|
209
|
+
return this;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
after(...middleware: Middleware[]): RouteBuilder {
|
|
213
|
+
if (!this.schema.middleware) this.schema.middleware = {};
|
|
214
|
+
this.schema.middleware.after = [
|
|
215
|
+
...(this.schema.middleware.after || []),
|
|
216
|
+
...middleware,
|
|
217
|
+
];
|
|
218
|
+
return this;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
transform(...middleware: Middleware[]): RouteBuilder {
|
|
222
|
+
if (!this.schema.middleware) this.schema.middleware = {};
|
|
223
|
+
this.schema.middleware.transform = [
|
|
224
|
+
...(this.schema.middleware.transform || []),
|
|
225
|
+
...middleware,
|
|
226
|
+
];
|
|
227
|
+
return this;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
use(...middleware: Middleware[]): RouteBuilder {
|
|
231
|
+
return this.after(...middleware);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Metadata
|
|
235
|
+
describe(description: string): RouteBuilder {
|
|
236
|
+
this.schema.description = description;
|
|
237
|
+
return this;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
tag(...tags: string[]): RouteBuilder {
|
|
241
|
+
this.schema.tags = [...(this.schema.tags || []), ...tags];
|
|
242
|
+
return this;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Terminal method - compiles the route
|
|
246
|
+
handler<T>(handler: RouteHandler<T>): CompiledRoute {
|
|
247
|
+
if (!handler) {
|
|
248
|
+
throw new Error("Handler is required");
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const completeSchema: RouteSchema = {
|
|
252
|
+
...(this.schema as RouteSchema),
|
|
253
|
+
handler,
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
logger.debug(
|
|
257
|
+
`Compiled route: ${completeSchema.method} ${completeSchema.path}`,
|
|
258
|
+
"RouteCompilation",
|
|
259
|
+
{
|
|
260
|
+
hasValidation: !!completeSchema.validation,
|
|
261
|
+
hasAuth: !!completeSchema.auth,
|
|
262
|
+
hasRateLimit: !!completeSchema.rateLimit,
|
|
263
|
+
hasCache: !!completeSchema.cache,
|
|
264
|
+
customMiddleware: {
|
|
265
|
+
before: completeSchema.middleware?.before?.length || 0,
|
|
266
|
+
after: completeSchema.middleware?.after?.length || 0,
|
|
267
|
+
transform: completeSchema.middleware?.transform?.length || 0,
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
return new ExecutableRoute(completeSchema);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Executable route with intelligent middleware ordering
|
|
277
|
+
export class ExecutableRoute implements CompiledRoute {
|
|
278
|
+
constructor(public readonly schema: RouteSchema) {}
|
|
279
|
+
|
|
280
|
+
async execute(req: HttpRequest, res: HttpResponse): Promise<void> {
|
|
281
|
+
const validatedReq = req as ValidatedRequest;
|
|
282
|
+
|
|
283
|
+
try {
|
|
284
|
+
// Execute middleware in intelligent order
|
|
285
|
+
await this.executePhase("before", validatedReq, res);
|
|
286
|
+
await this.executePhase("rateLimit", validatedReq, res);
|
|
287
|
+
await this.executePhase("auth", validatedReq, res);
|
|
288
|
+
await this.executePhase("validation", validatedReq, res);
|
|
289
|
+
await this.executePhase("transform", validatedReq, res);
|
|
290
|
+
await this.executePhase("cache", validatedReq, res);
|
|
291
|
+
await this.executePhase("after", validatedReq, res);
|
|
292
|
+
|
|
293
|
+
// Execute handler last
|
|
294
|
+
if (!res.headersSent) {
|
|
295
|
+
await this.executePhase("handler", validatedReq, res);
|
|
296
|
+
}
|
|
297
|
+
} catch (error) {
|
|
298
|
+
logger.error("Route execution error", "RouteExecution", {
|
|
299
|
+
error: error instanceof Error ? error.message : String(error),
|
|
300
|
+
route: `${this.schema.method} ${this.schema.path}`,
|
|
301
|
+
requestId: req.requestId,
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
if (!res.headersSent) {
|
|
305
|
+
res.status(500).json({
|
|
306
|
+
success: false,
|
|
307
|
+
error: "Internal server error",
|
|
308
|
+
requestId: req.requestId,
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
private async executePhase(
|
|
315
|
+
phase: ExecutionPhase,
|
|
316
|
+
req: ValidatedRequest,
|
|
317
|
+
res: HttpResponse,
|
|
318
|
+
): Promise<void> {
|
|
319
|
+
switch (phase) {
|
|
320
|
+
case "before":
|
|
321
|
+
if (this.schema.middleware?.before) {
|
|
322
|
+
for (const middleware of this.schema.middleware.before) {
|
|
323
|
+
await this.executeMiddleware(middleware, req, res);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
break;
|
|
327
|
+
|
|
328
|
+
case "rateLimit":
|
|
329
|
+
if (this.schema.rateLimit) {
|
|
330
|
+
await this.executeRateLimit(req, res);
|
|
331
|
+
}
|
|
332
|
+
break;
|
|
333
|
+
|
|
334
|
+
case "auth":
|
|
335
|
+
if (this.schema.auth) {
|
|
336
|
+
await this.executeAuth(req, res);
|
|
337
|
+
}
|
|
338
|
+
break;
|
|
339
|
+
|
|
340
|
+
case "validation":
|
|
341
|
+
if (this.schema.validation) {
|
|
342
|
+
await this.executeValidation(req, res);
|
|
343
|
+
}
|
|
344
|
+
break;
|
|
345
|
+
|
|
346
|
+
case "transform":
|
|
347
|
+
if (this.schema.middleware?.transform) {
|
|
348
|
+
for (const middleware of this.schema.middleware.transform) {
|
|
349
|
+
await this.executeMiddleware(middleware, req, res);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
break;
|
|
353
|
+
|
|
354
|
+
case "cache":
|
|
355
|
+
if (this.schema.cache) {
|
|
356
|
+
await this.executeCache(req, res);
|
|
357
|
+
}
|
|
358
|
+
break;
|
|
359
|
+
|
|
360
|
+
case "after":
|
|
361
|
+
if (this.schema.middleware?.after) {
|
|
362
|
+
for (const middleware of this.schema.middleware.after) {
|
|
363
|
+
await this.executeMiddleware(middleware, req, res);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
break;
|
|
367
|
+
|
|
368
|
+
case "handler": {
|
|
369
|
+
const result = await this.schema.handler(req, res);
|
|
370
|
+
if (result !== undefined && !res.headersSent) {
|
|
371
|
+
res.json(result);
|
|
372
|
+
}
|
|
373
|
+
break;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
private async executeMiddleware(
|
|
379
|
+
middleware: Middleware,
|
|
380
|
+
req: HttpRequest,
|
|
381
|
+
res: HttpResponse,
|
|
382
|
+
): Promise<void> {
|
|
383
|
+
return new Promise((resolve, reject) => {
|
|
384
|
+
try {
|
|
385
|
+
const next = () => resolve();
|
|
386
|
+
const result = middleware(req, res, next);
|
|
387
|
+
if (result instanceof Promise) {
|
|
388
|
+
result.then(() => resolve()).catch(reject);
|
|
389
|
+
}
|
|
390
|
+
} catch (error) {
|
|
391
|
+
reject(error);
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
private async executeRateLimit(
|
|
397
|
+
req: HttpRequest,
|
|
398
|
+
res: HttpResponse,
|
|
399
|
+
): Promise<void> {
|
|
400
|
+
// Rate limiting implementation will be added
|
|
401
|
+
logger.debug("Rate limit check", "RateLimit", {
|
|
402
|
+
config: this.schema.rateLimit,
|
|
403
|
+
ip: req.ip,
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
private async executeAuth(
|
|
408
|
+
req: ValidatedRequest,
|
|
409
|
+
res: HttpResponse,
|
|
410
|
+
): Promise<void> {
|
|
411
|
+
// Authentication implementation will be added
|
|
412
|
+
logger.debug("Auth check", "Auth", {
|
|
413
|
+
config: this.schema.auth,
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
private async executeValidation(
|
|
418
|
+
req: ValidatedRequest,
|
|
419
|
+
res: HttpResponse,
|
|
420
|
+
): Promise<void> {
|
|
421
|
+
if (!this.schema.validation) return;
|
|
422
|
+
|
|
423
|
+
const { body, query, params, headers } = this.schema.validation;
|
|
424
|
+
|
|
425
|
+
// Validate body
|
|
426
|
+
if (body && req.body !== undefined) {
|
|
427
|
+
try {
|
|
428
|
+
req.validatedBody = await body.parseAsync(req.body);
|
|
429
|
+
req.body = req.validatedBody; // Update original for compatibility
|
|
430
|
+
} catch (error: any) {
|
|
431
|
+
this.sendValidationError(res, error, "body", req.requestId);
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// Validate query
|
|
437
|
+
if (query && req.query !== undefined) {
|
|
438
|
+
try {
|
|
439
|
+
req.validatedQuery = await query.parseAsync(req.query);
|
|
440
|
+
req.query = req.validatedQuery; // Update original for compatibility
|
|
441
|
+
} catch (error: any) {
|
|
442
|
+
this.sendValidationError(res, error, "query", req.requestId);
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// Validate params
|
|
448
|
+
if (params && req.params !== undefined) {
|
|
449
|
+
try {
|
|
450
|
+
req.validatedParams = await params.parseAsync(req.params);
|
|
451
|
+
req.params = req.validatedParams; // Update original for compatibility
|
|
452
|
+
} catch (error: any) {
|
|
453
|
+
this.sendValidationError(res, error, "params", req.requestId);
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// Validate headers
|
|
459
|
+
if (headers && req.headers !== undefined) {
|
|
460
|
+
try {
|
|
461
|
+
req.validatedHeaders = await headers.parseAsync(req.headers);
|
|
462
|
+
} catch (error: any) {
|
|
463
|
+
this.sendValidationError(res, error, "headers", req.requestId);
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
logger.debug("Validation passed", "Validation", {
|
|
469
|
+
route: `${this.schema.method} ${this.schema.path}`,
|
|
470
|
+
validatedFields: Object.keys(this.schema.validation),
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
private sendValidationError(
|
|
475
|
+
res: HttpResponse,
|
|
476
|
+
error: any,
|
|
477
|
+
field: string,
|
|
478
|
+
requestId?: string,
|
|
479
|
+
): void {
|
|
480
|
+
if (error.issues) {
|
|
481
|
+
res.status(400).json({
|
|
482
|
+
success: false,
|
|
483
|
+
error: `Validation failed for ${field}`,
|
|
484
|
+
details: error.issues.map((issue: any) => ({
|
|
485
|
+
field: issue.path.length > 0 ? issue.path.join(".") : field,
|
|
486
|
+
message: issue.message,
|
|
487
|
+
code: issue.code,
|
|
488
|
+
})),
|
|
489
|
+
requestId,
|
|
490
|
+
});
|
|
491
|
+
} else {
|
|
492
|
+
res.status(400).json({
|
|
493
|
+
success: false,
|
|
494
|
+
error: `Validation failed for ${field}`,
|
|
495
|
+
requestId,
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
private async executeCache(
|
|
501
|
+
req: HttpRequest,
|
|
502
|
+
res: HttpResponse,
|
|
503
|
+
): Promise<void> {
|
|
504
|
+
// Caching implementation will be added
|
|
505
|
+
logger.debug("Cache check", "Cache", {
|
|
506
|
+
config: this.schema.cache,
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
// Factory functions for creating routes
|
|
512
|
+
export function createRoute(method: HttpMethod, path: string): RouteBuilder {
|
|
513
|
+
return new IntelligentRouteBuilder(method, path);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// Schema-first route creation
|
|
517
|
+
export function defineRoute(schema: RouteSchema): CompiledRoute {
|
|
518
|
+
return new ExecutableRoute(schema);
|
|
519
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
// AWS Lambda runtime adapter
|
|
2
|
+
import { BaseRuntimeAdapter } from "./base-adapter";
|
|
3
|
+
import { HttpRequest, HttpResponse } from "../../types/http";
|
|
4
|
+
import { RuntimeHttpResponse } from "../../types/runtime";
|
|
5
|
+
|
|
6
|
+
export interface LambdaEvent {
|
|
7
|
+
httpMethod: string;
|
|
8
|
+
path: string;
|
|
9
|
+
pathParameters?: Record<string, string> | null;
|
|
10
|
+
queryStringParameters?: Record<string, string> | null;
|
|
11
|
+
headers?: Record<string, string> | null;
|
|
12
|
+
multiValueHeaders?: Record<string, string[]> | null;
|
|
13
|
+
body?: string | null;
|
|
14
|
+
isBase64Encoded?: boolean;
|
|
15
|
+
requestContext?: {
|
|
16
|
+
identity?: {
|
|
17
|
+
sourceIp?: string;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface LambdaContext {
|
|
23
|
+
requestId: string;
|
|
24
|
+
functionName: string;
|
|
25
|
+
functionVersion: string;
|
|
26
|
+
invokedFunctionArn: string;
|
|
27
|
+
memoryLimitInMB: string;
|
|
28
|
+
awsRequestId: string;
|
|
29
|
+
logGroupName: string;
|
|
30
|
+
logStreamName: string;
|
|
31
|
+
getRemainingTimeInMillis(): number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface LambdaResponse {
|
|
35
|
+
statusCode: number;
|
|
36
|
+
headers?: Record<string, string>;
|
|
37
|
+
multiValueHeaders?: Record<string, string[]>;
|
|
38
|
+
body: string;
|
|
39
|
+
isBase64Encoded?: boolean;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export class AWSLambdaAdapter extends BaseRuntimeAdapter {
|
|
43
|
+
readonly type = "aws-lambda" as const;
|
|
44
|
+
|
|
45
|
+
async adaptRequest(
|
|
46
|
+
event: LambdaEvent,
|
|
47
|
+
context: LambdaContext,
|
|
48
|
+
): Promise<HttpRequest> {
|
|
49
|
+
const { pathname, query } = this.parseUrl(event.path);
|
|
50
|
+
|
|
51
|
+
// Merge query parameters from event
|
|
52
|
+
const mergedQuery = {
|
|
53
|
+
...query,
|
|
54
|
+
...(event.queryStringParameters || {}),
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// Parse body
|
|
58
|
+
let body: any;
|
|
59
|
+
if (event.body) {
|
|
60
|
+
const contentType =
|
|
61
|
+
event.headers?.["content-type"] ||
|
|
62
|
+
event.headers?.["Content-Type"] ||
|
|
63
|
+
"";
|
|
64
|
+
if (event.isBase64Encoded) {
|
|
65
|
+
body = Buffer.from(event.body, "base64").toString();
|
|
66
|
+
} else {
|
|
67
|
+
body = event.body;
|
|
68
|
+
}
|
|
69
|
+
body = await this.parseBody(body, contentType);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const baseRequest = {
|
|
73
|
+
method: event.httpMethod,
|
|
74
|
+
url: event.path,
|
|
75
|
+
path: pathname,
|
|
76
|
+
query: mergedQuery,
|
|
77
|
+
body,
|
|
78
|
+
headers: event.headers || {},
|
|
79
|
+
ip: event.requestContext?.identity?.sourceIp || "unknown",
|
|
80
|
+
params: event.pathParameters || {},
|
|
81
|
+
requestId: context.awsRequestId,
|
|
82
|
+
cookies: this.parseCookies(event.headers?.cookie || ""),
|
|
83
|
+
files: {},
|
|
84
|
+
} as Partial<HttpRequest>;
|
|
85
|
+
|
|
86
|
+
return this.enhanceRequest(baseRequest);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async adaptResponse(
|
|
90
|
+
moroResponse: HttpResponse | RuntimeHttpResponse,
|
|
91
|
+
): Promise<LambdaResponse> {
|
|
92
|
+
const runtimeResponse = moroResponse as RuntimeHttpResponse;
|
|
93
|
+
|
|
94
|
+
let body = runtimeResponse.body;
|
|
95
|
+
const status = runtimeResponse.statusCode || 200;
|
|
96
|
+
const headers = runtimeResponse.headers || {};
|
|
97
|
+
|
|
98
|
+
// Convert body to string
|
|
99
|
+
if (typeof body === "object" && body !== null) {
|
|
100
|
+
body = JSON.stringify(body);
|
|
101
|
+
headers["Content-Type"] = "application/json";
|
|
102
|
+
} else if (body === null || body === undefined) {
|
|
103
|
+
body = "";
|
|
104
|
+
} else {
|
|
105
|
+
body = String(body);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
statusCode: status,
|
|
110
|
+
headers,
|
|
111
|
+
body,
|
|
112
|
+
isBase64Encoded: false,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
createServer(
|
|
117
|
+
handler: (req: HttpRequest, res: HttpResponse) => Promise<void>,
|
|
118
|
+
) {
|
|
119
|
+
// Return a Lambda-compatible handler function
|
|
120
|
+
return async (event: LambdaEvent, context: LambdaContext) => {
|
|
121
|
+
try {
|
|
122
|
+
const moroReq = await this.adaptRequest(event, context);
|
|
123
|
+
const moroRes = this.createMockResponse();
|
|
124
|
+
|
|
125
|
+
await handler(moroReq, moroRes as any);
|
|
126
|
+
|
|
127
|
+
return await this.adaptResponse(moroRes);
|
|
128
|
+
} catch (error) {
|
|
129
|
+
return {
|
|
130
|
+
statusCode: 500,
|
|
131
|
+
headers: { "Content-Type": "application/json" },
|
|
132
|
+
body: JSON.stringify({
|
|
133
|
+
success: false,
|
|
134
|
+
error: "Internal server error",
|
|
135
|
+
message: error instanceof Error ? error.message : "Unknown error",
|
|
136
|
+
}),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Lambda doesn't have a listen method - it's event-driven
|
|
143
|
+
// listen method is optional in the interface
|
|
144
|
+
|
|
145
|
+
private parseCookies(cookieHeader: string): Record<string, string> {
|
|
146
|
+
const cookies: Record<string, string> = {};
|
|
147
|
+
if (cookieHeader) {
|
|
148
|
+
cookieHeader.split(";").forEach((cookie) => {
|
|
149
|
+
const [name, ...rest] = cookie.trim().split("=");
|
|
150
|
+
if (name && rest.length > 0) {
|
|
151
|
+
cookies[name] = rest.join("=");
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
return cookies;
|
|
156
|
+
}
|
|
157
|
+
}
|