@morojs/moro 1.8.12 → 1.8.14

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 (90) hide show
  1. package/README.md +4 -2
  2. package/dist/core/cluster/thread-cluster.d.ts +25 -0
  3. package/dist/core/cluster/thread-cluster.js +95 -3
  4. package/dist/core/cluster/thread-cluster.js.map +1 -1
  5. package/dist/core/config/config-validator.js +20 -0
  6. package/dist/core/config/config-validator.js.map +1 -1
  7. package/dist/core/config/index.js +19 -2
  8. package/dist/core/config/index.js.map +1 -1
  9. package/dist/core/config/schema.js +1 -0
  10. package/dist/core/config/schema.js.map +1 -1
  11. package/dist/core/framework.d.ts +26 -0
  12. package/dist/core/framework.js +195 -6
  13. package/dist/core/framework.js.map +1 -1
  14. package/dist/core/http/http-server.d.ts +19 -0
  15. package/dist/core/http/http-server.js +75 -1
  16. package/dist/core/http/http-server.js.map +1 -1
  17. package/dist/core/http/http2-server.d.ts +15 -0
  18. package/dist/core/http/http2-server.js +36 -3
  19. package/dist/core/http/http2-server.js.map +1 -1
  20. package/dist/core/http/moro-engine-server.d.ts +28 -0
  21. package/dist/core/http/moro-engine-server.js +138 -12
  22. package/dist/core/http/moro-engine-server.js.map +1 -1
  23. package/dist/core/http/utils/body-type.d.ts +12 -0
  24. package/dist/core/http/utils/body-type.js +70 -0
  25. package/dist/core/http/utils/body-type.js.map +1 -0
  26. package/dist/core/http/utils/compression.d.ts +21 -0
  27. package/dist/core/http/utils/compression.js +53 -7
  28. package/dist/core/http/utils/compression.js.map +1 -1
  29. package/dist/core/http/utils/ssl-config.d.ts +11 -0
  30. package/dist/core/http/utils/ssl-config.js +3 -0
  31. package/dist/core/http/utils/ssl-config.js.map +1 -1
  32. package/dist/core/http/utils/uws-worker-clustering.js +5 -4
  33. package/dist/core/http/utils/uws-worker-clustering.js.map +1 -1
  34. package/dist/core/http/uws-http-server.d.ts +3 -0
  35. package/dist/core/http/uws-http-server.js +47 -2
  36. package/dist/core/http/uws-http-server.js.map +1 -1
  37. package/dist/core/middleware/built-in/body-parsers/index.d.ts +18 -0
  38. package/dist/core/middleware/built-in/body-parsers/index.js +41 -0
  39. package/dist/core/middleware/built-in/body-parsers/index.js.map +1 -1
  40. package/dist/core/middleware/built-in/cache/adapters/cache/redis.d.ts +32 -8
  41. package/dist/core/middleware/built-in/cache/adapters/cache/redis.js +117 -25
  42. package/dist/core/middleware/built-in/cache/adapters/cache/redis.js.map +1 -1
  43. package/dist/core/middleware/built-in/compression/core.d.ts +7 -0
  44. package/dist/core/middleware/built-in/compression/core.js +32 -1
  45. package/dist/core/middleware/built-in/compression/core.js.map +1 -1
  46. package/dist/core/middleware/built-in/session/core.d.ts +1 -0
  47. package/dist/core/middleware/built-in/session/core.js.map +1 -1
  48. package/dist/core/middleware/built-in/static/core.d.ts +18 -0
  49. package/dist/core/middleware/built-in/static/core.js +128 -7
  50. package/dist/core/middleware/built-in/static/core.js.map +1 -1
  51. package/dist/core/networking/adapters/engine-adapter.d.ts +2 -2
  52. package/dist/core/networking/adapters/engine-adapter.js +40 -1
  53. package/dist/core/networking/adapters/engine-adapter.js.map +1 -1
  54. package/dist/core/networking/adapters/socketio-adapter.d.ts +2 -2
  55. package/dist/core/networking/adapters/socketio-adapter.js +10 -1
  56. package/dist/core/networking/adapters/socketio-adapter.js.map +1 -1
  57. package/dist/core/networking/adapters/uws-adapter.d.ts +2 -2
  58. package/dist/core/networking/adapters/uws-adapter.js +54 -3
  59. package/dist/core/networking/adapters/uws-adapter.js.map +1 -1
  60. package/dist/core/networking/adapters/ws-adapter.d.ts +9 -2
  61. package/dist/core/networking/adapters/ws-adapter.js +97 -12
  62. package/dist/core/networking/adapters/ws-adapter.js.map +1 -1
  63. package/dist/core/networking/websocket-adapter.d.ts +19 -1
  64. package/dist/core/networking/websocket-adapter.js.map +1 -1
  65. package/dist/core/routing/index.d.ts +12 -8
  66. package/dist/core/routing/index.js +7 -2
  67. package/dist/core/routing/index.js.map +1 -1
  68. package/dist/core/routing/unified-router.d.ts +46 -8
  69. package/dist/core/routing/unified-router.js +108 -32
  70. package/dist/core/routing/unified-router.js.map +1 -1
  71. package/dist/core/utilities/package-utils.d.ts +8 -1
  72. package/dist/core/utilities/package-utils.js +2 -0
  73. package/dist/core/utilities/package-utils.js.map +1 -1
  74. package/dist/core/workers/worker-manager.js +2 -2
  75. package/dist/core/workers/worker-manager.js.map +1 -1
  76. package/dist/index.d.ts +4 -3
  77. package/dist/index.js +2 -1
  78. package/dist/index.js.map +1 -1
  79. package/dist/moro.d.ts +12 -1
  80. package/dist/moro.js +63 -7
  81. package/dist/moro.js.map +1 -1
  82. package/dist/types/cache.d.ts +2 -0
  83. package/dist/types/cache.js.map +1 -1
  84. package/dist/types/config.d.ts +16 -0
  85. package/dist/types/config.js.map +1 -1
  86. package/dist/types/http.d.ts +6 -0
  87. package/dist/types/http.js.map +1 -1
  88. package/dist/types/session.d.ts +1 -0
  89. package/dist/types/session.js.map +1 -1
  90. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/routing/index.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,oEAAoE;AACpE,EAAE;AACF,kEAAkE;AAClE,+DAA+D;AAI/D,OAAO,EACL,aAAa,EACb,kBAAkB,GAInB,MAAM,qBAAqB,CAAC;AA8D7B,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,UAAU;IACV,SAAS;IACT,WAAW;IACX,QAAQ;IACR,MAAM;IACN,YAAY;IACZ,WAAW;IACX,OAAO;IACP,OAAO;IACP,SAAS;CACD,CAAC;AA0CX,iEAAiE;AAEjE;;;GAGG;AACH,MAAM,OAAO,uBAAuB;IAC1B,MAAM,CAAuB;IAC7B,MAAM,GAAG,aAAa,CAAC,WAAW,EAAE,CAAC;IAE7C,YAAY,MAAkB,EAAE,IAAY;QAC1C,IAAI,CAAC,MAAM,GAAG;YACZ,MAAM;YACN,IAAI;YACJ,UAAU,EAAE,EAAsB;SACnC,CAAC;IACJ,CAAC;IAED,QAAQ,CAAC,MAAwB;QAC/B,oDAAoD;QACpD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;YAC5B,IAAI,CAAC,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC;QAClC,CAAC;aAAM,CAAC;YACN,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS;gBAAE,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;YACzE,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS;gBAAE,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;YAC5E,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS;gBAAE,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;YAC/E,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS;gBAAE,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QACpF,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAI,MAA2B;QACjC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU;YAAE,IAAI,CAAC,MAAM,CAAC,UAAU,GAAG,EAAE,CAAC;QACzD,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,GAAG,MAAM,CAAC;QACrC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAI,MAA2B;QAClC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU;YAAE,IAAI,CAAC,MAAM,CAAC,UAAU,GAAG,EAAE,CAAC;QACzD,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,GAAG,MAAM,CAAC;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,CAAI,MAA2B;QACnC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU;YAAE,IAAI,CAAC,MAAM,CAAC,UAAU,GAAG,EAAE,CAAC;QACzD,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,MAAM,CAAC;QACvC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CAAI,MAA2B;QACpC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU;YAAE,IAAI,CAAC,MAAM,CAAC,UAAU,GAAG,EAAE,CAAC;QACzD,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,GAAG,MAAM,CAAC;QACxC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,MAAkB;QACrB,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,SAAS,CAAC,MAAuB;QAC/B,IAAI,CAAC,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,MAAmB;QACvB,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,CAAC,GAAG,UAAwB;QAChC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU;YAAE,IAAI,CAAC,MAAM,CAAC,UAAU,GAAG,EAAE,CAAC;QACzD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,UAA8B,CAAC;QAC1D,gDAAgD;QAChD,IAAI,CAAC,MAAM,CAAC,MAAM;YAAE,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC;QACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAe,CAAC,CAAC;QAClD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,GAAG,UAAwB;QAC/B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU;YAAE,IAAI,CAAC,MAAM,CAAC,UAAU,GAAG,EAAE,CAAC;QACzD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,UAA8B,CAAC;QAC1D,gDAAgD;QAChD,IAAI,CAAC,MAAM,CAAC,KAAK;YAAE,MAAM,CAAC,KAAK,GAAG,EAAE,CAAC;QACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3C,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAe,CAAC,CAAC;QACjD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,SAAS,CAAC,GAAG,UAAwB;QACnC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU;YAAE,IAAI,CAAC,MAAM,CAAC,UAAU,GAAG,EAAE,CAAC;QACzD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,UAA8B,CAAC;QAC1D,gDAAgD;QAChD,IAAI,CAAC,MAAM,CAAC,SAAS;YAAE,MAAM,CAAC,SAAS,GAAG,EAAE,CAAC;QAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3C,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAe,CAAC,CAAC;QACrD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,GAAG,CAAC,GAAG,UAAwB;QAC7B,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,UAAU,CAAC,CAAC;IACnC,CAAC;IAED,QAAQ,CAAC,WAAmB;QAC1B,IAAI,CAAC,MAAM,CAAC,WAAW,GAAG,WAAW,CAAC;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,GAAG,CAAC,GAAG,IAAc;QACnB,gDAAgD;QAChD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI;YAAE,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;QAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAW,CAAC,CAAC;QAC3C,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CAAI,OAAqC;QAC9C,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;YAClC,+CAA+C;YAC/C,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;YAE9B,4BAA4B;YAC5B,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,MAAqB,CAAC,CAAC;YACtD,OAAO;QACT,CAAC;QACD,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5D,IAAI,CAAC,MAAM,CAAC,aAAa,CACvB,kBAAkB,CAAC,IAAI,CAAC,MAAqC,EAAE,OAAO,CAAC,CACxE,CAAC;YACF,OAAO;QACT,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC;IACjG,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,eAAe;IACE;IAA5B,YAA4B,MAAmB;QAAnB,WAAM,GAAN,MAAM,CAAa;QAC7C,8BAA8B;QAC9B,aAAa,CAAC,WAAW,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,IAAiB,EAAE,IAAkB;QACjD,yDAAyD;QACzD,kDAAkD;QAClD,MAAM,IAAI,KAAK,CACb,4FAA4F,CAC7F,CAAC;IACJ,CAAC;CACF;AAED,yDAAyD;AAEzD,MAAM,UAAU,WAAW,CAAC,MAAkB,EAAE,IAAY;IAC1D,OAAO,IAAI,uBAAuB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAmB;IAC7C,OAAO,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC;AACrC,CAAC;AAED,6CAA6C;AAE7C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,IAAI,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAuC,MAAM,mBAAmB,CAAC;AACrF,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC","sourcesContent":["// Intelligent Routing System for Moro Framework\n// Schema-first with automatic middleware ordering and chainable API\n//\n// NOTE: This file exports types and thin facades to UnifiedRouter\n// All routing logic has been consolidated in unified-router.ts\n\nimport { ValidationSchema } from '../validation/schema-interface.js';\nimport { HttpRequest, HttpResponse } from '../http/index.js';\nimport {\n UnifiedRouter,\n compileStaticRoute,\n type RouteSchema as UnifiedRouteSchema,\n type StaticBody,\n type StaticResponse,\n} from './unified-router.js';\n\nexport type { StaticBody, StaticResponse };\n\n// ===== TYPE EXPORTS (Keep all - used by app code) =====\n\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';\nexport type RouteHandler<T = any> = (req: HttpRequest, res: HttpResponse) => T | Promise<T>;\nexport type Middleware = (\n req: HttpRequest,\n res: HttpResponse,\n next: () => void\n) => void | Promise<void>;\n\nexport interface ValidationConfig {\n body?: ValidationSchema;\n query?: ValidationSchema;\n params?: ValidationSchema;\n headers?: ValidationSchema;\n}\n\nexport interface AuthConfig {\n roles?: string[];\n permissions?: string[];\n optional?: boolean;\n}\n\nexport interface RateLimitConfig {\n requests: number;\n window: number;\n skipSuccessfulRequests?: boolean;\n skipFailedRequests?: boolean;\n}\n\nexport interface CacheConfig {\n ttl: number;\n key?: string;\n tags?: string[];\n}\n\nexport interface MiddlewarePhases {\n before?: Middleware[];\n after?: Middleware[];\n transform?: Middleware[];\n}\n\nexport interface RouteSchema {\n method: HttpMethod;\n path: string;\n /** A function, or the response body itself (see StaticBody / .handler()) */\n handler: RouteHandler | StaticBody;\n validation?: ValidationConfig;\n auth?: AuthConfig;\n rateLimit?: RateLimitConfig;\n cache?: CacheConfig;\n middleware?: MiddlewarePhases;\n description?: string;\n tags?: string[];\n /** Fixed reply of a literal handler; see StaticResponse */\n static?: StaticResponse;\n}\n\nexport const EXECUTION_PHASES = [\n 'security',\n 'parsing',\n 'rateLimit',\n 'before',\n 'auth',\n 'validation',\n 'transform',\n 'cache',\n 'after',\n 'handler',\n] as const;\n\nexport type ExecutionPhase = (typeof EXECUTION_PHASES)[number];\n\nexport interface ValidatedRequest<T = any> extends HttpRequest {\n validatedBody?: T;\n validatedQuery?: any;\n validatedParams?: any;\n validatedHeaders?: any;\n user?: any;\n}\n\n// ===== ROUTE BUILDER INTERFACE (Public API) =====\n\nexport interface RouteBuilder {\n validate(config: ValidationConfig): RouteBuilder;\n body<T>(schema: ValidationSchema<T>): RouteBuilder;\n query<T>(schema: ValidationSchema<T>): RouteBuilder;\n params<T>(schema: ValidationSchema<T>): RouteBuilder;\n headers<T>(schema: ValidationSchema<T>): RouteBuilder;\n auth(config: AuthConfig): RouteBuilder;\n rateLimit(config: RateLimitConfig): RouteBuilder;\n cache(config: CacheConfig): RouteBuilder;\n before(...middleware: Middleware[]): RouteBuilder;\n after(...middleware: Middleware[]): RouteBuilder;\n transform(...middleware: Middleware[]): RouteBuilder;\n use(...middleware: Middleware[]): RouteBuilder;\n describe(description: string): RouteBuilder;\n tag(...tags: string[]): RouteBuilder;\n /** Terminal. A function handles the request; a string or Buffer IS the\n * response body (as res.send would send it), and on a route with nothing\n * else configured Moro's native engine answers it without calling JS. */\n handler<T>(handler: RouteHandler<T> | StaticBody): void;\n}\n\n// ===== COMPILED ROUTE INTERFACE (Public API) =====\n\nexport interface CompiledRoute {\n schema: RouteSchema;\n execute(req: HttpRequest, res: HttpResponse): Promise<void>;\n}\n\n// ===== FACADE IMPLEMENTATIONS (Delegate to UnifiedRouter) =====\n\n/**\n * Thin facade to UnifiedRouter.RouteBuilder\n * Maintains backward compatibility while using optimized implementation\n */\nexport class IntelligentRouteBuilder implements RouteBuilder {\n private schema: Partial<RouteSchema>;\n private router = UnifiedRouter.getInstance();\n\n constructor(method: HttpMethod, path: string) {\n this.schema = {\n method,\n path,\n middleware: {} as MiddlewarePhases,\n };\n }\n\n validate(config: ValidationConfig): RouteBuilder {\n // Avoid spread operator - manually merge properties\n if (!this.schema.validation) {\n this.schema.validation = config;\n } else {\n if (config.body !== undefined) this.schema.validation.body = config.body;\n if (config.query !== undefined) this.schema.validation.query = config.query;\n if (config.params !== undefined) this.schema.validation.params = config.params;\n if (config.headers !== undefined) this.schema.validation.headers = config.headers;\n }\n return this;\n }\n\n body<T>(schema: ValidationSchema<T>): RouteBuilder {\n if (!this.schema.validation) this.schema.validation = {};\n this.schema.validation.body = schema;\n return this;\n }\n\n query<T>(schema: ValidationSchema<T>): RouteBuilder {\n if (!this.schema.validation) this.schema.validation = {};\n this.schema.validation.query = schema;\n return this;\n }\n\n params<T>(schema: ValidationSchema<T>): RouteBuilder {\n if (!this.schema.validation) this.schema.validation = {};\n this.schema.validation.params = schema;\n return this;\n }\n\n headers<T>(schema: ValidationSchema<T>): RouteBuilder {\n if (!this.schema.validation) this.schema.validation = {};\n this.schema.validation.headers = schema;\n return this;\n }\n\n auth(config: AuthConfig): RouteBuilder {\n this.schema.auth = config;\n return this;\n }\n\n rateLimit(config: RateLimitConfig): RouteBuilder {\n this.schema.rateLimit = config;\n return this;\n }\n\n cache(config: CacheConfig): RouteBuilder {\n this.schema.cache = config;\n return this;\n }\n\n before(...middleware: Middleware[]): RouteBuilder {\n if (!this.schema.middleware) this.schema.middleware = {};\n const phases = this.schema.middleware as MiddlewarePhases;\n // Avoid spread, use push for better performance\n if (!phases.before) phases.before = [];\n for (let i = 0; i < middleware.length; i++) {\n phases.before.push(middleware[i] as Middleware);\n }\n return this;\n }\n\n after(...middleware: Middleware[]): RouteBuilder {\n if (!this.schema.middleware) this.schema.middleware = {};\n const phases = this.schema.middleware as MiddlewarePhases;\n // Avoid spread, use push for better performance\n if (!phases.after) phases.after = [];\n for (let i = 0; i < middleware.length; i++) {\n phases.after.push(middleware[i] as Middleware);\n }\n return this;\n }\n\n transform(...middleware: Middleware[]): RouteBuilder {\n if (!this.schema.middleware) this.schema.middleware = {};\n const phases = this.schema.middleware as MiddlewarePhases;\n // Avoid spread, use push for better performance\n if (!phases.transform) phases.transform = [];\n for (let i = 0; i < middleware.length; i++) {\n phases.transform.push(middleware[i] as Middleware);\n }\n return this;\n }\n\n use(...middleware: Middleware[]): RouteBuilder {\n return this.after(...middleware);\n }\n\n describe(description: string): RouteBuilder {\n this.schema.description = description;\n return this;\n }\n\n tag(...tags: string[]): RouteBuilder {\n // Avoid spread, use push for better performance\n if (!this.schema.tags) this.schema.tags = [];\n for (let i = 0; i < tags.length; i++) {\n this.schema.tags.push(tags[i] as string);\n }\n return this;\n }\n\n handler<T>(handler: RouteHandler<T> | StaticBody): void {\n if (typeof handler === 'function') {\n // Avoid spread operator - add handler directly\n this.schema.handler = handler;\n\n // Delegate to UnifiedRouter\n this.router.registerRoute(this.schema as RouteSchema);\n return;\n }\n if (typeof handler === 'string' || Buffer.isBuffer(handler)) {\n this.router.registerRoute(\n compileStaticRoute(this.schema as Partial<UnifiedRouteSchema>, handler)\n );\n return;\n }\n throw new Error('Handler is required: a function, or the response body as a string or Buffer');\n }\n}\n\n/**\n * Thin facade implementing CompiledRoute interface\n * Just stores schema for documentation purposes\n */\nexport class ExecutableRoute implements CompiledRoute {\n constructor(public readonly schema: RouteSchema) {\n // Register with UnifiedRouter\n UnifiedRouter.getInstance().registerRoute(schema);\n }\n\n async execute(_req: HttpRequest, _res: HttpResponse): Promise<void> {\n // This is never called - UnifiedRouter handles execution\n // But we implement it for interface compatibility\n throw new Error(\n 'ExecutableRoute.execute() should not be called directly - routing handled by UnifiedRouter'\n );\n }\n}\n\n// ===== FACTORY FUNCTIONS (Backward Compatibility) =====\n\nexport function createRoute(method: HttpMethod, path: string): RouteBuilder {\n return new IntelligentRouteBuilder(method, path);\n}\n\nexport function defineRoute(schema: RouteSchema): CompiledRoute {\n return new ExecutableRoute(schema);\n}\n\n// ===== RE-EXPORTS FROM UNIFIED ROUTER =====\n\nexport { UnifiedRouter } from './unified-router.js';\nexport { RouteBuilder as UnifiedRouteBuilder } from './unified-router.js';\nexport { PathMatcher, type CompiledPath, type MatchResult } from './path-matcher.js';\nexport { ObjectPoolManager, getPoolManager } from '../pooling/object-pool-manager.js';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/routing/index.ts"],"names":[],"mappings":"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","sourcesContent":["// Intelligent Routing System for Moro Framework\n// Schema-first with automatic middleware ordering and chainable API\n//\n// NOTE: This file exports types and thin facades to UnifiedRouter\n// All routing logic has been consolidated in unified-router.ts\n\nimport { ValidationSchema } from '../validation/schema-interface.js';\nimport { HttpRequest, HttpResponse } from '../http/index.js';\nimport {\n UnifiedRouter,\n compileStaticRoute,\n compileParamRoute,\n isParamEcho,\n param,\n type RouteSchema as UnifiedRouteSchema,\n type StaticBody,\n type StaticResponse,\n type ParamEcho,\n type ParamRouteReply,\n} from './unified-router.js';\n\nexport type { StaticBody, StaticResponse, ParamEcho, ParamRouteReply };\nexport { param };\n\n// ===== TYPE EXPORTS (Keep all - used by app code) =====\n\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';\nexport type RouteHandler<T = any> = (req: HttpRequest, res: HttpResponse) => T | Promise<T>;\nexport type Middleware = (\n req: HttpRequest,\n res: HttpResponse,\n next: () => void\n) => void | Promise<void>;\n\nexport interface ValidationConfig {\n body?: ValidationSchema;\n query?: ValidationSchema;\n params?: ValidationSchema;\n headers?: ValidationSchema;\n}\n\nexport interface AuthConfig {\n roles?: string[];\n permissions?: string[];\n optional?: boolean;\n}\n\nexport interface RateLimitConfig {\n requests: number;\n window: number;\n skipSuccessfulRequests?: boolean;\n skipFailedRequests?: boolean;\n}\n\nexport interface CacheConfig {\n ttl: number;\n key?: string;\n tags?: string[];\n}\n\nexport interface MiddlewarePhases {\n before?: Middleware[];\n after?: Middleware[];\n transform?: Middleware[];\n}\n\nexport interface RouteSchema {\n method: HttpMethod;\n path: string;\n /** A function, the response body itself (StaticBody), or param(name) */\n handler: RouteHandler | StaticBody | ParamEcho;\n validation?: ValidationConfig;\n auth?: AuthConfig;\n rateLimit?: RateLimitConfig;\n cache?: CacheConfig;\n middleware?: MiddlewarePhases;\n description?: string;\n tags?: string[];\n /** Fixed reply of a literal handler; see StaticResponse */\n static?: StaticResponse;\n /** Engine shape of a param(name) handler; see ParamRouteReply */\n paramEcho?: ParamRouteReply;\n}\n\nexport const EXECUTION_PHASES = [\n 'security',\n 'parsing',\n 'rateLimit',\n 'before',\n 'auth',\n 'validation',\n 'transform',\n 'cache',\n 'after',\n 'handler',\n] as const;\n\nexport type ExecutionPhase = (typeof EXECUTION_PHASES)[number];\n\nexport interface ValidatedRequest<T = any> extends HttpRequest {\n validatedBody?: T;\n validatedQuery?: any;\n validatedParams?: any;\n validatedHeaders?: any;\n user?: any;\n}\n\n// ===== ROUTE BUILDER INTERFACE (Public API) =====\n\nexport interface RouteBuilder {\n validate(config: ValidationConfig): RouteBuilder;\n body<T>(schema: ValidationSchema<T>): RouteBuilder;\n query<T>(schema: ValidationSchema<T>): RouteBuilder;\n params<T>(schema: ValidationSchema<T>): RouteBuilder;\n headers<T>(schema: ValidationSchema<T>): RouteBuilder;\n auth(config: AuthConfig): RouteBuilder;\n rateLimit(config: RateLimitConfig): RouteBuilder;\n cache(config: CacheConfig): RouteBuilder;\n before(...middleware: Middleware[]): RouteBuilder;\n after(...middleware: Middleware[]): RouteBuilder;\n transform(...middleware: Middleware[]): RouteBuilder;\n use(...middleware: Middleware[]): RouteBuilder;\n describe(description: string): RouteBuilder;\n tag(...tags: string[]): RouteBuilder;\n /** Terminal. A function handles the request; a string or Buffer IS the\n * response body (as res.send would send it); param(name) echoes that path\n * parameter as the body. On a route with nothing else configured Moro's\n * native engine answers the last two without calling JS. */\n handler<T>(handler: RouteHandler<T> | StaticBody | ParamEcho): void;\n}\n\n// ===== COMPILED ROUTE INTERFACE (Public API) =====\n\nexport interface CompiledRoute {\n schema: RouteSchema;\n execute(req: HttpRequest, res: HttpResponse): Promise<void>;\n}\n\n// ===== FACADE IMPLEMENTATIONS (Delegate to UnifiedRouter) =====\n\n/**\n * Thin facade to UnifiedRouter.RouteBuilder\n * Maintains backward compatibility while using optimized implementation\n */\nexport class IntelligentRouteBuilder implements RouteBuilder {\n private schema: Partial<RouteSchema>;\n private router = UnifiedRouter.getInstance();\n\n constructor(method: HttpMethod, path: string) {\n this.schema = {\n method,\n path,\n middleware: {} as MiddlewarePhases,\n };\n }\n\n validate(config: ValidationConfig): RouteBuilder {\n // Avoid spread operator - manually merge properties\n if (!this.schema.validation) {\n this.schema.validation = config;\n } else {\n if (config.body !== undefined) this.schema.validation.body = config.body;\n if (config.query !== undefined) this.schema.validation.query = config.query;\n if (config.params !== undefined) this.schema.validation.params = config.params;\n if (config.headers !== undefined) this.schema.validation.headers = config.headers;\n }\n return this;\n }\n\n body<T>(schema: ValidationSchema<T>): RouteBuilder {\n if (!this.schema.validation) this.schema.validation = {};\n this.schema.validation.body = schema;\n return this;\n }\n\n query<T>(schema: ValidationSchema<T>): RouteBuilder {\n if (!this.schema.validation) this.schema.validation = {};\n this.schema.validation.query = schema;\n return this;\n }\n\n params<T>(schema: ValidationSchema<T>): RouteBuilder {\n if (!this.schema.validation) this.schema.validation = {};\n this.schema.validation.params = schema;\n return this;\n }\n\n headers<T>(schema: ValidationSchema<T>): RouteBuilder {\n if (!this.schema.validation) this.schema.validation = {};\n this.schema.validation.headers = schema;\n return this;\n }\n\n auth(config: AuthConfig): RouteBuilder {\n this.schema.auth = config;\n return this;\n }\n\n rateLimit(config: RateLimitConfig): RouteBuilder {\n this.schema.rateLimit = config;\n return this;\n }\n\n cache(config: CacheConfig): RouteBuilder {\n this.schema.cache = config;\n return this;\n }\n\n before(...middleware: Middleware[]): RouteBuilder {\n if (!this.schema.middleware) this.schema.middleware = {};\n const phases = this.schema.middleware as MiddlewarePhases;\n // Avoid spread, use push for better performance\n if (!phases.before) phases.before = [];\n for (let i = 0; i < middleware.length; i++) {\n phases.before.push(middleware[i] as Middleware);\n }\n return this;\n }\n\n after(...middleware: Middleware[]): RouteBuilder {\n if (!this.schema.middleware) this.schema.middleware = {};\n const phases = this.schema.middleware as MiddlewarePhases;\n // Avoid spread, use push for better performance\n if (!phases.after) phases.after = [];\n for (let i = 0; i < middleware.length; i++) {\n phases.after.push(middleware[i] as Middleware);\n }\n return this;\n }\n\n transform(...middleware: Middleware[]): RouteBuilder {\n if (!this.schema.middleware) this.schema.middleware = {};\n const phases = this.schema.middleware as MiddlewarePhases;\n // Avoid spread, use push for better performance\n if (!phases.transform) phases.transform = [];\n for (let i = 0; i < middleware.length; i++) {\n phases.transform.push(middleware[i] as Middleware);\n }\n return this;\n }\n\n use(...middleware: Middleware[]): RouteBuilder {\n return this.after(...middleware);\n }\n\n describe(description: string): RouteBuilder {\n this.schema.description = description;\n return this;\n }\n\n tag(...tags: string[]): RouteBuilder {\n // Avoid spread, use push for better performance\n if (!this.schema.tags) this.schema.tags = [];\n for (let i = 0; i < tags.length; i++) {\n this.schema.tags.push(tags[i] as string);\n }\n return this;\n }\n\n handler<T>(handler: RouteHandler<T> | StaticBody | ParamEcho): void {\n if (typeof handler === 'function') {\n // Avoid spread operator - add handler directly\n this.schema.handler = handler;\n\n // Delegate to UnifiedRouter\n this.router.registerRoute(this.schema as RouteSchema);\n return;\n }\n if (typeof handler === 'string' || Buffer.isBuffer(handler)) {\n this.router.registerRoute(\n compileStaticRoute(this.schema as Partial<UnifiedRouteSchema>, handler)\n );\n return;\n }\n if (isParamEcho(handler)) {\n this.router.registerRoute(\n compileParamRoute(this.schema as Partial<UnifiedRouteSchema>, handler)\n );\n return;\n }\n throw new Error(\n 'Handler is required: a function, the response body as a string or Buffer, or param(name)'\n );\n }\n}\n\n/**\n * Thin facade implementing CompiledRoute interface\n * Just stores schema for documentation purposes\n */\nexport class ExecutableRoute implements CompiledRoute {\n constructor(public readonly schema: RouteSchema) {\n // Register with UnifiedRouter\n UnifiedRouter.getInstance().registerRoute(schema);\n }\n\n async execute(_req: HttpRequest, _res: HttpResponse): Promise<void> {\n // This is never called - UnifiedRouter handles execution\n // But we implement it for interface compatibility\n throw new Error(\n 'ExecutableRoute.execute() should not be called directly - routing handled by UnifiedRouter'\n );\n }\n}\n\n// ===== FACTORY FUNCTIONS (Backward Compatibility) =====\n\nexport function createRoute(method: HttpMethod, path: string): RouteBuilder {\n return new IntelligentRouteBuilder(method, path);\n}\n\nexport function defineRoute(schema: RouteSchema): CompiledRoute {\n return new ExecutableRoute(schema);\n}\n\n// ===== RE-EXPORTS FROM UNIFIED ROUTER =====\n\nexport { UnifiedRouter } from './unified-router.js';\nexport { RouteBuilder as UnifiedRouteBuilder } from './unified-router.js';\nexport { PathMatcher, type CompiledPath, type MatchResult } from './path-matcher.js';\nexport { ObjectPoolManager, getPoolManager } from '../pooling/object-pool-manager.js';\n"]}
@@ -21,7 +21,7 @@ export interface RouteSchema {
21
21
  method: HttpMethod;
22
22
  path: string;
23
23
  /** A function, or the response body itself (see StaticBody) */
24
- handler: RouteHandler | StaticBody;
24
+ handler: RouteHandler | StaticBody | ParamEcho;
25
25
  validation?: ValidationConfig;
26
26
  auth?: AuthConfig;
27
27
  rateLimit?: RateLimitConfig;
@@ -34,6 +34,18 @@ export interface RouteSchema {
34
34
  * calling into JS; every other server runs `handler`, which sends the
35
35
  * same bytes. */
36
36
  static?: StaticResponse;
37
+ /** The engine shape of a param(name) handler on a bare route with exactly
38
+ * that one parameter: the path segment between prefix and suffix is the
39
+ * body. MoroEngineServer on @morojs/engine >= 1.1.9 (paramRoutes) answers
40
+ * it without calling into JS; every other server runs `handler`. */
41
+ paramEcho?: ParamRouteReply;
42
+ }
43
+ export interface ParamRouteReply {
44
+ name: string;
45
+ prefix: string;
46
+ suffix: string;
47
+ status: number;
48
+ headers: string[] | null;
37
49
  }
38
50
  /** The reply a literal handler sends, in the engine's shape. */
39
51
  export interface StaticResponse {
@@ -44,14 +56,40 @@ export interface StaticResponse {
44
56
  }
45
57
  /** What .handler() accepts in place of a function: the response body itself. */
46
58
  export type StaticBody = string | Buffer;
59
+ export declare const PARAM_ECHO: unique symbol;
60
+ /** The marker param(name) produces: "answer with this path parameter as the
61
+ * body". `.handler(param('id'))` on `/user/:id` answers `GET /user/42` with
62
+ * `42`, as `res.end(req.params.id)` would - and on Moro's native engine, on
63
+ * a route with nothing else configured, without entering JS at all. */
64
+ export interface ParamEcho {
65
+ readonly [PARAM_ECHO]: true;
66
+ readonly name: string;
67
+ }
68
+ export declare function param(name: string): ParamEcho;
69
+ export declare function isParamEcho(value: unknown): value is ParamEcho;
70
+ /**
71
+ * param(name) in place of a handler: the route answers with that path
72
+ * parameter as the body, as res.end(req.params[name]) would. When `:name` is
73
+ * a whole segment of the path, the only parameter in it, and nothing else is
74
+ * configured, the schema also carries `paramEcho` - prefix and suffix around
75
+ * the segment - so a server that can answer it natively does so without
76
+ * calling into JS. The engine echoes the segment as it is on the wire,
77
+ * undecoded (as uWS does); a parameter that needs decoding stays a function
78
+ * handler.
79
+ */
80
+ export declare function compileParamRoute(schema: Partial<RouteSchema>, echo: ParamEcho): RouteSchema;
47
81
  /**
48
82
  * A literal body in place of a handler: the route answers with exactly that
49
- * body, as res.send(body) would (status 200, the implied content-type). When
50
- * nothing else is configured on the route - no auth, validation, rate limit,
51
- * cache or middleware, and a literal path - the schema also carries `static`,
52
- * so a server that can answer it natively does so without calling into JS.
53
- * Anything configured keeps the route on the normal pipeline, where the
54
- * handler sends the same bytes after that configuration has run.
83
+ * body. A non-empty body goes out as res.send(body) would (status 200, the
84
+ * implied content-type). An empty body has nothing a content-type could
85
+ * describe, so it goes out as res.end() would: status and Content-Length: 0,
86
+ * no header block - 38 bytes less per response, and byte-identical to the
87
+ * engine's own static reply with no headers. When nothing else is configured
88
+ * on the route - no auth, validation, rate limit, cache or middleware, and a
89
+ * literal path - the schema also carries `static`, so a server that can
90
+ * answer it natively does so without calling into JS. Anything configured
91
+ * keeps the route on the normal pipeline, where the handler sends the same
92
+ * bytes after that configuration has run.
55
93
  */
56
94
  export declare function compileStaticRoute(schema: Partial<RouteSchema>, body: StaticBody): RouteSchema;
57
95
  export declare class RouteBuilder {
@@ -72,7 +110,7 @@ export declare class RouteBuilder {
72
110
  use(...middleware: Middleware[]): this;
73
111
  describe(description: string): this;
74
112
  tag(...tags: string[]): this;
75
- handler<T>(handler: RouteHandler<T> | StaticBody): void;
113
+ handler<T>(handler: RouteHandler<T> | StaticBody | ParamEcho): void;
76
114
  }
77
115
  export declare class UnifiedRouter {
78
116
  private static instance;
@@ -13,6 +13,74 @@ const logger = createFrameworkLogger('UnifiedRouter');
13
13
  const rateLimitCore = new RateLimitCore();
14
14
  const cacheCore = new CacheCore();
15
15
  const validationCore = new ValidationCore();
16
+ export const PARAM_ECHO = Symbol.for('moro.paramEcho');
17
+ export function param(name) {
18
+ if (typeof name !== 'string' || name.length === 0) {
19
+ throw new Error('param(name) needs the parameter name, e.g. param("id") for "/user/:id"');
20
+ }
21
+ return Object.freeze({ [PARAM_ECHO]: true, name });
22
+ }
23
+ export function isParamEcho(value) {
24
+ return (typeof value === 'object' &&
25
+ value !== null &&
26
+ value[PARAM_ECHO] === true);
27
+ }
28
+ // Nothing configured that a reply answered inside the engine would skip:
29
+ // no auth, validation, rate limit, cache or middleware. (Static replies also
30
+ // need a literal path; parameter echoes need exactly one parameter.)
31
+ function isBareRoute(schema) {
32
+ const mw = schema.middleware;
33
+ const hasMiddleware = Array.isArray(mw)
34
+ ? mw.length > 0
35
+ : mw !== undefined &&
36
+ Object.keys(mw).some(phase => {
37
+ const list = mw[phase];
38
+ return Array.isArray(list) && list.length > 0;
39
+ });
40
+ return !schema.auth && !schema.validation && !schema.rateLimit && !schema.cache && !hasMiddleware;
41
+ }
42
+ /**
43
+ * param(name) in place of a handler: the route answers with that path
44
+ * parameter as the body, as res.end(req.params[name]) would. When `:name` is
45
+ * a whole segment of the path, the only parameter in it, and nothing else is
46
+ * configured, the schema also carries `paramEcho` - prefix and suffix around
47
+ * the segment - so a server that can answer it natively does so without
48
+ * calling into JS. The engine echoes the segment as it is on the wire,
49
+ * undecoded (as uWS does); a parameter that needs decoding stays a function
50
+ * handler.
51
+ */
52
+ export function compileParamRoute(schema, echo) {
53
+ const name = echo.name;
54
+ schema.handler = (req, res) => {
55
+ const value = req.params?.[name];
56
+ res.end(value === undefined ? undefined : String(value));
57
+ };
58
+ const path = schema.path ?? '';
59
+ const segments = path.split('/');
60
+ const marker = `:${name}`;
61
+ const at = segments.indexOf(marker);
62
+ if (at === -1) {
63
+ // The router names a parameter after its whole segment, so ":name.json"
64
+ // is a parameter called "name.json" and param('name') would never see it.
65
+ // (":names" is a different parameter, not a misuse; it gets no echo.)
66
+ const partial = segments.some(seg => seg.startsWith(marker) && /^[^A-Za-z0-9_$]/.test(seg.slice(marker.length)));
67
+ if (partial) {
68
+ throw new Error(`param('${name}') needs '${marker}' as a whole segment of the route path; ` +
69
+ `'${path}' has it inside a segment`);
70
+ }
71
+ return schema;
72
+ }
73
+ const rest = segments.slice(at + 1);
74
+ const plainShape = !segments.some((seg, i) => i !== at && seg.startsWith(':')) &&
75
+ !path.includes('*') &&
76
+ !rest.includes(''); // no trailing or doubled slash after the parameter
77
+ if (plainShape && isBareRoute(schema)) {
78
+ const prefix = segments.slice(0, at).join('/') + '/';
79
+ const suffix = rest.length > 0 ? '/' + rest.join('/') : '';
80
+ schema.paramEcho = { name, prefix, suffix, status: 200, headers: null };
81
+ }
82
+ return schema;
83
+ }
16
84
  // The content-type res.send() implies for a body it was given no header for:
17
85
  // the same three cases MoroEngineServer's send() picks a template by, spelled
18
86
  // out here so an engine-answered reply carries the bytes send() would have.
@@ -26,35 +94,34 @@ function impliedContentType(body) {
26
94
  }
27
95
  /**
28
96
  * A literal body in place of a handler: the route answers with exactly that
29
- * body, as res.send(body) would (status 200, the implied content-type). When
30
- * nothing else is configured on the route - no auth, validation, rate limit,
31
- * cache or middleware, and a literal path - the schema also carries `static`,
32
- * so a server that can answer it natively does so without calling into JS.
33
- * Anything configured keeps the route on the normal pipeline, where the
34
- * handler sends the same bytes after that configuration has run.
97
+ * body. A non-empty body goes out as res.send(body) would (status 200, the
98
+ * implied content-type). An empty body has nothing a content-type could
99
+ * describe, so it goes out as res.end() would: status and Content-Length: 0,
100
+ * no header block - 38 bytes less per response, and byte-identical to the
101
+ * engine's own static reply with no headers. When nothing else is configured
102
+ * on the route - no auth, validation, rate limit, cache or middleware, and a
103
+ * literal path - the schema also carries `static`, so a server that can
104
+ * answer it natively does so without calling into JS. Anything configured
105
+ * keeps the route on the normal pipeline, where the handler sends the same
106
+ * bytes after that configuration has run.
35
107
  */
36
108
  export function compileStaticRoute(schema, body) {
37
- schema.handler = (_req, res) => {
38
- res.send(body);
39
- };
109
+ const empty = body.length === 0;
110
+ schema.handler = empty
111
+ ? (_req, res) => {
112
+ res.end();
113
+ }
114
+ : (_req, res) => {
115
+ res.send(body);
116
+ };
40
117
  const path = schema.path ?? '';
41
- const mw = schema.middleware;
42
- const hasMiddleware = Array.isArray(mw)
43
- ? mw.length > 0
44
- : mw !== undefined &&
45
- Object.keys(mw).some(phase => {
46
- const list = mw[phase];
47
- return Array.isArray(list) && list.length > 0;
48
- });
49
- const bare = !path.includes(':') &&
50
- !path.includes('*') &&
51
- !schema.auth &&
52
- !schema.validation &&
53
- !schema.rateLimit &&
54
- !schema.cache &&
55
- !hasMiddleware;
118
+ const bare = !path.includes(':') && !path.includes('*') && isBareRoute(schema);
56
119
  if (bare) {
57
- schema.static = { status: 200, headers: ['content-type', impliedContentType(body)], body };
120
+ schema.static = {
121
+ status: 200,
122
+ headers: empty ? null : ['content-type', impliedContentType(body)],
123
+ body,
124
+ };
58
125
  }
59
126
  return schema;
60
127
  }
@@ -188,8 +255,8 @@ export class RouteBuilder {
188
255
  }
189
256
  return this;
190
257
  }
191
- // Terminal method: a function, or the response body itself (see
192
- // compileStaticRoute for what a literal body means).
258
+ // Terminal method: a function, the response body itself (see
259
+ // compileStaticRoute), or param(name) (see compileParamRoute).
193
260
  handler(handler) {
194
261
  if (typeof handler === 'function') {
195
262
  // Avoid spread operator - add handler directly
@@ -201,7 +268,11 @@ export class RouteBuilder {
201
268
  this.router.registerRoute(compileStaticRoute(this.schema, handler));
202
269
  return;
203
270
  }
204
- throw new Error('Handler is required: a function, or the response body as a string or Buffer');
271
+ if (isParamEcho(handler)) {
272
+ this.router.registerRoute(compileParamRoute(this.schema, handler));
273
+ return;
274
+ }
275
+ throw new Error('Handler is required: a function, the response body as a string or Buffer, or param(name)');
205
276
  }
206
277
  }
207
278
  // ===== Unified Router =====
@@ -334,12 +405,17 @@ export class UnifiedRouter {
334
405
  // - so this is where the body becomes a handler and, on a bare route, a
335
406
  // reply the native engine can answer itself.
336
407
  if (typeof schema.handler !== 'function') {
337
- const body = schema.handler;
338
- if (typeof body !== 'string' && !Buffer.isBuffer(body)) {
408
+ const given = schema.handler;
409
+ if (isParamEcho(given)) {
410
+ compileParamRoute(schema, given);
411
+ }
412
+ else if (typeof given === 'string' || Buffer.isBuffer(given)) {
413
+ compileStaticRoute(schema, given);
414
+ }
415
+ else {
339
416
  throw new Error(`Handler for ${schema.method} ${schema.path} must be a function, ` +
340
- 'or the response body as a string or Buffer');
417
+ 'the response body as a string or Buffer, or param(name)');
341
418
  }
342
- compileStaticRoute(schema, body);
343
419
  }
344
420
  // From here on the handler is a function, whichever form was registered.
345
421
  const registered = schema;