@morojs/moro 1.8.14 → 1.8.15

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.
@@ -13,6 +13,7 @@ export interface Http2ServerOptions {
13
13
  limits?: HttpRuntimeLimits;
14
14
  settings?: {
15
15
  headerTableSize?: number;
16
+ /** Accepted for compatibility but never sent: RFC 9113 forbids a server from advertising ENABLE_PUSH=1 (clients drop the connection), and whether push is possible is the client's setting, read per stream. */
16
17
  enablePush?: boolean;
17
18
  initialWindowSize?: number;
18
19
  maxFrameSize?: number;
@@ -99,11 +99,15 @@ export class MoroHttp2Server {
99
99
  serverOptions.ca = options.ca;
100
100
  }
101
101
  }
102
- // Add HTTP/2 settings
102
+ // Add HTTP/2 settings. SETTINGS_ENABLE_PUSH is never sent: RFC 9113
103
+ // §6.5.2 forbids a server from advertising it as 1, and nghttp2 (curl,
104
+ // Node's own client, browsers) treats that frame as a connection-level
105
+ // PROTOCOL_ERROR - every stream died before its response could be read.
106
+ // Whether push is possible is the CLIENT's setting, read per stream from
107
+ // stream.pushAllowed, so settings.enablePush changes nothing on the wire.
103
108
  if (options.settings) {
104
109
  serverOptions.settings = {
105
110
  headerTableSize: options.settings.headerTableSize,
106
- enablePush: options.settings.enablePush !== false,
107
111
  initialWindowSize: options.settings.initialWindowSize || 65535,
108
112
  maxFrameSize: options.settings.maxFrameSize || 16384,
109
113
  maxConcurrentStreams: options.settings.maxConcurrentStreams || 100,
@@ -114,7 +118,6 @@ export class MoroHttp2Server {
114
118
  }
115
119
  else {
116
120
  serverOptions.settings = {
117
- enablePush: true,
118
121
  initialWindowSize: 65535,
119
122
  maxFrameSize: 16384,
120
123
  maxConcurrentStreams: 100,
@@ -479,6 +482,25 @@ export class MoroHttp2Server {
479
482
  httpRes.getHeaders = () => {
480
483
  return { ...httpRes._headers };
481
484
  };
485
+ // Event surface for middleware written against Node's ServerResponse -
486
+ // the built-in request logger, Prometheus, CloudWatch and performance
487
+ // monitors all call res.on('finish', ...). This response is a plain
488
+ // object, so its events are the stream's: a Duplex emits 'finish' once
489
+ // the body has been flushed and 'close' when the stream is gone, the two
490
+ // events ServerResponse fires. Without these, enabling request logging
491
+ // (the default) turned every HTTP/2 request into a 500.
492
+ httpRes.on = (event, listener) => {
493
+ stream.on(event, listener);
494
+ return httpRes;
495
+ };
496
+ httpRes.once = (event, listener) => {
497
+ stream.once(event, listener);
498
+ return httpRes;
499
+ };
500
+ httpRes.off = httpRes.removeListener = (event, listener) => {
501
+ stream.off(event, listener);
502
+ return httpRes;
503
+ };
482
504
  // JSON response
483
505
  httpRes.json = async (data) => {
484
506
  if (httpRes.headersSent || stream.destroyed)
@@ -534,14 +556,14 @@ export class MoroHttp2Server {
534
556
  if (httpRes.headersSent || stream.destroyed)
535
557
  return;
536
558
  if (!httpRes._headers['content-type']) {
559
+ // The same sniff the engine and Node servers use: a body that starts
560
+ // with '{' or '[' is JSON, anything else text. Parsing the whole body
561
+ // to decide cost a JSON.parse per response and labelled a bare number
562
+ // or `true` as JSON.
537
563
  if (typeof data === 'string') {
538
- try {
539
- JSON.parse(data);
540
- httpRes._headers['content-type'] = 'application/json; charset=utf-8';
541
- }
542
- catch {
543
- httpRes._headers['content-type'] = 'text/plain; charset=utf-8';
544
- }
564
+ httpRes._headers['content-type'] = /^\s*[{[]/.test(data)
565
+ ? 'application/json; charset=utf-8'
566
+ : 'text/plain; charset=utf-8';
545
567
  }
546
568
  else {
547
569
  httpRes._headers['content-type'] = 'application/octet-stream';
@@ -1 +1 @@
1
- {"version":3,"file":"http2-server.js","sourceRoot":"","sources":["../../../src/core/http/http2-server.ts"],"names":[],"mappings":"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","sourcesContent":["// HTTP/2 Server Implementation for Moro Framework\n//\n// `node:http2` and `node:zlib` are resolved on first use, not at import time.\n// framework.ts imports this module unconditionally (it has to - the HTTP/2\n// branch is chosen at construction), but the vast majority of apps never take\n// that branch. Loading node:http2 eagerly costs every app ~1 MB RSS on top of\n// http/https, and the zlib compressors another ~0.3 MB, for code they never\n// run. Builtins are always synchronously requirable on every supported Node,\n// so this needs no dynamic import and no engines bump.\nimport type {\n Http2Server,\n Http2SecureServer,\n ServerHttp2Stream,\n IncomingHttpHeaders,\n OutgoingHttpHeaders,\n} from 'http2';\nimport { createRequire } from 'module';\nimport { promisify } from 'util';\nimport { createFrameworkLogger } from '../logger/index.js';\nimport {\n HttpRequest,\n HttpResponse,\n Middleware,\n HttpHandler,\n RouteEntry,\n} from '../../types/http.js';\nimport { PathMatcher } from '../routing/path-matcher.js';\nimport { ObjectPoolManager } from '../pooling/object-pool-manager.js';\nimport {\n parseMultipart as parseMultipartBuffer,\n type MultipartLimits,\n} from './utils/multipart-parser.js';\nimport type { HttpRuntimeLimits } from './utils/size.js';\n\n// Builtins only, so the base is irrelevant; 'file:///' keeps this compiling\n// under the CJS transform Jest applies to the test suite (import.meta is a\n// syntax error there).\nconst requireBuiltin = createRequire('file:///');\n\nlet http2Mod: typeof import('http2') | undefined;\nfunction http2(): typeof import('http2') {\n return (http2Mod ??= requireBuiltin('http2') as typeof import('http2'));\n}\n\nlet gzip: ((buf: Buffer) => Promise<Buffer>) | undefined;\nlet deflate: ((buf: Buffer) => Promise<Buffer>) | undefined;\nlet gzipSync: ((buf: Buffer) => Buffer) | undefined;\nlet deflateSync: ((buf: Buffer) => Buffer) | undefined;\nfunction compressors() {\n if (!gzip) {\n const zlib = requireBuiltin('zlib') as typeof import('zlib');\n gzip = promisify(zlib.gzip) as (buf: Buffer) => Promise<Buffer>;\n deflate = promisify(zlib.deflate) as (buf: Buffer) => Promise<Buffer>;\n gzipSync = (buf: Buffer) => zlib.gzipSync(buf);\n deflateSync = (buf: Buffer) => zlib.deflateSync(buf);\n }\n return {\n gzip: gzip,\n deflate: deflate as (buf: Buffer) => Promise<Buffer>,\n gzipSync: gzipSync as (buf: Buffer) => Buffer,\n deflateSync: deflateSync as (buf: Buffer) => Buffer,\n };\n}\n\nexport interface Http2ServerOptions {\n key?: string | Buffer;\n cert?: string | Buffer;\n ca?: string | Buffer | Array<string | Buffer>;\n allowHTTP1?: boolean;\n maxSessionMemory?: number;\n maxBodySize?: number; // Maximum body size for JSON/form data\n maxUploadSize?: number; // Maximum size for file uploads\n /** Flattened runtime limits (timeouts, maxConnections, multipart, ...). */\n limits?: HttpRuntimeLimits;\n settings?: {\n headerTableSize?: number;\n enablePush?: boolean;\n initialWindowSize?: number;\n maxFrameSize?: number;\n maxConcurrentStreams?: number;\n maxHeaderListSize?: number;\n maxHeaderSize?: number;\n enableConnectProtocol?: boolean;\n };\n}\n\nexport class MoroHttp2Server {\n private server: Http2Server | Http2SecureServer;\n private routes: RouteEntry[] = [];\n private globalMiddleware: Middleware[] = [];\n private compressionEnabled = true;\n private compressionThreshold = 1024;\n // Bodies at or below this size compress on the calling thread; 0 = never\n private compressionMaxInlineBytes = 16384;\n private requestTrackingEnabled = true;\n private multipartLimits?: MultipartLimits;\n private _limits?: HttpRuntimeLimits;\n private logger = createFrameworkLogger('Http2Server');\n private hookManager: any;\n private requestCounter = 0;\n private isSecure: boolean;\n\n // Body size limits - defaults overridden by config in constructor\n private maxBodySize: number = 10 * 1024 * 1024; // Default 10MB (overridden by server.bodySizeLimit config)\n private maxUploadSize: number = 100 * 1024 * 1024; // Default 100MB for file uploads\n\n // Use shared object pool manager\n private poolManager = ObjectPoolManager.getInstance();\n\n // Interned method strings for fast comparison\n private static readonly METHOD_POST = 'POST';\n private static readonly METHOD_PUT = 'PUT';\n private static readonly METHOD_PATCH = 'PATCH';\n private static readonly METHOD_GET = 'GET';\n private static readonly METHOD_DELETE = 'DELETE';\n private static readonly METHOD_HEAD = 'HEAD';\n private static readonly METHOD_OPTIONS = 'OPTIONS';\n\n // Pre-compiled response templates\n private static readonly RESPONSE_TEMPLATES = {\n notFound: Buffer.from('{\"success\":false,\"error\":\"Not found\"}'),\n unauthorized: Buffer.from('{\"success\":false,\"error\":\"Unauthorized\"}'),\n forbidden: Buffer.from('{\"success\":false,\"error\":\"Forbidden\"}'),\n internalError: Buffer.from('{\"success\":false,\"error\":\"Internal server error\"}'),\n methodNotAllowed: Buffer.from('{\"success\":false,\"error\":\"Method not allowed\"}'),\n rateLimited: Buffer.from('{\"success\":false,\"error\":\"Rate limit exceeded\"}'),\n };\n\n // Route optimization structures\n private routeCache = new Map<string, RouteEntry | null>();\n private staticRoutes = new Map<string, RouteEntry>();\n private dynamicRoutes: RouteEntry[] = [];\n private routesBySegmentCount = new Map<number, RouteEntry[]>();\n private pathNormalizationCache = new Map<string, string>();\n\n constructor(options: Http2ServerOptions = {}) {\n this.isSecure = !!(options.key && options.cert);\n\n // Configure body size limits from options\n if (options.maxBodySize) {\n this.maxBodySize = options.maxBodySize;\n }\n if (options.maxUploadSize) {\n this.maxUploadSize = options.maxUploadSize;\n }\n if (options.limits?.multipart) this.multipartLimits = options.limits.multipart;\n if (options.limits) this._limits = options.limits;\n\n const serverOptions: any = {\n allowHTTP1: options.allowHTTP1 !== false,\n ...(options.maxSessionMemory && { maxSessionMemory: options.maxSessionMemory }),\n };\n\n // Add SSL options if secure\n if (this.isSecure) {\n serverOptions.key = options.key;\n serverOptions.cert = options.cert;\n if (options.ca) {\n serverOptions.ca = options.ca;\n }\n }\n\n // Add HTTP/2 settings\n if (options.settings) {\n serverOptions.settings = {\n headerTableSize: options.settings.headerTableSize,\n enablePush: options.settings.enablePush !== false,\n initialWindowSize: options.settings.initialWindowSize || 65535,\n maxFrameSize: options.settings.maxFrameSize || 16384,\n maxConcurrentStreams: options.settings.maxConcurrentStreams || 100,\n maxHeaderListSize: options.settings.maxHeaderListSize,\n maxHeaderSize: options.settings.maxHeaderSize,\n enableConnectProtocol: options.settings.enableConnectProtocol,\n };\n } else {\n serverOptions.settings = {\n enablePush: true,\n initialWindowSize: 65535,\n maxFrameSize: 16384,\n maxConcurrentStreams: 100,\n };\n }\n\n // Create server\n if (this.isSecure) {\n this.server = http2().createSecureServer(serverOptions);\n this.logger.info('HTTP/2 secure server created', 'ServerInit');\n } else {\n this.server = http2().createServer(serverOptions);\n this.logger.info('HTTP/2 server created', 'ServerInit');\n }\n\n // Configure server settings. Socket idle timeout defaults to 30s (its\n // historical hardcode) unless timeouts.idle is set (0 disables).\n this.server.setTimeout(options.limits?.timeouts?.idle ?? 30000);\n if (options.limits?.maxConnections && options.limits.maxConnections > 0) {\n (this.server as any).maxConnections = options.limits.maxConnections;\n }\n\n // Handle streams (HTTP/2 requests). Wrap so the async handler's promise is\n // always caught - a rejection escaping here becomes an unhandled rejection\n // that can crash the process.\n this.server.on('stream', (stream: ServerHttp2Stream, headers: IncomingHttpHeaders) => {\n void this.handleStream(stream, headers).catch(error => {\n this.logger.error('Unhandled HTTP/2 stream error', 'StreamError', {\n error: error instanceof Error ? error.message : String(error),\n });\n });\n });\n\n // Handle session events\n this.server.on('session', session => {\n this.logger.debug('HTTP/2 session created', 'Session');\n\n session.on('error', err => {\n this.logger.error('HTTP/2 session error', 'Session', { error: err.message });\n });\n });\n\n // Handle server errors\n this.server.on('error', err => {\n this.logger.error('HTTP/2 server error', 'ServerError', { error: err.message });\n });\n }\n\n // Configure server for maximum performance\n configurePerformance(\n config: {\n compression?: { enabled: boolean; threshold?: number; maxInlineBytes?: number };\n minimal?: boolean;\n } = {}\n ) {\n if (config.compression !== undefined) {\n this.compressionEnabled = config.compression.enabled;\n if (config.compression.threshold !== undefined) {\n this.compressionThreshold = config.compression.threshold;\n }\n if (config.compression.maxInlineBytes !== undefined) {\n this.compressionMaxInlineBytes = config.compression.maxInlineBytes;\n }\n }\n\n if (config.minimal) {\n this.compressionEnabled = false;\n this.compressionThreshold = Infinity;\n }\n }\n\n // Configure request tracking\n setRequestTracking(enabled: boolean): void {\n this.requestTrackingEnabled = enabled;\n }\n\n // Middleware management\n use(middleware: Middleware): void {\n // Defensive check: Don't add MiddlewareInterface objects to globalMiddleware\n // MiddlewareInterface objects should only be handled by MiddlewareManager\n if (\n middleware &&\n typeof middleware === 'object' &&\n (middleware as any).install &&\n (middleware as any).metadata\n ) {\n this.logger?.warn?.(\n `Attempted to add MiddlewareInterface \"${(middleware as any).metadata?.name}\" to HTTP server globalMiddleware. ` +\n `This should be handled by MiddlewareManager instead. Skipping.`,\n 'Middleware'\n );\n return;\n }\n\n this.globalMiddleware.push(middleware);\n }\n\n // Set hooks manager\n setHookManager(hookManager: any): void {\n this.hookManager = hookManager;\n }\n\n // Routing methods\n get(path: string, ...handlers: (Middleware | HttpHandler)[]): void {\n this.addRoute('GET', path, handlers);\n }\n\n post(path: string, ...handlers: (Middleware | HttpHandler)[]): void {\n this.addRoute('POST', path, handlers);\n }\n\n put(path: string, ...handlers: (Middleware | HttpHandler)[]): void {\n this.addRoute('PUT', path, handlers);\n }\n\n delete(path: string, ...handlers: (Middleware | HttpHandler)[]): void {\n this.addRoute('DELETE', path, handlers);\n }\n\n patch(path: string, ...handlers: (Middleware | HttpHandler)[]): void {\n this.addRoute('PATCH', path, handlers);\n }\n\n private addRoute(method: string, path: string, handlers: (Middleware | HttpHandler)[]): void {\n const { pattern, paramNames } = this.pathToRegex(path);\n const handler = handlers.pop() as HttpHandler;\n const middleware = handlers as Middleware[];\n\n const route = {\n method,\n path,\n pattern,\n paramNames,\n handler,\n middleware,\n };\n\n this.routes.push(route);\n\n // Organize routes for optimal lookup\n if (paramNames.length === 0) {\n const staticKey = `${method}:${path}`;\n this.staticRoutes.set(staticKey, route);\n } else {\n this.dynamicRoutes.push(route);\n const segmentCount = PathMatcher.countSegments(path);\n if (!this.routesBySegmentCount.has(segmentCount)) {\n this.routesBySegmentCount.set(segmentCount, []);\n }\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.routesBySegmentCount.get(segmentCount)!.push(route);\n }\n }\n\n private pathToRegex(path: string): { pattern: RegExp; paramNames: string[] } {\n const compiled = PathMatcher.compile(path);\n return {\n pattern: compiled.pattern || new RegExp(`^${path.replace(/\\//g, '\\\\/')}$`),\n paramNames: compiled.paramNames,\n };\n }\n\n private async handleStream(\n stream: ServerHttp2Stream,\n headers: IncomingHttpHeaders\n ): Promise<void> {\n this.requestCounter++;\n\n const httpReq = this.createRequestFromStream(stream, headers);\n const httpRes = this.createResponseFromStream(stream, httpReq);\n\n try {\n // Parse URL and query\n const url = (headers[':path'] as string) || '/';\n const queryIndex = url.indexOf('?');\n\n if (queryIndex === -1) {\n httpReq.path = url;\n httpReq.query = {};\n } else {\n httpReq.path = url.substring(0, queryIndex);\n httpReq.query = this.parseQueryString(url.substring(queryIndex + 1));\n }\n\n // Parse body for POST/PUT/PATCH\n const method = httpReq.method;\n if (\n method === MoroHttp2Server.METHOD_POST ||\n method === MoroHttp2Server.METHOD_PUT ||\n method === MoroHttp2Server.METHOD_PATCH\n ) {\n httpReq.body = await this.parseBody(stream, headers);\n }\n\n // Execute hooks\n if (this.hookManager) {\n await this.hookManager.execute('request', {\n request: httpReq,\n response: httpRes,\n });\n\n // Post-response hooks. The HTTP/2 response object is a plain object\n // (no event emitter), so listen on the underlying stream instead.\n if (this.hookManager.hasHooks === undefined || this.hookManager.hasHooks('response')) {\n stream.once('close', () => {\n void Promise.resolve(\n this.hookManager.execute('response', { request: httpReq, response: httpRes })\n ).catch((error: any) =>\n this.logger?.error?.(`Response hook error: ${error?.message || error}`, 'Hooks')\n );\n });\n }\n }\n\n // A request hook may answer the request itself (rate limiting, auth\n // rejection). Registration of the response hooks above still stands.\n if (httpRes.headersSent) return;\n\n // Execute global middleware\n if (this.globalMiddleware.length > 0) {\n await this.executeMiddleware(this.globalMiddleware, httpReq, httpRes);\n }\n\n // If middleware handled the request, don't continue\n if (httpRes.headersSent) {\n return;\n }\n\n // Find matching route (path is always set after URL parsing)\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const route = this.findRoute(method || MoroHttp2Server.METHOD_GET, httpReq.path!);\n if (!route) {\n httpRes.statusCode = 404;\n httpRes.setHeader('Content-Type', 'application/json; charset=utf-8');\n httpRes.setHeader('Content-Length', MoroHttp2Server.RESPONSE_TEMPLATES.notFound.length);\n httpRes.end(MoroHttp2Server.RESPONSE_TEMPLATES.notFound);\n return;\n }\n\n // Extract path parameters\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const matches = httpReq.path!.match(route.pattern);\n if (matches) {\n httpReq.params = this.poolManager.acquireParams();\n const paramNames = route.paramNames;\n for (let i = 0; i < paramNames.length; i++) {\n const paramName = paramNames[i];\n const value = matches[i + 1];\n if (paramName !== undefined && value !== undefined) {\n httpReq.params[paramName] = value;\n }\n }\n }\n\n // Execute route middleware\n if (route.middleware.length > 0) {\n await this.executeMiddleware(route.middleware, httpReq, httpRes);\n }\n\n // Execute handler\n const handlerResult = route.handler(httpReq, httpRes);\n if (handlerResult && typeof handlerResult.then === 'function') {\n await handlerResult;\n }\n } catch (error) {\n this.logger.error('HTTP/2 stream error', 'StreamError', {\n error: error instanceof Error ? error.message : String(error),\n requestId: httpReq.requestId,\n path: httpReq.path,\n });\n\n // Error hooks are observational: fire-and-forget so a slow or throwing\n // observer can never delay or alter the error response.\n if (\n this.hookManager &&\n (this.hookManager.hasHooks === undefined || this.hookManager.hasHooks('error'))\n ) {\n void Promise.resolve(\n this.hookManager.execute('error', { request: httpReq, response: httpRes, error })\n ).catch((hookError: any) =>\n this.logger?.error?.(`Error hook error: ${hookError?.message || hookError}`, 'Hooks')\n );\n }\n\n if (!httpRes.headersSent) {\n httpRes.status(500).json({\n success: false,\n error: 'Internal server error',\n requestId: httpReq.requestId,\n });\n }\n } finally {\n // Release pooled objects\n if (httpReq.params && Object.keys(httpReq.params).length === 0) {\n this.poolManager.releaseParams(httpReq.params);\n }\n if (httpReq.query && Object.keys(httpReq.query).length === 0) {\n this.poolManager.releaseQuery(httpReq.query);\n }\n }\n }\n\n private createRequestFromStream(\n stream: ServerHttp2Stream,\n headers: IncomingHttpHeaders\n ): HttpRequest {\n // Extract method from pseudo-header\n const methodRaw = ((headers[':method'] as string) || 'GET').toUpperCase();\n\n // Intern method string for fast comparison\n let method: string;\n switch (methodRaw) {\n case 'POST':\n method = MoroHttp2Server.METHOD_POST;\n break;\n case 'PUT':\n method = MoroHttp2Server.METHOD_PUT;\n break;\n case 'PATCH':\n method = MoroHttp2Server.METHOD_PATCH;\n break;\n case 'GET':\n method = MoroHttp2Server.METHOD_GET;\n break;\n case 'DELETE':\n method = MoroHttp2Server.METHOD_DELETE;\n break;\n case 'HEAD':\n method = MoroHttp2Server.METHOD_HEAD;\n break;\n case 'OPTIONS':\n method = MoroHttp2Server.METHOD_OPTIONS;\n break;\n default:\n method = methodRaw;\n }\n\n // Convert HTTP/2 headers to standard headers (remove pseudo-headers)\n const standardHeaders: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (!key.startsWith(':')) {\n standardHeaders[key] = Array.isArray(value) ? value.join(', ') : (value as string);\n }\n }\n\n // Parse cookies\n const cookieHeader = standardHeaders['cookie'];\n const cookies: Record<string, string> = {};\n if (cookieHeader) {\n const cookieParts = cookieHeader.split(';');\n for (const cookie of cookieParts) {\n const equalIndex = cookie.indexOf('=');\n if (equalIndex > 0) {\n const name = cookie.substring(0, equalIndex).trim();\n const value = cookie.substring(equalIndex + 1);\n if (name && value) {\n try {\n cookies[name] = decodeURIComponent(value);\n } catch {\n // Malformed percent-encoding: keep the raw value rather than\n // throwing a URIError. createRequestFromStream runs before\n // handleStream's try block, so an escape here would surface as\n // an unhandled rejection and crash the process.\n cookies[name] = value;\n }\n }\n }\n }\n }\n\n const httpReq: HttpRequest = {\n method,\n path: '',\n url: (headers[':path'] as string) || '/',\n query: {},\n params: {},\n headers: standardHeaders,\n body: null,\n cookies,\n ip: (stream.session?.socket as any)?.remoteAddress || '',\n requestId: this.requestTrackingEnabled ? this.poolManager.generateRequestId() : '',\n httpVersion: '2.0',\n } as HttpRequest;\n\n // Store stream reference for push capability\n (httpReq as any)._http2Stream = stream;\n (httpReq as any)._http2Headers = headers;\n\n return httpReq;\n }\n\n private createResponseFromStream(stream: ServerHttp2Stream, req: HttpRequest): HttpResponse {\n const httpRes: any = {\n statusCode: 200,\n headersSent: false,\n _headers: {} as OutgoingHttpHeaders,\n _stream: stream,\n _req: req,\n _logger: this.logger,\n _poolManager: this.poolManager,\n _compressionEnabled: this.compressionEnabled,\n _compressionThreshold: this.compressionThreshold,\n _compressionMaxInlineBytes: this.compressionMaxInlineBytes,\n };\n\n // Status method\n httpRes.status = (code: number) => {\n httpRes.statusCode = code;\n return httpRes;\n };\n\n // Set header\n httpRes.setHeader = (name: string, value: string | string[]) => {\n httpRes._headers[name.toLowerCase()] = value;\n return httpRes;\n };\n\n // Get header\n httpRes.getHeader = (name: string) => {\n return httpRes._headers[name.toLowerCase()];\n };\n\n // Remove header\n httpRes.removeHeader = (name: string) => {\n delete httpRes._headers[name.toLowerCase()];\n return httpRes;\n };\n\n // Has header\n httpRes.hasHeader = (name: string): boolean => {\n return httpRes._headers[name.toLowerCase()] !== undefined;\n };\n\n // Get headers\n httpRes.getHeaders = () => {\n return { ...httpRes._headers };\n };\n\n // JSON response\n httpRes.json = async (data: any) => {\n if (httpRes.headersSent || stream.destroyed) return;\n\n const jsonString = JSON.stringify(data);\n const finalBuffer = Buffer.from(jsonString, 'utf8');\n\n httpRes._headers['content-type'] = 'application/json; charset=utf-8';\n\n // Compression\n if (httpRes._compressionEnabled && finalBuffer.length > httpRes._compressionThreshold) {\n const acceptEncoding = req.headers['accept-encoding'];\n\n if (acceptEncoding && acceptEncoding.includes('gzip')) {\n // A small body is compressed on this thread (see compressionMaxInlineBytes)\n const compressed =\n httpRes._compressionMaxInlineBytes > 0 &&\n finalBuffer.length <= httpRes._compressionMaxInlineBytes\n ? compressors().gzipSync(finalBuffer)\n : await compressors().gzip(finalBuffer);\n httpRes._headers['content-encoding'] = 'gzip';\n httpRes._headers['content-length'] = compressed.length;\n\n stream.respond({\n ':status': httpRes.statusCode,\n ...httpRes._headers,\n });\n stream.end(compressed);\n httpRes.headersSent = true;\n return;\n } else if (acceptEncoding && acceptEncoding.includes('deflate')) {\n const compressed =\n httpRes._compressionMaxInlineBytes > 0 &&\n finalBuffer.length <= httpRes._compressionMaxInlineBytes\n ? compressors().deflateSync(finalBuffer)\n : await compressors().deflate(finalBuffer);\n httpRes._headers['content-encoding'] = 'deflate';\n httpRes._headers['content-length'] = compressed.length;\n\n stream.respond({\n ':status': httpRes.statusCode,\n ...httpRes._headers,\n });\n stream.end(compressed);\n httpRes.headersSent = true;\n return;\n }\n }\n\n httpRes._headers['content-length'] = finalBuffer.length;\n\n stream.respond({\n ':status': httpRes.statusCode,\n ...httpRes._headers,\n });\n stream.end(finalBuffer);\n httpRes.headersSent = true;\n };\n\n // Send response\n httpRes.send = (data: string | Buffer) => {\n if (httpRes.headersSent || stream.destroyed) return;\n\n if (!httpRes._headers['content-type']) {\n if (typeof data === 'string') {\n try {\n JSON.parse(data);\n httpRes._headers['content-type'] = 'application/json; charset=utf-8';\n } catch {\n httpRes._headers['content-type'] = 'text/plain; charset=utf-8';\n }\n } else {\n httpRes._headers['content-type'] = 'application/octet-stream';\n }\n }\n\n const buffer = typeof data === 'string' ? Buffer.from(data) : data;\n httpRes._headers['content-length'] = buffer.length;\n\n stream.respond({\n ':status': httpRes.statusCode,\n ...httpRes._headers,\n });\n stream.end(buffer);\n httpRes.headersSent = true;\n };\n\n // End response\n httpRes.end = (data?: any) => {\n if (httpRes.headersSent || stream.destroyed) return httpRes;\n\n stream.respond({\n ':status': httpRes.statusCode,\n ...httpRes._headers,\n });\n stream.end(data || '');\n httpRes.headersSent = true;\n return httpRes;\n };\n\n // Standardized response helpers\n httpRes.success = <T = any>(data: T, message?: string) => {\n const response: any = {\n success: true,\n data,\n };\n if (message !== undefined) {\n response.message = message;\n }\n httpRes.json(response);\n };\n\n httpRes.error = (error: string, code?: string, message?: string) => {\n const response: any = {\n success: false,\n error,\n };\n if (code !== undefined) {\n response.code = code;\n }\n if (message !== undefined) {\n response.message = message;\n }\n httpRes.json(response);\n };\n\n // Common HTTP error helpers (automatically set status code)\n httpRes.unauthorized = (message: string = 'Authentication required') => {\n httpRes.statusCode = 401;\n httpRes.json({\n success: false,\n error: 'Unauthorized',\n code: 'UNAUTHORIZED',\n message,\n });\n };\n\n httpRes.forbidden = (message: string = 'Insufficient permissions') => {\n httpRes.statusCode = 403;\n httpRes.json({\n success: false,\n error: 'Forbidden',\n code: 'FORBIDDEN',\n message,\n });\n };\n\n httpRes.notFound = (resource: string = 'Resource') => {\n httpRes.statusCode = 404;\n httpRes.json({\n success: false,\n error: 'Not Found',\n code: 'NOT_FOUND',\n message: `${resource} not found`,\n });\n };\n\n httpRes.badRequest = (message: string = 'Invalid request') => {\n httpRes.statusCode = 400;\n httpRes.json({\n success: false,\n error: 'Bad Request',\n code: 'BAD_REQUEST',\n message,\n });\n };\n\n httpRes.conflict = (message: string) => {\n httpRes.statusCode = 409;\n httpRes.json({\n success: false,\n error: 'Conflict',\n code: 'CONFLICT',\n message,\n });\n };\n\n httpRes.internalError = (message: string = 'Internal server error') => {\n httpRes.statusCode = 500;\n httpRes.json({\n success: false,\n error: 'Internal Server Error',\n code: 'INTERNAL_ERROR',\n message,\n });\n };\n\n httpRes.validationError = (\n errors: Array<{ field: string; message: string; code?: string }>\n ) => {\n httpRes.statusCode = 422;\n httpRes.json({\n success: false,\n error: 'Validation Failed',\n code: 'VALIDATION_ERROR',\n errors,\n });\n };\n\n httpRes.rateLimited = (retryAfter?: number) => {\n httpRes.statusCode = 429;\n if (retryAfter) {\n httpRes.setHeader('Retry-After', retryAfter.toString());\n }\n httpRes.json({\n success: false,\n error: 'Rate Limit Exceeded',\n code: 'RATE_LIMITED',\n message: retryAfter\n ? `Too many requests. Retry after ${retryAfter} seconds.`\n : 'Too many requests',\n retryAfter,\n });\n };\n\n // Common success patterns\n httpRes.created = <T = any>(data: T, location?: string) => {\n httpRes.statusCode = 201;\n if (location) {\n httpRes.setHeader('Location', location);\n }\n httpRes.json({\n success: true,\n data,\n });\n };\n\n httpRes.noContent = () => {\n httpRes.statusCode = 204;\n httpRes.end();\n };\n\n httpRes.paginated = <T = any>(\n data: T[],\n pagination: { page: number; limit: number; total: number }\n ) => {\n const totalPages = Math.ceil(pagination.total / pagination.limit);\n httpRes.json({\n success: true,\n data,\n pagination: {\n page: pagination.page,\n limit: pagination.limit,\n total: pagination.total,\n totalPages,\n hasNext: pagination.page < totalPages,\n hasPrev: pagination.page > 1,\n },\n });\n };\n\n // Cookie handling\n httpRes.cookie = (name: string, value: string, options: any = {}) => {\n if (httpRes.headersSent) {\n const isCritical = options.critical || name.includes('session') || name.includes('auth');\n const message = `Cookie '${name}' could not be set - headers already sent`;\n\n if (isCritical || options.throwOnLateSet) {\n throw new Error(`${message}. This may cause authentication or security issues.`);\n } else {\n httpRes._logger.warn(message, 'CookieWarning', { cookieName: name });\n }\n return httpRes;\n }\n\n const cookieValue = encodeURIComponent(value);\n let cookieString = `${name}=${cookieValue}`;\n\n if (options.maxAge) cookieString += `; Max-Age=${options.maxAge}`;\n if (options.expires) cookieString += `; Expires=${options.expires.toUTCString()}`;\n if (options.httpOnly) cookieString += '; HttpOnly';\n if (options.secure) cookieString += '; Secure';\n if (options.sameSite) cookieString += `; SameSite=${options.sameSite}`;\n if (options.domain) cookieString += `; Domain=${options.domain}`;\n if (options.path) cookieString += `; Path=${options.path}`;\n\n const existingCookies = httpRes._headers['set-cookie'] || [];\n const cookies = Array.isArray(existingCookies)\n ? existingCookies\n : [existingCookies as string];\n cookies.push(cookieString);\n httpRes._headers['set-cookie'] = cookies;\n\n return httpRes;\n };\n\n // Clear cookie\n httpRes.clearCookie = (name: string, options: any = {}) => {\n return httpRes.cookie(name, '', {\n expires: new Date(0),\n maxAge: 0,\n ...options,\n });\n };\n\n // Redirect\n httpRes.redirect = (url: string, status: number = 302) => {\n if (httpRes.headersSent || stream.destroyed) return;\n\n httpRes.statusCode = status;\n httpRes._headers['location'] = url;\n\n stream.respond({\n ':status': status,\n ...httpRes._headers,\n });\n stream.end();\n httpRes.headersSent = true;\n };\n\n // HTTP/2 Server Push\n httpRes.push = (\n path: string,\n options: { headers?: OutgoingHttpHeaders; priority?: number } = {}\n ) => {\n if (httpRes.headersSent || stream.destroyed || !stream.pushAllowed) {\n return null;\n }\n\n try {\n const pushHeaders: any = {\n ':path': path,\n ':method': 'GET',\n ...options.headers,\n };\n\n const pushStream = stream.pushStream(pushHeaders, err => {\n if (err) {\n httpRes._logger.debug('Server push failed', 'ServerPush', {\n path,\n error: err.message,\n });\n }\n });\n\n // Set stream priority if specified\n if (options.priority !== undefined && pushStream) {\n try {\n // Priority weight: 1-256 (default 16)\n // Higher values = higher priority\n const weight = Math.max(1, Math.min(256, options.priority));\n (pushStream as any).priority({\n parent: 0,\n weight,\n exclusive: false,\n });\n } catch (error) {\n httpRes._logger.debug('Failed to set stream priority', 'StreamPriority', {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n return pushStream;\n } catch (error) {\n httpRes._logger.debug('Server push error', 'ServerPush', {\n path,\n error: error instanceof Error ? error.message : String(error),\n });\n return null;\n }\n };\n\n // Set stream priority for current response\n httpRes.setPriority = (\n options: { parent?: number; weight?: number; exclusive?: boolean } = {}\n ) => {\n if (httpRes.headersSent || stream.destroyed) {\n return httpRes;\n }\n\n try {\n stream.priority({\n parent: options.parent || 0,\n weight: options.weight ? Math.max(1, Math.min(256, options.weight)) : 16,\n exclusive: options.exclusive || false,\n });\n } catch (error) {\n httpRes._logger.debug('Failed to set stream priority', 'StreamPriority', {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n\n return httpRes;\n };\n\n // Set bulk headers\n httpRes.setBulkHeaders = (headers: Record<string, string | number>) => {\n if (httpRes.headersSent) {\n httpRes._logger.warn('Cannot set headers - headers already sent', 'HeaderWarning');\n return httpRes;\n }\n\n for (const key in headers) {\n httpRes._headers[key.toLowerCase()] = String(headers[key]);\n }\n return httpRes;\n };\n\n // Response state\n httpRes.canSetHeaders = (): boolean => {\n return !httpRes.headersSent;\n };\n\n httpRes.getResponseState = () => {\n return {\n headersSent: httpRes.headersSent,\n statusCode: httpRes.statusCode,\n headers: httpRes.getHeaders(),\n finished: stream.destroyed,\n writable: !stream.destroyed,\n };\n };\n\n return httpRes as HttpResponse;\n }\n\n private async parseBody(stream: ServerHttp2Stream, headers: IncomingHttpHeaders): Promise<any> {\n const contentType = (headers['content-type'] as string) || '';\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const contentLength = parseInt((headers['content-length'] as string) || '0');\n\n // Use different limits based on content type\n const isMultipart = contentType.includes('multipart/form-data');\n const maxSize = isMultipart\n ? this.maxUploadSize // Configurable file upload limit (default 100MB)\n : this.maxBodySize; // Configurable body size limit (default 10MB, from server.bodySizeLimit config)\n\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let totalLength = 0;\n\n stream.on('data', (chunk: Buffer) => {\n totalLength += chunk.length;\n if (totalLength > maxSize) {\n const errorMessage = isMultipart\n ? `File upload too large. Maximum ${Math.floor(maxSize / (1024 * 1024))}MB allowed.`\n : 'Request body too large';\n reject(new Error(errorMessage));\n return;\n }\n chunks.push(chunk);\n });\n\n stream.on('end', () => {\n try {\n const body = Buffer.concat(chunks);\n\n if (contentType.includes('application/json')) {\n resolve(JSON.parse(body.toString()));\n } else if (contentType.includes('application/x-www-form-urlencoded')) {\n resolve(this.parseUrlEncoded(body.toString()));\n } else if (contentType.includes('multipart/form-data')) {\n resolve(parseMultipartBuffer(body, contentType, this.multipartLimits));\n } else {\n resolve(body.toString());\n }\n } catch (error) {\n reject(error);\n }\n });\n\n stream.on('error', reject);\n });\n }\n\n private parseUrlEncoded(body: string): Record<string, string> {\n const params = new URLSearchParams(body);\n const result: Record<string, string> = {};\n for (const [key, value] of params) {\n result[key] = value;\n }\n return result;\n }\n\n private parseQueryString(queryString: string): Record<string, string> {\n if (!queryString) return {};\n\n const result = this.poolManager.acquireQuery();\n const pairs = queryString.split('&');\n\n for (const pair of pairs) {\n const equalIndex = pair.indexOf('=');\n if (equalIndex === -1) {\n result[decodeURIComponent(pair)] = '';\n } else {\n const key = decodeURIComponent(pair.substring(0, equalIndex));\n const value = decodeURIComponent(pair.substring(equalIndex + 1));\n result[key] = value;\n }\n }\n return result;\n }\n\n private normalizePath(path: string): string {\n if (this.pathNormalizationCache.has(path)) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return this.pathNormalizationCache.get(path)!;\n }\n\n let normalized = path;\n if (normalized.length > 1 && normalized.endsWith('/')) {\n normalized = normalized.slice(0, -1);\n }\n\n if (this.pathNormalizationCache.size < 200) {\n this.pathNormalizationCache.set(path, normalized);\n }\n\n return normalized;\n }\n\n private findRoute(method: string, path: string | undefined): RouteEntry | null {\n // Default to '/' if path is undefined\n const searchPath = path || '/';\n const cacheKey = `${method}:${searchPath}`;\n\n if (this.routeCache.has(cacheKey)) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return this.routeCache.get(cacheKey)!;\n }\n\n const normalizedPath = this.normalizePath(searchPath);\n const normalizedCacheKey =\n normalizedPath !== searchPath ? `${method}:${normalizedPath}` : cacheKey;\n\n if (normalizedPath !== path && this.routeCache.has(normalizedCacheKey)) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return this.routeCache.get(normalizedCacheKey)!;\n }\n\n const staticRoute = this.staticRoutes.get(normalizedCacheKey);\n if (staticRoute) {\n this.routeCache.set(normalizedCacheKey, staticRoute);\n if (normalizedPath !== path) {\n this.routeCache.set(cacheKey, staticRoute);\n }\n return staticRoute;\n }\n\n let route: RouteEntry | null = null;\n if (this.dynamicRoutes.length > 0) {\n const segmentCount = PathMatcher.countSegments(normalizedPath);\n const candidateRoutes = this.routesBySegmentCount.get(segmentCount) || this.dynamicRoutes;\n\n for (const candidateRoute of candidateRoutes) {\n if (candidateRoute.method === method && candidateRoute.pattern.test(normalizedPath)) {\n route = candidateRoute;\n break;\n }\n }\n }\n\n if (this.routeCache.size < 500) {\n this.routeCache.set(normalizedCacheKey, route);\n if (normalizedPath !== path) {\n this.routeCache.set(cacheKey, route);\n }\n }\n\n return route;\n }\n\n private async executeMiddleware(\n middleware: Middleware[],\n req: HttpRequest,\n res: HttpResponse\n ): Promise<void> {\n for (const mw of middleware) {\n if (res.headersSent) return;\n\n await new Promise<void>((resolve, reject) => {\n let resolved = false;\n\n const next = () => {\n if (resolved) return;\n resolved = true;\n resolve();\n };\n\n try {\n const result = mw(req, res, next);\n\n if (result && typeof result.then === 'function') {\n (result as Promise<void>)\n .then(() => {\n if (!resolved) next();\n })\n .catch(reject);\n } else if (!resolved) {\n next();\n }\n } catch (error) {\n if (!resolved) {\n resolved = true;\n reject(error);\n }\n }\n });\n }\n }\n\n listen(port: number, callback?: () => void): void;\n listen(port: number, host: string, callback?: () => void): void;\n listen(port: number, host?: string | (() => void), callback?: () => void): void {\n if (typeof host === 'function') {\n callback = host;\n host = undefined;\n }\n\n if (host) {\n this.server.listen(port, host, callback);\n } else {\n this.server.listen(port, callback);\n }\n }\n\n close(): Promise<void> {\n return new Promise(resolve => {\n this.server.close(() => resolve());\n });\n }\n\n forceCleanup(): void {\n this.poolManager.clearAll();\n if (globalThis?.gc) {\n globalThis.gc();\n }\n }\n\n /**\n * Replace the TLS certificate/key for new handshakes (Http2SecureServer is\n * a tls.Server; setSecureContext applies to every later handshake).\n */\n updateSsl(ssl: {\n key: string | Buffer;\n cert: string | Buffer;\n ca?: Array<string | Buffer>;\n passphrase?: string;\n minVersion?: string;\n requestCert?: boolean;\n rejectUnauthorized?: boolean;\n }): void {\n const server = this.server as any;\n if (typeof server.setSecureContext !== 'function') {\n throw new Error('updateSsl: this server was not started with TLS (server.ssl)');\n }\n server.setSecureContext(ssl);\n }\n\n getServer(): Http2Server | Http2SecureServer {\n return this.server;\n }\n\n getPerformanceStats() {\n const poolStats = this.poolManager.getStats();\n return {\n paramObjectPoolSize: poolStats.paramPool.poolSize,\n queryObjectPoolSize: poolStats.queryPool.poolSize,\n headerObjectPoolSize: poolStats.headerPool.poolSize,\n poolManager: poolStats,\n };\n }\n}\n"]}
1
+ {"version":3,"file":"http2-server.js","sourceRoot":"","sources":["../../../src/core/http/http2-server.ts"],"names":[],"mappings":"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","sourcesContent":["// HTTP/2 Server Implementation for Moro Framework\n//\n// `node:http2` and `node:zlib` are resolved on first use, not at import time.\n// framework.ts imports this module unconditionally (it has to - the HTTP/2\n// branch is chosen at construction), but the vast majority of apps never take\n// that branch. Loading node:http2 eagerly costs every app ~1 MB RSS on top of\n// http/https, and the zlib compressors another ~0.3 MB, for code they never\n// run. Builtins are always synchronously requirable on every supported Node,\n// so this needs no dynamic import and no engines bump.\nimport type {\n Http2Server,\n Http2SecureServer,\n ServerHttp2Stream,\n IncomingHttpHeaders,\n OutgoingHttpHeaders,\n} from 'http2';\nimport { createRequire } from 'module';\nimport { promisify } from 'util';\nimport { createFrameworkLogger } from '../logger/index.js';\nimport {\n HttpRequest,\n HttpResponse,\n Middleware,\n HttpHandler,\n RouteEntry,\n} from '../../types/http.js';\nimport { PathMatcher } from '../routing/path-matcher.js';\nimport { ObjectPoolManager } from '../pooling/object-pool-manager.js';\nimport {\n parseMultipart as parseMultipartBuffer,\n type MultipartLimits,\n} from './utils/multipart-parser.js';\nimport type { HttpRuntimeLimits } from './utils/size.js';\n\n// Builtins only, so the base is irrelevant; 'file:///' keeps this compiling\n// under the CJS transform Jest applies to the test suite (import.meta is a\n// syntax error there).\nconst requireBuiltin = createRequire('file:///');\n\nlet http2Mod: typeof import('http2') | undefined;\nfunction http2(): typeof import('http2') {\n return (http2Mod ??= requireBuiltin('http2') as typeof import('http2'));\n}\n\nlet gzip: ((buf: Buffer) => Promise<Buffer>) | undefined;\nlet deflate: ((buf: Buffer) => Promise<Buffer>) | undefined;\nlet gzipSync: ((buf: Buffer) => Buffer) | undefined;\nlet deflateSync: ((buf: Buffer) => Buffer) | undefined;\nfunction compressors() {\n if (!gzip) {\n const zlib = requireBuiltin('zlib') as typeof import('zlib');\n gzip = promisify(zlib.gzip) as (buf: Buffer) => Promise<Buffer>;\n deflate = promisify(zlib.deflate) as (buf: Buffer) => Promise<Buffer>;\n gzipSync = (buf: Buffer) => zlib.gzipSync(buf);\n deflateSync = (buf: Buffer) => zlib.deflateSync(buf);\n }\n return {\n gzip: gzip,\n deflate: deflate as (buf: Buffer) => Promise<Buffer>,\n gzipSync: gzipSync as (buf: Buffer) => Buffer,\n deflateSync: deflateSync as (buf: Buffer) => Buffer,\n };\n}\n\nexport interface Http2ServerOptions {\n key?: string | Buffer;\n cert?: string | Buffer;\n ca?: string | Buffer | Array<string | Buffer>;\n allowHTTP1?: boolean;\n maxSessionMemory?: number;\n maxBodySize?: number; // Maximum body size for JSON/form data\n maxUploadSize?: number; // Maximum size for file uploads\n /** Flattened runtime limits (timeouts, maxConnections, multipart, ...). */\n limits?: HttpRuntimeLimits;\n settings?: {\n headerTableSize?: number;\n /** Accepted for compatibility but never sent: RFC 9113 forbids a server from advertising ENABLE_PUSH=1 (clients drop the connection), and whether push is possible is the client's setting, read per stream. */\n enablePush?: boolean;\n initialWindowSize?: number;\n maxFrameSize?: number;\n maxConcurrentStreams?: number;\n maxHeaderListSize?: number;\n maxHeaderSize?: number;\n enableConnectProtocol?: boolean;\n };\n}\n\nexport class MoroHttp2Server {\n private server: Http2Server | Http2SecureServer;\n private routes: RouteEntry[] = [];\n private globalMiddleware: Middleware[] = [];\n private compressionEnabled = true;\n private compressionThreshold = 1024;\n // Bodies at or below this size compress on the calling thread; 0 = never\n private compressionMaxInlineBytes = 16384;\n private requestTrackingEnabled = true;\n private multipartLimits?: MultipartLimits;\n private _limits?: HttpRuntimeLimits;\n private logger = createFrameworkLogger('Http2Server');\n private hookManager: any;\n private requestCounter = 0;\n private isSecure: boolean;\n\n // Body size limits - defaults overridden by config in constructor\n private maxBodySize: number = 10 * 1024 * 1024; // Default 10MB (overridden by server.bodySizeLimit config)\n private maxUploadSize: number = 100 * 1024 * 1024; // Default 100MB for file uploads\n\n // Use shared object pool manager\n private poolManager = ObjectPoolManager.getInstance();\n\n // Interned method strings for fast comparison\n private static readonly METHOD_POST = 'POST';\n private static readonly METHOD_PUT = 'PUT';\n private static readonly METHOD_PATCH = 'PATCH';\n private static readonly METHOD_GET = 'GET';\n private static readonly METHOD_DELETE = 'DELETE';\n private static readonly METHOD_HEAD = 'HEAD';\n private static readonly METHOD_OPTIONS = 'OPTIONS';\n\n // Pre-compiled response templates\n private static readonly RESPONSE_TEMPLATES = {\n notFound: Buffer.from('{\"success\":false,\"error\":\"Not found\"}'),\n unauthorized: Buffer.from('{\"success\":false,\"error\":\"Unauthorized\"}'),\n forbidden: Buffer.from('{\"success\":false,\"error\":\"Forbidden\"}'),\n internalError: Buffer.from('{\"success\":false,\"error\":\"Internal server error\"}'),\n methodNotAllowed: Buffer.from('{\"success\":false,\"error\":\"Method not allowed\"}'),\n rateLimited: Buffer.from('{\"success\":false,\"error\":\"Rate limit exceeded\"}'),\n };\n\n // Route optimization structures\n private routeCache = new Map<string, RouteEntry | null>();\n private staticRoutes = new Map<string, RouteEntry>();\n private dynamicRoutes: RouteEntry[] = [];\n private routesBySegmentCount = new Map<number, RouteEntry[]>();\n private pathNormalizationCache = new Map<string, string>();\n\n constructor(options: Http2ServerOptions = {}) {\n this.isSecure = !!(options.key && options.cert);\n\n // Configure body size limits from options\n if (options.maxBodySize) {\n this.maxBodySize = options.maxBodySize;\n }\n if (options.maxUploadSize) {\n this.maxUploadSize = options.maxUploadSize;\n }\n if (options.limits?.multipart) this.multipartLimits = options.limits.multipart;\n if (options.limits) this._limits = options.limits;\n\n const serverOptions: any = {\n allowHTTP1: options.allowHTTP1 !== false,\n ...(options.maxSessionMemory && { maxSessionMemory: options.maxSessionMemory }),\n };\n\n // Add SSL options if secure\n if (this.isSecure) {\n serverOptions.key = options.key;\n serverOptions.cert = options.cert;\n if (options.ca) {\n serverOptions.ca = options.ca;\n }\n }\n\n // Add HTTP/2 settings. SETTINGS_ENABLE_PUSH is never sent: RFC 9113\n // §6.5.2 forbids a server from advertising it as 1, and nghttp2 (curl,\n // Node's own client, browsers) treats that frame as a connection-level\n // PROTOCOL_ERROR - every stream died before its response could be read.\n // Whether push is possible is the CLIENT's setting, read per stream from\n // stream.pushAllowed, so settings.enablePush changes nothing on the wire.\n if (options.settings) {\n serverOptions.settings = {\n headerTableSize: options.settings.headerTableSize,\n initialWindowSize: options.settings.initialWindowSize || 65535,\n maxFrameSize: options.settings.maxFrameSize || 16384,\n maxConcurrentStreams: options.settings.maxConcurrentStreams || 100,\n maxHeaderListSize: options.settings.maxHeaderListSize,\n maxHeaderSize: options.settings.maxHeaderSize,\n enableConnectProtocol: options.settings.enableConnectProtocol,\n };\n } else {\n serverOptions.settings = {\n initialWindowSize: 65535,\n maxFrameSize: 16384,\n maxConcurrentStreams: 100,\n };\n }\n\n // Create server\n if (this.isSecure) {\n this.server = http2().createSecureServer(serverOptions);\n this.logger.info('HTTP/2 secure server created', 'ServerInit');\n } else {\n this.server = http2().createServer(serverOptions);\n this.logger.info('HTTP/2 server created', 'ServerInit');\n }\n\n // Configure server settings. Socket idle timeout defaults to 30s (its\n // historical hardcode) unless timeouts.idle is set (0 disables).\n this.server.setTimeout(options.limits?.timeouts?.idle ?? 30000);\n if (options.limits?.maxConnections && options.limits.maxConnections > 0) {\n (this.server as any).maxConnections = options.limits.maxConnections;\n }\n\n // Handle streams (HTTP/2 requests). Wrap so the async handler's promise is\n // always caught - a rejection escaping here becomes an unhandled rejection\n // that can crash the process.\n this.server.on('stream', (stream: ServerHttp2Stream, headers: IncomingHttpHeaders) => {\n void this.handleStream(stream, headers).catch(error => {\n this.logger.error('Unhandled HTTP/2 stream error', 'StreamError', {\n error: error instanceof Error ? error.message : String(error),\n });\n });\n });\n\n // Handle session events\n this.server.on('session', session => {\n this.logger.debug('HTTP/2 session created', 'Session');\n\n session.on('error', err => {\n this.logger.error('HTTP/2 session error', 'Session', { error: err.message });\n });\n });\n\n // Handle server errors\n this.server.on('error', err => {\n this.logger.error('HTTP/2 server error', 'ServerError', { error: err.message });\n });\n }\n\n // Configure server for maximum performance\n configurePerformance(\n config: {\n compression?: { enabled: boolean; threshold?: number; maxInlineBytes?: number };\n minimal?: boolean;\n } = {}\n ) {\n if (config.compression !== undefined) {\n this.compressionEnabled = config.compression.enabled;\n if (config.compression.threshold !== undefined) {\n this.compressionThreshold = config.compression.threshold;\n }\n if (config.compression.maxInlineBytes !== undefined) {\n this.compressionMaxInlineBytes = config.compression.maxInlineBytes;\n }\n }\n\n if (config.minimal) {\n this.compressionEnabled = false;\n this.compressionThreshold = Infinity;\n }\n }\n\n // Configure request tracking\n setRequestTracking(enabled: boolean): void {\n this.requestTrackingEnabled = enabled;\n }\n\n // Middleware management\n use(middleware: Middleware): void {\n // Defensive check: Don't add MiddlewareInterface objects to globalMiddleware\n // MiddlewareInterface objects should only be handled by MiddlewareManager\n if (\n middleware &&\n typeof middleware === 'object' &&\n (middleware as any).install &&\n (middleware as any).metadata\n ) {\n this.logger?.warn?.(\n `Attempted to add MiddlewareInterface \"${(middleware as any).metadata?.name}\" to HTTP server globalMiddleware. ` +\n `This should be handled by MiddlewareManager instead. Skipping.`,\n 'Middleware'\n );\n return;\n }\n\n this.globalMiddleware.push(middleware);\n }\n\n // Set hooks manager\n setHookManager(hookManager: any): void {\n this.hookManager = hookManager;\n }\n\n // Routing methods\n get(path: string, ...handlers: (Middleware | HttpHandler)[]): void {\n this.addRoute('GET', path, handlers);\n }\n\n post(path: string, ...handlers: (Middleware | HttpHandler)[]): void {\n this.addRoute('POST', path, handlers);\n }\n\n put(path: string, ...handlers: (Middleware | HttpHandler)[]): void {\n this.addRoute('PUT', path, handlers);\n }\n\n delete(path: string, ...handlers: (Middleware | HttpHandler)[]): void {\n this.addRoute('DELETE', path, handlers);\n }\n\n patch(path: string, ...handlers: (Middleware | HttpHandler)[]): void {\n this.addRoute('PATCH', path, handlers);\n }\n\n private addRoute(method: string, path: string, handlers: (Middleware | HttpHandler)[]): void {\n const { pattern, paramNames } = this.pathToRegex(path);\n const handler = handlers.pop() as HttpHandler;\n const middleware = handlers as Middleware[];\n\n const route = {\n method,\n path,\n pattern,\n paramNames,\n handler,\n middleware,\n };\n\n this.routes.push(route);\n\n // Organize routes for optimal lookup\n if (paramNames.length === 0) {\n const staticKey = `${method}:${path}`;\n this.staticRoutes.set(staticKey, route);\n } else {\n this.dynamicRoutes.push(route);\n const segmentCount = PathMatcher.countSegments(path);\n if (!this.routesBySegmentCount.has(segmentCount)) {\n this.routesBySegmentCount.set(segmentCount, []);\n }\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.routesBySegmentCount.get(segmentCount)!.push(route);\n }\n }\n\n private pathToRegex(path: string): { pattern: RegExp; paramNames: string[] } {\n const compiled = PathMatcher.compile(path);\n return {\n pattern: compiled.pattern || new RegExp(`^${path.replace(/\\//g, '\\\\/')}$`),\n paramNames: compiled.paramNames,\n };\n }\n\n private async handleStream(\n stream: ServerHttp2Stream,\n headers: IncomingHttpHeaders\n ): Promise<void> {\n this.requestCounter++;\n\n const httpReq = this.createRequestFromStream(stream, headers);\n const httpRes = this.createResponseFromStream(stream, httpReq);\n\n try {\n // Parse URL and query\n const url = (headers[':path'] as string) || '/';\n const queryIndex = url.indexOf('?');\n\n if (queryIndex === -1) {\n httpReq.path = url;\n httpReq.query = {};\n } else {\n httpReq.path = url.substring(0, queryIndex);\n httpReq.query = this.parseQueryString(url.substring(queryIndex + 1));\n }\n\n // Parse body for POST/PUT/PATCH\n const method = httpReq.method;\n if (\n method === MoroHttp2Server.METHOD_POST ||\n method === MoroHttp2Server.METHOD_PUT ||\n method === MoroHttp2Server.METHOD_PATCH\n ) {\n httpReq.body = await this.parseBody(stream, headers);\n }\n\n // Execute hooks\n if (this.hookManager) {\n await this.hookManager.execute('request', {\n request: httpReq,\n response: httpRes,\n });\n\n // Post-response hooks. The HTTP/2 response object is a plain object\n // (no event emitter), so listen on the underlying stream instead.\n if (this.hookManager.hasHooks === undefined || this.hookManager.hasHooks('response')) {\n stream.once('close', () => {\n void Promise.resolve(\n this.hookManager.execute('response', { request: httpReq, response: httpRes })\n ).catch((error: any) =>\n this.logger?.error?.(`Response hook error: ${error?.message || error}`, 'Hooks')\n );\n });\n }\n }\n\n // A request hook may answer the request itself (rate limiting, auth\n // rejection). Registration of the response hooks above still stands.\n if (httpRes.headersSent) return;\n\n // Execute global middleware\n if (this.globalMiddleware.length > 0) {\n await this.executeMiddleware(this.globalMiddleware, httpReq, httpRes);\n }\n\n // If middleware handled the request, don't continue\n if (httpRes.headersSent) {\n return;\n }\n\n // Find matching route (path is always set after URL parsing)\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const route = this.findRoute(method || MoroHttp2Server.METHOD_GET, httpReq.path!);\n if (!route) {\n httpRes.statusCode = 404;\n httpRes.setHeader('Content-Type', 'application/json; charset=utf-8');\n httpRes.setHeader('Content-Length', MoroHttp2Server.RESPONSE_TEMPLATES.notFound.length);\n httpRes.end(MoroHttp2Server.RESPONSE_TEMPLATES.notFound);\n return;\n }\n\n // Extract path parameters\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const matches = httpReq.path!.match(route.pattern);\n if (matches) {\n httpReq.params = this.poolManager.acquireParams();\n const paramNames = route.paramNames;\n for (let i = 0; i < paramNames.length; i++) {\n const paramName = paramNames[i];\n const value = matches[i + 1];\n if (paramName !== undefined && value !== undefined) {\n httpReq.params[paramName] = value;\n }\n }\n }\n\n // Execute route middleware\n if (route.middleware.length > 0) {\n await this.executeMiddleware(route.middleware, httpReq, httpRes);\n }\n\n // Execute handler\n const handlerResult = route.handler(httpReq, httpRes);\n if (handlerResult && typeof handlerResult.then === 'function') {\n await handlerResult;\n }\n } catch (error) {\n this.logger.error('HTTP/2 stream error', 'StreamError', {\n error: error instanceof Error ? error.message : String(error),\n requestId: httpReq.requestId,\n path: httpReq.path,\n });\n\n // Error hooks are observational: fire-and-forget so a slow or throwing\n // observer can never delay or alter the error response.\n if (\n this.hookManager &&\n (this.hookManager.hasHooks === undefined || this.hookManager.hasHooks('error'))\n ) {\n void Promise.resolve(\n this.hookManager.execute('error', { request: httpReq, response: httpRes, error })\n ).catch((hookError: any) =>\n this.logger?.error?.(`Error hook error: ${hookError?.message || hookError}`, 'Hooks')\n );\n }\n\n if (!httpRes.headersSent) {\n httpRes.status(500).json({\n success: false,\n error: 'Internal server error',\n requestId: httpReq.requestId,\n });\n }\n } finally {\n // Release pooled objects\n if (httpReq.params && Object.keys(httpReq.params).length === 0) {\n this.poolManager.releaseParams(httpReq.params);\n }\n if (httpReq.query && Object.keys(httpReq.query).length === 0) {\n this.poolManager.releaseQuery(httpReq.query);\n }\n }\n }\n\n private createRequestFromStream(\n stream: ServerHttp2Stream,\n headers: IncomingHttpHeaders\n ): HttpRequest {\n // Extract method from pseudo-header\n const methodRaw = ((headers[':method'] as string) || 'GET').toUpperCase();\n\n // Intern method string for fast comparison\n let method: string;\n switch (methodRaw) {\n case 'POST':\n method = MoroHttp2Server.METHOD_POST;\n break;\n case 'PUT':\n method = MoroHttp2Server.METHOD_PUT;\n break;\n case 'PATCH':\n method = MoroHttp2Server.METHOD_PATCH;\n break;\n case 'GET':\n method = MoroHttp2Server.METHOD_GET;\n break;\n case 'DELETE':\n method = MoroHttp2Server.METHOD_DELETE;\n break;\n case 'HEAD':\n method = MoroHttp2Server.METHOD_HEAD;\n break;\n case 'OPTIONS':\n method = MoroHttp2Server.METHOD_OPTIONS;\n break;\n default:\n method = methodRaw;\n }\n\n // Convert HTTP/2 headers to standard headers (remove pseudo-headers)\n const standardHeaders: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (!key.startsWith(':')) {\n standardHeaders[key] = Array.isArray(value) ? value.join(', ') : (value as string);\n }\n }\n\n // Parse cookies\n const cookieHeader = standardHeaders['cookie'];\n const cookies: Record<string, string> = {};\n if (cookieHeader) {\n const cookieParts = cookieHeader.split(';');\n for (const cookie of cookieParts) {\n const equalIndex = cookie.indexOf('=');\n if (equalIndex > 0) {\n const name = cookie.substring(0, equalIndex).trim();\n const value = cookie.substring(equalIndex + 1);\n if (name && value) {\n try {\n cookies[name] = decodeURIComponent(value);\n } catch {\n // Malformed percent-encoding: keep the raw value rather than\n // throwing a URIError. createRequestFromStream runs before\n // handleStream's try block, so an escape here would surface as\n // an unhandled rejection and crash the process.\n cookies[name] = value;\n }\n }\n }\n }\n }\n\n const httpReq: HttpRequest = {\n method,\n path: '',\n url: (headers[':path'] as string) || '/',\n query: {},\n params: {},\n headers: standardHeaders,\n body: null,\n cookies,\n ip: (stream.session?.socket as any)?.remoteAddress || '',\n requestId: this.requestTrackingEnabled ? this.poolManager.generateRequestId() : '',\n httpVersion: '2.0',\n } as HttpRequest;\n\n // Store stream reference for push capability\n (httpReq as any)._http2Stream = stream;\n (httpReq as any)._http2Headers = headers;\n\n return httpReq;\n }\n\n private createResponseFromStream(stream: ServerHttp2Stream, req: HttpRequest): HttpResponse {\n const httpRes: any = {\n statusCode: 200,\n headersSent: false,\n _headers: {} as OutgoingHttpHeaders,\n _stream: stream,\n _req: req,\n _logger: this.logger,\n _poolManager: this.poolManager,\n _compressionEnabled: this.compressionEnabled,\n _compressionThreshold: this.compressionThreshold,\n _compressionMaxInlineBytes: this.compressionMaxInlineBytes,\n };\n\n // Status method\n httpRes.status = (code: number) => {\n httpRes.statusCode = code;\n return httpRes;\n };\n\n // Set header\n httpRes.setHeader = (name: string, value: string | string[]) => {\n httpRes._headers[name.toLowerCase()] = value;\n return httpRes;\n };\n\n // Get header\n httpRes.getHeader = (name: string) => {\n return httpRes._headers[name.toLowerCase()];\n };\n\n // Remove header\n httpRes.removeHeader = (name: string) => {\n delete httpRes._headers[name.toLowerCase()];\n return httpRes;\n };\n\n // Has header\n httpRes.hasHeader = (name: string): boolean => {\n return httpRes._headers[name.toLowerCase()] !== undefined;\n };\n\n // Get headers\n httpRes.getHeaders = () => {\n return { ...httpRes._headers };\n };\n\n // Event surface for middleware written against Node's ServerResponse -\n // the built-in request logger, Prometheus, CloudWatch and performance\n // monitors all call res.on('finish', ...). This response is a plain\n // object, so its events are the stream's: a Duplex emits 'finish' once\n // the body has been flushed and 'close' when the stream is gone, the two\n // events ServerResponse fires. Without these, enabling request logging\n // (the default) turned every HTTP/2 request into a 500.\n httpRes.on = (event: string, listener: (...args: any[]) => void) => {\n stream.on(event, listener);\n return httpRes;\n };\n httpRes.once = (event: string, listener: (...args: any[]) => void) => {\n stream.once(event, listener);\n return httpRes;\n };\n httpRes.off = httpRes.removeListener = (event: string, listener: (...args: any[]) => void) => {\n stream.off(event, listener);\n return httpRes;\n };\n\n // JSON response\n httpRes.json = async (data: any) => {\n if (httpRes.headersSent || stream.destroyed) return;\n\n const jsonString = JSON.stringify(data);\n const finalBuffer = Buffer.from(jsonString, 'utf8');\n\n httpRes._headers['content-type'] = 'application/json; charset=utf-8';\n\n // Compression\n if (httpRes._compressionEnabled && finalBuffer.length > httpRes._compressionThreshold) {\n const acceptEncoding = req.headers['accept-encoding'];\n\n if (acceptEncoding && acceptEncoding.includes('gzip')) {\n // A small body is compressed on this thread (see compressionMaxInlineBytes)\n const compressed =\n httpRes._compressionMaxInlineBytes > 0 &&\n finalBuffer.length <= httpRes._compressionMaxInlineBytes\n ? compressors().gzipSync(finalBuffer)\n : await compressors().gzip(finalBuffer);\n httpRes._headers['content-encoding'] = 'gzip';\n httpRes._headers['content-length'] = compressed.length;\n\n stream.respond({\n ':status': httpRes.statusCode,\n ...httpRes._headers,\n });\n stream.end(compressed);\n httpRes.headersSent = true;\n return;\n } else if (acceptEncoding && acceptEncoding.includes('deflate')) {\n const compressed =\n httpRes._compressionMaxInlineBytes > 0 &&\n finalBuffer.length <= httpRes._compressionMaxInlineBytes\n ? compressors().deflateSync(finalBuffer)\n : await compressors().deflate(finalBuffer);\n httpRes._headers['content-encoding'] = 'deflate';\n httpRes._headers['content-length'] = compressed.length;\n\n stream.respond({\n ':status': httpRes.statusCode,\n ...httpRes._headers,\n });\n stream.end(compressed);\n httpRes.headersSent = true;\n return;\n }\n }\n\n httpRes._headers['content-length'] = finalBuffer.length;\n\n stream.respond({\n ':status': httpRes.statusCode,\n ...httpRes._headers,\n });\n stream.end(finalBuffer);\n httpRes.headersSent = true;\n };\n\n // Send response\n httpRes.send = (data: string | Buffer) => {\n if (httpRes.headersSent || stream.destroyed) return;\n\n if (!httpRes._headers['content-type']) {\n // The same sniff the engine and Node servers use: a body that starts\n // with '{' or '[' is JSON, anything else text. Parsing the whole body\n // to decide cost a JSON.parse per response and labelled a bare number\n // or `true` as JSON.\n if (typeof data === 'string') {\n httpRes._headers['content-type'] = /^\\s*[{[]/.test(data)\n ? 'application/json; charset=utf-8'\n : 'text/plain; charset=utf-8';\n } else {\n httpRes._headers['content-type'] = 'application/octet-stream';\n }\n }\n\n const buffer = typeof data === 'string' ? Buffer.from(data) : data;\n httpRes._headers['content-length'] = buffer.length;\n\n stream.respond({\n ':status': httpRes.statusCode,\n ...httpRes._headers,\n });\n stream.end(buffer);\n httpRes.headersSent = true;\n };\n\n // End response\n httpRes.end = (data?: any) => {\n if (httpRes.headersSent || stream.destroyed) return httpRes;\n\n stream.respond({\n ':status': httpRes.statusCode,\n ...httpRes._headers,\n });\n stream.end(data || '');\n httpRes.headersSent = true;\n return httpRes;\n };\n\n // Standardized response helpers\n httpRes.success = <T = any>(data: T, message?: string) => {\n const response: any = {\n success: true,\n data,\n };\n if (message !== undefined) {\n response.message = message;\n }\n httpRes.json(response);\n };\n\n httpRes.error = (error: string, code?: string, message?: string) => {\n const response: any = {\n success: false,\n error,\n };\n if (code !== undefined) {\n response.code = code;\n }\n if (message !== undefined) {\n response.message = message;\n }\n httpRes.json(response);\n };\n\n // Common HTTP error helpers (automatically set status code)\n httpRes.unauthorized = (message: string = 'Authentication required') => {\n httpRes.statusCode = 401;\n httpRes.json({\n success: false,\n error: 'Unauthorized',\n code: 'UNAUTHORIZED',\n message,\n });\n };\n\n httpRes.forbidden = (message: string = 'Insufficient permissions') => {\n httpRes.statusCode = 403;\n httpRes.json({\n success: false,\n error: 'Forbidden',\n code: 'FORBIDDEN',\n message,\n });\n };\n\n httpRes.notFound = (resource: string = 'Resource') => {\n httpRes.statusCode = 404;\n httpRes.json({\n success: false,\n error: 'Not Found',\n code: 'NOT_FOUND',\n message: `${resource} not found`,\n });\n };\n\n httpRes.badRequest = (message: string = 'Invalid request') => {\n httpRes.statusCode = 400;\n httpRes.json({\n success: false,\n error: 'Bad Request',\n code: 'BAD_REQUEST',\n message,\n });\n };\n\n httpRes.conflict = (message: string) => {\n httpRes.statusCode = 409;\n httpRes.json({\n success: false,\n error: 'Conflict',\n code: 'CONFLICT',\n message,\n });\n };\n\n httpRes.internalError = (message: string = 'Internal server error') => {\n httpRes.statusCode = 500;\n httpRes.json({\n success: false,\n error: 'Internal Server Error',\n code: 'INTERNAL_ERROR',\n message,\n });\n };\n\n httpRes.validationError = (\n errors: Array<{ field: string; message: string; code?: string }>\n ) => {\n httpRes.statusCode = 422;\n httpRes.json({\n success: false,\n error: 'Validation Failed',\n code: 'VALIDATION_ERROR',\n errors,\n });\n };\n\n httpRes.rateLimited = (retryAfter?: number) => {\n httpRes.statusCode = 429;\n if (retryAfter) {\n httpRes.setHeader('Retry-After', retryAfter.toString());\n }\n httpRes.json({\n success: false,\n error: 'Rate Limit Exceeded',\n code: 'RATE_LIMITED',\n message: retryAfter\n ? `Too many requests. Retry after ${retryAfter} seconds.`\n : 'Too many requests',\n retryAfter,\n });\n };\n\n // Common success patterns\n httpRes.created = <T = any>(data: T, location?: string) => {\n httpRes.statusCode = 201;\n if (location) {\n httpRes.setHeader('Location', location);\n }\n httpRes.json({\n success: true,\n data,\n });\n };\n\n httpRes.noContent = () => {\n httpRes.statusCode = 204;\n httpRes.end();\n };\n\n httpRes.paginated = <T = any>(\n data: T[],\n pagination: { page: number; limit: number; total: number }\n ) => {\n const totalPages = Math.ceil(pagination.total / pagination.limit);\n httpRes.json({\n success: true,\n data,\n pagination: {\n page: pagination.page,\n limit: pagination.limit,\n total: pagination.total,\n totalPages,\n hasNext: pagination.page < totalPages,\n hasPrev: pagination.page > 1,\n },\n });\n };\n\n // Cookie handling\n httpRes.cookie = (name: string, value: string, options: any = {}) => {\n if (httpRes.headersSent) {\n const isCritical = options.critical || name.includes('session') || name.includes('auth');\n const message = `Cookie '${name}' could not be set - headers already sent`;\n\n if (isCritical || options.throwOnLateSet) {\n throw new Error(`${message}. This may cause authentication or security issues.`);\n } else {\n httpRes._logger.warn(message, 'CookieWarning', { cookieName: name });\n }\n return httpRes;\n }\n\n const cookieValue = encodeURIComponent(value);\n let cookieString = `${name}=${cookieValue}`;\n\n if (options.maxAge) cookieString += `; Max-Age=${options.maxAge}`;\n if (options.expires) cookieString += `; Expires=${options.expires.toUTCString()}`;\n if (options.httpOnly) cookieString += '; HttpOnly';\n if (options.secure) cookieString += '; Secure';\n if (options.sameSite) cookieString += `; SameSite=${options.sameSite}`;\n if (options.domain) cookieString += `; Domain=${options.domain}`;\n if (options.path) cookieString += `; Path=${options.path}`;\n\n const existingCookies = httpRes._headers['set-cookie'] || [];\n const cookies = Array.isArray(existingCookies)\n ? existingCookies\n : [existingCookies as string];\n cookies.push(cookieString);\n httpRes._headers['set-cookie'] = cookies;\n\n return httpRes;\n };\n\n // Clear cookie\n httpRes.clearCookie = (name: string, options: any = {}) => {\n return httpRes.cookie(name, '', {\n expires: new Date(0),\n maxAge: 0,\n ...options,\n });\n };\n\n // Redirect\n httpRes.redirect = (url: string, status: number = 302) => {\n if (httpRes.headersSent || stream.destroyed) return;\n\n httpRes.statusCode = status;\n httpRes._headers['location'] = url;\n\n stream.respond({\n ':status': status,\n ...httpRes._headers,\n });\n stream.end();\n httpRes.headersSent = true;\n };\n\n // HTTP/2 Server Push\n httpRes.push = (\n path: string,\n options: { headers?: OutgoingHttpHeaders; priority?: number } = {}\n ) => {\n if (httpRes.headersSent || stream.destroyed || !stream.pushAllowed) {\n return null;\n }\n\n try {\n const pushHeaders: any = {\n ':path': path,\n ':method': 'GET',\n ...options.headers,\n };\n\n const pushStream = stream.pushStream(pushHeaders, err => {\n if (err) {\n httpRes._logger.debug('Server push failed', 'ServerPush', {\n path,\n error: err.message,\n });\n }\n });\n\n // Set stream priority if specified\n if (options.priority !== undefined && pushStream) {\n try {\n // Priority weight: 1-256 (default 16)\n // Higher values = higher priority\n const weight = Math.max(1, Math.min(256, options.priority));\n (pushStream as any).priority({\n parent: 0,\n weight,\n exclusive: false,\n });\n } catch (error) {\n httpRes._logger.debug('Failed to set stream priority', 'StreamPriority', {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n return pushStream;\n } catch (error) {\n httpRes._logger.debug('Server push error', 'ServerPush', {\n path,\n error: error instanceof Error ? error.message : String(error),\n });\n return null;\n }\n };\n\n // Set stream priority for current response\n httpRes.setPriority = (\n options: { parent?: number; weight?: number; exclusive?: boolean } = {}\n ) => {\n if (httpRes.headersSent || stream.destroyed) {\n return httpRes;\n }\n\n try {\n stream.priority({\n parent: options.parent || 0,\n weight: options.weight ? Math.max(1, Math.min(256, options.weight)) : 16,\n exclusive: options.exclusive || false,\n });\n } catch (error) {\n httpRes._logger.debug('Failed to set stream priority', 'StreamPriority', {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n\n return httpRes;\n };\n\n // Set bulk headers\n httpRes.setBulkHeaders = (headers: Record<string, string | number>) => {\n if (httpRes.headersSent) {\n httpRes._logger.warn('Cannot set headers - headers already sent', 'HeaderWarning');\n return httpRes;\n }\n\n for (const key in headers) {\n httpRes._headers[key.toLowerCase()] = String(headers[key]);\n }\n return httpRes;\n };\n\n // Response state\n httpRes.canSetHeaders = (): boolean => {\n return !httpRes.headersSent;\n };\n\n httpRes.getResponseState = () => {\n return {\n headersSent: httpRes.headersSent,\n statusCode: httpRes.statusCode,\n headers: httpRes.getHeaders(),\n finished: stream.destroyed,\n writable: !stream.destroyed,\n };\n };\n\n return httpRes as HttpResponse;\n }\n\n private async parseBody(stream: ServerHttp2Stream, headers: IncomingHttpHeaders): Promise<any> {\n const contentType = (headers['content-type'] as string) || '';\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const contentLength = parseInt((headers['content-length'] as string) || '0');\n\n // Use different limits based on content type\n const isMultipart = contentType.includes('multipart/form-data');\n const maxSize = isMultipart\n ? this.maxUploadSize // Configurable file upload limit (default 100MB)\n : this.maxBodySize; // Configurable body size limit (default 10MB, from server.bodySizeLimit config)\n\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let totalLength = 0;\n\n stream.on('data', (chunk: Buffer) => {\n totalLength += chunk.length;\n if (totalLength > maxSize) {\n const errorMessage = isMultipart\n ? `File upload too large. Maximum ${Math.floor(maxSize / (1024 * 1024))}MB allowed.`\n : 'Request body too large';\n reject(new Error(errorMessage));\n return;\n }\n chunks.push(chunk);\n });\n\n stream.on('end', () => {\n try {\n const body = Buffer.concat(chunks);\n\n if (contentType.includes('application/json')) {\n resolve(JSON.parse(body.toString()));\n } else if (contentType.includes('application/x-www-form-urlencoded')) {\n resolve(this.parseUrlEncoded(body.toString()));\n } else if (contentType.includes('multipart/form-data')) {\n resolve(parseMultipartBuffer(body, contentType, this.multipartLimits));\n } else {\n resolve(body.toString());\n }\n } catch (error) {\n reject(error);\n }\n });\n\n stream.on('error', reject);\n });\n }\n\n private parseUrlEncoded(body: string): Record<string, string> {\n const params = new URLSearchParams(body);\n const result: Record<string, string> = {};\n for (const [key, value] of params) {\n result[key] = value;\n }\n return result;\n }\n\n private parseQueryString(queryString: string): Record<string, string> {\n if (!queryString) return {};\n\n const result = this.poolManager.acquireQuery();\n const pairs = queryString.split('&');\n\n for (const pair of pairs) {\n const equalIndex = pair.indexOf('=');\n if (equalIndex === -1) {\n result[decodeURIComponent(pair)] = '';\n } else {\n const key = decodeURIComponent(pair.substring(0, equalIndex));\n const value = decodeURIComponent(pair.substring(equalIndex + 1));\n result[key] = value;\n }\n }\n return result;\n }\n\n private normalizePath(path: string): string {\n if (this.pathNormalizationCache.has(path)) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return this.pathNormalizationCache.get(path)!;\n }\n\n let normalized = path;\n if (normalized.length > 1 && normalized.endsWith('/')) {\n normalized = normalized.slice(0, -1);\n }\n\n if (this.pathNormalizationCache.size < 200) {\n this.pathNormalizationCache.set(path, normalized);\n }\n\n return normalized;\n }\n\n private findRoute(method: string, path: string | undefined): RouteEntry | null {\n // Default to '/' if path is undefined\n const searchPath = path || '/';\n const cacheKey = `${method}:${searchPath}`;\n\n if (this.routeCache.has(cacheKey)) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return this.routeCache.get(cacheKey)!;\n }\n\n const normalizedPath = this.normalizePath(searchPath);\n const normalizedCacheKey =\n normalizedPath !== searchPath ? `${method}:${normalizedPath}` : cacheKey;\n\n if (normalizedPath !== path && this.routeCache.has(normalizedCacheKey)) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return this.routeCache.get(normalizedCacheKey)!;\n }\n\n const staticRoute = this.staticRoutes.get(normalizedCacheKey);\n if (staticRoute) {\n this.routeCache.set(normalizedCacheKey, staticRoute);\n if (normalizedPath !== path) {\n this.routeCache.set(cacheKey, staticRoute);\n }\n return staticRoute;\n }\n\n let route: RouteEntry | null = null;\n if (this.dynamicRoutes.length > 0) {\n const segmentCount = PathMatcher.countSegments(normalizedPath);\n const candidateRoutes = this.routesBySegmentCount.get(segmentCount) || this.dynamicRoutes;\n\n for (const candidateRoute of candidateRoutes) {\n if (candidateRoute.method === method && candidateRoute.pattern.test(normalizedPath)) {\n route = candidateRoute;\n break;\n }\n }\n }\n\n if (this.routeCache.size < 500) {\n this.routeCache.set(normalizedCacheKey, route);\n if (normalizedPath !== path) {\n this.routeCache.set(cacheKey, route);\n }\n }\n\n return route;\n }\n\n private async executeMiddleware(\n middleware: Middleware[],\n req: HttpRequest,\n res: HttpResponse\n ): Promise<void> {\n for (const mw of middleware) {\n if (res.headersSent) return;\n\n await new Promise<void>((resolve, reject) => {\n let resolved = false;\n\n const next = () => {\n if (resolved) return;\n resolved = true;\n resolve();\n };\n\n try {\n const result = mw(req, res, next);\n\n if (result && typeof result.then === 'function') {\n (result as Promise<void>)\n .then(() => {\n if (!resolved) next();\n })\n .catch(reject);\n } else if (!resolved) {\n next();\n }\n } catch (error) {\n if (!resolved) {\n resolved = true;\n reject(error);\n }\n }\n });\n }\n }\n\n listen(port: number, callback?: () => void): void;\n listen(port: number, host: string, callback?: () => void): void;\n listen(port: number, host?: string | (() => void), callback?: () => void): void {\n if (typeof host === 'function') {\n callback = host;\n host = undefined;\n }\n\n if (host) {\n this.server.listen(port, host, callback);\n } else {\n this.server.listen(port, callback);\n }\n }\n\n close(): Promise<void> {\n return new Promise(resolve => {\n this.server.close(() => resolve());\n });\n }\n\n forceCleanup(): void {\n this.poolManager.clearAll();\n if (globalThis?.gc) {\n globalThis.gc();\n }\n }\n\n /**\n * Replace the TLS certificate/key for new handshakes (Http2SecureServer is\n * a tls.Server; setSecureContext applies to every later handshake).\n */\n updateSsl(ssl: {\n key: string | Buffer;\n cert: string | Buffer;\n ca?: Array<string | Buffer>;\n passphrase?: string;\n minVersion?: string;\n requestCert?: boolean;\n rejectUnauthorized?: boolean;\n }): void {\n const server = this.server as any;\n if (typeof server.setSecureContext !== 'function') {\n throw new Error('updateSsl: this server was not started with TLS (server.ssl)');\n }\n server.setSecureContext(ssl);\n }\n\n getServer(): Http2Server | Http2SecureServer {\n return this.server;\n }\n\n getPerformanceStats() {\n const poolStats = this.poolManager.getStats();\n return {\n paramObjectPoolSize: poolStats.paramPool.poolSize,\n queryObjectPoolSize: poolStats.queryPool.poolSize,\n headerObjectPoolSize: poolStats.headerPool.poolSize,\n poolManager: poolStats,\n };\n }\n}\n"]}
@@ -74,6 +74,7 @@ export interface Http2SettingsConfig {
74
74
  maxFrameSize?: number;
75
75
  maxHeaderListSize?: number;
76
76
  headerTableSize?: number;
77
+ /** Accepted for compatibility but never sent: RFC 9113 forbids a server from advertising ENABLE_PUSH=1 (clients drop the connection), and whether push is possible is the client's setting, read per stream. */
77
78
  enablePush?: boolean;
78
79
  enableConnectProtocol?: boolean;
79
80
  maxHeaderSize?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA,0DAA0D","sourcesContent":["// TypeScript-based Configuration Types for Moro Framework\n\n/**\n * CORS origin function type for dynamic origin validation\n */\nexport type OriginFunction = (\n origin: string | undefined,\n req: any\n) => string | string[] | boolean | Promise<string | string[] | boolean>;\n\n/**\n * Deep partial type that makes all properties and nested properties optional\n * Used for user-provided configuration where only partial overrides are needed\n */\nexport type DeepPartial<T> = T extends object\n ? T extends Array<infer U>\n ? Array<DeepPartial<U>>\n : T extends (...args: any[]) => any\n ? T\n : { [P in keyof T]?: DeepPartial<T[P]> }\n : T;\n\n/** Unified SSL/TLS config (superset of both historical shapes). */\nexport interface SSLConfig {\n /** File-path shape (uWS-style; keyFile/certFile also accepted) */\n key_file_name?: string;\n cert_file_name?: string;\n ca_file_name?: string | string[];\n keyFile?: string;\n certFile?: string;\n caFile?: string | string[];\n /** Inline-PEM shape (node-style) */\n key?: string | Buffer;\n cert?: string | Buffer;\n ca?: string | Buffer | Array<string | Buffer>;\n passphrase?: string;\n minVersion?: 'TLSv1.2' | 'TLSv1.3';\n requestCert?: boolean;\n rejectUnauthorized?: boolean;\n /**\n * Reload the certificate when the key/cert files change on disk (file-path\n * shape only; `true` = 1000 ms debounce). Equivalent to calling\n * `app.reloadTLS()` after each change.\n */\n watch?: boolean | { debounceMs?: number };\n}\n\n/** Per-phase receive timeouts. 0 = use the per-server default / disabled. */\nexport interface ServerTimeoutsConfig {\n /** Full-request receive budget (ms); does NOT reset on activity. */\n request?: number;\n /** Socket inactivity timeout (ms). */\n idle?: number;\n /** Node keep-alive socket timeout (ms). Default 5000. */\n keepAlive?: number;\n /** Node headers-received timeout (ms). Default 6000. */\n headers?: number;\n}\n\nexport interface MultipartLimitsConfig {\n maxParts?: number;\n maxPartHeaderBytes?: number | string;\n maxFiles?: number;\n maxFileSize?: number | string;\n}\n\n/** Fine-grained limits; every value is a documented default, not a hard cap. */\nexport interface ServerLimitsConfig {\n /** Max request head (request line + headers) size. Node maxHeaderSize / engine maxHeadSize. */\n maxHeaderSize?: number | string;\n /** Max header count. Node maxHeadersCount / engine maxHeaders. */\n maxHeaders?: number;\n multipart?: MultipartLimitsConfig;\n /** Reassembled WebSocket message cap (engine wsMaxMessageSize). */\n wsMaxMessageSize?: number | string;\n /** WebSocket send backpressure cap (engine wsBackpressureLimit). 0 = unlimited. */\n wsBackpressureLimit?: number | string;\n /** Write-queue high-water mark (engine writeHighWaterMark). */\n writeHighWaterMark?: number | string;\n /** Per-connection not-yet-parsed backlog cap (engine maxPendingBytes). */\n maxPendingBytes?: number | string;\n}\n\nexport interface Http2SettingsConfig {\n maxConcurrentStreams?: number;\n initialWindowSize?: number;\n maxFrameSize?: number;\n maxHeaderListSize?: number;\n headerTableSize?: number;\n enablePush?: boolean;\n enableConnectProtocol?: boolean;\n maxHeaderSize?: number;\n}\n\nexport interface ServerConfig {\n port: number;\n host: string;\n maxConnections: number;\n /** @deprecated Use timeouts.request. Kept as an alias; still honored. */\n timeout: number;\n bodySizeLimit: string;\n maxUploadSize: string; // Maximum size for file uploads (multipart/form-data)\n /** Per-phase receive timeouts (finally applied to every runtime). */\n timeouts?: ServerTimeoutsConfig;\n /** Fine-grained size/count limits, passed through to whichever runtime serves. */\n limits?: ServerLimitsConfig;\n /** TCP listen backlog. */\n backlog?: number;\n /** HTTP/2: true, or an options object. Served natively by the engine when\n * it supports h2 (feature-detected), else by the Node http2 server. */\n http2?:\n boolean | { allowHTTP1?: boolean; maxSessionMemory?: number; settings?: Http2SettingsConfig };\n requestTracking: {\n enabled: boolean;\n };\n requestLogging: {\n enabled: boolean;\n };\n errorBoundary: {\n enabled: boolean;\n };\n /**\n * HTTP engine selection. Default: 'moro'.\n * - 'moro' (default): Moro's own native engine (@morojs/engine), falling back\n * to the Node.js http server if it cannot load on this platform/Node ABI\n * - 'node': the Node.js http server (no native engine)\n * - 'uws': opt in to uWebSockets.js, falling back to Node.js if it cannot load\n * Any chosen engine that cannot load degrades to Node.js and logs why; the app\n * never fails to boot. Inspect what actually booted via app.engine.\n */\n engine?: 'moro' | 'node' | 'uws';\n /** @deprecated Use engine: 'uws' instead. Enable uWebSockets for both HTTP and WebSocket */\n useUWebSockets?: boolean;\n /** Unified SSL/TLS config; flows to whichever runtime serves. */\n ssl?: SSLConfig;\n}\n\nexport interface ServiceDiscoveryConfig {\n enabled: boolean;\n type: 'memory' | 'consul' | 'kubernetes';\n consulUrl: string;\n kubernetesNamespace: string;\n healthCheckInterval: number;\n retryAttempts: number;\n}\n\nexport interface DatabaseConfig {\n url?: string;\n redis?: {\n url: string;\n maxRetries: number;\n retryDelay: number;\n keyPrefix: string;\n };\n mysql?: {\n host: string;\n port: number;\n database?: string;\n username?: string;\n password?: string;\n connectionLimit: number;\n acquireTimeout: number;\n timeout: number;\n };\n postgresql?: {\n host: string;\n port: number;\n database?: string;\n user?: string;\n password?: string;\n connectionLimit: number;\n ssl?: boolean;\n };\n sqlite?: {\n filename: string;\n memory?: boolean;\n verbose?: boolean;\n };\n mongodb?: {\n url?: string;\n host?: string;\n port?: number;\n database?: string;\n username?: string;\n password?: string;\n };\n}\n\n// Validation error context passed to error handlers\nexport interface ValidationErrorContext {\n request: {\n method: string;\n path: string;\n url: string;\n headers: Record<string, any>;\n };\n route?: {\n path: string;\n method: string;\n };\n field: 'body' | 'query' | 'params' | 'headers';\n}\n\n// Validation error detail structure\nexport interface ValidationErrorDetail {\n field: string;\n message: string;\n code?: string;\n value?: any;\n path?: (string | number)[];\n}\n\n// Validation error response structure\nexport interface ValidationErrorResponse {\n status: number;\n body: any;\n headers?: Record<string, string>;\n}\n\n// Validation error handler function type\nexport type ValidationErrorHandler = (\n errors: ValidationErrorDetail[],\n context: ValidationErrorContext\n) => ValidationErrorResponse;\n\nexport interface ModuleDefaultsConfig {\n apiPrefix?: string; // Prefix for module routes, defaults to '/api/' - set to empty string '' to disable\n cache: {\n enabled: boolean;\n defaultTtl: number;\n maxSize: number;\n strategy: 'lru' | 'lfu' | 'fifo';\n };\n rateLimit: {\n enabled: boolean;\n defaultRequests: number;\n defaultWindow: number;\n skipSuccessfulRequests: boolean;\n skipFailedRequests: boolean;\n };\n validation: {\n enabled: boolean;\n stripUnknown: boolean;\n abortEarly: boolean;\n allowUnknown?: boolean;\n onError?: ValidationErrorHandler;\n };\n session?: {\n enabled: boolean;\n store: 'memory' | 'redis' | 'file';\n storeOptions?: {\n url?: string;\n host?: string;\n port?: number;\n password?: string;\n keyPrefix?: string;\n path?: string;\n max?: number;\n };\n secret?: string;\n name?: string;\n rolling?: boolean;\n resave?: boolean;\n saveUninitialized?: boolean;\n cookie?: {\n maxAge?: number;\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: 'strict' | 'lax' | 'none';\n domain?: string;\n path?: string;\n };\n proxy?: boolean;\n unset?: 'destroy' | 'keep';\n };\n autoDiscovery: {\n enabled: boolean;\n paths: string[];\n patterns: string[];\n recursive: boolean;\n loadingStrategy: 'eager' | 'lazy' | 'conditional';\n watchForChanges: boolean;\n ignorePatterns: string[];\n loadOrder: 'alphabetical' | 'dependency' | 'custom';\n failOnError: boolean;\n maxDepth: number;\n };\n}\n\nexport interface LoggingConfig {\n level: 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n format: 'pretty' | 'json' | 'compact';\n enableColors: boolean;\n enableTimestamp: boolean;\n enableContext: boolean;\n // Opt-in: appends a JSON metadata object (e.g. {\"framework\":\"moro\",...}) to pretty log lines.\n // Has no effect on 'json' format - structured output always includes metadata.\n enableMetadata: boolean;\n // Opt-in: collects and renders per-log performance data such as memory usage (e.g. \"(210MB)\").\n // Disabling skips the process.memoryUsage() call on every log line.\n enablePerformance: boolean;\n outputs: {\n console: boolean;\n file: {\n enabled: boolean;\n path: string;\n maxSize: string;\n maxFiles: number;\n };\n webhook: {\n enabled: boolean;\n url?: string;\n headers: Record<string, string>;\n };\n };\n}\n\nexport interface SecurityConfig {\n cors: {\n enabled: boolean;\n origin: string | string[] | boolean | OriginFunction;\n methods: string[];\n allowedHeaders: string[];\n exposedHeaders?: string[];\n credentials: boolean;\n maxAge?: number;\n preflightContinue?: boolean;\n };\n helmet: {\n enabled: boolean;\n // Simplified options (backward compatible)\n contentSecurityPolicy?: boolean;\n hsts?: boolean;\n noSniff?: boolean;\n frameguard?: boolean;\n // Detailed options (for advanced configuration)\n xFrameOptions?: 'DENY' | 'SAMEORIGIN';\n xContentTypeOptions?: boolean;\n xXssProtection?: boolean;\n referrerPolicy?: string;\n strictTransportSecurity?: { maxAge?: number; includeSubDomains?: boolean };\n xDownloadOptions?: boolean;\n xPermittedCrossDomainPolicies?: boolean;\n };\n csrf?: {\n enabled: boolean;\n secret?: string;\n tokenLength?: number;\n cookieName?: string;\n headerName?: string;\n ignoreMethods?: string[];\n sameSite?: boolean;\n };\n csp?: {\n enabled: boolean;\n directives?: {\n defaultSrc?: string[];\n scriptSrc?: string[];\n styleSrc?: string[];\n imgSrc?: string[];\n connectSrc?: string[];\n fontSrc?: string[];\n objectSrc?: string[];\n mediaSrc?: string[];\n frameSrc?: string[];\n childSrc?: string[];\n workerSrc?: string[];\n formAction?: string[];\n upgradeInsecureRequests?: boolean;\n blockAllMixedContent?: boolean;\n };\n reportOnly?: boolean;\n reportUri?: string;\n nonce?: boolean;\n };\n rateLimit: {\n global: {\n enabled: boolean;\n requests: number;\n window: number;\n };\n };\n}\n\nexport interface ExternalServicesConfig {\n stripe?: {\n secretKey?: string | undefined;\n publishableKey?: string | undefined;\n webhookSecret?: string | undefined;\n apiVersion: string;\n };\n paypal?: {\n clientId?: string | undefined;\n clientSecret?: string | undefined;\n webhookId?: string | undefined;\n environment: 'sandbox' | 'production';\n };\n smtp?: {\n host?: string | undefined;\n port: number;\n secure: boolean;\n username?: string | undefined;\n password?: string | undefined;\n };\n}\n\nexport interface PerformanceConfig {\n compression: {\n enabled: boolean;\n level: number;\n threshold: number;\n /** Encoding preference order (default ['br','gzip','deflate']). */\n encodings?: Array<'br' | 'gzip' | 'deflate'>;\n /**\n * Bodies at or below this size are compressed on the calling thread and\n * sent with a Content-Length; larger ones are compressed on the\n * threadpool and streamed. 0 sends every body through the pool.\n * Default 16384.\n */\n maxInlineBytes?: number;\n };\n circuitBreaker: {\n enabled: boolean;\n failureThreshold: number;\n resetTimeout: number;\n monitoringPeriod: number;\n };\n clustering: {\n enabled: boolean;\n workers: number | 'auto';\n memoryPerWorkerGB?: number | undefined;\n };\n}\n\nexport interface WebSocketConfig {\n enabled: boolean;\n adapter?: string | 'socket.io' | 'ws' | 'uws';\n compression?: boolean;\n customIdGenerator?: () => string;\n options?: {\n cors?: {\n origin?: string | string[];\n credentials?: boolean;\n };\n path?: string;\n maxPayloadLength?: number;\n idleTimeout?: number;\n ssl?: {\n key_file_name?: string;\n cert_file_name?: string;\n passphrase?: string;\n };\n };\n}\n\nexport interface JobsConfig {\n enabled?: boolean;\n maxConcurrentJobs?: number;\n gracefulShutdownTimeout?: number;\n leaderElection?: {\n enabled?: boolean;\n strategy?: 'file' | 'redis' | 'none';\n lockPath?: string;\n lockTimeout?: number;\n heartbeatInterval?: number;\n };\n executor?: {\n maxRetries?: number;\n retryDelay?: number;\n retryBackoff?: 'linear' | 'exponential';\n retryBackoffMultiplier?: number;\n maxRetryDelay?: number;\n timeout?: number;\n enableCircuitBreaker?: boolean;\n circuitBreakerThreshold?: number;\n circuitBreakerResetTimeout?: number;\n enableMemoryMonitoring?: boolean;\n memoryThreshold?: number;\n };\n stateManager?: {\n persistPath?: string;\n historySize?: number;\n persistInterval?: number;\n enableAutoPersist?: boolean;\n enableRecovery?: boolean;\n };\n}\n\n// File-based routing configuration. When enabled, route files under the\n// configured directories are imported during startup (after module discovery)\n// so their `getApp().get(...)` registrations execute automatically.\nexport interface RoutingConfig {\n enabled: boolean;\n // Directories scanned via loadRoutes(). Defaults to ./src/routes in\n // development and ./dist/(src/)routes in production when omitted.\n paths?: string[];\n}\n\n// Main configuration interface\nexport interface AppConfig {\n server: ServerConfig;\n serviceDiscovery: ServiceDiscoveryConfig;\n database: DatabaseConfig;\n modules: ModuleDefaultsConfig;\n // Enable file-based auto routing (./src/routes). Defaults to true.\n routing: boolean | RoutingConfig;\n logging: LoggingConfig;\n security: SecurityConfig;\n external: ExternalServicesConfig;\n performance: PerformanceConfig;\n websocket: WebSocketConfig;\n jobs?: JobsConfig;\n queue?: QueueConfig;\n}\n\n// Queue Configuration\nexport interface QueueConfig {\n adapter?: 'bull' | 'rabbitmq' | 'sqs' | 'kafka' | 'memory';\n connection?: {\n host?: string;\n port?: number;\n username?: string;\n password?: string;\n database?: number;\n brokers?: string[];\n groupId?: string;\n region?: string;\n queueUrl?: string;\n [key: string]: any;\n };\n concurrency?: number;\n retry?: {\n maxAttempts: number;\n backoff: 'fixed' | 'exponential' | 'linear';\n initialDelay: number;\n maxDelay?: number;\n };\n deadLetterQueue?: {\n enabled: boolean;\n maxRetries: number;\n queueName?: string;\n };\n defaultJobOptions?: {\n removeOnComplete?: boolean | number;\n removeOnFail?: boolean | number;\n attempts?: number;\n backoff?: {\n type: 'fixed' | 'exponential' | 'linear';\n delay: number;\n };\n };\n prefix?: string;\n limiter?: {\n max: number;\n duration: number;\n };\n}\n"]}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA,0DAA0D","sourcesContent":["// TypeScript-based Configuration Types for Moro Framework\n\n/**\n * CORS origin function type for dynamic origin validation\n */\nexport type OriginFunction = (\n origin: string | undefined,\n req: any\n) => string | string[] | boolean | Promise<string | string[] | boolean>;\n\n/**\n * Deep partial type that makes all properties and nested properties optional\n * Used for user-provided configuration where only partial overrides are needed\n */\nexport type DeepPartial<T> = T extends object\n ? T extends Array<infer U>\n ? Array<DeepPartial<U>>\n : T extends (...args: any[]) => any\n ? T\n : { [P in keyof T]?: DeepPartial<T[P]> }\n : T;\n\n/** Unified SSL/TLS config (superset of both historical shapes). */\nexport interface SSLConfig {\n /** File-path shape (uWS-style; keyFile/certFile also accepted) */\n key_file_name?: string;\n cert_file_name?: string;\n ca_file_name?: string | string[];\n keyFile?: string;\n certFile?: string;\n caFile?: string | string[];\n /** Inline-PEM shape (node-style) */\n key?: string | Buffer;\n cert?: string | Buffer;\n ca?: string | Buffer | Array<string | Buffer>;\n passphrase?: string;\n minVersion?: 'TLSv1.2' | 'TLSv1.3';\n requestCert?: boolean;\n rejectUnauthorized?: boolean;\n /**\n * Reload the certificate when the key/cert files change on disk (file-path\n * shape only; `true` = 1000 ms debounce). Equivalent to calling\n * `app.reloadTLS()` after each change.\n */\n watch?: boolean | { debounceMs?: number };\n}\n\n/** Per-phase receive timeouts. 0 = use the per-server default / disabled. */\nexport interface ServerTimeoutsConfig {\n /** Full-request receive budget (ms); does NOT reset on activity. */\n request?: number;\n /** Socket inactivity timeout (ms). */\n idle?: number;\n /** Node keep-alive socket timeout (ms). Default 5000. */\n keepAlive?: number;\n /** Node headers-received timeout (ms). Default 6000. */\n headers?: number;\n}\n\nexport interface MultipartLimitsConfig {\n maxParts?: number;\n maxPartHeaderBytes?: number | string;\n maxFiles?: number;\n maxFileSize?: number | string;\n}\n\n/** Fine-grained limits; every value is a documented default, not a hard cap. */\nexport interface ServerLimitsConfig {\n /** Max request head (request line + headers) size. Node maxHeaderSize / engine maxHeadSize. */\n maxHeaderSize?: number | string;\n /** Max header count. Node maxHeadersCount / engine maxHeaders. */\n maxHeaders?: number;\n multipart?: MultipartLimitsConfig;\n /** Reassembled WebSocket message cap (engine wsMaxMessageSize). */\n wsMaxMessageSize?: number | string;\n /** WebSocket send backpressure cap (engine wsBackpressureLimit). 0 = unlimited. */\n wsBackpressureLimit?: number | string;\n /** Write-queue high-water mark (engine writeHighWaterMark). */\n writeHighWaterMark?: number | string;\n /** Per-connection not-yet-parsed backlog cap (engine maxPendingBytes). */\n maxPendingBytes?: number | string;\n}\n\nexport interface Http2SettingsConfig {\n maxConcurrentStreams?: number;\n initialWindowSize?: number;\n maxFrameSize?: number;\n maxHeaderListSize?: number;\n headerTableSize?: number;\n /** Accepted for compatibility but never sent: RFC 9113 forbids a server from advertising ENABLE_PUSH=1 (clients drop the connection), and whether push is possible is the client's setting, read per stream. */\n enablePush?: boolean;\n enableConnectProtocol?: boolean;\n maxHeaderSize?: number;\n}\n\nexport interface ServerConfig {\n port: number;\n host: string;\n maxConnections: number;\n /** @deprecated Use timeouts.request. Kept as an alias; still honored. */\n timeout: number;\n bodySizeLimit: string;\n maxUploadSize: string; // Maximum size for file uploads (multipart/form-data)\n /** Per-phase receive timeouts (finally applied to every runtime). */\n timeouts?: ServerTimeoutsConfig;\n /** Fine-grained size/count limits, passed through to whichever runtime serves. */\n limits?: ServerLimitsConfig;\n /** TCP listen backlog. */\n backlog?: number;\n /** HTTP/2: true, or an options object. Served natively by the engine when\n * it supports h2 (feature-detected), else by the Node http2 server. */\n http2?:\n boolean | { allowHTTP1?: boolean; maxSessionMemory?: number; settings?: Http2SettingsConfig };\n requestTracking: {\n enabled: boolean;\n };\n requestLogging: {\n enabled: boolean;\n };\n errorBoundary: {\n enabled: boolean;\n };\n /**\n * HTTP engine selection. Default: 'moro'.\n * - 'moro' (default): Moro's own native engine (@morojs/engine), falling back\n * to the Node.js http server if it cannot load on this platform/Node ABI\n * - 'node': the Node.js http server (no native engine)\n * - 'uws': opt in to uWebSockets.js, falling back to Node.js if it cannot load\n * Any chosen engine that cannot load degrades to Node.js and logs why; the app\n * never fails to boot. Inspect what actually booted via app.engine.\n */\n engine?: 'moro' | 'node' | 'uws';\n /** @deprecated Use engine: 'uws' instead. Enable uWebSockets for both HTTP and WebSocket */\n useUWebSockets?: boolean;\n /** Unified SSL/TLS config; flows to whichever runtime serves. */\n ssl?: SSLConfig;\n}\n\nexport interface ServiceDiscoveryConfig {\n enabled: boolean;\n type: 'memory' | 'consul' | 'kubernetes';\n consulUrl: string;\n kubernetesNamespace: string;\n healthCheckInterval: number;\n retryAttempts: number;\n}\n\nexport interface DatabaseConfig {\n url?: string;\n redis?: {\n url: string;\n maxRetries: number;\n retryDelay: number;\n keyPrefix: string;\n };\n mysql?: {\n host: string;\n port: number;\n database?: string;\n username?: string;\n password?: string;\n connectionLimit: number;\n acquireTimeout: number;\n timeout: number;\n };\n postgresql?: {\n host: string;\n port: number;\n database?: string;\n user?: string;\n password?: string;\n connectionLimit: number;\n ssl?: boolean;\n };\n sqlite?: {\n filename: string;\n memory?: boolean;\n verbose?: boolean;\n };\n mongodb?: {\n url?: string;\n host?: string;\n port?: number;\n database?: string;\n username?: string;\n password?: string;\n };\n}\n\n// Validation error context passed to error handlers\nexport interface ValidationErrorContext {\n request: {\n method: string;\n path: string;\n url: string;\n headers: Record<string, any>;\n };\n route?: {\n path: string;\n method: string;\n };\n field: 'body' | 'query' | 'params' | 'headers';\n}\n\n// Validation error detail structure\nexport interface ValidationErrorDetail {\n field: string;\n message: string;\n code?: string;\n value?: any;\n path?: (string | number)[];\n}\n\n// Validation error response structure\nexport interface ValidationErrorResponse {\n status: number;\n body: any;\n headers?: Record<string, string>;\n}\n\n// Validation error handler function type\nexport type ValidationErrorHandler = (\n errors: ValidationErrorDetail[],\n context: ValidationErrorContext\n) => ValidationErrorResponse;\n\nexport interface ModuleDefaultsConfig {\n apiPrefix?: string; // Prefix for module routes, defaults to '/api/' - set to empty string '' to disable\n cache: {\n enabled: boolean;\n defaultTtl: number;\n maxSize: number;\n strategy: 'lru' | 'lfu' | 'fifo';\n };\n rateLimit: {\n enabled: boolean;\n defaultRequests: number;\n defaultWindow: number;\n skipSuccessfulRequests: boolean;\n skipFailedRequests: boolean;\n };\n validation: {\n enabled: boolean;\n stripUnknown: boolean;\n abortEarly: boolean;\n allowUnknown?: boolean;\n onError?: ValidationErrorHandler;\n };\n session?: {\n enabled: boolean;\n store: 'memory' | 'redis' | 'file';\n storeOptions?: {\n url?: string;\n host?: string;\n port?: number;\n password?: string;\n keyPrefix?: string;\n path?: string;\n max?: number;\n };\n secret?: string;\n name?: string;\n rolling?: boolean;\n resave?: boolean;\n saveUninitialized?: boolean;\n cookie?: {\n maxAge?: number;\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: 'strict' | 'lax' | 'none';\n domain?: string;\n path?: string;\n };\n proxy?: boolean;\n unset?: 'destroy' | 'keep';\n };\n autoDiscovery: {\n enabled: boolean;\n paths: string[];\n patterns: string[];\n recursive: boolean;\n loadingStrategy: 'eager' | 'lazy' | 'conditional';\n watchForChanges: boolean;\n ignorePatterns: string[];\n loadOrder: 'alphabetical' | 'dependency' | 'custom';\n failOnError: boolean;\n maxDepth: number;\n };\n}\n\nexport interface LoggingConfig {\n level: 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n format: 'pretty' | 'json' | 'compact';\n enableColors: boolean;\n enableTimestamp: boolean;\n enableContext: boolean;\n // Opt-in: appends a JSON metadata object (e.g. {\"framework\":\"moro\",...}) to pretty log lines.\n // Has no effect on 'json' format - structured output always includes metadata.\n enableMetadata: boolean;\n // Opt-in: collects and renders per-log performance data such as memory usage (e.g. \"(210MB)\").\n // Disabling skips the process.memoryUsage() call on every log line.\n enablePerformance: boolean;\n outputs: {\n console: boolean;\n file: {\n enabled: boolean;\n path: string;\n maxSize: string;\n maxFiles: number;\n };\n webhook: {\n enabled: boolean;\n url?: string;\n headers: Record<string, string>;\n };\n };\n}\n\nexport interface SecurityConfig {\n cors: {\n enabled: boolean;\n origin: string | string[] | boolean | OriginFunction;\n methods: string[];\n allowedHeaders: string[];\n exposedHeaders?: string[];\n credentials: boolean;\n maxAge?: number;\n preflightContinue?: boolean;\n };\n helmet: {\n enabled: boolean;\n // Simplified options (backward compatible)\n contentSecurityPolicy?: boolean;\n hsts?: boolean;\n noSniff?: boolean;\n frameguard?: boolean;\n // Detailed options (for advanced configuration)\n xFrameOptions?: 'DENY' | 'SAMEORIGIN';\n xContentTypeOptions?: boolean;\n xXssProtection?: boolean;\n referrerPolicy?: string;\n strictTransportSecurity?: { maxAge?: number; includeSubDomains?: boolean };\n xDownloadOptions?: boolean;\n xPermittedCrossDomainPolicies?: boolean;\n };\n csrf?: {\n enabled: boolean;\n secret?: string;\n tokenLength?: number;\n cookieName?: string;\n headerName?: string;\n ignoreMethods?: string[];\n sameSite?: boolean;\n };\n csp?: {\n enabled: boolean;\n directives?: {\n defaultSrc?: string[];\n scriptSrc?: string[];\n styleSrc?: string[];\n imgSrc?: string[];\n connectSrc?: string[];\n fontSrc?: string[];\n objectSrc?: string[];\n mediaSrc?: string[];\n frameSrc?: string[];\n childSrc?: string[];\n workerSrc?: string[];\n formAction?: string[];\n upgradeInsecureRequests?: boolean;\n blockAllMixedContent?: boolean;\n };\n reportOnly?: boolean;\n reportUri?: string;\n nonce?: boolean;\n };\n rateLimit: {\n global: {\n enabled: boolean;\n requests: number;\n window: number;\n };\n };\n}\n\nexport interface ExternalServicesConfig {\n stripe?: {\n secretKey?: string | undefined;\n publishableKey?: string | undefined;\n webhookSecret?: string | undefined;\n apiVersion: string;\n };\n paypal?: {\n clientId?: string | undefined;\n clientSecret?: string | undefined;\n webhookId?: string | undefined;\n environment: 'sandbox' | 'production';\n };\n smtp?: {\n host?: string | undefined;\n port: number;\n secure: boolean;\n username?: string | undefined;\n password?: string | undefined;\n };\n}\n\nexport interface PerformanceConfig {\n compression: {\n enabled: boolean;\n level: number;\n threshold: number;\n /** Encoding preference order (default ['br','gzip','deflate']). */\n encodings?: Array<'br' | 'gzip' | 'deflate'>;\n /**\n * Bodies at or below this size are compressed on the calling thread and\n * sent with a Content-Length; larger ones are compressed on the\n * threadpool and streamed. 0 sends every body through the pool.\n * Default 16384.\n */\n maxInlineBytes?: number;\n };\n circuitBreaker: {\n enabled: boolean;\n failureThreshold: number;\n resetTimeout: number;\n monitoringPeriod: number;\n };\n clustering: {\n enabled: boolean;\n workers: number | 'auto';\n memoryPerWorkerGB?: number | undefined;\n };\n}\n\nexport interface WebSocketConfig {\n enabled: boolean;\n adapter?: string | 'socket.io' | 'ws' | 'uws';\n compression?: boolean;\n customIdGenerator?: () => string;\n options?: {\n cors?: {\n origin?: string | string[];\n credentials?: boolean;\n };\n path?: string;\n maxPayloadLength?: number;\n idleTimeout?: number;\n ssl?: {\n key_file_name?: string;\n cert_file_name?: string;\n passphrase?: string;\n };\n };\n}\n\nexport interface JobsConfig {\n enabled?: boolean;\n maxConcurrentJobs?: number;\n gracefulShutdownTimeout?: number;\n leaderElection?: {\n enabled?: boolean;\n strategy?: 'file' | 'redis' | 'none';\n lockPath?: string;\n lockTimeout?: number;\n heartbeatInterval?: number;\n };\n executor?: {\n maxRetries?: number;\n retryDelay?: number;\n retryBackoff?: 'linear' | 'exponential';\n retryBackoffMultiplier?: number;\n maxRetryDelay?: number;\n timeout?: number;\n enableCircuitBreaker?: boolean;\n circuitBreakerThreshold?: number;\n circuitBreakerResetTimeout?: number;\n enableMemoryMonitoring?: boolean;\n memoryThreshold?: number;\n };\n stateManager?: {\n persistPath?: string;\n historySize?: number;\n persistInterval?: number;\n enableAutoPersist?: boolean;\n enableRecovery?: boolean;\n };\n}\n\n// File-based routing configuration. When enabled, route files under the\n// configured directories are imported during startup (after module discovery)\n// so their `getApp().get(...)` registrations execute automatically.\nexport interface RoutingConfig {\n enabled: boolean;\n // Directories scanned via loadRoutes(). Defaults to ./src/routes in\n // development and ./dist/(src/)routes in production when omitted.\n paths?: string[];\n}\n\n// Main configuration interface\nexport interface AppConfig {\n server: ServerConfig;\n serviceDiscovery: ServiceDiscoveryConfig;\n database: DatabaseConfig;\n modules: ModuleDefaultsConfig;\n // Enable file-based auto routing (./src/routes). Defaults to true.\n routing: boolean | RoutingConfig;\n logging: LoggingConfig;\n security: SecurityConfig;\n external: ExternalServicesConfig;\n performance: PerformanceConfig;\n websocket: WebSocketConfig;\n jobs?: JobsConfig;\n queue?: QueueConfig;\n}\n\n// Queue Configuration\nexport interface QueueConfig {\n adapter?: 'bull' | 'rabbitmq' | 'sqs' | 'kafka' | 'memory';\n connection?: {\n host?: string;\n port?: number;\n username?: string;\n password?: string;\n database?: number;\n brokers?: string[];\n groupId?: string;\n region?: string;\n queueUrl?: string;\n [key: string]: any;\n };\n concurrency?: number;\n retry?: {\n maxAttempts: number;\n backoff: 'fixed' | 'exponential' | 'linear';\n initialDelay: number;\n maxDelay?: number;\n };\n deadLetterQueue?: {\n enabled: boolean;\n maxRetries: number;\n queueName?: string;\n };\n defaultJobOptions?: {\n removeOnComplete?: boolean | number;\n removeOnFail?: boolean | number;\n attempts?: number;\n backoff?: {\n type: 'fixed' | 'exponential' | 'linear';\n delay: number;\n };\n };\n prefix?: string;\n limiter?: {\n max: number;\n duration: number;\n };\n}\n"]}
@@ -22,6 +22,7 @@ export interface MoroOptions {
22
22
  maxSessionMemory?: number;
23
23
  settings?: {
24
24
  headerTableSize?: number;
25
+ /** Accepted for compatibility but never sent: RFC 9113 forbids a server from advertising ENABLE_PUSH=1 (clients drop the connection), and whether push is possible is the client's setting, read per stream. */
25
26
  enablePush?: boolean;
26
27
  initialWindowSize?: number;
27
28
  maxFrameSize?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"core.js","sourceRoot":"","sources":["../../src/types/core.ts"],"names":[],"mappings":"","sourcesContent":["// Core Framework Types\nimport { RuntimeConfig } from './runtime.js';\nimport { LoggerOptions } from './logger.js';\nimport { AppConfig, ValidationErrorHandler } from './config.js';\n\nexport interface MoroOptions {\n autoDiscover?:\n | boolean\n | {\n enabled?: boolean;\n paths?: string[];\n patterns?: string[];\n recursive?: boolean;\n loadingStrategy?: 'eager' | 'lazy' | 'conditional';\n watchForChanges?: boolean;\n ignorePatterns?: string[];\n loadOrder?: 'alphabetical' | 'dependency' | 'custom';\n failOnError?: boolean;\n maxDepth?: number;\n };\n modulesPath?: string; // Deprecated: use autoDiscover.paths instead\n middleware?: any[];\n\n // Runtime configuration\n runtime?: RuntimeConfig;\n\n // HTTP/WebSocket options\n http2?:\n | boolean\n | {\n allowHTTP1?: boolean;\n maxSessionMemory?: number;\n settings?: {\n headerTableSize?: number;\n enablePush?: boolean;\n initialWindowSize?: number;\n maxFrameSize?: number;\n maxConcurrentStreams?: number;\n maxHeaderListSize?: number;\n maxHeaderSize?: number;\n enableConnectProtocol?: boolean;\n };\n };\n https?: {\n key: string | Buffer;\n cert: string | Buffer;\n ca?: string | Buffer;\n };\n websocket?:\n | {\n enabled?: boolean;\n adapter?: any;\n compression?: boolean;\n customIdGenerator?: () => string;\n options?: any;\n }\n | false;\n\n // Simplified config options (these map to the full config)\n cors?: boolean | object;\n compression?: boolean | object;\n helmet?: boolean | object;\n logger?: LoggerOptions | boolean;\n\n // Worker threads configuration\n workers?: {\n enabled?: boolean;\n count?: number;\n maxQueueSize?: number;\n };\n\n // Validation configuration (top-level for convenience, maps to modules.validation)\n validation?: {\n enabled?: boolean;\n stripUnknown?: boolean;\n abortEarly?: boolean;\n allowUnknown?: boolean;\n onError?: ValidationErrorHandler;\n };\n\n // Direct config overrides (partial)\n server?: Partial<AppConfig['server']>;\n database?: Partial<AppConfig['database']>;\n modules?: Partial<AppConfig['modules']>;\n logging?: Partial<AppConfig['logging']>;\n security?: Partial<AppConfig['security']>;\n external?: Partial<AppConfig['external']>;\n performance?: Partial<AppConfig['performance']>;\n jobs?: Partial<AppConfig['jobs']>;\n}\n"]}
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["../../src/types/core.ts"],"names":[],"mappings":"","sourcesContent":["// Core Framework Types\nimport { RuntimeConfig } from './runtime.js';\nimport { LoggerOptions } from './logger.js';\nimport { AppConfig, ValidationErrorHandler } from './config.js';\n\nexport interface MoroOptions {\n autoDiscover?:\n | boolean\n | {\n enabled?: boolean;\n paths?: string[];\n patterns?: string[];\n recursive?: boolean;\n loadingStrategy?: 'eager' | 'lazy' | 'conditional';\n watchForChanges?: boolean;\n ignorePatterns?: string[];\n loadOrder?: 'alphabetical' | 'dependency' | 'custom';\n failOnError?: boolean;\n maxDepth?: number;\n };\n modulesPath?: string; // Deprecated: use autoDiscover.paths instead\n middleware?: any[];\n\n // Runtime configuration\n runtime?: RuntimeConfig;\n\n // HTTP/WebSocket options\n http2?:\n | boolean\n | {\n allowHTTP1?: boolean;\n maxSessionMemory?: number;\n settings?: {\n headerTableSize?: number;\n /** Accepted for compatibility but never sent: RFC 9113 forbids a server from advertising ENABLE_PUSH=1 (clients drop the connection), and whether push is possible is the client's setting, read per stream. */\n enablePush?: boolean;\n initialWindowSize?: number;\n maxFrameSize?: number;\n maxConcurrentStreams?: number;\n maxHeaderListSize?: number;\n maxHeaderSize?: number;\n enableConnectProtocol?: boolean;\n };\n };\n https?: {\n key: string | Buffer;\n cert: string | Buffer;\n ca?: string | Buffer;\n };\n websocket?:\n | {\n enabled?: boolean;\n adapter?: any;\n compression?: boolean;\n customIdGenerator?: () => string;\n options?: any;\n }\n | false;\n\n // Simplified config options (these map to the full config)\n cors?: boolean | object;\n compression?: boolean | object;\n helmet?: boolean | object;\n logger?: LoggerOptions | boolean;\n\n // Worker threads configuration\n workers?: {\n enabled?: boolean;\n count?: number;\n maxQueueSize?: number;\n };\n\n // Validation configuration (top-level for convenience, maps to modules.validation)\n validation?: {\n enabled?: boolean;\n stripUnknown?: boolean;\n abortEarly?: boolean;\n allowUnknown?: boolean;\n onError?: ValidationErrorHandler;\n };\n\n // Direct config overrides (partial)\n server?: Partial<AppConfig['server']>;\n database?: Partial<AppConfig['database']>;\n modules?: Partial<AppConfig['modules']>;\n logging?: Partial<AppConfig['logging']>;\n security?: Partial<AppConfig['security']>;\n external?: Partial<AppConfig['external']>;\n performance?: Partial<AppConfig['performance']>;\n jobs?: Partial<AppConfig['jobs']>;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@morojs/moro",
3
- "version": "1.8.14",
3
+ "version": "1.8.15",
4
4
  "description": "High-performance Node.js framework with intelligent routing, automatic middleware ordering, enterprise authentication (Better Auth), type-safe validation, and functional architecture",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -137,7 +137,7 @@
137
137
  "ejs": ">=3.1.10",
138
138
  "graphql": ">=16.12.0",
139
139
  "graphql-jit": ">=0.8.7",
140
- "handlebars": ">=4.7.8",
140
+ "handlebars": ">=4.7.10",
141
141
  "ioredis": ">=5.7.0",
142
142
  "joi": ">=17.0.0",
143
143
  "kafkajs": ">=2.2.4",