yinzerflow 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/docs/core/websockets.md +343 -0
- package/index.d.ts +269 -0
- package/index.js +33 -21
- package/index.js.map +16 -8
- package/package.json +1 -1
package/index.js.map
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../app/core/YinzerFlow.ts", "../app/core/execution/RequestHandlerImpl.ts", "../app/constants/colors.ts", "../app/constants/log.ts", "../app/core/utils/log.ts", "../app/core/utils/bytes.ts", "../app/core/execution/utils/parseJson.ts", "../app/core/execution/utils/parseMultipart.ts", "../app/constants/http.ts", "../app/core/execution/utils/parseUrlEncodedForm.ts", "../app/core/execution/utils/determineEncoding.ts", "../app/core/execution/utils/inferContentType.ts", "../app/core/execution/utils/parseBody.ts", "../app/core/utils/string.ts", "../app/core/execution/utils/parseHttpRequest.ts", "../app/core/execution/utils/parseQuery.ts", "../app/core/execution/utils/parseIpAddress.ts", "../app/core/execution/utils/extractBoundaryFromHeader.ts", "../app/core/execution/utils/parseRequestHeaders.ts", "../app/core/execution/RequestImpl.ts", "../app/core/execution/utils/formatBodyIntoString.ts", "../app/core/execution/utils/mapStatusCodeToMessage.ts", "../app/core/execution/utils/validateResponseHeaders.ts", "../app/core/execution/ResponseImpl.ts", "../app/core/execution/ContextImpl.ts", "../app/core/utils/time.ts", "../app/core/setup/utils/handleCustomConfiguration.ts", "../app/core/execution/HookRegistryImpl.ts", "../app/core/setup/utils/compileRoutePatter.ts", "../app/core/setup/utils/normalizeStringPatterns.ts", "../app/core/setup/utils/validateParameterNames.ts", "../app/core/setup/RouteRegistryImpl.ts", "../app/core/setup/utils/routeUtils.ts", "../app/core/setup/GroupApp.ts", "../app/core/setup/SetupImpl.ts", "../app/core/utils/accessLog.ts", "../app/core/modules/rateLimit/stores/inMemory.ts", "../app/core/modules/rateLimit/stores/redis.ts", "../app/core/modules/rateLimit/stores/index.ts", "../app/core/modules/rateLimit/strategies/SlidingWindowCounterStrategy.ts", "../app/core/modules/rateLimit/RateLimiter.ts", "../app/constants/rateLimit.ts", "../app/core/modules/rateLimit/RateLimitConfig.ts", "../app/core/modules/rateLimit/rateLimithooks.ts", "../app/core/modules/cookieParser/CookieParser.ts", "../app/core/modules/cookieParser/CookieParserConfig.ts", "../app/core/modules/cookieParser/cookieParserHooks.ts", "../app/core/modules/cors/Cors.ts", "../app/core/modules/cors/corsHooks.ts", "../app/core/modules/cors/CorsConfig.ts", "../app/core/utils/sanitize.ts", "../app/core/modules/diagnostics/DiagnosticsMonitor.ts"],
|
|
3
|
+
"sources": ["../app/core/YinzerFlow.ts", "../app/core/execution/RequestHandlerImpl.ts", "../app/constants/colors.ts", "../app/constants/log.ts", "../app/core/utils/log.ts", "../app/core/utils/bytes.ts", "../app/core/execution/utils/parseJson.ts", "../app/core/execution/utils/parseMultipart.ts", "../app/constants/http.ts", "../app/core/execution/utils/parseUrlEncodedForm.ts", "../app/core/execution/utils/determineEncoding.ts", "../app/core/execution/utils/inferContentType.ts", "../app/core/execution/utils/parseBody.ts", "../app/core/utils/string.ts", "../app/core/execution/utils/parseHttpRequest.ts", "../app/core/execution/utils/parseQuery.ts", "../app/core/execution/utils/parseIpAddress.ts", "../app/core/execution/utils/extractBoundaryFromHeader.ts", "../app/core/execution/utils/parseRequestHeaders.ts", "../app/core/execution/RequestImpl.ts", "../app/core/execution/utils/formatBodyIntoString.ts", "../app/core/execution/utils/mapStatusCodeToMessage.ts", "../app/core/execution/utils/validateResponseHeaders.ts", "../app/core/execution/ResponseImpl.ts", "../app/core/execution/ContextImpl.ts", "../app/core/modules/websocket/WebSocketConfig.ts", "../app/core/utils/time.ts", "../app/core/setup/utils/handleCustomConfiguration.ts", "../app/core/execution/HookRegistryImpl.ts", "../app/core/setup/utils/compileRoutePatter.ts", "../app/core/setup/utils/normalizeStringPatterns.ts", "../app/core/setup/utils/validateParameterNames.ts", "../app/core/setup/RouteRegistryImpl.ts", "../app/core/setup/utils/routeUtils.ts", "../app/core/setup/GroupApp.ts", "../app/core/modules/websocket/WebSocketRouter.ts", "../app/core/setup/SetupImpl.ts", "../app/core/utils/accessLog.ts", "../app/core/modules/rateLimit/stores/inMemory.ts", "../app/core/modules/rateLimit/stores/redis.ts", "../app/core/modules/rateLimit/stores/index.ts", "../app/core/modules/rateLimit/strategies/SlidingWindowCounterStrategy.ts", "../app/core/modules/rateLimit/RateLimiter.ts", "../app/constants/rateLimit.ts", "../app/core/modules/rateLimit/RateLimitConfig.ts", "../app/core/modules/rateLimit/rateLimithooks.ts", "../app/core/modules/cookieParser/CookieParser.ts", "../app/core/modules/cookieParser/CookieParserConfig.ts", "../app/core/modules/cookieParser/cookieParserHooks.ts", "../app/core/modules/cors/Cors.ts", "../app/core/modules/cors/corsHooks.ts", "../app/core/modules/cors/CorsConfig.ts", "../app/core/utils/sanitize.ts", "../app/core/modules/diagnostics/DiagnosticsMonitor.ts", "../app/core/modules/websocket/WebSocketHandshake.ts", "../app/constants/websocket.ts", "../app/core/modules/websocket/WebSocketFrame.ts", "../app/core/modules/websocket/WebSocketConnection.ts", "../app/core/modules/websocket/WebSocketChannelManager.ts", "../app/core/modules/websocket/WebSocketSecurity.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import { createServer } from 'net';\nimport type { Socket } from 'net';\n\nimport { RequestHandlerImpl } from '@core/execution/RequestHandlerImpl.ts';\nimport { ContextImpl } from '@core/execution/ContextImpl.ts';\nimport { SetupImpl } from '@core/setup/SetupImpl.ts';\nimport { createLogger, loggerBrand } from '@core/utils/log.ts';\nimport type { ServerOptions } from '@typedefs/public/Configuration.js';\nimport { accessLogBaseConfig, getStatusEmoji } from '@core/utils/accessLog.ts';\nimport { _createGlobalRateLimitHook } from '@core/modules/rateLimit/rateLimithooks.ts';\nimport { RateLimiter } from '@core/modules/rateLimit/RateLimiter.ts';\nimport { _convertTimeToMs } from '@core/utils/time.ts';\nimport { RateLimitConfig } from '@core/modules/rateLimit/RateLimitConfig.ts';\nimport { cookieParserHook } from '@core/modules/cookieParser/cookieParserHooks.ts';\nimport { CookieParserConfig } from '@core/modules/cookieParser/CookieParserConfig.ts';\nimport { corsHook } from '@core/modules/cors/corsHooks.ts';\nimport { CorsConfig } from '@core/modules/cors/CorsConfig.ts';\nimport type { InternalCorsEnabledOptions } from '@typedefs/internal/InternalConfiguration.js';\nimport { DiagnosticsMonitor } from '@core/modules/diagnostics/DiagnosticsMonitor.ts';\nimport { _sanitizeLogField } from '@core/utils/sanitize.ts';\n\n/**\n * Maximum overhead allowance for HTTP headers on top of body parser limits (64KB).\n *\n * The TCP buffer limit is `max(bodyParserLimits) + maxHeaderOverhead` because the raw\n * TCP stream contains both headers and body. The body portion is bounded by the user's\n * body parser config (json.maxSize, urlEncoded.maxSize, fileUploads.maxTotalSize), but\n * we also need room for the request line, headers, and the blank line separator.\n *\n * 64KB is generous — most HTTP headers are 2-8KB (nginx defaults to 8KB max). This\n * leaves plenty of room for large cookie headers or verbose auth tokens while still\n * rejecting obviously malicious oversized requests at the TCP level before parsing.\n */\nconst maxHeaderOverhead = 65_536;\n\n/**\n * Main YinzerFlow application class for building HTTP servers.\n *\n * YinzerFlow is a lightweight, high-performance HTTP server framework built on Node.js\n * that provides an elegant API for routing, middleware, and request handling. It extends\n * the Setup interface to provide all route configuration capabilities plus server management.\n *\n * ## Key Features\n *\n * - **High Performance**: Built on Node.js net module for maximum performance\n * - **Type Safety**: Full TypeScript support with generics for type-safe contexts\n * - **Route Groups**: Nested route organization with shared hooks and middleware\n * - **Global Hooks**: beforeAll/afterAll hooks for cross-cutting concerns\n * - **State Management**: Request-scoped state for sharing data between middleware\n * - **Graceful Shutdown**: Automatic graceful shutdown handling\n * - **Logging**: Built-in logging with custom logger support\n * - **Network Logging**: Request/response logging with performance metrics\n *\n * ## Basic Usage\n *\n * @example\n * ```typescript\n * import { YinzerFlow } from 'yinzerflow';\n *\n * // Create app with basic configuration\n * const app = new YinzerFlow({ port: 3000 });\n *\n * // Register routes\n * app.get('/api/users', async (ctx) => {\n * return { users: ['John', 'Jane'] };\n * });\n *\n * app.post('/api/users', async (ctx) => {\n * const { name, email } = ctx.request.body;\n * return { message: 'User created', name, email };\n * });\n *\n * // Set up global hooks\n * app.beforeAll([\n * async (ctx) => {\n * ctx.state.requestId = generateRequestId();\n * ctx.state.startTime = Date.now();\n * }\n * ]);\n *\n * app.afterAll([\n * async (ctx) => {\n * const processingTime = Date.now() - ctx.state.startTime;\n * ctx.response.addHeaders({\n * 'X-Processing-Time': `${processingTime}ms`,\n * 'X-Request-ID': ctx.state.requestId\n * });\n * }\n * ]);\n *\n * // Create route groups\n * app.group('/api/v1', (api) => {\n * api.group('/admin', (admin) => {\n * admin.get('/users', async (ctx) => {\n * return { adminUsers: ['Admin1', 'Admin2'] };\n * });\n * });\n * });\n *\n * // Start the server\n * app.listen();\n * ```\n *\n * ## Advanced Configuration\n *\n * @example\n * ```typescript\n * // Advanced configuration with custom logging\n * const app = new YinzerFlow({\n * port: 8080,\n * host: '0.0.0.0',\n * logging: {\n * level: 'debug',\n * personality: true,\n * requests: true,\n * logger: {\n * info: (message, ...args) => console.log(`[INFO] ${message}`, ...args),\n * warn: (message, ...args) => console.warn(`[WARN] ${message}`, ...args),\n * error: (message, ...args) => console.error(`[ERROR] ${message}`, ...args),\n * debug: (message, ...args) => console.debug(`[DEBUG] ${message}`, ...args)\n * }\n * }\n * });\n *\n * // Custom error handling\n * app.onError(async (ctx, error) => {\n * ctx.response.setStatusCode(500);\n * return {\n * error: 'Internal server error',\n * message: process.env.NODE_ENV === 'production' ? 'Something went wrong' : error.message\n * };\n * });\n *\n * // Custom not-found handling\n * app.onNotFound(async (ctx) => {\n * ctx.response.setStatusCode(404);\n * return {\n * error: 'Not found',\n * path: ctx.request.path,\n * availableEndpoints: ['/api/users', '/api/posts', '/health']\n * };\n * });\n * ```\n *\n * ## Server Lifecycle\n *\n * 1. **Initialization**: Constructor sets up logging and configuration\n * 2. **Route Setup**: Register routes, hooks, and middleware\n * 3. **Server Start**: Call `listen()` to start accepting connections\n * 4. **Request Processing**: Handle incoming HTTP requests\n * 5. **Graceful Shutdown**: Automatic cleanup on process termination\n *\n * @see {@link SetupImpl} for route configuration capabilities\n * @see {@link ServerOptions} for configuration options\n * @see {@link ContextImpl} for request context implementation\n * @see {@link RequestHandlerImpl} for request processing\n */\nexport class YinzerFlow extends SetupImpl {\n private _isListening = false;\n private _server?: ReturnType<typeof createServer>;\n private _globalRateLimiter?: RateLimiter | undefined;\n private _diagnostics?: DiagnosticsMonitor | undefined;\n private readonly _maxBufferSize: number;\n private _accessLog?: ReturnType<typeof createLogger>;\n private _accessLogEnabled = false;\n\n constructor(configuration?: ServerOptions) {\n super(configuration);\n\n // Pre-compute max buffer size from body parser limits (immutable after construction)\n this._maxBufferSize =\n Math.max(\n this._configuration.bodyParser.json.maxSize,\n this._configuration.bodyParser.urlEncoded.maxSize,\n this._configuration.bodyParser.fileUploads.maxTotalSize,\n ) + maxHeaderOverhead;\n\n this._configureLogging();\n\n // Setup global rate limiting, if there is none provided, it will be enabled by default. We need to set the confgratin before the conditional since it is defaulted on and users might not pass it in the configuration.\n const rateLimitConfig = new RateLimitConfig(configuration?.rateLimit, this._log);\n if (configuration?.rateLimit?.enabled) {\n this._globalRateLimiter = new RateLimiter(rateLimitConfig);\n const onRateLimitHit = this._diagnostics ? (ip: string, path: string): void => this._diagnostics?.onRateLimitHit(ip, path) : undefined;\n const hook = _createGlobalRateLimitHook(this._globalRateLimiter, onRateLimitHit);\n this.beforeAll([hook]);\n }\n\n // Setup cookie parser, if enabled, since it is deisabled by default we can set the configuration after the conditional\n if (configuration?.cookieParser?.enabled) {\n const cookieParserConfig = new CookieParserConfig(configuration.cookieParser, this._log);\n const cookieParserHookFunc = cookieParserHook(cookieParserConfig.config);\n this.beforeAll([cookieParserHookFunc]);\n }\n\n // Setup CORS, if enabled, as a beforeRouting hook\n if (configuration?.cors?.enabled) {\n const corsConfig = CorsConfig.merge(configuration.cors);\n CorsConfig.validate(corsConfig);\n // Type assertion safe here: validate() throws if config is disabled\n const corsHookFunc = corsHook(corsConfig as InternalCorsEnabledOptions);\n this.beforeRouting([corsHookFunc]);\n }\n\n // Setup automatic graceful shutdown if enabled\n if (this._configuration.gracefulShutdownTimeout) {\n const gracefulShutdownTimeout = _convertTimeToMs(this._configuration.gracefulShutdownTimeout);\n if (gracefulShutdownTimeout > 0) {\n this._setupGracefulShutdown(gracefulShutdownTimeout);\n }\n }\n }\n\n /** Public accessor for this instance's logger. */\n get log(): typeof this._log {\n return this._log;\n }\n\n /**\n * Configure all three logging channels: app logger, access logs, diagnostics.\n *\n * Creates a per-instance logger (D1 fix — no more singleton mutation).\n * Uses Symbol brand to detect framework loggers (D2/2.4 fix — replaces duck-typed `_state`).\n */\n private _configureLogging(): void {\n const loggingConfig = this._configuration.logging;\n\n // C2 fix: If a branded logger was provided, extract its underlying output sink\n // instead of mutating the user's branded logger state. Mutating caused cross-instance\n // side effects when the same branded logger was shared between YinzerFlow instances.\n // The per-instance this._log handles its own formatting (prefix, personality).\n let loggerSink = loggingConfig.logger;\n if (loggerSink && loggerBrand in (loggerSink as unknown as Record<string | symbol, unknown>)) {\n const brandedState = (loggerSink as unknown as Record<string | symbol, unknown>)[loggerBrand] as { logger?: typeof loggerSink };\n loggerSink = brandedState.logger ?? undefined;\n }\n\n // Create per-instance logger (D1 fix: no more Object.assign to module-level singleton)\n this._log = createLogger({\n level: loggingConfig.level,\n prefix: loggingConfig.prefix,\n personality: loggingConfig.personality,\n logger: loggerSink,\n });\n\n // Thread logger into subsystems\n this._hooks.setLogger(this._log);\n\n // C1 fix: Create per-instance access log (no more module-level singleton)\n if (loggingConfig.requests) {\n this._accessLog = createLogger({\n ...accessLogBaseConfig,\n level: 'info',\n logger: loggingConfig.accessLogger,\n });\n this._accessLogEnabled = true;\n }\n\n // Setup diagnostics monitor if any thresholds are configured\n const diagnostics = new DiagnosticsMonitor(loggingConfig.diagnostics, loggingConfig.personality);\n if (diagnostics.hasAnyEnabled()) {\n this._diagnostics = diagnostics;\n this._diagnostics.start();\n }\n }\n\n /**\n * Setup server with all event listeners\n */\n private _setupServer(resolve: () => void, reject: (error: Error) => void, requestHandler: RequestHandlerImpl): void {\n if (!this._server) return;\n\n this._server.on('error', (error: Error) => {\n this._log.error(`YinzerFlow server error at ${this._configuration.host}:${this._configuration.port} - ${error.message}`);\n // Clean up the failed server to prevent handle leaks on re-listen\n this._server?.close();\n delete this._server;\n reject(error);\n });\n\n this._server.on('listening', () => {\n this._isListening = true;\n this._log.info(`YinzerFlow server at ${this._configuration.host}:${this._configuration.port} is up and running`);\n resolve();\n });\n\n this._server.on('connection', (socket) => {\n this._handleConnection(socket, requestHandler);\n });\n }\n\n /**\n * Process incoming request data\n */\n private async _processRequest({\n data,\n socket,\n requestHandler,\n clientAddress,\n }: {\n data: Buffer;\n socket: Socket;\n requestHandler: RequestHandlerImpl;\n clientAddress: string;\n }): Promise<void> {\n const startTime = Date.now();\n\n const context = new ContextImpl(data, this, clientAddress);\n\n await requestHandler.handle(context);\n\n // Guard against writing to a socket that was destroyed (client disconnect, timeout, etc.)\n if (!socket.destroyed) {\n socket.write(context._response._stringBody);\n socket.end();\n }\n\n const processingTime = Date.now() - startTime;\n\n // Only compute byte length and build log strings when something will consume them\n if (this._accessLogEnabled || this._diagnostics) {\n const responseBytes = Buffer.byteLength(context._response._stringBody, 'utf8');\n\n // H3 fix: Sanitize attacker-controlled fields once for both channels\n const safeMethod = _sanitizeLogField(context.request.method);\n const safePath = _sanitizeLogField(context.request.path);\n\n // Access log — one nginx-style line per request (C1: per-instance, H4: separate guard)\n if (this._accessLogEnabled) {\n this._accessLog?.info(\n `${getStatusEmoji(context._response._statusCode)} ${clientAddress} \"${safeMethod} ${safePath} ${context.request.protocol}\" ${context._response._statusCode} ${responseBytes}bytes \"${_sanitizeLogField(context.request.headers.referer ?? '-')}\" \"${_sanitizeLogField(context.request.headers['user-agent'] ?? '-')}\" ${processingTime}ms`,\n );\n }\n\n // Diagnostics — check thresholds after response is sent (receives pre-sanitized values)\n this._diagnostics?.checkRequest({\n duration: processingTime,\n reqBytes: data.length,\n resBytes: responseBytes,\n method: safeMethod,\n path: safePath,\n });\n }\n }\n\n /**\n * Handle errors from request processing — log and destroy socket\n */\n private _handleRequestError(error: unknown, clientAddress: string, socket: Socket): void {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n this._log.error(`Request processing error from ${clientAddress}: ${errorMessage}`, error);\n if (!socket.destroyed) {\n socket.destroy();\n }\n }\n\n /**\n * Dispatch assembled request buffer to the request processor.\n * Wraps `_processRequest` with the standard error catch handler.\n */\n private _dispatchRequest({\n data,\n socket,\n requestHandler,\n clientAddress,\n }: {\n data: Buffer;\n socket: Socket;\n requestHandler: RequestHandlerImpl;\n clientAddress: string;\n }): void {\n this._processRequest({ data, socket, requestHandler, clientAddress }).catch((error: unknown) => this._handleRequestError(error, clientAddress, socket));\n }\n\n /**\n * Reject an oversized request with HTTP 413 (if headers were parsed) and destroy the socket.\n * Logs the current body parser limits for debugging.\n */\n private _rejectOversizedRequest({\n socket,\n clientAddress,\n totalLength,\n headersParsed,\n }: {\n socket: Socket;\n clientAddress: string;\n totalLength: number;\n headersParsed: boolean;\n }): void {\n if (headersParsed) {\n const errorBody = JSON.stringify({\n error: 'Payload too large',\n maxSize: this._maxBufferSize,\n received: totalLength,\n });\n socket.write(\n `HTTP/1.1 413 Payload Too Large\\r\\n` +\n `Content-Type: application/json\\r\\n` +\n `Content-Length: ${Buffer.byteLength(errorBody, 'utf8')}\\r\\n` +\n `Connection: close\\r\\n\\r\\n${errorBody}`,\n );\n }\n this._log.warn(\n `Request from ${clientAddress} exceeded maximum buffer size (${totalLength} > ${this._maxBufferSize} bytes). ` +\n `Current limits: json=${this._configuration.bodyParser.json.maxSize}, ` +\n `urlEncoded=${this._configuration.bodyParser.urlEncoded.maxSize}, ` +\n `fileUploads=${this._configuration.bodyParser.fileUploads.maxTotalSize}`,\n );\n socket.destroy();\n }\n\n /**\n * Check if buffered data looks like the start of an HTTP request.\n *\n * First checks the first byte against known HTTP method start characters\n * (G, P, D, H, O), then validates the first 8 bytes against the full method pattern.\n * Returns `false` for non-HTTP traffic so it can be dispatched for a graceful error.\n */\n private _looksLikeHttp(chunks: Array<Buffer>, totalLength: number, buffer: Buffer): boolean {\n if (totalLength >= 1) {\n const firstByte = chunks[0]?.[0] ?? 0;\n // cspell:disable-next-line\n // HTTP methods start with: G(ET)=0x47, P(OST/UT/ATCH)=0x50, D(ELETE)=0x44, H(EAD)=0x48, O(PTIONS)=0x4f\n if (firstByte !== 0x47 && firstByte !== 0x50 && firstByte !== 0x44 && firstByte !== 0x48 && firstByte !== 0x4f) {\n return false;\n }\n }\n if (totalLength >= 8) {\n const start = buffer.subarray(0, 8).toString();\n if (!/^(?:GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\\s/.test(start)) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Extract Content-Length value from raw HTTP headers.\n * Returns 0 if the header is missing (e.g. GET requests with no body).\n */\n private _parseContentLength(buffer: Buffer, headerEndIndex: number): number {\n const headersStr = buffer.subarray(0, headerEndIndex).toString();\n const match = /content-length:\\s*(?<digits>\\d+)/i.exec(headersStr);\n return match?.groups?.digits ? parseInt(match.groups.digits, 10) : 0;\n }\n\n /**\n * Handle incoming TCP socket connections and their complete lifecycle.\n *\n * Implements a TCP stream reassembly state machine that buffers chunks until the\n * complete HTTP request is received, then dispatches to `_processRequest`.\n *\n * **Header Phase**: Accumulate chunks, search for `\\r\\n\\r\\n`, parse Content-Length.\n * **Body Phase**: Track totalLength without concatenating until body is complete.\n * **Dispatch**: `Buffer.concat(chunks)` once to produce the final contiguous buffer.\n *\n * @see _looksLikeHttp for non-HTTP early detection\n * @see _rejectOversizedRequest for DoS protection (413 + socket destroy)\n * @see _processRequest for how the assembled buffer is parsed and handled\n */\n private _handleConnection(socket: Socket, requestHandler: RequestHandlerImpl): void {\n const clientAddress = socket.remoteAddress ?? 'unknown';\n const connectionStartTime = Date.now();\n let hasReceivedData = false;\n\n this._log.debug(`New connection from ${clientAddress}`);\n\n // TCP stream reassembly state — mutable, read/written by data handler\n const chunks: Array<Buffer> = [];\n let totalLength = 0;\n let headersParsed = false;\n let expectedBodyLength = 0;\n let headerEndIndex = -1;\n let requestDispatched = false;\n\n socket.on('data', (chunk) => {\n if (!hasReceivedData) {\n hasReceivedData = true;\n const delay = Date.now() - connectionStartTime;\n if (delay > 100) {\n this._log.debug(`Delayed data from ${clientAddress} (${delay}ms connection delay)`);\n }\n }\n\n if (requestDispatched) return;\n\n chunks.push(chunk);\n totalLength += chunk.length;\n\n if (totalLength > this._maxBufferSize) {\n this._rejectOversizedRequest({ socket, clientAddress, totalLength, headersParsed });\n return;\n }\n\n // Header phase: find \\r\\n\\r\\n boundary and parse Content-Length\n if (!headersParsed) {\n const buffer = Buffer.concat(chunks, totalLength);\n headerEndIndex = buffer.indexOf('\\r\\n\\r\\n');\n\n if (headerEndIndex === -1) {\n if (!this._looksLikeHttp(chunks, totalLength, buffer)) {\n requestDispatched = true;\n this._dispatchRequest({ data: buffer, socket, requestHandler, clientAddress });\n }\n return;\n }\n\n headersParsed = true;\n expectedBodyLength = this._parseContentLength(buffer, headerEndIndex);\n const bodyStart = headerEndIndex + 4;\n\n if (buffer.length - bodyStart >= expectedBodyLength) {\n requestDispatched = true;\n this._dispatchRequest({ data: buffer, socket, requestHandler, clientAddress });\n }\n return;\n }\n\n // Body phase: check if accumulated length satisfies Content-Length\n if (totalLength - (headerEndIndex + 4) >= expectedBodyLength) {\n requestDispatched = true;\n this._dispatchRequest({ data: Buffer.concat(chunks, totalLength), socket, requestHandler, clientAddress });\n }\n });\n\n socket.on('error', (error: Error) => {\n this._log.error(`Socket error from ${clientAddress}: ${error.message}`, error);\n });\n\n socket.on('close', () => {\n const connectionDuration = Date.now() - connectionStartTime;\n\n if (hasReceivedData) {\n this._log.debug(`Connection closed from ${clientAddress} (${connectionDuration}ms total)`);\n return;\n }\n\n if (connectionDuration < 10) {\n this._log.debug(`${clientAddress} quick connectivity check (${connectionDuration}ms) - health probe`);\n } else {\n this._log.debug(`${clientAddress} disconnected without sending data (${connectionDuration}ms) - potential probe`);\n }\n });\n }\n\n async listen(): Promise<void> {\n if (this._isListening) {\n throw new Error('Server is already listening');\n }\n\n return new Promise((resolve, reject) => {\n const requestHandler = new RequestHandlerImpl(this);\n this._server = createServer();\n\n this._setupServer(resolve, reject, requestHandler);\n this._server.listen(this._configuration.port, this._configuration.host);\n });\n }\n\n async close(): Promise<void> {\n if (!this._isListening || !this._server) {\n return;\n }\n\n // Clean up rate limiter resources (intervals, memory)\n if (this._globalRateLimiter) {\n await this._globalRateLimiter.destroy();\n this._globalRateLimiter = undefined;\n }\n\n // Clean up diagnostics timers\n if (this._diagnostics) {\n this._diagnostics.destroy();\n this._diagnostics = undefined;\n }\n\n return new Promise((resolve) => {\n if (!this._server) {\n this._isListening = false; // Probably redundant but just in case\n resolve();\n return;\n }\n\n this._server.close(() => {\n this._isListening = false;\n this._log.warn(`YinzerFlow server at ${this._configuration.host}:${this._configuration.port} is shutting down`);\n resolve();\n });\n });\n }\n\n status(): {\n isListening: boolean;\n port: number | undefined;\n host: string | undefined;\n } {\n return {\n isListening: this._isListening,\n port: this._configuration.port,\n host: this._configuration.host,\n };\n }\n\n /**\n * Setup automatic graceful shutdown handlers\n */\n private _setupGracefulShutdown(gracefulShutdownTimeout: number): void {\n if (gracefulShutdownTimeout <= 0) {\n return;\n }\n\n // Only setup if no handlers are already registered\n if (process.listenerCount('SIGTERM') === 0 && process.listenerCount('SIGINT') === 0) {\n const shutdown = (signal: string): void => {\n this._log.info(`🛑 Received ${signal}, shutting down gracefully in ${this._configuration.gracefulShutdownTimeout}...`);\n setTimeout(() => {\n this.close()\n .then(() => {\n this._log.info('✅ Server shut down gracefully');\n process.exit(0);\n })\n .catch((error) => {\n this._log.error('❌ Error during graceful shutdown:', error);\n process.exit(1);\n });\n }, gracefulShutdownTimeout);\n };\n\n process.on('SIGTERM', () => shutdown('SIGTERM'));\n process.on('SIGINT', () => shutdown('SIGINT'));\n }\n }\n}\n",
|
|
5
|
+
"/* eslint-disable max-lines -- WebSocket upgrade handler temporarily increases file size during Phase 3 integration. Will be extracted to dedicated module in Phase 4 (pub/sub implementation). */\nimport { createServer } from 'net';\nimport type { Socket } from 'net';\n\nimport { RequestHandlerImpl } from '@core/execution/RequestHandlerImpl.ts';\nimport { ContextImpl } from '@core/execution/ContextImpl.ts';\nimport { SetupImpl } from '@core/setup/SetupImpl.ts';\nimport { createLogger, loggerBrand } from '@core/utils/log.ts';\nimport type { ServerOptions } from '@typedefs/public/Configuration.js';\nimport { accessLogBaseConfig, getStatusEmoji } from '@core/utils/accessLog.ts';\nimport { _createGlobalRateLimitHook } from '@core/modules/rateLimit/rateLimithooks.ts';\nimport { RateLimiter } from '@core/modules/rateLimit/RateLimiter.ts';\nimport { _convertTimeToMs } from '@core/utils/time.ts';\nimport { RateLimitConfig } from '@core/modules/rateLimit/RateLimitConfig.ts';\nimport { cookieParserHook } from '@core/modules/cookieParser/cookieParserHooks.ts';\nimport { CookieParserConfig } from '@core/modules/cookieParser/CookieParserConfig.ts';\nimport { corsHook } from '@core/modules/cors/corsHooks.ts';\nimport { CorsConfig } from '@core/modules/cors/CorsConfig.ts';\nimport type { InternalCorsEnabledOptions } from '@typedefs/internal/InternalConfiguration.js';\nimport { DiagnosticsMonitor } from '@core/modules/diagnostics/DiagnosticsMonitor.ts';\nimport { _sanitizeLogField } from '@core/utils/sanitize.ts';\nimport { _buildHandshakeResponse, _generateAcceptKey, _isWebSocketUpgrade, _validateHandshake } from '@core/modules/websocket/WebSocketHandshake.ts';\nimport { WebSocketConnection } from '@core/modules/websocket/WebSocketConnection.ts';\nimport { WebSocketChannelManager } from '@core/modules/websocket/WebSocketChannelManager.ts';\nimport { WebSocketSecurity } from '@core/modules/websocket/WebSocketSecurity.ts';\nimport type { WebSocketHandlers, WebSocketRouteOptions } from '@typedefs/public/WebSocket.js';\n\n/**\n * Maximum overhead allowance for HTTP headers on top of body parser limits (64KB).\n *\n * The TCP buffer limit is `max(bodyParserLimits) + maxHeaderOverhead` because the raw\n * TCP stream contains both headers and body. The body portion is bounded by the user's\n * body parser config (json.maxSize, urlEncoded.maxSize, fileUploads.maxTotalSize), but\n * we also need room for the request line, headers, and the blank line separator.\n *\n * 64KB is generous — most HTTP headers are 2-8KB (nginx defaults to 8KB max). This\n * leaves plenty of room for large cookie headers or verbose auth tokens while still\n * rejecting obviously malicious oversized requests at the TCP level before parsing.\n */\nconst maxHeaderOverhead = 65_536;\n\n/**\n * Main YinzerFlow application class for building HTTP servers.\n *\n * YinzerFlow is a lightweight, high-performance HTTP server framework built on Node.js\n * that provides an elegant API for routing, middleware, and request handling. It extends\n * the Setup interface to provide all route configuration capabilities plus server management.\n *\n * ## Key Features\n *\n * - **High Performance**: Built on Node.js net module for maximum performance\n * - **Type Safety**: Full TypeScript support with generics for type-safe contexts\n * - **Route Groups**: Nested route organization with shared hooks and middleware\n * - **Global Hooks**: beforeAll/afterAll hooks for cross-cutting concerns\n * - **State Management**: Request-scoped state for sharing data between middleware\n * - **Graceful Shutdown**: Automatic graceful shutdown handling\n * - **Logging**: Built-in logging with custom logger support\n * - **Network Logging**: Request/response logging with performance metrics\n *\n * ## Basic Usage\n *\n * @example\n * ```typescript\n * import { YinzerFlow } from 'yinzerflow';\n *\n * // Create app with basic configuration\n * const app = new YinzerFlow({ port: 3000 });\n *\n * // Register routes\n * app.get('/api/users', async (ctx) => {\n * return { users: ['John', 'Jane'] };\n * });\n *\n * app.post('/api/users', async (ctx) => {\n * const { name, email } = ctx.request.body;\n * return { message: 'User created', name, email };\n * });\n *\n * // Set up global hooks\n * app.beforeAll([\n * async (ctx) => {\n * ctx.state.requestId = generateRequestId();\n * ctx.state.startTime = Date.now();\n * }\n * ]);\n *\n * app.afterAll([\n * async (ctx) => {\n * const processingTime = Date.now() - ctx.state.startTime;\n * ctx.response.addHeaders({\n * 'X-Processing-Time': `${processingTime}ms`,\n * 'X-Request-ID': ctx.state.requestId\n * });\n * }\n * ]);\n *\n * // Create route groups\n * app.group('/api/v1', (api) => {\n * api.group('/admin', (admin) => {\n * admin.get('/users', async (ctx) => {\n * return { adminUsers: ['Admin1', 'Admin2'] };\n * });\n * });\n * });\n *\n * // Start the server\n * app.listen();\n * ```\n *\n * ## Advanced Configuration\n *\n * @example\n * ```typescript\n * // Advanced configuration with custom logging\n * const app = new YinzerFlow({\n * port: 8080,\n * host: '0.0.0.0',\n * logging: {\n * level: 'debug',\n * personality: true,\n * requests: true,\n * logger: {\n * info: (message, ...args) => console.log(`[INFO] ${message}`, ...args),\n * warn: (message, ...args) => console.warn(`[WARN] ${message}`, ...args),\n * error: (message, ...args) => console.error(`[ERROR] ${message}`, ...args),\n * debug: (message, ...args) => console.debug(`[DEBUG] ${message}`, ...args)\n * }\n * }\n * });\n *\n * // Custom error handling\n * app.onError(async (ctx, error) => {\n * ctx.response.setStatusCode(500);\n * return {\n * error: 'Internal server error',\n * message: process.env.NODE_ENV === 'production' ? 'Something went wrong' : error.message\n * };\n * });\n *\n * // Custom not-found handling\n * app.onNotFound(async (ctx) => {\n * ctx.response.setStatusCode(404);\n * return {\n * error: 'Not found',\n * path: ctx.request.path,\n * availableEndpoints: ['/api/users', '/api/posts', '/health']\n * };\n * });\n * ```\n *\n * ## Server Lifecycle\n *\n * 1. **Initialization**: Constructor sets up logging and configuration\n * 2. **Route Setup**: Register routes, hooks, and middleware\n * 3. **Server Start**: Call `listen()` to start accepting connections\n * 4. **Request Processing**: Handle incoming HTTP requests\n * 5. **Graceful Shutdown**: Automatic cleanup on process termination\n *\n * @see {@link SetupImpl} for route configuration capabilities\n * @see {@link ServerOptions} for configuration options\n * @see {@link ContextImpl} for request context implementation\n * @see {@link RequestHandlerImpl} for request processing\n */\nexport class YinzerFlow extends SetupImpl {\n private _isListening = false;\n private _server?: ReturnType<typeof createServer>;\n private _globalRateLimiter?: RateLimiter | undefined;\n private _diagnostics?: DiagnosticsMonitor | undefined;\n private readonly _maxBufferSize: number;\n private _accessLog?: ReturnType<typeof createLogger>;\n private _accessLogEnabled = false;\n private _wsConnections?: Set<WebSocketConnection>;\n private _wsChannelManager?: WebSocketChannelManager;\n private _wsSecurity?: WebSocketSecurity;\n\n constructor(configuration?: ServerOptions) {\n super(configuration);\n\n // Pre-compute max buffer size from body parser limits (immutable after construction)\n this._maxBufferSize =\n Math.max(\n this._configuration.bodyParser.json.maxSize,\n this._configuration.bodyParser.urlEncoded.maxSize,\n this._configuration.bodyParser.fileUploads.maxTotalSize,\n ) + maxHeaderOverhead;\n\n this._configureLogging();\n\n // Setup global rate limiting, if there is none provided, it will be enabled by default. We need to set the confgratin before the conditional since it is defaulted on and users might not pass it in the configuration.\n const rateLimitConfig = new RateLimitConfig(configuration?.rateLimit, this._log);\n if (configuration?.rateLimit?.enabled) {\n this._globalRateLimiter = new RateLimiter(rateLimitConfig);\n const onRateLimitHit = this._diagnostics ? (ip: string, path: string): void => this._diagnostics?.onRateLimitHit(ip, path) : undefined;\n const hook = _createGlobalRateLimitHook(this._globalRateLimiter, onRateLimitHit);\n this.beforeAll([hook]);\n }\n\n // Setup cookie parser, if enabled, since it is deisabled by default we can set the configuration after the conditional\n if (configuration?.cookieParser?.enabled) {\n const cookieParserConfig = new CookieParserConfig(configuration.cookieParser, this._log);\n const cookieParserHookFunc = cookieParserHook(cookieParserConfig.config);\n this.beforeAll([cookieParserHookFunc]);\n }\n\n // Setup CORS, if enabled, as a beforeRouting hook\n if (configuration?.cors?.enabled) {\n const corsConfig = CorsConfig.merge(configuration.cors);\n CorsConfig.validate(corsConfig);\n // Type assertion safe here: validate() throws if config is disabled\n const corsHookFunc = corsHook(corsConfig as InternalCorsEnabledOptions);\n this.beforeRouting([corsHookFunc]);\n }\n\n // Setup automatic graceful shutdown if enabled\n if (this._configuration.gracefulShutdownTimeout) {\n const gracefulShutdownTimeout = _convertTimeToMs(this._configuration.gracefulShutdownTimeout);\n if (gracefulShutdownTimeout > 0) {\n this._setupGracefulShutdown(gracefulShutdownTimeout);\n }\n }\n }\n\n /** Public accessor for this instance's logger. */\n get log(): typeof this._log {\n return this._log;\n }\n\n /**\n * Configure all three logging channels: app logger, access logs, diagnostics.\n *\n * Creates a per-instance logger (D1 fix — no more singleton mutation).\n * Uses Symbol brand to detect framework loggers (D2/2.4 fix — replaces duck-typed `_state`).\n */\n private _configureLogging(): void {\n const loggingConfig = this._configuration.logging;\n\n // C2 fix: If a branded logger was provided, extract its underlying output sink\n // instead of mutating the user's branded logger state. Mutating caused cross-instance\n // side effects when the same branded logger was shared between YinzerFlow instances.\n // The per-instance this._log handles its own formatting (prefix, personality).\n let loggerSink = loggingConfig.logger;\n if (loggerSink && loggerBrand in (loggerSink as unknown as Record<string | symbol, unknown>)) {\n const brandedState = (loggerSink as unknown as Record<string | symbol, unknown>)[loggerBrand] as { logger?: typeof loggerSink };\n loggerSink = brandedState.logger ?? undefined;\n }\n\n // Create per-instance logger (D1 fix: no more Object.assign to module-level singleton)\n this._log = createLogger({\n level: loggingConfig.level,\n prefix: loggingConfig.prefix,\n personality: loggingConfig.personality,\n logger: loggerSink,\n });\n\n // Thread logger into subsystems\n this._hooks.setLogger(this._log);\n\n // C1 fix: Create per-instance access log (no more module-level singleton)\n if (loggingConfig.requests) {\n this._accessLog = createLogger({\n ...accessLogBaseConfig,\n level: 'info',\n logger: loggingConfig.accessLogger,\n });\n this._accessLogEnabled = true;\n }\n\n // Setup diagnostics monitor if any thresholds are configured\n const diagnostics = new DiagnosticsMonitor(loggingConfig.diagnostics, loggingConfig.personality);\n if (diagnostics.hasAnyEnabled()) {\n this._diagnostics = diagnostics;\n this._diagnostics.start();\n }\n }\n\n /**\n * Setup server with all event listeners\n */\n private _setupServer(resolve: () => void, reject: (error: Error) => void, requestHandler: RequestHandlerImpl): void {\n if (!this._server) return;\n\n this._server.on('error', (error: Error) => {\n this._log.error(`YinzerFlow server error at ${this._configuration.host}:${this._configuration.port} - ${error.message}`);\n // Clean up the failed server to prevent handle leaks on re-listen\n this._server?.close();\n delete this._server;\n reject(error);\n });\n\n this._server.on('listening', () => {\n this._isListening = true;\n this._log.info(`YinzerFlow server at ${this._configuration.host}:${this._configuration.port} is up and running`);\n resolve();\n });\n\n this._server.on('connection', (socket) => {\n this._handleConnection(socket, requestHandler);\n });\n }\n\n /**\n * Process incoming request data\n */\n private async _processRequest({\n data,\n socket,\n requestHandler,\n clientAddress,\n }: {\n data: Buffer;\n socket: Socket;\n requestHandler: RequestHandlerImpl;\n clientAddress: string;\n }): Promise<void> {\n const startTime = Date.now();\n\n const context = new ContextImpl(data, this, clientAddress);\n\n await requestHandler.handle(context);\n\n // Guard against writing to a socket that was destroyed (client disconnect, timeout, etc.)\n if (!socket.destroyed) {\n socket.write(context._response._stringBody);\n socket.end();\n }\n\n const processingTime = Date.now() - startTime;\n\n // Only compute byte length and build log strings when something will consume them\n if (this._accessLogEnabled || this._diagnostics) {\n const responseBytes = Buffer.byteLength(context._response._stringBody, 'utf8');\n\n // H3 fix: Sanitize attacker-controlled fields once for both channels\n const safeMethod = _sanitizeLogField(context.request.method);\n const safePath = _sanitizeLogField(context.request.path);\n\n // Access log — one nginx-style line per request (C1: per-instance, H4: separate guard)\n if (this._accessLogEnabled) {\n this._accessLog?.info(\n `${getStatusEmoji(context._response._statusCode)} ${clientAddress} \"${safeMethod} ${safePath} ${context.request.protocol}\" ${context._response._statusCode} ${responseBytes}bytes \"${_sanitizeLogField(context.request.headers.referer ?? '-')}\" \"${_sanitizeLogField(context.request.headers['user-agent'] ?? '-')}\" ${processingTime}ms`,\n );\n }\n\n // Diagnostics — check thresholds after response is sent (receives pre-sanitized values)\n this._diagnostics?.checkRequest({\n duration: processingTime,\n reqBytes: data.length,\n resBytes: responseBytes,\n method: safeMethod,\n path: safePath,\n });\n }\n }\n\n /**\n * Handle errors from request processing — log and destroy socket\n */\n private _handleRequestError(error: unknown, clientAddress: string, socket: Socket): void {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n this._log.error(`Request processing error from ${clientAddress}: ${errorMessage}`, error);\n if (!socket.destroyed) {\n socket.destroy();\n }\n }\n\n /**\n * Dispatch assembled request buffer to the request processor.\n * Wraps `_processRequest` with the standard error catch handler.\n */\n private _dispatchRequest({\n data,\n socket,\n requestHandler,\n clientAddress,\n }: {\n data: Buffer;\n socket: Socket;\n requestHandler: RequestHandlerImpl;\n clientAddress: string;\n }): void {\n this._processRequest({ data, socket, requestHandler, clientAddress }).catch((error: unknown) => this._handleRequestError(error, clientAddress, socket));\n }\n\n /**\n * Reject an oversized request with HTTP 413 (if headers were parsed) and destroy the socket.\n * Logs the current body parser limits for debugging.\n */\n private _rejectOversizedRequest({\n socket,\n clientAddress,\n totalLength,\n headersParsed,\n }: {\n socket: Socket;\n clientAddress: string;\n totalLength: number;\n headersParsed: boolean;\n }): void {\n if (headersParsed) {\n const errorBody = JSON.stringify({\n error: 'Payload too large',\n maxSize: this._maxBufferSize,\n received: totalLength,\n });\n socket.write(\n `HTTP/1.1 413 Payload Too Large\\r\\n` +\n `Content-Type: application/json\\r\\n` +\n `Content-Length: ${Buffer.byteLength(errorBody, 'utf8')}\\r\\n` +\n `Connection: close\\r\\n\\r\\n${errorBody}`,\n );\n }\n this._log.warn(\n `Request from ${clientAddress} exceeded maximum buffer size (${totalLength} > ${this._maxBufferSize} bytes). ` +\n `Current limits: json=${this._configuration.bodyParser.json.maxSize}, ` +\n `urlEncoded=${this._configuration.bodyParser.urlEncoded.maxSize}, ` +\n `fileUploads=${this._configuration.bodyParser.fileUploads.maxTotalSize}`,\n );\n socket.destroy();\n }\n\n /**\n * Check if buffered data looks like the start of an HTTP request.\n *\n * First checks the first byte against known HTTP method start characters\n * (G, P, D, H, O), then validates the first 8 bytes against the full method pattern.\n * Returns `false` for non-HTTP traffic so it can be dispatched for a graceful error.\n */\n private _looksLikeHttp(chunks: Array<Buffer>, totalLength: number, buffer: Buffer): boolean {\n if (totalLength >= 1) {\n const firstByte = chunks[0]?.[0] ?? 0;\n // cspell:disable-next-line\n // HTTP methods start with: G(ET)=0x47, P(OST/UT/ATCH)=0x50, D(ELETE)=0x44, H(EAD)=0x48, O(PTIONS)=0x4f\n if (firstByte !== 0x47 && firstByte !== 0x50 && firstByte !== 0x44 && firstByte !== 0x48 && firstByte !== 0x4f) {\n return false;\n }\n }\n if (totalLength >= 8) {\n const start = buffer.subarray(0, 8).toString();\n if (!/^(?:GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\\s/.test(start)) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Extract Content-Length value from raw HTTP headers.\n * Returns 0 if the header is missing (e.g. GET requests with no body).\n */\n private _parseContentLength(buffer: Buffer, headerEndIndex: number): number {\n const headersStr = buffer.subarray(0, headerEndIndex).toString();\n const match = /content-length:\\s*(?<digits>\\d+)/i.exec(headersStr);\n return match?.groups?.digits ? parseInt(match.groups.digits, 10) : 0;\n }\n\n /**\n * Handle incoming TCP socket connections and their complete lifecycle.\n *\n * Implements a TCP stream reassembly state machine that buffers chunks until the\n * complete HTTP request is received, then dispatches to `_processRequest`.\n *\n * **Header Phase**: Accumulate chunks, search for `\\r\\n\\r\\n`, parse Content-Length.\n * **Body Phase**: Track totalLength without concatenating until body is complete.\n * **Dispatch**: `Buffer.concat(chunks)` once to produce the final contiguous buffer.\n *\n * @see _looksLikeHttp for non-HTTP early detection\n * @see _rejectOversizedRequest for DoS protection (413 + socket destroy)\n * @see _processRequest for how the assembled buffer is parsed and handled\n */\n private _handleConnection(socket: Socket, requestHandler: RequestHandlerImpl): void {\n const clientAddress = socket.remoteAddress ?? 'unknown';\n const connectionStartTime = Date.now();\n let hasReceivedData = false;\n\n this._log.debug(`New connection from ${clientAddress}`);\n\n // TCP stream reassembly state — mutable, read/written by data handler\n const chunks: Array<Buffer> = [];\n let totalLength = 0;\n\n const state = { headersParsed: false, expectedBodyLength: 0, headerEndIndex: -1, requestDispatched: false };\n\n socket.on('data', (chunk) => {\n this._handleConnectionData({\n chunk,\n socket,\n requestHandler,\n clientAddress,\n connectionStartTime,\n chunks,\n state,\n hasReceivedData: () => hasReceivedData,\n setHasReceivedData: (val: boolean) => {\n hasReceivedData = val;\n },\n totalLength: () => totalLength,\n setTotalLength: (val: number) => {\n totalLength = val;\n },\n shouldDispatch: () => state.requestDispatched,\n });\n });\n\n socket.on('error', (error: Error) => {\n this._log.error(`Socket error from ${clientAddress}: ${error.message}`, error);\n });\n\n socket.on('close', () => {\n const connectionDuration = Date.now() - connectionStartTime;\n\n if (hasReceivedData) {\n this._log.debug(`Connection closed from ${clientAddress} (${connectionDuration}ms total)`);\n return;\n }\n\n if (connectionDuration < 10) {\n this._log.debug(`${clientAddress} quick connectivity check (${connectionDuration}ms) - health probe`);\n } else {\n this._log.debug(`${clientAddress} disconnected without sending data (${connectionDuration}ms) - potential probe`);\n }\n });\n }\n\n /**\n * Handle a single data chunk in the TCP stream reassembly state machine.\n */\n private _handleConnectionData({\n chunk,\n socket,\n requestHandler,\n clientAddress,\n connectionStartTime,\n chunks,\n state,\n hasReceivedData,\n setHasReceivedData,\n totalLength,\n setTotalLength,\n shouldDispatch,\n }: {\n chunk: Buffer;\n socket: Socket;\n requestHandler: RequestHandlerImpl;\n clientAddress: string;\n connectionStartTime: number;\n chunks: Array<Buffer>;\n state: { headersParsed: boolean; expectedBodyLength: number; headerEndIndex: number; requestDispatched: boolean };\n hasReceivedData: () => boolean;\n setHasReceivedData: (val: boolean) => void;\n totalLength: () => number;\n setTotalLength: (val: number) => void;\n shouldDispatch: () => boolean;\n }): void {\n if (!hasReceivedData()) {\n setHasReceivedData(true);\n const delay = Date.now() - connectionStartTime;\n if (delay > 100) {\n this._log.debug(`Delayed data from ${clientAddress} (${delay}ms connection delay)`);\n }\n }\n\n if (shouldDispatch()) return;\n\n chunks.push(chunk);\n setTotalLength(totalLength() + chunk.length);\n\n if (totalLength() > this._maxBufferSize) {\n this._rejectOversizedRequest({ socket, clientAddress, totalLength: totalLength(), headersParsed: state.headersParsed });\n return;\n }\n\n // Header phase: find \\r\\n\\r\\n boundary and parse Content-Length\n if (!state.headersParsed) {\n this._handleHeaderPhase({ chunks, totalLength: totalLength(), state, socket, requestHandler, clientAddress });\n return;\n }\n\n // Body phase: check if accumulated length satisfies Content-Length\n if (totalLength() - (state.headerEndIndex + 4) >= state.expectedBodyLength) {\n state.requestDispatched = true;\n this._dispatchRequest({ data: Buffer.concat(chunks, totalLength()), socket, requestHandler, clientAddress });\n }\n }\n\n /**\n * Handle the header phase of TCP stream reassembly.\n */\n private _handleHeaderPhase({\n chunks,\n totalLength,\n state,\n socket,\n requestHandler,\n clientAddress,\n }: {\n chunks: Array<Buffer>;\n totalLength: number;\n state: { headersParsed: boolean; expectedBodyLength: number; headerEndIndex: number; requestDispatched: boolean };\n socket: Socket;\n requestHandler: RequestHandlerImpl;\n clientAddress: string;\n }): void {\n const buffer = Buffer.concat(chunks, totalLength);\n state.headerEndIndex = buffer.indexOf('\\r\\n\\r\\n');\n\n if (state.headerEndIndex === -1) {\n if (!this._looksLikeHttp(chunks, totalLength, buffer)) {\n state.requestDispatched = true;\n this._dispatchRequest({ data: buffer, socket, requestHandler, clientAddress });\n }\n return;\n }\n\n state.headersParsed = true;\n\n // WebSocket upgrade check — before body assembly (zero overhead when no WS routes)\n if (this._wsRouter._hasRoutes()) {\n const headersStr = buffer.subarray(0, state.headerEndIndex).toString();\n if (_isWebSocketUpgrade(headersStr)) {\n state.requestDispatched = true;\n this._handleWebSocketUpgrade(buffer, socket, clientAddress);\n return;\n }\n }\n\n state.expectedBodyLength = this._parseContentLength(buffer, state.headerEndIndex);\n const bodyStart = state.headerEndIndex + 4;\n\n if (buffer.length - bodyStart >= state.expectedBodyLength) {\n state.requestDispatched = true;\n this._dispatchRequest({ data: buffer, socket, requestHandler, clientAddress });\n }\n }\n\n /**\n * Handle a WebSocket upgrade request. Validates handshake, matches route,\n * calls upgrade handler, sends 101, and creates the connection.\n */\n private _handleWebSocketUpgrade(buffer: Buffer, socket: Socket, clientAddress: string): void {\n this._handleWebSocketUpgradeAsync(buffer, socket, clientAddress).catch((error: unknown) => this._handleRequestError(error, clientAddress, socket));\n }\n\n private async _handleWebSocketUpgradeAsync(buffer: Buffer, socket: Socket, clientAddress: string): Promise<void> {\n const headerEndIndex = buffer.indexOf('\\r\\n\\r\\n');\n const headersStr = buffer.subarray(0, headerEndIndex).toString();\n\n const validation = _validateHandshake(headersStr);\n if (!validation.valid) {\n this._sendHttpError(socket, 400, validation.reason);\n return;\n }\n\n // Security checks (lazy allocation)\n this._wsSecurity ??= new WebSocketSecurity();\n const wsConfig = this._configuration.websocket;\n\n if (!this._wsSecurity.validateOrigin(validation.origin, wsConfig.allowedOrigins)) {\n this._sendHttpError(socket, 403, 'Origin not allowed');\n return;\n }\n\n if (!this._wsSecurity.canConnect(clientAddress, wsConfig.maxConnectionsPerIp)) {\n this._sendHttpError(socket, 429, 'Too many WebSocket connections from this IP');\n return;\n }\n\n const match = this._wsRouter._match(validation.path);\n if (!match) {\n this._sendHttpError(socket, 404, 'No WebSocket route matches this path');\n return;\n }\n\n const upgradeRequest = {\n headers: this._parseHeadersMap(headersStr),\n path: validation.path,\n query: validation.query,\n params: match.params,\n remoteAddress: clientAddress,\n };\n\n const data = match.handlers.upgrade ? await match.handlers.upgrade(upgradeRequest) : undefined;\n if (data === false) {\n this._sendHttpError(socket, 403, 'WebSocket upgrade rejected');\n return;\n }\n\n // Send 101 handshake response\n const acceptKey = _generateAcceptKey(validation.key);\n socket.write(_buildHandshakeResponse(acceptKey));\n socket.removeAllListeners();\n\n this._wsSecurity.trackConnect(clientAddress);\n this._setupWsConnection(socket, data, match.handlers, match.options, clientAddress, validation.path);\n }\n\n // eslint-disable-next-line max-params\n private _setupWsConnection(\n socket: Socket,\n data: unknown,\n handlers: WebSocketHandlers,\n routeOptions: WebSocketRouteOptions | undefined,\n clientAddress: string,\n path: string,\n ): void {\n const connectionOptions = this._mergeWsConnectionOptions(routeOptions);\n const wrappedHandlers = this._wrapWsHandlers(handlers);\n const connection = new WebSocketConnection(socket, data, wrappedHandlers, connectionOptions);\n\n this._wsChannelManager ??= new WebSocketChannelManager();\n connection.setChannelManager(this._wsChannelManager);\n\n this._wsConnections ??= new Set();\n this._wsConnections.add(connection);\n\n const originalClose = wrappedHandlers.close;\n wrappedHandlers.close = (ws, code, reason): void => {\n this._wsConnections?.delete(connection);\n this._wsSecurity?.trackDisconnect(clientAddress);\n originalClose?.(ws, code, reason);\n };\n\n this._log.debug(`WebSocket connection established from ${clientAddress} on ${path}`);\n handlers.open?.(connection as never);\n }\n\n private _mergeWsConnectionOptions(routeOpts?: WebSocketRouteOptions): {\n maxPayloadLength: number;\n idleTimeout: number;\n backpressure: { strategy: 'buffer' | 'drop'; limit: number };\n } {\n const wsConfig = this._configuration.websocket;\n return {\n maxPayloadLength: routeOpts?.maxPayloadLength ?? wsConfig.maxPayloadLength,\n idleTimeout: routeOpts?.idleTimeout ?? wsConfig.idleTimeout,\n backpressure: {\n strategy: routeOpts?.backpressure?.strategy ?? wsConfig.backpressure.strategy,\n limit: routeOpts?.backpressure?.limit ?? wsConfig.backpressure.limit,\n },\n };\n }\n\n /**\n * Wrap WebSocket handlers with wsBeforeMessage/wsAfterMessage hooks.\n */\n private _wrapWsHandlers(handlers: WebSocketHandlers): WebSocketHandlers {\n const hasBeforeHooks = this._hooks._wsBeforeMessage.size > 0;\n const hasAfterHooks = this._hooks._wsAfterMessage.size > 0;\n\n if (!hasBeforeHooks && !hasAfterHooks) {\n return handlers;\n }\n\n return {\n ...handlers,\n message: (ws, messageData, isBinary): void => {\n // Fire-and-forget async handler to match void return type signature\n void (async (): Promise<void> => {\n for (const hook of this._hooks._wsBeforeMessage) {\n const result = hook.handler(ws, messageData, isBinary);\n if (result && typeof result === 'object' && 'catch' in result) {\n await result;\n }\n }\n handlers.message?.(ws, messageData, isBinary);\n for (const hook of this._hooks._wsAfterMessage) {\n const hookResult = hook.handler(ws, messageData, isBinary);\n if (hookResult && typeof hookResult === 'object' && 'catch' in hookResult) {\n await hookResult;\n }\n }\n })().catch((error: unknown) => {\n this._log.error('Error in WebSocket message handler hooks:', error);\n });\n },\n };\n }\n\n /**\n * Parse raw headers string into a Record (lowercased keys).\n */\n private _parseHeadersMap(headersStr: string): Record<string, string> {\n const headers: Record<string, string> = {};\n const lines = headersStr.split('\\r\\n');\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i];\n if (!line) continue;\n const colonIndex = line.indexOf(':');\n if (colonIndex < 0) continue;\n headers[line.substring(0, colonIndex).trim().toLowerCase()] = line.substring(colonIndex + 1).trim();\n }\n return headers;\n }\n\n /**\n * Send an HTTP error response on a socket and destroy it.\n */\n private _sendHttpError(socket: Socket, statusCode: number, message: string): void {\n const body = JSON.stringify({ error: message });\n const statusTextMap: Record<number, string> = {\n 400: 'Bad Request',\n 403: 'Forbidden',\n 404: 'Not Found',\n };\n const statusText = statusTextMap[statusCode] ?? 'Error';\n socket.write(\n `HTTP/1.1 ${statusCode} ${statusText}\\r\\n` +\n `Content-Type: application/json\\r\\n` +\n `Content-Length: ${Buffer.byteLength(body, 'utf8')}\\r\\n` +\n `Connection: close\\r\\n\\r\\n${body}`,\n );\n socket.destroy();\n }\n\n /** Publish a message to all subscribers of a WebSocket channel. Returns recipient count. */\n publish(channel: string, data: Buffer | string): number {\n return this._wsChannelManager?.publish(channel, data) ?? 0;\n }\n\n /** Get the number of subscribers on a WebSocket channel. */\n subscriberCount(channel: string): number {\n return this._wsChannelManager?.subscriberCount(channel) ?? 0;\n }\n\n async listen(): Promise<void> {\n if (this._isListening) {\n throw new Error('Server is already listening');\n }\n\n return new Promise((resolve, reject) => {\n const requestHandler = new RequestHandlerImpl(this);\n this._server = createServer();\n\n this._setupServer(resolve, reject, requestHandler);\n this._server.listen(this._configuration.port, this._configuration.host);\n });\n }\n\n async close(): Promise<void> {\n if (!this._isListening || !this._server) {\n return;\n }\n\n // Clean up rate limiter resources (intervals, memory)\n if (this._globalRateLimiter) {\n await this._globalRateLimiter.destroy();\n this._globalRateLimiter = undefined;\n }\n\n // Clean up diagnostics timers\n if (this._diagnostics) {\n this._diagnostics.destroy();\n this._diagnostics = undefined;\n }\n\n // Close all active WebSocket connections gracefully\n if (this._wsConnections?.size) {\n for (const conn of this._wsConnections) {\n conn.close(1001, 'Server shutting down');\n }\n this._wsConnections.clear();\n }\n\n return new Promise((resolve) => {\n if (!this._server) {\n this._isListening = false; // Probably redundant but just in case\n resolve();\n return;\n }\n\n this._server.close(() => {\n this._isListening = false;\n this._log.warn(`YinzerFlow server at ${this._configuration.host}:${this._configuration.port} is shutting down`);\n resolve();\n });\n });\n }\n\n status(): {\n isListening: boolean;\n port: number | undefined;\n host: string | undefined;\n } {\n return {\n isListening: this._isListening,\n port: this._configuration.port,\n host: this._configuration.host,\n };\n }\n\n /**\n * Setup automatic graceful shutdown handlers\n */\n private _setupGracefulShutdown(gracefulShutdownTimeout: number): void {\n if (gracefulShutdownTimeout <= 0) {\n return;\n }\n\n // Only setup if no handlers are already registered\n if (process.listenerCount('SIGTERM') === 0 && process.listenerCount('SIGINT') === 0) {\n const shutdown = (signal: string): void => {\n this._log.info(`🛑 Received ${signal}, shutting down gracefully in ${this._configuration.gracefulShutdownTimeout}...`);\n setTimeout(() => {\n this.close()\n .then(() => {\n this._log.info('✅ Server shut down gracefully');\n process.exit(0);\n })\n .catch((error) => {\n this._log.error('❌ Error during graceful shutdown:', error);\n process.exit(1);\n });\n }, gracefulShutdownTimeout);\n };\n\n process.on('SIGTERM', () => shutdown('SIGTERM'));\n process.on('SIGINT', () => shutdown('SIGINT'));\n }\n }\n}\n",
|
|
6
6
|
"import type { SetupImpl } from '@core/setup/SetupImpl.ts';\nimport type { InternalContextImpl } from '@typedefs/internal/InternalContextImpl.ts';\nimport type { InternalSetupImpl } from '@typedefs/internal/InternalSetupImpl.js';\nimport type { HandlerCallback } from '@typedefs/public/Context.js';\nimport type { InternalRouteRegistry } from '@typedefs/internal/InternalRouteRegistryImpl.js';\nimport type { InternalGlobalHookOptions } from '@typedefs/internal/InternalHookRegistryImpl.js';\n\n/**\n * Handles the complete lifecycle of an HTTP request\n *\n * Flow:\n * 1. Receive parsed context (request + response builders)\n * 2. Match route and execute handlers\n * 3. Build final response in context\n * 4. Context.rawResponse is ready for sending\n */\nexport class RequestHandlerImpl {\n private readonly setup: InternalSetupImpl;\n\n constructor(setup: SetupImpl) {\n this.setup = setup;\n }\n\n /**\n * Process an HTTP request using the provided context\n */\n async handle(context: InternalContextImpl): Promise<void> {\n try {\n // 1. Run beforeRouting hooks (includes CORS if enabled) - stop if any hook returns a value\n if (await this._handleBeforeRoutingHooks(context)) {\n return void 0;\n }\n\n // 2. Match route based on context.request.method + context.request.path\n const matchedRoute = await this._matchRoute(context);\n if (!matchedRoute) return void 0;\n\n // Set route params in the request context\n Object.assign(context.request.params as unknown as Record<string, string>, matchedRoute.params);\n\n const { handler, options } = matchedRoute;\n const { beforeHooks = [], afterHooks = [] } = options;\n\n // 3. Run beforeAll hooks - stop if any hook returns a value\n if (await this._handleBeforeAllHooks(context)) {\n return void 0;\n }\n\n // 4. Run beforeGroup hooks and beforeRoute hooks - stop if any hook returns a value\n // * The before group hooks and beforeRoute hooks are in the same array and ordered on route registration.\n if (await this._handleBeforeHooks(context, beforeHooks)) {\n return void 0;\n }\n\n // 5. Execute route handler\n const routeResponse = await handler(context);\n\n // 6. Set body BEFORE after-hooks so it's preserved even if a hook throws\n context._response._setBody(routeResponse);\n\n // 7. Run afterRoute hooks and afterGroup hooks\n // * The after group hooks and afterRoute hooks are in the same array and ordered on route registration.\n for (const hook of afterHooks) await hook(context);\n\n // 8. Run afterAll hooks\n const afterAllHooks = this.setup._hooks._afterAll;\n for (const hook of afterAllHooks) {\n if (!this._shouldRunHook(hook.options, context.request.path)) {\n continue;\n }\n await hook.handler(context);\n }\n\n // 9. If this was a HEAD request, remove the body.\n // Waiting until after hooks since they might modify the response, headers, etc.\n if (context.request.method === 'HEAD') {\n context._response._setBody(null);\n }\n\n // 10. Add default framework headers and parse the body into a string\n context._response._parseResponseIntoString();\n\n return void 0;\n } catch (error) {\n // Use the error handler from setup\n await this.handleError(context, error);\n }\n }\n\n /**\n * Handle errors using the user-defined or default error handler\n * The error handler returns a response object that we apply to the context\n */\n private async handleError(context: InternalContextImpl, error: unknown): Promise<void> {\n try {\n // Get the error handler (user-defined or default)\n const errorHandler = this.setup._hooks._onError;\n\n // Call the error handler - it returns a response object\n const errorResponse = await errorHandler(context, error);\n\n // Apply the response to the context\n context._response._setBody(errorResponse);\n\n // Format the response for sending (same as normal flow)\n context._response._parseResponseIntoString();\n } catch (errorHandlerError) {\n // If the error handler itself fails, fall back to basic response\n this.setup._log.error('Your custom error handler threw an error. Check your onError() handler for bugs: ', errorHandlerError);\n\n context.response.setStatusCode(500);\n context._response._setBody({\n success: false,\n message: 'Internal Server Error',\n });\n\n // Format the fallback response too\n context._response._parseResponseIntoString();\n }\n }\n\n async _handleBeforeRoutingHooks(context: InternalContextImpl): Promise<boolean> {\n const beforeRoutingHooks = this.setup._hooks._beforeRouting;\n for (const hook of beforeRoutingHooks) {\n // Check if hook should run based on route options\n if (!this._shouldRunHook(hook.options, context.request.path)) {\n continue;\n }\n\n const result = await hook.handler(context);\n if (this._applyHookResponse(result, context)) return true;\n }\n return false;\n }\n\n async _matchRoute(context: InternalContextImpl): Promise<InternalRouteRegistry | null> {\n const matchedRoute = this.setup._routeRegistry._findRoute(context.request.method, context.request.path);\n\n if (!matchedRoute) {\n const notFoundResponse = await this.setup._hooks._onNotFound(context);\n context._response._setBody(notFoundResponse);\n context._response._parseResponseIntoString(); // Needed so the YinzerFlow can send the response as a string\n return null; // Signal that no route was found and response is already set\n }\n\n return matchedRoute;\n }\n\n async _handleBeforeAllHooks(context: InternalContextImpl): Promise<boolean> {\n const beforeAllHooks = this.setup._hooks._beforeAll;\n for (const hook of beforeAllHooks) {\n // Check if hook should run based on route options\n if (!this._shouldRunHook(hook.options, context.request.path)) {\n continue;\n }\n\n const result = await hook.handler(context);\n if (this._applyHookResponse(result, context)) return true;\n }\n return false;\n }\n\n async _handleBeforeHooks(context: InternalContextImpl, hooks: Array<HandlerCallback>): Promise<boolean> {\n for (const hook of hooks) {\n const result = await hook(context);\n if (this._applyHookResponse(result, context)) return true;\n }\n return false;\n }\n\n /** Apply a hook's return value as the response. Returns true if hook short-circuited. */\n _applyHookResponse(result: unknown, context: InternalContextImpl): boolean {\n if (result === undefined) return false;\n context._response._setBody(result);\n context._response._parseResponseIntoString();\n return true;\n }\n\n /**\n * Determines if a hook should run based on its options and the current request path\n */\n _shouldRunHook(options: InternalGlobalHookOptions | undefined, requestPath: string): boolean {\n if (!options) {\n return true; // No options means run for all routes\n }\n\n const { routesToInclude = [], routesToExclude = [] } = options;\n\n // If routesToExclude contains the current path, don't run\n if (routesToExclude.some((pattern) => this._matchesPattern(requestPath, pattern))) {\n return false;\n }\n\n // If routesToInclude is empty, run for all routes (unless excluded above)\n if (routesToInclude.length === 0) {\n return true;\n }\n\n // If routesToInclude has patterns, only run if current path matches one of them\n return routesToInclude.some((pattern) => this._matchesPattern(requestPath, pattern));\n }\n\n /**\n * Simple pattern matching for route filtering\n * Supports basic wildcard patterns like /api/* and exact matches\n */\n _matchesPattern(path: string, pattern: string): boolean {\n // Exact match\n if (pattern === path) {\n return true;\n }\n\n // Wildcard pattern (e.g., /api/*) — must match segment boundary\n if (pattern.endsWith('/*')) {\n const prefix = pattern.slice(0, -1); // Keep trailing slash: \"/api/\" from \"/api/*\"\n return path.startsWith(prefix) || path === pattern.slice(0, -2);\n }\n\n // No match\n return false;\n }\n}\n",
|
|
7
7
|
"// Shared ANSI Color codes (reused from main log system)\nexport const colors = {\n reset: '\\x1b[0m',\n cyan: '\\x1b[96m', // Cyan for info\n yellow: '\\x1b[93m', // Yellow for warn\n red: '\\x1b[91m', // Red for error\n green: '\\x1b[92m', // Green for success\n magenta: '\\x1b[95m', // Magenta for performance\n gray: '\\x1b[90m', // Gray for network logs\n} as const;\n",
|
|
8
8
|
"/**\n * YinzerFlow Logging Levels\n *\n * String-based logging levels for intuitive configuration:\n * - 'off': No logging at all\n * - 'error': Only errors\n * - 'warn': Warnings and errors (includes security warnings)\n * - 'info': Info, warnings, and errors (standard application logging)\n * - 'debug': All messages including verbose connection details\n *\n * Access logging (request/response lines) is controlled separately via `logging.requests`.\n */\nexport const logLevels = {\n off: 'off',\n error: 'error',\n warn: 'warn',\n info: 'info',\n debug: 'debug',\n} as const;\n",
|
|
@@ -27,16 +27,18 @@
|
|
|
27
27
|
"/**\n * Response header validation utilities for security and format compliance\n *\n * This module contains security-focused header validation functions,\n * particularly for preventing CRLF injection attacks in outgoing response headers.\n */\n\n/**\n * Validate response header value for CRLF injection attempts\n * Use this when setting response headers with user input\n */\nexport const validateResponseHeaderValue = (headerName: string, headerValue: string): void => {\n // SECURITY: Check for CRLF injection in response header values\n // This is where CRLF injection actually matters - when setting response headers\n\n if (typeof headerValue !== 'string') {\n throw new Error(`Header value must be a string, got ${typeof headerValue}`);\n }\n\n // SECURITY: Detect CRLF injection patterns that could inject additional headers\n if (headerValue.includes('\\r') || headerValue.includes('\\n')) {\n throw new Error(`Header value contains invalid line break characters: ${headerName}`);\n }\n\n // SECURITY: Detect common injection patterns\n const suspiciousPatterns = [\n // Pattern: value\\r\\nSet-Cookie: or value\\nLocation: etc.\n /[\\r\\n](?:set-cookie|location|authorization|www-authenticate):/i,\n // Pattern: Double CRLF (could inject HTTP response)\n /\\r\\n\\r\\n|\\n\\n/,\n // Pattern: HTTP response line injection\n /[\\r\\n]http\\/\\d\\.\\d\\s+\\d+/i,\n ];\n\n for (const pattern of suspiciousPatterns) {\n if (pattern.test(headerValue)) {\n throw new Error(`Header value contains suspicious injection pattern: ${headerName}`);\n }\n }\n};\n\n/**\n * Validate multiple response header values\n * Convenience function for validating header objects\n */\nexport const validateResponseHeaders = (headers: Record<string, string>): void => {\n for (const [name, value] of Object.entries(headers)) {\n validateResponseHeaderValue(name, value);\n }\n};\n\n/**\n * Filter and validate headers, removing undefined values and validating security\n * Returns only valid, defined header entries\n */\nexport const filterAndValidateHeaders = (headers: Partial<Record<string, string | undefined>>): Record<string, string> => {\n // Filter out undefined values using simple, readable approach\n const definedHeaders: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (value !== undefined) {\n definedHeaders[key] = value;\n }\n }\n\n // Validate the filtered headers\n validateResponseHeaders(definedHeaders);\n\n return definedHeaders;\n};\n",
|
|
28
28
|
"import { formatBodyIntoString } from '@core/execution/utils/formatBodyIntoString.ts';\nimport { determineEncoding } from '@core/execution/utils/determineEncoding.ts';\nimport { inferContentType } from '@core/execution/utils/inferContentType.ts';\nimport { mapStatusCodeToMessage } from '@core/execution/utils/mapStatusCodeToMessage.ts';\nimport { filterAndValidateHeaders } from '@core/execution/utils/validateResponseHeaders.ts';\nimport { httpEncoding, httpStatus, httpStatusCode } from '@constants/http.ts';\nimport type { InternalHttpEncoding, InternalHttpHeaders, InternalHttpStatus, InternalHttpStatusCode } from '@typedefs/constants/http.js';\nimport type { Request } from '@typedefs/public/Request.ts';\nimport type { InternalResponseImpl } from '@typedefs/internal/InternalResponseImpl.d.ts';\n\n/** Format current time as HTTP Date header (RFC 7231 §7.1.1.1) */\nconst _formatHttpDate = (): string => {\n const d = new Date();\n const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] as const;\n const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] as const;\n const pad = (n: number): string => (n < 10 ? `0${n}` : String(n));\n return `${days[d.getUTCDay()]}, ${pad(d.getUTCDate())} ${months[d.getUTCMonth()]} ${d.getUTCFullYear()} ${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}:${pad(d.getUTCSeconds())} GMT`;\n};\n\n/** Cached HTTP Date header — refreshed every second. Avoids Date allocation per response. */\nlet _cachedDateHeader = _formatHttpDate();\nconst _dateRefreshTimer = setInterval(() => {\n _cachedDateHeader = _formatHttpDate();\n}, 1000);\n_dateRefreshTimer.unref();\n\nexport class ResponseImpl implements InternalResponseImpl {\n readonly _request: Request;\n\n _statusCode: InternalHttpStatusCode = httpStatusCode.ok;\n _status: InternalHttpStatus = httpStatus.ok;\n _headers: Partial<Record<InternalHttpHeaders, string>> = {};\n _setCookies: Array<string> = []; // Track multiple Set-Cookie headers\n _body: unknown = '';\n _stringBody = '';\n _encoding: InternalHttpEncoding = httpEncoding.utf8;\n\n constructor(request: Request) {\n this._request = request;\n this._setSecurityHeaders();\n }\n\n _parseResponseIntoString(): void {\n const statusLine = `${this._request.protocol} ${this._statusCode} ${this._status}`;\n const encoding = determineEncoding(this._headers['content-type'], this._body);\n const body = formatBodyIntoString(this._body, { encoding });\n\n // Set Date + Content-Length BEFORE assembling headers into the response string.\n // Content-Length = body bytes only (not status line + headers), per HTTP/1.1 spec.\n this._setHeadersIfNotSet({\n Date: _cachedDateHeader,\n 'Content-Length': String(Buffer.byteLength(body, 'utf8')),\n });\n\n this._encoding = encoding;\n\n const headerLines = Object.entries(this._headers).map(([key, value]) => `${key}: ${value}`);\n const setCookieLines = this._setCookies.map((value) => `Set-Cookie: ${value}`);\n const allHeaderLines = [...headerLines, ...setCookieLines];\n const headersSection = allHeaderLines.length > 0 ? `${allHeaderLines.join('\\r\\n')}\\r\\n` : '';\n\n this._stringBody = `${statusLine}\\r\\n${headersSection}\\r\\n${body}`;\n }\n\n _setHeadersIfNotSet(headers: Partial<Record<InternalHttpHeaders, string>>): void {\n // SECURITY: Filter undefined values and validate response headers for CRLF injection\n // Only validate headers that aren't already set\n const headersToSet: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (value !== undefined && !(key in this._headers)) {\n headersToSet[key] = value;\n }\n }\n\n const validatedHeaders = filterAndValidateHeaders(headersToSet);\n\n // Set headers after validation passes\n Object.assign(this._headers, validatedHeaders);\n }\n\n _setBody(body: unknown): void {\n this._body = body;\n\n // Auto-set content-type if not already set\n if (!this._headers['content-type']) {\n const detectedContentType = inferContentType(body);\n this._setHeadersIfNotSet({\n 'Content-Type': detectedContentType,\n });\n }\n }\n\n setStatusCode(statusCode: InternalHttpStatusCode): void {\n this._statusCode = statusCode;\n this._status = mapStatusCodeToMessage(statusCode);\n }\n\n addHeaders(headers: Partial<Record<InternalHttpHeaders, string>>): void {\n // SECURITY: Filter undefined values and validate response headers for CRLF injection\n const validatedHeaders = filterAndValidateHeaders(headers);\n\n // Handle Set-Cookie specially - support multiple values\n for (const [key, value] of Object.entries(validatedHeaders)) {\n if (key === 'Set-Cookie') {\n if (value) {\n this._setCookies.push(value);\n }\n } else {\n // Regular headers overwrite if duplicate\n this._headers[key] = value;\n }\n }\n }\n\n removeHeaders(headerNames: Array<InternalHttpHeaders>): void {\n for (const headerName of headerNames) {\n delete this._headers[headerName];\n }\n }\n\n /**\n * Set default security headers to protect against common vulnerabilities\n * These headers are set only if not already present, allowing users to override if needed\n */\n _setSecurityHeaders(): void {\n this._setHeadersIfNotSet({\n 'X-Content-Type-Options': 'nosniff',\n 'X-Frame-Options': 'DENY',\n 'X-XSS-Protection': '1; mode=block',\n 'Referrer-Policy': 'strict-origin-when-cross-origin',\n });\n }\n}\n",
|
|
29
29
|
"import { RequestImpl } from '@core/execution/RequestImpl.ts';\nimport { ResponseImpl } from '@core/execution/ResponseImpl.ts';\nimport type { SetupImpl } from '@core/setup/SetupImpl.ts';\nimport type { InternalContextImpl } from '@typedefs/internal/InternalContextImpl.js';\nimport type { InternalRequestImpl } from '@typedefs/internal/InternalRequestImpl.js';\nimport type { InternalResponseImpl } from '@typedefs/internal/InternalResponseImpl.js';\nimport type { CookieOptions, Cookies } from '@typedefs/public/CookieParser.js';\nimport type { Request } from '@typedefs/public/Request.ts';\nimport type { Response } from '@typedefs/public/Response.ts';\n\n/**\n * ContextImpl is the core class that handles the building of the context.\n * It is responsible for building the request and response objects, plus\n * managing user-defined state data.\n *\n * ## What is ContextImpl?\n *\n * ContextImpl is the concrete implementation of the Context interface. It's\n * automatically created for each incoming request and provides a unified\n * interface for accessing request data, controlling responses, and managing\n * request-scoped state.\n *\n * ## How ContextImpl Works\n *\n * 1. **Construction**: Creates RequestImpl and ResponseImpl instances\n * 2. **State Initialization**: Initializes empty state object for user data\n * 3. **Request Processing**: Handles raw request data and builds structured request\n * 4. **Response Control**: Provides methods to control HTTP response behavior\n * 5. **State Management**: Allows middleware and handlers to store custom data\n * 6. **Cleanup**: Automatically garbage collected when request completes\n *\n * @example\n * ```typescript\n * // ContextImpl is automatically created for each request\n * const context = new ContextImpl(rawRequest, setup, clientAddress);\n *\n * // Access request data\n * const userId = context.request.params.id;\n * const userData = context.request.body;\n *\n * // Store custom state\n * context.state.user = { id: userId, name: 'John' };\n * context.state.requestId = generateRequestId();\n *\n * // Control response\n * context.response.setStatusCode(200);\n * context.response.addHeaders({ 'X-User-ID': userId });\n *\n * // Return response data\n * return { success: true, user: context.state.user };\n * ```\n *\n * @see {@link Context} for the public interface\n * @see {@link RequestImpl} for request implementation details\n * @see {@link ResponseImpl} for response implementation details\n * @see {@link InternalContextImpl} for internal interface details\n */\nexport class ContextImpl implements InternalContextImpl {\n readonly _request: InternalRequestImpl;\n readonly _response: InternalResponseImpl;\n\n /**\n * The incoming request object containing all request data and metadata.\n *\n * Provides access to headers, body, query parameters, route parameters,\n * and client information like IP address.\n *\n * @example\n * ```typescript\n * const handler: HandlerCallback = async (ctx) => {\n * // Access route parameters\n * const userId = ctx.request.params.id;\n *\n * // Access request body\n * const userData = ctx.request.body;\n *\n * // Access headers\n * const authToken = ctx.request.headers.authorization;\n *\n * // Access client information\n * const clientIp = ctx.request.ipAddress;\n *\n * return { userId, userData, hasAuth: !!authToken };\n * };\n * ```\n *\n * @see {@link Request} for complete request interface documentation\n */\n request: Request;\n\n /**\n * The outgoing response object for controlling HTTP response behavior.\n *\n * Provides methods to set status codes, add headers, and control\n * response formatting and content.\n *\n * @example\n * ```typescript\n * const handler: HandlerCallback = async (ctx) => {\n * const { request, response } = ctx;\n *\n * // Set successful status code\n * response.setStatusCode(201);\n *\n * // Add custom headers\n * response.addHeaders({\n * 'Location': `/api/users/${request.params.id}`,\n * 'X-User-ID': request.params.id,\n * 'Cache-Control': 'max-age=3600'\n * });\n *\n * // Return response body (Content-Type automatically set)\n * return { message: 'User created successfully' };\n * };\n * ```\n *\n * @see {@link Response} for complete response interface documentation\n */\n response: Response;\n\n /**\n * User-defined state data that persists throughout the request lifecycle.\n *\n * This property allows middleware and route handlers to store and share\n * custom data. The state is request-scoped and will be automatically garbage\n * collected when the request completes and the context goes out of scope.\n *\n * ## State Lifecycle\n *\n * 1. **Request Start**: State object is created as empty object\n * 2. **Global Hooks**: `beforeAll` hooks can populate state\n * 3. **Route Hooks**: `beforeHooks` can access and modify state\n * 4. **Route Handler**: Your handler can access and modify state\n * 5. **Route Hooks**: `afterHooks` can access state and modify response\n * 6. **Global Hooks**: `afterAll` hooks can access state and modify response\n * 7. **Request End**: Context goes out of scope and is automatically garbage collected\n *\n * @example\n * ```typescript\n * // Authentication middleware\n * const authMiddleware: HandlerCallback = async (ctx) => {\n * const token = ctx.request.headers.authorization;\n * const user = await validateToken(token);\n *\n * // Store user data in state for route handlers\n * ctx.state.user = user;\n * ctx.state.permissions = await getUserPermissions(user.id);\n * ctx.state.isAuthenticated = true;\n * };\n *\n * // Route that uses the authenticated state\n * app.get('/api/admin/users', authMiddleware, async (ctx) => {\n * // Access the user data set by middleware\n * const { user, permissions, isAuthenticated } = ctx.state;\n *\n * if (!permissions.includes('admin')) {\n * throw new Error('Insufficient permissions');\n * }\n *\n * // Add route-specific state\n * ctx.state.routeAccessed = true;\n * ctx.state.lastAccess = new Date();\n *\n * return { message: 'Admin access granted', user };\n * });\n * ```\n *\n * @see {@link Context} for complete context interface documentation\n */\n state: Record<string, unknown> = {};\n\n /**\n * Creates a new ContextImpl instance for handling a single request.\n *\n * @param rawRequest - The raw request data (Buffer or string) from the client\n * @param setup - The SetupImpl instance that manages routes and hooks\n * @param clientAddress - Optional client IP address for security and logging\n *\n * @example\n * ```typescript\n * // ContextImpl is typically created internally by YinzerFlow\n * const context = new ContextImpl(\n * Buffer.from('GET /api/users HTTP/1.1...'),\n * setupInstance,\n * '192.168.1.100'\n * );\n *\n * // Access the context properties\n * console.log(context.request.method); // \"GET\"\n * console.log(context.request.url); // \"/api/users\"\n * console.log(context.request.ipAddress); // \"192.168.1.100\"\n * ```\n *\n * @see {@link SetupImpl} for setup implementation details\n * @see {@link RequestImpl} for request building details\n * @see {@link ResponseImpl} for response building details\n */\n cookies: Cookies = {\n set: (_name: string, _value: string, _options?: CookieOptions): void => {\n // Initialized by cookieParserHook if enabled\n },\n sign: (_name: string, _value: string): string => '',\n unsign: (_name: string, _signedValue: string): string | false => false,\n };\n\n constructor(rawRequest: Buffer | string, setup: SetupImpl, clientAddress?: string) {\n this._request = new RequestImpl(rawRequest, setup, clientAddress);\n this._response = new ResponseImpl(this._request);\n\n this.request = this._request;\n this.response = this._response;\n }\n}\n",
|
|
30
|
+
"import { log } from '@core/utils/log.ts';\nimport { _formatBytesForDisplay } from '@core/utils/bytes.ts';\nimport type { InternalWebSocketOptions } from '@typedefs/internal/InternalConfiguration.js';\n\n/**\n * Default WebSocket configuration with sensible production defaults.\n */\nexport const DEFAULT_WEBSOCKET_CONFIG: InternalWebSocketOptions = {\n maxPayloadLength: 16_777_216, // 16MB\n idleTimeout: 120, // seconds\n maxConnectionsPerIp: 50,\n allowedOrigins: [],\n backpressure: {\n strategy: 'buffer',\n limit: 1_048_576, // 1MB\n },\n};\n\n/**\n * Validate WebSocket configuration values.\n */\nexport const _validateWebSocketConfig = (config: InternalWebSocketOptions): void => {\n if (config.maxPayloadLength < 1) {\n throw new Error('websocket.maxPayloadLength must be at least 1 byte');\n }\n\n if (config.idleTimeout < 0) {\n throw new Error('websocket.idleTimeout must be >= 0 (0 = no timeout)');\n }\n\n if (config.maxConnectionsPerIp < 1) {\n throw new Error('websocket.maxConnectionsPerIp must be at least 1');\n }\n\n if (config.backpressure.limit < 0) {\n throw new Error('websocket.backpressure.limit must be >= 0');\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- runtime validation for JS users who bypass TypeScript\n if (config.backpressure.strategy !== 'buffer' && config.backpressure.strategy !== 'drop') {\n throw new Error(`websocket.backpressure.strategy must be 'buffer' or 'drop'. Got: \"${config.backpressure.strategy as unknown as string}\"`);\n }\n};\n\n/**\n * Issue security warnings for risky WebSocket configurations.\n */\nexport const _warnWebSocketConfig = (config: InternalWebSocketOptions): void => {\n if (config.maxPayloadLength > 67_108_864) {\n // 64MB\n log.warn(\n `[SECURITY WARNING] websocket.maxPayloadLength is set to ${_formatBytesForDisplay(config.maxPayloadLength)}. ` +\n 'Very large payloads can cause memory exhaustion. Consider if this size is necessary.',\n );\n }\n\n if (config.idleTimeout === 0) {\n log.warn(\n '[SECURITY WARNING] websocket.idleTimeout is 0 (disabled). ' +\n 'Idle connections will never be closed automatically, which can lead to resource exhaustion.',\n );\n }\n};\n",
|
|
30
31
|
"import type { TimeString } from '@typedefs/public/Time.js';\n\n/**\n * Convert time string to milliseconds\n *\n * Internal helper for parsing user-friendly time formats into milliseconds.\n * Supports seconds (s), minutes (m), hours (h), and days (d).\n *\n * @param time - Time string in format: number + unit (s/m/h/d)\n * @returns Time in milliseconds\n * @throws Error if time format is invalid\n *\n * @example\n * ```typescript\n * _convertTimeToMs('500ms') // 500\n * _convertTimeToMs('30s') // 30000\n * _convertTimeToMs('15m') // 900000\n * _convertTimeToMs('2h') // 7200000\n * _convertTimeToMs('1d') // 86400000\n * ```\n *\n * @internal\n */\nexport const _convertTimeToMs = (time: TimeString | number): number => {\n if (typeof time === 'number') {\n if (!Number.isFinite(time) || time <= 0) {\n throw new Error(`Invalid time value: \"${time}\". Must be a positive number`);\n }\n return time;\n }\n\n // Validate string format\n if (typeof time !== 'string' || time.length < 2) {\n throw new Error('Invalid time format. Expected format: 1ms, 1s, 1m, 1h, 1d');\n }\n\n // Extract unit (last character)\n const unit = time.includes('ms') ? time.slice(-2) : time.slice(-1);\n const value = time.includes('ms') ? time.slice(0, -2) : time.slice(0, -1);\n\n // Validate unit\n if (!['ms', 's', 'm', 'h', 'd'].includes(unit)) {\n throw new Error(`Invalid time unit: \"${unit}\". Expected: s (seconds), m (minutes), h (hours), or d (days)`);\n }\n\n // Parse numeric value\n const numValue = Number(value);\n if (isNaN(numValue) || numValue <= 0) {\n throw new Error(`Invalid time value: \"${value}\". Must be a positive number`);\n }\n\n // Convert to milliseconds based on unit\n switch (unit) {\n case 'ms':\n return numValue;\n case 's':\n return numValue * 1000;\n case 'm':\n return numValue * 60 * 1000;\n case 'h':\n return numValue * 60 * 60 * 1000;\n case 'd':\n return numValue * 24 * 60 * 60 * 1000;\n default:\n throw new Error(`Unsupported time unit: \"${unit}\"`);\n }\n};\n",
|
|
31
|
-
"import type { ServerOptions } from '@typedefs/public/Configuration.js';\nimport type { InternalLoggingOptions, InternalServerOptions } from '@typedefs/internal/InternalConfiguration.js';\nimport { log, loggerBrand } from '@core/utils/log.ts';\nimport { logLevels } from '@constants/log.ts';\nimport { _convertTimeToMs } from '@core/utils/time.ts';\nimport { _convertBytesToBytes, _formatBytesForDisplay } from '@core/utils/bytes.ts';\n\n/**\n * Default body parser configuration with secure defaults\n */\nconst DEFAULT_BODY_PARSER_CONFIG = {\n json: {\n maxSize: 262144, // 256KB - reasonable for JSON APIs (Express uses 100KB)\n maxDepth: 10, // Prevent deeply nested objects that can cause stack overflow\n allowPrototypeProperties: false, // SECURITY: Block prototype pollution by default\n maxKeys: 1000, // Prevent memory exhaustion from objects with too many keys\n maxStringLength: 1048576, // 1MB per string - prevent memory exhaustion\n maxArrayLength: 10000, // Prevent memory exhaustion from large arrays\n },\n fileUploads: {\n maxFileSize: 10485760, // 10MB per file - reasonable for documents/images\n maxTotalSize: 52428800, // 50MB total - prevent bulk upload attacks\n maxFiles: 10, // Reasonable number of files per request\n allowedExtensions: [], // Empty array = all extensions allowed\n blockedExtensions: ['.exe', '.bat', '.cmd', '.scr', '.pif', '.com'], // Block dangerous executables\n maxFilenameLength: 255, // Standard filesystem limit\n },\n urlEncoded: {\n maxSize: 1048576, // 1MB for form data\n maxFields: 1000, // Prevent field spam attacks\n maxFieldNameLength: 100, // Reasonable field name length\n maxFieldLength: 1048576, // 1MB per field value\n },\n};\n\n/**\n * Default IP security configuration with secure defaults\n */\nconst DEFAULT_IP_SECURITY_CONFIG = {\n trustedProxies: ['127.0.0.1', '::1'], // Localhost only by default\n allowPrivateIps: true, // Allow private IPs for internal usage\n headerPreference: ['x-forwarded-for', 'x-real-ip', 'cf-connecting-ip', 'x-client-ip', 'true-client-ip'],\n maxChainLength: 10, // Reasonable proxy chain length\n detectSpoofing: true, // Enable security by default\n};\n\n/**\n * Default diagnostics configuration — all disabled (zero noise)\n */\nconst DEFAULT_DIAGNOSTICS_CONFIG = {\n slowRequests: false as const,\n largeResponses: false as const,\n largeRequests: false as const,\n memory: false as const,\n eventLoop: false as const,\n rateLimits: false,\n};\n\n/**\n * Default logging configuration\n */\nconst DEFAULT_LOGGING_CONFIG: InternalLoggingOptions = {\n level: 'warn',\n prefix: 'YINZER',\n personality: true,\n requests: false,\n diagnostics: DEFAULT_DIAGNOSTICS_CONFIG,\n};\n\n/**\n * Default configuration object\n */\nconst DEFAULT_CONFIGURATION: InternalServerOptions = {\n port: 5000,\n host: '0.0.0.0',\n gracefulShutdownTimeout: '15m', // Enabled by default\n cors: {\n enabled: false, // Disabled by default\n },\n logging: DEFAULT_LOGGING_CONFIG,\n bodyParser: DEFAULT_BODY_PARSER_CONFIG,\n ipSecurity: DEFAULT_IP_SECURITY_CONFIG,\n};\n\n/**\n * Validate JSON parser configuration minimums\n */\nconst _validateJsonConfig = (config: InternalServerOptions['bodyParser']['json']): void => {\n if (config.maxSize < 1) {\n throw new Error('bodyParser.json.maxSize must be at least 1 byte');\n }\n\n if (config.maxDepth < 1) {\n throw new Error('bodyParser.json.maxDepth must be at least 1');\n }\n\n if (config.maxKeys < 1) {\n throw new Error('bodyParser.json.maxKeys must be at least 1');\n }\n\n if (config.maxStringLength < 1) {\n throw new Error('bodyParser.json.maxStringLength must be at least 1 byte');\n }\n\n if (config.maxArrayLength < 1) {\n throw new Error('bodyParser.json.maxArrayLength must be at least 1');\n }\n};\n\n/**\n * Validate file upload configuration minimums\n */\nconst _validateFileUploadConfig = (config: InternalServerOptions['bodyParser']['fileUploads']): void => {\n if (config.maxFileSize < 1) {\n throw new Error('bodyParser.fileUploads.maxFileSize must be at least 1 byte');\n }\n\n if (config.maxTotalSize < 1) {\n throw new Error('bodyParser.fileUploads.maxTotalSize must be at least 1 byte');\n }\n\n if (config.maxFiles < 1) {\n throw new Error('bodyParser.fileUploads.maxFiles must be at least 1');\n }\n\n if (config.maxFilenameLength < 1) {\n throw new Error('bodyParser.fileUploads.maxFilenameLength must be at least 1 character');\n }\n};\n\n/**\n * Validate URL-encoded configuration minimums\n */\nconst _validateUrlEncodedConfig = (config: InternalServerOptions['bodyParser']['urlEncoded']): void => {\n if (config.maxSize < 1) {\n throw new Error('bodyParser.urlEncoded.maxSize must be at least 1 byte');\n }\n\n if (config.maxFields < 1) {\n throw new Error('bodyParser.urlEncoded.maxFields must be at least 1');\n }\n\n if (config.maxFieldNameLength < 1) {\n throw new Error('bodyParser.urlEncoded.maxFieldNameLength must be at least 1 character');\n }\n\n if (config.maxFieldLength < 1) {\n throw new Error('bodyParser.urlEncoded.maxFieldLength must be at least 1 byte');\n }\n};\n\n/**\n * Validate IP security configuration minimums\n */\nconst _validateIpSecurityConfig = (config: InternalServerOptions['ipSecurity']): void => {\n if (!Array.isArray(config.trustedProxies)) {\n throw new Error('ipSecurity.trustedProxies must be an array');\n }\n\n if (!Array.isArray(config.headerPreference)) {\n throw new Error('ipSecurity.headerPreference must be an array');\n }\n\n if (config.headerPreference.length === 0) {\n throw new Error('ipSecurity.headerPreference must contain at least one header');\n }\n\n if (config.maxChainLength < 1) {\n throw new Error('ipSecurity.maxChainLength must be at least 1');\n }\n\n if (config.maxChainLength > 50) {\n throw new Error('ipSecurity.maxChainLength must not exceed 50 to prevent DoS attacks');\n }\n};\n\n/**\n * Issue security warnings for risky JSON configurations\n */\nconst _warnJsonConfig = (config: InternalServerOptions['bodyParser']['json']): void => {\n if (config.allowPrototypeProperties) {\n log.warn(\n '[SECURITY WARNING] bodyParser.json.allowPrototypeProperties is enabled. This allows prototype pollution attacks. ' +\n 'Only enable this if you absolutely need it and have other protections in place.',\n );\n }\n\n // Warn about very large JSON sizes (but don't block them)\n if (config.maxSize > 10485760) {\n // 10MB\n log.warn(\n `[SECURITY WARNING] bodyParser.json.maxSize is set to ${config.maxSize} bytes (${_formatBytesForDisplay(config.maxSize)}). ` +\n 'Large JSON payloads can cause memory exhaustion and DoS attacks. Consider if this size is necessary.',\n );\n }\n\n // Warn about very deep nesting (but don't block it)\n if (config.maxDepth > 50) {\n log.warn(\n `[SECURITY WARNING] bodyParser.json.maxDepth is set to ${config.maxDepth}. ` +\n 'Very deep JSON nesting can cause stack overflow attacks. Consider if this depth is necessary.',\n );\n }\n};\n\n/**\n * Issue security warnings for risky file upload configurations\n */\nconst _warnFileUploadConfig = (config: InternalServerOptions['bodyParser']['fileUploads']): void => {\n // Warn about very large file uploads (but don't block them)\n if (config.maxFileSize > 104857600) {\n // 100MB\n log.warn(\n `[SECURITY WARNING] bodyParser.fileUploads.maxFileSize is set to ${config.maxFileSize} bytes (${_formatBytesForDisplay(config.maxFileSize)}). ` +\n 'Large file uploads can consume significant server resources.',\n );\n }\n\n if (config.maxTotalSize > 1073741824) {\n // 1GB\n log.warn(\n `[SECURITY WARNING] bodyParser.fileUploads.maxTotalSize is set to ${config.maxTotalSize} bytes (${_formatBytesForDisplay(config.maxTotalSize)}). ` +\n 'Very large total upload sizes can cause memory and disk space exhaustion.',\n );\n }\n\n // Validate file extension security\n const dangerousExtensions = ['.exe', '.bat', '.cmd', '.scr', '.pif', '.com', '.vbs', '.jar', '.app'];\n const allowedDangerous = config.allowedExtensions.filter((ext) => dangerousExtensions.includes(ext.toLowerCase()));\n\n if (allowedDangerous.length > 0) {\n log.warn(\n `[SECURITY WARNING] bodyParser.fileUploads.allowedExtensions includes dangerous file types: ${allowedDangerous.join(', ')}. ` +\n 'This could allow execution of malicious files. Only allow these if absolutely necessary.',\n );\n }\n\n // Warn if no blocked extensions and no allowed extensions (completely open)\n if (config.blockedExtensions.length === 0 && config.allowedExtensions.length === 0) {\n log.warn(\n '[SECURITY WARNING] File uploads have no extension restrictions (no blockedExtensions and no allowedExtensions). ' +\n 'Consider adding blockedExtensions or allowedExtensions to improve security.',\n );\n }\n};\n\n/**\n * Issue security warnings for risky IP security configurations\n */\nconst _warnIpSecurityConfig = (config: InternalServerOptions['ipSecurity']): void => {\n // Warn about wildcard or overly permissive trusted proxies\n if (config.trustedProxies.length === 0) {\n log.warn('[SECURITY WARNING] ipSecurity.trustedProxies is empty. No proxy headers will be trusted, which may prevent proper client IP detection.');\n }\n\n // Warn about very long proxy chains\n if (config.maxChainLength > 20) {\n log.warn(\n `[SECURITY WARNING] ipSecurity.maxChainLength is set to ${config.maxChainLength}. ` +\n 'Very long proxy chains can consume significant resources and may indicate amplification attacks.',\n );\n }\n\n // Warn if spoofing detection is disabled\n if (!config.detectSpoofing) {\n log.warn(\n '[SECURITY WARNING] ipSecurity.detectSpoofing is disabled. ' +\n 'This reduces protection against IP spoofing attacks. Only disable if you have other protective measures.',\n );\n }\n};\n\n/**\n * Handle body parser configuration merging and validation\n */\nconst _handleBodyParserConfig = (defaultConfig: InternalServerOptions, userConfig?: ServerOptions): void => {\n if (userConfig?.bodyParser) {\n defaultConfig.bodyParser = {\n json: {\n ...DEFAULT_BODY_PARSER_CONFIG.json,\n ...userConfig.bodyParser.json,\n },\n fileUploads: {\n ...DEFAULT_BODY_PARSER_CONFIG.fileUploads,\n ...userConfig.bodyParser.fileUploads,\n },\n urlEncoded: {\n ...DEFAULT_BODY_PARSER_CONFIG.urlEncoded,\n ...userConfig.bodyParser.urlEncoded,\n },\n };\n\n // Validate configuration for security\n _validateBodyParserConfig(defaultConfig.bodyParser);\n }\n};\n\n/**\n * Handle IP security configuration merging and validation\n */\nconst _handleIpSecurityConfig = (defaultConfig: InternalServerOptions, userConfig?: ServerOptions): void => {\n if (userConfig?.ipSecurity) {\n defaultConfig.ipSecurity = {\n ...DEFAULT_IP_SECURITY_CONFIG,\n ...userConfig.ipSecurity,\n };\n\n // Validate configuration for security\n _validateIpSecurityConfig(defaultConfig.ipSecurity);\n _warnIpSecurityConfig(defaultConfig.ipSecurity);\n }\n};\n\n/**\n * Validate port number\n */\nconst _validatePort = (defaultConfig: InternalServerOptions, userConfig?: ServerOptions): void => {\n if (userConfig?.port !== undefined) {\n const normalizedPort = Number(userConfig.port);\n if (isNaN(normalizedPort) || normalizedPort < 1 || normalizedPort > 65535) {\n throw new Error('Invalid port number');\n }\n defaultConfig.port = normalizedPort;\n }\n};\n\n/**\n * Validate body parser configuration to prevent broken settings and warn about risky configurations\n */\nconst _validateBodyParserConfig = (config: InternalServerOptions['bodyParser']): void => {\n // Validate minimums for all parser types\n _validateJsonConfig(config.json);\n _validateFileUploadConfig(config.fileUploads);\n _validateUrlEncodedConfig(config.urlEncoded);\n\n // Issue security warnings for risky configurations (but don't block them)\n _warnJsonConfig(config.json);\n _warnFileUploadConfig(config.fileUploads);\n};\n\n/**\n * Valid log level values for validation\n */\nconst VALID_LOG_LEVELS = new Set(Object.values(logLevels));\n\n/**\n * Keys that have dedicated deep-merge handlers in handleCustomConfiguration.\n * These are skipped during the shallow merge pass to avoid clobbering the\n * deep-merged result with a raw user-provided value.\n */\nconst DEEP_MERGE_KEYS = new Set(['logging', 'bodyParser', 'ipSecurity']);\n\n/**\n * Validate a single diagnostic threshold field (TimeString or ByteString).\n * Wraps the converter call, re-throws with a descriptive field-specific message.\n */\nconst _validateThresholdField = (opts: { field: string; value: number | string; converter: (v: never) => number; examples: string }): void => {\n try {\n opts.converter(opts.value as never);\n } catch {\n throw new Error(`logging.diagnostics.${opts.field} must be a valid threshold value (e.g. ${opts.examples}). Got: \"${String(opts.value)}\"`);\n }\n};\n\n/**\n * Validate logging configuration values\n */\nconst _validateLoggingConfig = (config: InternalLoggingOptions): void => {\n if (!VALID_LOG_LEVELS.has(config.level)) {\n throw new Error(`logging.level must be one of: ${[...VALID_LOG_LEVELS].join(', ')}. Got: \"${config.level}\"`);\n }\n\n const diag = config.diagnostics;\n\n // Validate TimeString/number thresholds\n if (diag.slowRequests !== false) {\n _validateThresholdField({ field: 'slowRequests', value: diag.slowRequests, converter: _convertTimeToMs, examples: \"'100ms', '1s', '30s'\" });\n }\n if (diag.memory !== false) {\n _validateThresholdField({ field: 'memory', value: diag.memory, converter: _convertTimeToMs, examples: \"'100ms', '1s', '30s'\" });\n }\n if (diag.eventLoop !== false) {\n _validateThresholdField({ field: 'eventLoop', value: diag.eventLoop, converter: _convertTimeToMs, examples: \"'100ms', '1s', '30s'\" });\n }\n\n // Validate ByteString/number thresholds\n if (diag.largeResponses !== false) {\n _validateThresholdField({ field: 'largeResponses', value: diag.largeResponses, converter: _convertBytesToBytes, examples: \"'1mb', '256kb', '10mb'\" });\n }\n if (diag.largeRequests !== false) {\n _validateThresholdField({ field: 'largeRequests', value: diag.largeRequests, converter: _convertBytesToBytes, examples: \"'1mb', '256kb', '10mb'\" });\n }\n};\n\n/**\n * Handle logging configuration merging and validation\n */\nconst _handleLoggingConfig = (defaultConfig: InternalServerOptions, userConfig?: ServerOptions): void => {\n if (userConfig?.logging) {\n // If the user passed a branded logger (created with createLogger()), inherit its settings.\n // Merge cascade: DEFAULT_LOGGING_CONFIG → branded logger settings → explicit user config\n let brandedDefaults: Partial<InternalLoggingOptions> = {};\n const customLogger = userConfig.logging.logger as Record<string | symbol, unknown> | undefined;\n if (customLogger && loggerBrand in customLogger) {\n const branded = customLogger[loggerBrand] as { level: string; prefix: string; personality: boolean };\n brandedDefaults = {\n level: branded.level as InternalLoggingOptions['level'],\n prefix: branded.prefix,\n personality: branded.personality,\n };\n }\n\n defaultConfig.logging = {\n ...DEFAULT_LOGGING_CONFIG,\n ...brandedDefaults,\n ...userConfig.logging,\n diagnostics: {\n ...DEFAULT_DIAGNOSTICS_CONFIG,\n ...userConfig.logging.diagnostics,\n },\n };\n\n _validateLoggingConfig(defaultConfig.logging);\n }\n};\n\n/**\n * Handle custom configuration\n */\nexport const handleCustomConfiguration = (configuration?: ServerOptions): InternalServerOptions => {\n // Start with default configuration\n const result = { ...DEFAULT_CONFIGURATION };\n\n // Shallow merge — filter out explicit undefined values so they don't overwrite defaults.\n // Without this, `new YinzerFlow({ logging: undefined })` would clobber the default logging config.\n if (configuration) {\n for (const key of Object.keys(configuration)) {\n if (!DEEP_MERGE_KEYS.has(key) && (configuration as Record<string, unknown>)[key] !== undefined) {\n (result as Record<string, unknown>)[key] = (configuration as Record<string, unknown>)[key];\n }\n }\n }\n\n // Handle special configuration sections (deep merge + validation)\n _handleLoggingConfig(result, configuration);\n _handleBodyParserConfig(result, configuration);\n _handleIpSecurityConfig(result, configuration);\n _validatePort(result, configuration);\n\n return result;\n};\n",
|
|
32
|
-
"import { colors } from '@constants/colors.ts';\nimport { httpStatusCode } from '@constants/http.ts';\nimport { log } from '@core/utils/log.ts';\nimport type { InternalGlobalHookOptions, InternalHookRegistryImpl } from '@typedefs/internal/InternalHookRegistryImpl.js';\nimport type { HandlerCallback } from '@typedefs/public/Context.js';\n\nexport class HookRegistryImpl implements InternalHookRegistryImpl {\n readonly _beforeRouting: Set<{\n handler: HandlerCallback;\n options?: InternalGlobalHookOptions;\n }>;\n readonly _beforeAll: Set<{\n handler: HandlerCallback;\n options?: InternalGlobalHookOptions;\n }>;\n readonly _afterAll: Set<{\n handler: HandlerCallback;\n options?: InternalGlobalHookOptions;\n }>;\n _onError: HandlerCallback;\n _onNotFound: HandlerCallback;\n\n /** Per-instance logger. Reads `this._logger` at call time so it picks up the logger set by YinzerFlow. */\n private _logger: { info: (...args: Array<unknown>) => void; warn: (...args: Array<unknown>) => void; error: (...args: Array<unknown>) => void } = log;\n\n /** Called by YinzerFlow._configureLogging() to inject the per-instance logger. */\n setLogger(logger: { info: (...args: Array<unknown>) => void; warn: (...args: Array<unknown>) => void; error: (...args: Array<unknown>) => void }): void {\n this._logger = logger;\n }\n\n constructor() {\n this._beforeRouting = new Set();\n this._beforeAll = new Set();\n this._afterAll = new Set();\n this._onError = (ctx, error: unknown): unknown => {\n this._logger.error('Error while handling your request: ', error);\n ctx.response.setStatusCode(httpStatusCode.internalServerError);\n return { success: false, message: 'Internal Server Error' };\n };\n this._onNotFound = (ctx): unknown => {\n ctx.response.setStatusCode(httpStatusCode.notFound);\n return { success: false, message: '404 Not Found' };\n };\n }\n\n _addBeforeRoutingHooks(handlers: Array<HandlerCallback>, options?: InternalGlobalHookOptions): void {\n this._validateHandlersArray(handlers, 'beforeRouting');\n for (const handler of handlers) this._beforeRouting.add({ handler, options: options ?? { routesToExclude: [], routesToInclude: [] } });\n }\n\n _addBeforeHooks(handlers: Array<HandlerCallback>, options?: InternalGlobalHookOptions): void {\n this._validateHandlersArray(handlers, 'beforeAll');\n for (const handler of handlers) this._beforeAll.add({ handler, options: options ?? { routesToExclude: [], routesToInclude: [] } });\n }\n\n _addAfterHooks(handlers: Array<HandlerCallback>, options?: InternalGlobalHookOptions): void {\n this._validateHandlersArray(handlers, 'afterAll');\n for (const handler of handlers) this._afterAll.add({ handler, options: options ?? { routesToExclude: [], routesToInclude: [] } });\n }\n\n private _validateHandlersArray(handlers: unknown, methodName: string): asserts handlers is Array<HandlerCallback> {\n if (!Array.isArray(handlers)) {\n const receivedType = typeof handlers;\n const isFunction = receivedType === 'function';\n\n throw new Error(\n `YinzerFlow: ${methodName}() expects an array of handler functions, but received ${receivedType}.${\n isFunction ?\n `\\n\\n❌ Incorrect: app.${methodName}${colors.red}(${colors.reset}(ctx) => { ... }${colors.red})${colors.reset}\\n✅ Correct: app.${methodName}${colors.green}([${colors.reset}(ctx) => { ... }${colors.green}])${colors.reset}\\n\\nNote: Wrap your handler function in ${colors.magenta}square brackets${colors.reset} to make it an array.\\n\\n`\n : `\\n\\n Expected: Array<HandlerCallback>\\n Received: ${receivedType}`\n }`,\n );\n }\n\n if (handlers.length === 0) {\n this._logger.warn(`${methodName}() called with empty array. No hooks will be registered.`);\n return;\n }\n\n for (let i = 0; i < handlers.length; i++) {\n const handler = handlers[i] as unknown;\n if (typeof handler !== 'function') {\n throw new Error(`YinzerFlow: ${methodName}() array contains non-function at index ${i}. Expected: function, received: ${typeof handler}`);\n }\n }\n }\n\n _addOnError(handler: HandlerCallback): void {\n this._onError = handler;\n }\n\n _addOnNotFound(handler: HandlerCallback): void {\n this._onNotFound = handler;\n }\n}\n",
|
|
32
|
+
"import type { ServerOptions } from '@typedefs/public/Configuration.js';\nimport type { InternalLoggingOptions, InternalServerOptions, InternalWebSocketOptions } from '@typedefs/internal/InternalConfiguration.js';\nimport { DEFAULT_WEBSOCKET_CONFIG, _validateWebSocketConfig, _warnWebSocketConfig } from '@core/modules/websocket/WebSocketConfig.ts';\nimport { log, loggerBrand } from '@core/utils/log.ts';\nimport { logLevels } from '@constants/log.ts';\nimport { _convertTimeToMs } from '@core/utils/time.ts';\nimport { _convertBytesToBytes, _formatBytesForDisplay } from '@core/utils/bytes.ts';\n\n/**\n * Default body parser configuration with secure defaults\n */\nconst DEFAULT_BODY_PARSER_CONFIG = {\n json: {\n maxSize: 262144, // 256KB - reasonable for JSON APIs (Express uses 100KB)\n maxDepth: 10, // Prevent deeply nested objects that can cause stack overflow\n allowPrototypeProperties: false, // SECURITY: Block prototype pollution by default\n maxKeys: 1000, // Prevent memory exhaustion from objects with too many keys\n maxStringLength: 1048576, // 1MB per string - prevent memory exhaustion\n maxArrayLength: 10000, // Prevent memory exhaustion from large arrays\n },\n fileUploads: {\n maxFileSize: 10485760, // 10MB per file - reasonable for documents/images\n maxTotalSize: 52428800, // 50MB total - prevent bulk upload attacks\n maxFiles: 10, // Reasonable number of files per request\n allowedExtensions: [], // Empty array = all extensions allowed\n blockedExtensions: ['.exe', '.bat', '.cmd', '.scr', '.pif', '.com'], // Block dangerous executables\n maxFilenameLength: 255, // Standard filesystem limit\n },\n urlEncoded: {\n maxSize: 1048576, // 1MB for form data\n maxFields: 1000, // Prevent field spam attacks\n maxFieldNameLength: 100, // Reasonable field name length\n maxFieldLength: 1048576, // 1MB per field value\n },\n};\n\n/**\n * Default IP security configuration with secure defaults\n */\nconst DEFAULT_IP_SECURITY_CONFIG = {\n trustedProxies: ['127.0.0.1', '::1'], // Localhost only by default\n allowPrivateIps: true, // Allow private IPs for internal usage\n headerPreference: ['x-forwarded-for', 'x-real-ip', 'cf-connecting-ip', 'x-client-ip', 'true-client-ip'],\n maxChainLength: 10, // Reasonable proxy chain length\n detectSpoofing: true, // Enable security by default\n};\n\n/**\n * Default diagnostics configuration — all disabled (zero noise)\n */\nconst DEFAULT_DIAGNOSTICS_CONFIG = {\n slowRequests: false as const,\n largeResponses: false as const,\n largeRequests: false as const,\n memory: false as const,\n eventLoop: false as const,\n rateLimits: false,\n};\n\n/**\n * Default logging configuration\n */\nconst DEFAULT_LOGGING_CONFIG: InternalLoggingOptions = {\n level: 'warn',\n prefix: 'YINZER',\n personality: true,\n requests: false,\n diagnostics: DEFAULT_DIAGNOSTICS_CONFIG,\n};\n\n/**\n * Default configuration object\n */\nconst DEFAULT_CONFIGURATION: InternalServerOptions = {\n port: 5000,\n host: '0.0.0.0',\n gracefulShutdownTimeout: '15m', // Enabled by default\n cors: {\n enabled: false, // Disabled by default\n },\n logging: DEFAULT_LOGGING_CONFIG,\n bodyParser: DEFAULT_BODY_PARSER_CONFIG,\n ipSecurity: DEFAULT_IP_SECURITY_CONFIG,\n websocket: DEFAULT_WEBSOCKET_CONFIG,\n};\n\n/**\n * Validate JSON parser configuration minimums\n */\nconst _validateJsonConfig = (config: InternalServerOptions['bodyParser']['json']): void => {\n if (config.maxSize < 1) {\n throw new Error('bodyParser.json.maxSize must be at least 1 byte');\n }\n\n if (config.maxDepth < 1) {\n throw new Error('bodyParser.json.maxDepth must be at least 1');\n }\n\n if (config.maxKeys < 1) {\n throw new Error('bodyParser.json.maxKeys must be at least 1');\n }\n\n if (config.maxStringLength < 1) {\n throw new Error('bodyParser.json.maxStringLength must be at least 1 byte');\n }\n\n if (config.maxArrayLength < 1) {\n throw new Error('bodyParser.json.maxArrayLength must be at least 1');\n }\n};\n\n/**\n * Validate file upload configuration minimums\n */\nconst _validateFileUploadConfig = (config: InternalServerOptions['bodyParser']['fileUploads']): void => {\n if (config.maxFileSize < 1) {\n throw new Error('bodyParser.fileUploads.maxFileSize must be at least 1 byte');\n }\n\n if (config.maxTotalSize < 1) {\n throw new Error('bodyParser.fileUploads.maxTotalSize must be at least 1 byte');\n }\n\n if (config.maxFiles < 1) {\n throw new Error('bodyParser.fileUploads.maxFiles must be at least 1');\n }\n\n if (config.maxFilenameLength < 1) {\n throw new Error('bodyParser.fileUploads.maxFilenameLength must be at least 1 character');\n }\n};\n\n/**\n * Validate URL-encoded configuration minimums\n */\nconst _validateUrlEncodedConfig = (config: InternalServerOptions['bodyParser']['urlEncoded']): void => {\n if (config.maxSize < 1) {\n throw new Error('bodyParser.urlEncoded.maxSize must be at least 1 byte');\n }\n\n if (config.maxFields < 1) {\n throw new Error('bodyParser.urlEncoded.maxFields must be at least 1');\n }\n\n if (config.maxFieldNameLength < 1) {\n throw new Error('bodyParser.urlEncoded.maxFieldNameLength must be at least 1 character');\n }\n\n if (config.maxFieldLength < 1) {\n throw new Error('bodyParser.urlEncoded.maxFieldLength must be at least 1 byte');\n }\n};\n\n/**\n * Validate IP security configuration minimums\n */\nconst _validateIpSecurityConfig = (config: InternalServerOptions['ipSecurity']): void => {\n if (!Array.isArray(config.trustedProxies)) {\n throw new Error('ipSecurity.trustedProxies must be an array');\n }\n\n if (!Array.isArray(config.headerPreference)) {\n throw new Error('ipSecurity.headerPreference must be an array');\n }\n\n if (config.headerPreference.length === 0) {\n throw new Error('ipSecurity.headerPreference must contain at least one header');\n }\n\n if (config.maxChainLength < 1) {\n throw new Error('ipSecurity.maxChainLength must be at least 1');\n }\n\n if (config.maxChainLength > 50) {\n throw new Error('ipSecurity.maxChainLength must not exceed 50 to prevent DoS attacks');\n }\n};\n\n/**\n * Issue security warnings for risky JSON configurations\n */\nconst _warnJsonConfig = (config: InternalServerOptions['bodyParser']['json']): void => {\n if (config.allowPrototypeProperties) {\n log.warn(\n '[SECURITY WARNING] bodyParser.json.allowPrototypeProperties is enabled. This allows prototype pollution attacks. ' +\n 'Only enable this if you absolutely need it and have other protections in place.',\n );\n }\n\n // Warn about very large JSON sizes (but don't block them)\n if (config.maxSize > 10485760) {\n // 10MB\n log.warn(\n `[SECURITY WARNING] bodyParser.json.maxSize is set to ${config.maxSize} bytes (${_formatBytesForDisplay(config.maxSize)}). ` +\n 'Large JSON payloads can cause memory exhaustion and DoS attacks. Consider if this size is necessary.',\n );\n }\n\n // Warn about very deep nesting (but don't block it)\n if (config.maxDepth > 50) {\n log.warn(\n `[SECURITY WARNING] bodyParser.json.maxDepth is set to ${config.maxDepth}. ` +\n 'Very deep JSON nesting can cause stack overflow attacks. Consider if this depth is necessary.',\n );\n }\n};\n\n/**\n * Issue security warnings for risky file upload configurations\n */\nconst _warnFileUploadConfig = (config: InternalServerOptions['bodyParser']['fileUploads']): void => {\n // Warn about very large file uploads (but don't block them)\n if (config.maxFileSize > 104857600) {\n // 100MB\n log.warn(\n `[SECURITY WARNING] bodyParser.fileUploads.maxFileSize is set to ${config.maxFileSize} bytes (${_formatBytesForDisplay(config.maxFileSize)}). ` +\n 'Large file uploads can consume significant server resources.',\n );\n }\n\n if (config.maxTotalSize > 1073741824) {\n // 1GB\n log.warn(\n `[SECURITY WARNING] bodyParser.fileUploads.maxTotalSize is set to ${config.maxTotalSize} bytes (${_formatBytesForDisplay(config.maxTotalSize)}). ` +\n 'Very large total upload sizes can cause memory and disk space exhaustion.',\n );\n }\n\n // Validate file extension security\n const dangerousExtensions = ['.exe', '.bat', '.cmd', '.scr', '.pif', '.com', '.vbs', '.jar', '.app'];\n const allowedDangerous = config.allowedExtensions.filter((ext) => dangerousExtensions.includes(ext.toLowerCase()));\n\n if (allowedDangerous.length > 0) {\n log.warn(\n `[SECURITY WARNING] bodyParser.fileUploads.allowedExtensions includes dangerous file types: ${allowedDangerous.join(', ')}. ` +\n 'This could allow execution of malicious files. Only allow these if absolutely necessary.',\n );\n }\n\n // Warn if no blocked extensions and no allowed extensions (completely open)\n if (config.blockedExtensions.length === 0 && config.allowedExtensions.length === 0) {\n log.warn(\n '[SECURITY WARNING] File uploads have no extension restrictions (no blockedExtensions and no allowedExtensions). ' +\n 'Consider adding blockedExtensions or allowedExtensions to improve security.',\n );\n }\n};\n\n/**\n * Issue security warnings for risky IP security configurations\n */\nconst _warnIpSecurityConfig = (config: InternalServerOptions['ipSecurity']): void => {\n // Warn about wildcard or overly permissive trusted proxies\n if (config.trustedProxies.length === 0) {\n log.warn('[SECURITY WARNING] ipSecurity.trustedProxies is empty. No proxy headers will be trusted, which may prevent proper client IP detection.');\n }\n\n // Warn about very long proxy chains\n if (config.maxChainLength > 20) {\n log.warn(\n `[SECURITY WARNING] ipSecurity.maxChainLength is set to ${config.maxChainLength}. ` +\n 'Very long proxy chains can consume significant resources and may indicate amplification attacks.',\n );\n }\n\n // Warn if spoofing detection is disabled\n if (!config.detectSpoofing) {\n log.warn(\n '[SECURITY WARNING] ipSecurity.detectSpoofing is disabled. ' +\n 'This reduces protection against IP spoofing attacks. Only disable if you have other protective measures.',\n );\n }\n};\n\n/**\n * Handle body parser configuration merging and validation\n */\nconst _handleBodyParserConfig = (defaultConfig: InternalServerOptions, userConfig?: ServerOptions): void => {\n if (userConfig?.bodyParser) {\n defaultConfig.bodyParser = {\n json: {\n ...DEFAULT_BODY_PARSER_CONFIG.json,\n ...userConfig.bodyParser.json,\n },\n fileUploads: {\n ...DEFAULT_BODY_PARSER_CONFIG.fileUploads,\n ...userConfig.bodyParser.fileUploads,\n },\n urlEncoded: {\n ...DEFAULT_BODY_PARSER_CONFIG.urlEncoded,\n ...userConfig.bodyParser.urlEncoded,\n },\n };\n\n // Validate configuration for security\n _validateBodyParserConfig(defaultConfig.bodyParser);\n }\n};\n\n/**\n * Handle IP security configuration merging and validation\n */\nconst _handleIpSecurityConfig = (defaultConfig: InternalServerOptions, userConfig?: ServerOptions): void => {\n if (userConfig?.ipSecurity) {\n defaultConfig.ipSecurity = {\n ...DEFAULT_IP_SECURITY_CONFIG,\n ...userConfig.ipSecurity,\n };\n\n // Validate configuration for security\n _validateIpSecurityConfig(defaultConfig.ipSecurity);\n _warnIpSecurityConfig(defaultConfig.ipSecurity);\n }\n};\n\n/**\n * Validate port number\n */\nconst _validatePort = (defaultConfig: InternalServerOptions, userConfig?: ServerOptions): void => {\n if (userConfig?.port !== undefined) {\n const normalizedPort = Number(userConfig.port);\n if (isNaN(normalizedPort) || normalizedPort < 1 || normalizedPort > 65535) {\n throw new Error('Invalid port number');\n }\n defaultConfig.port = normalizedPort;\n }\n};\n\n/**\n * Validate body parser configuration to prevent broken settings and warn about risky configurations\n */\nconst _validateBodyParserConfig = (config: InternalServerOptions['bodyParser']): void => {\n // Validate minimums for all parser types\n _validateJsonConfig(config.json);\n _validateFileUploadConfig(config.fileUploads);\n _validateUrlEncodedConfig(config.urlEncoded);\n\n // Issue security warnings for risky configurations (but don't block them)\n _warnJsonConfig(config.json);\n _warnFileUploadConfig(config.fileUploads);\n};\n\n/**\n * Valid log level values for validation\n */\nconst VALID_LOG_LEVELS = new Set(Object.values(logLevels));\n\n/**\n * Keys that have dedicated deep-merge handlers in handleCustomConfiguration.\n * These are skipped during the shallow merge pass to avoid clobbering the\n * deep-merged result with a raw user-provided value.\n */\nconst DEEP_MERGE_KEYS = new Set(['logging', 'bodyParser', 'ipSecurity', 'websocket']);\n\n/**\n * Validate a single diagnostic threshold field (TimeString or ByteString).\n * Wraps the converter call, re-throws with a descriptive field-specific message.\n */\nconst _validateThresholdField = (opts: { field: string; value: number | string; converter: (v: never) => number; examples: string }): void => {\n try {\n opts.converter(opts.value as never);\n } catch {\n throw new Error(`logging.diagnostics.${opts.field} must be a valid threshold value (e.g. ${opts.examples}). Got: \"${String(opts.value)}\"`);\n }\n};\n\n/**\n * Validate logging configuration values\n */\nconst _validateLoggingConfig = (config: InternalLoggingOptions): void => {\n if (!VALID_LOG_LEVELS.has(config.level)) {\n throw new Error(`logging.level must be one of: ${[...VALID_LOG_LEVELS].join(', ')}. Got: \"${config.level}\"`);\n }\n\n const diag = config.diagnostics;\n\n // Validate TimeString/number thresholds\n if (diag.slowRequests !== false) {\n _validateThresholdField({ field: 'slowRequests', value: diag.slowRequests, converter: _convertTimeToMs, examples: \"'100ms', '1s', '30s'\" });\n }\n if (diag.memory !== false) {\n _validateThresholdField({ field: 'memory', value: diag.memory, converter: _convertTimeToMs, examples: \"'100ms', '1s', '30s'\" });\n }\n if (diag.eventLoop !== false) {\n _validateThresholdField({ field: 'eventLoop', value: diag.eventLoop, converter: _convertTimeToMs, examples: \"'100ms', '1s', '30s'\" });\n }\n\n // Validate ByteString/number thresholds\n if (diag.largeResponses !== false) {\n _validateThresholdField({ field: 'largeResponses', value: diag.largeResponses, converter: _convertBytesToBytes, examples: \"'1mb', '256kb', '10mb'\" });\n }\n if (diag.largeRequests !== false) {\n _validateThresholdField({ field: 'largeRequests', value: diag.largeRequests, converter: _convertBytesToBytes, examples: \"'1mb', '256kb', '10mb'\" });\n }\n};\n\n/**\n * Handle logging configuration merging and validation\n */\nconst _handleLoggingConfig = (defaultConfig: InternalServerOptions, userConfig?: ServerOptions): void => {\n if (userConfig?.logging) {\n // If the user passed a branded logger (created with createLogger()), inherit its settings.\n // Merge cascade: DEFAULT_LOGGING_CONFIG → branded logger settings → explicit user config\n let brandedDefaults: Partial<InternalLoggingOptions> = {};\n const customLogger = userConfig.logging.logger as Record<string | symbol, unknown> | undefined;\n if (customLogger && loggerBrand in customLogger) {\n const branded = customLogger[loggerBrand] as { level: string; prefix: string; personality: boolean };\n brandedDefaults = {\n level: branded.level as InternalLoggingOptions['level'],\n prefix: branded.prefix,\n personality: branded.personality,\n };\n }\n\n defaultConfig.logging = {\n ...DEFAULT_LOGGING_CONFIG,\n ...brandedDefaults,\n ...userConfig.logging,\n diagnostics: {\n ...DEFAULT_DIAGNOSTICS_CONFIG,\n ...userConfig.logging.diagnostics,\n },\n };\n\n _validateLoggingConfig(defaultConfig.logging);\n }\n};\n\n/**\n * Handle WebSocket configuration merging and validation\n */\nconst _handleWebSocketConfig = (defaultConfig: InternalServerOptions, userConfig?: ServerOptions): void => {\n if (userConfig?.websocket) {\n const merged: InternalWebSocketOptions = {\n ...DEFAULT_WEBSOCKET_CONFIG,\n ...userConfig.websocket,\n backpressure: {\n ...DEFAULT_WEBSOCKET_CONFIG.backpressure,\n ...userConfig.websocket.backpressure,\n },\n };\n defaultConfig.websocket = merged;\n _validateWebSocketConfig(merged);\n _warnWebSocketConfig(merged);\n }\n};\n\n/**\n * Handle custom configuration\n */\nexport const handleCustomConfiguration = (configuration?: ServerOptions): InternalServerOptions => {\n // Start with default configuration\n const result = { ...DEFAULT_CONFIGURATION };\n\n // Shallow merge — filter out explicit undefined values so they don't overwrite defaults.\n // Without this, `new YinzerFlow({ logging: undefined })` would clobber the default logging config.\n if (configuration) {\n for (const key of Object.keys(configuration)) {\n if (!DEEP_MERGE_KEYS.has(key) && (configuration as Record<string, unknown>)[key] !== undefined) {\n (result as Record<string, unknown>)[key] = (configuration as Record<string, unknown>)[key];\n }\n }\n }\n\n // Handle special configuration sections (deep merge + validation)\n _handleLoggingConfig(result, configuration);\n _handleBodyParserConfig(result, configuration);\n _handleIpSecurityConfig(result, configuration);\n _handleWebSocketConfig(result, configuration);\n _validatePort(result, configuration);\n\n return result;\n};\n",
|
|
33
|
+
"import { colors } from '@constants/colors.ts';\nimport { httpStatusCode } from '@constants/http.ts';\nimport { log } from '@core/utils/log.ts';\nimport type { InternalGlobalHookOptions, InternalHookRegistryImpl } from '@typedefs/internal/InternalHookRegistryImpl.js';\nimport type { HandlerCallback } from '@typedefs/public/Context.js';\nimport type { WebSocketMessageHook } from '@typedefs/public/WebSocket.js';\n\nexport class HookRegistryImpl implements InternalHookRegistryImpl {\n readonly _beforeRouting: Set<{\n handler: HandlerCallback;\n options?: InternalGlobalHookOptions;\n }>;\n readonly _beforeAll: Set<{\n handler: HandlerCallback;\n options?: InternalGlobalHookOptions;\n }>;\n readonly _afterAll: Set<{\n handler: HandlerCallback;\n options?: InternalGlobalHookOptions;\n }>;\n readonly _wsBeforeMessage: Set<{ handler: WebSocketMessageHook }>;\n readonly _wsAfterMessage: Set<{ handler: WebSocketMessageHook }>;\n _onError: HandlerCallback;\n _onNotFound: HandlerCallback;\n\n /** Per-instance logger. Reads `this._logger` at call time so it picks up the logger set by YinzerFlow. */\n private _logger: { info: (...args: Array<unknown>) => void; warn: (...args: Array<unknown>) => void; error: (...args: Array<unknown>) => void } = log;\n\n /** Called by YinzerFlow._configureLogging() to inject the per-instance logger. */\n setLogger(logger: { info: (...args: Array<unknown>) => void; warn: (...args: Array<unknown>) => void; error: (...args: Array<unknown>) => void }): void {\n this._logger = logger;\n }\n\n constructor() {\n this._beforeRouting = new Set();\n this._beforeAll = new Set();\n this._afterAll = new Set();\n this._wsBeforeMessage = new Set();\n this._wsAfterMessage = new Set();\n this._onError = (ctx, error: unknown): unknown => {\n this._logger.error('Error while handling your request: ', error);\n ctx.response.setStatusCode(httpStatusCode.internalServerError);\n return { success: false, message: 'Internal Server Error' };\n };\n this._onNotFound = (ctx): unknown => {\n ctx.response.setStatusCode(httpStatusCode.notFound);\n return { success: false, message: '404 Not Found' };\n };\n }\n\n _addBeforeRoutingHooks(handlers: Array<HandlerCallback>, options?: InternalGlobalHookOptions): void {\n this._validateHandlersArray(handlers, 'beforeRouting');\n for (const handler of handlers) this._beforeRouting.add({ handler, options: options ?? { routesToExclude: [], routesToInclude: [] } });\n }\n\n _addBeforeHooks(handlers: Array<HandlerCallback>, options?: InternalGlobalHookOptions): void {\n this._validateHandlersArray(handlers, 'beforeAll');\n for (const handler of handlers) this._beforeAll.add({ handler, options: options ?? { routesToExclude: [], routesToInclude: [] } });\n }\n\n _addAfterHooks(handlers: Array<HandlerCallback>, options?: InternalGlobalHookOptions): void {\n this._validateHandlersArray(handlers, 'afterAll');\n for (const handler of handlers) this._afterAll.add({ handler, options: options ?? { routesToExclude: [], routesToInclude: [] } });\n }\n\n _addWsBeforeMessageHooks(handlers: Array<WebSocketMessageHook>): void {\n this._validateHandlersArray(handlers as unknown as Array<HandlerCallback>, 'wsBeforeMessage');\n for (const handler of handlers) this._wsBeforeMessage.add({ handler });\n }\n\n _addWsAfterMessageHooks(handlers: Array<WebSocketMessageHook>): void {\n this._validateHandlersArray(handlers as unknown as Array<HandlerCallback>, 'wsAfterMessage');\n for (const handler of handlers) this._wsAfterMessage.add({ handler });\n }\n\n private _validateHandlersArray(handlers: unknown, methodName: string): asserts handlers is Array<HandlerCallback> {\n if (!Array.isArray(handlers)) {\n const receivedType = typeof handlers;\n const isFunction = receivedType === 'function';\n\n throw new Error(\n `YinzerFlow: ${methodName}() expects an array of handler functions, but received ${receivedType}.${\n isFunction ?\n `\\n\\n❌ Incorrect: app.${methodName}${colors.red}(${colors.reset}(ctx) => { ... }${colors.red})${colors.reset}\\n✅ Correct: app.${methodName}${colors.green}([${colors.reset}(ctx) => { ... }${colors.green}])${colors.reset}\\n\\nNote: Wrap your handler function in ${colors.magenta}square brackets${colors.reset} to make it an array.\\n\\n`\n : `\\n\\n Expected: Array<HandlerCallback>\\n Received: ${receivedType}`\n }`,\n );\n }\n\n if (handlers.length === 0) {\n this._logger.warn(`${methodName}() called with empty array. No hooks will be registered.`);\n return;\n }\n\n for (let i = 0; i < handlers.length; i++) {\n const handler = handlers[i] as unknown;\n if (typeof handler !== 'function') {\n throw new Error(`YinzerFlow: ${methodName}() array contains non-function at index ${i}. Expected: function, received: ${typeof handler}`);\n }\n }\n }\n\n _addOnError(handler: HandlerCallback): void {\n this._onError = handler;\n }\n\n _addOnNotFound(handler: HandlerCallback): void {\n this._onNotFound = handler;\n }\n}\n",
|
|
33
34
|
"import type { InternalPreCompiledRoute, InternalRouteRegistry } from '@typedefs/internal/InternalRouteRegistryImpl.d.ts';\n\n/**\n * Compile a route pattern into a regular expression\n *\n * @example\n * ```ts\n * compileRoutePattern({ path: '/users/:id/posts/:postId' });\n * // Returns { pattern: /^users\\/([^/]+)\\/posts\\/([^/]+)$/, paramNames: ['id', 'postId'], isParameterized: true }\n * ```\n */\nexport const compileRoutePattern = (route: InternalRouteRegistry): InternalPreCompiledRoute => {\n const paramNames: Array<string> = [];\n\n // Convert route pattern to regex with capture groups\n // Example: /users/:id/posts/:postId → /users/([^/]+)/posts/([^/]+)\n const pattern = route.path\n .replace(/:\\w+/g, (match) => {\n const paramName = match.slice(1); // Remove the ':' prefix\n paramNames.push(paramName);\n return '([^/]+)'; // Capture group: match any characters except '/'\n })\n .replace(/\\//g, '\\\\/'); // Escape forward slashes for regex\n\n return {\n ...route,\n pattern: new RegExp(`^${pattern}$`), // ^ and $ ensure full string match\n paramNames,\n isParameterized: true,\n };\n};\n",
|
|
34
35
|
"import { log } from '@core/utils/log.ts';\n\n/**\n * Normalize the path to ensure consistent format\n *\n * Handles common HTTP path variations for consistent route matching:\n * - Always starts with '/'\n * - No double slashes\n * - Consistent trailing slash handling\n * - Strips query parameters (for route matching)\n * - URL decodes encoded characters\n * - Resolves dot segments for security\n *\n * Examples:\n * - \"users\" → \"/users\"\n * - \"//users\" → \"/users\"\n * - \"/users/\" → \"/users\" (consistent - no trailing slash)\n * - \"/users?page=1\" → \"/users\"\n * - \"/users%20profile\" → \"/users profile\"\n * - \"/users/../admin\" → \"/admin\" (dot segment resolved)\n * - \"/api/./users\" → \"/api/users\" (current dir resolved)\n *\n * @example\n * ```ts\n * normalizePath('users');\n * // Returns \"/users\"\n * ```\n */\nexport const normalizePath = (path: string): string => {\n // Step 1: Strip query parameters and fragments for route matching\n // \"/users?page=1#section\" → \"/users\"\n let [normalizedPath] = path.split('?');\n if (!normalizedPath) return '';\n\n [normalizedPath] = normalizedPath.split('#');\n if (!normalizedPath) return '';\n\n // Step 2: URL decode encoded characters\n // \"/users%20profile\" → \"/users profile\"\n try {\n normalizedPath = decodeURIComponent(normalizedPath);\n } catch (_) {\n // If decoding fails (malformed URL), use original\n // This prevents crashes from malicious URLs\n log.warn('Failed to decode URL path', { path: normalizedPath });\n }\n\n // Step 3: Add leading slash if not present\n // \"users\" → \"/users\"\n normalizedPath = normalizedPath.startsWith('/') ? normalizedPath : `/${normalizedPath}`;\n\n // Step 4: Remove double slashes\n // \"//users\" → \"/users\"\n normalizedPath = normalizedPath.replace(/\\/\\/+/g, '/');\n\n // Step 5: Resolve dot segments for security and consistency\n // SECURITY CRITICAL: Prevents directory traversal attacks\n // \"/users/../admin\" → \"/admin\"\n // \"/api/./users\" → \"/api/users\"\n // \"/users/../../etc/passwd\" → \"/etc/passwd\" (contained within app context)\n normalizedPath = resolveDotSegments(normalizedPath);\n\n // Step 6: Remove trailing slash for consistency (except root path)\n // \"/users/\" → \"/users\", but \"/\" stays \"/\"\n if (normalizedPath.length > 1 && normalizedPath.endsWith('/')) {\n normalizedPath = normalizedPath.slice(0, -1);\n }\n\n return normalizedPath;\n};\n\n/**\n * Resolve dot segments according to RFC 3986 Section 5.2.4\n *\n * SECURITY PURPOSE: Prevents directory traversal attacks by resolving relative paths\n *\n * Dot segments are dangerous because they allow attackers to:\n * - Bypass access controls: \"/users/../admin\" → \"/admin\"\n * - Access system files: \"/api/../../etc/passwd\" → \"/etc/passwd\"\n * - Traverse outside intended directories\n *\n * ALGORITHM:\n * - \".\" (current directory) → remove completely\n * - \"..\" (parent directory) → remove this segment AND the previous segment\n * - Regular segments → keep as-is\n *\n * Examples:\n * - \"/users/./profile\" → \"/users/profile\"\n * - \"/users/../admin\" → \"/admin\"\n * - \"/a/b/c/../../d\" → \"/a/d\"\n * - \"/../secret\" → \"/secret\" (can't go above root)\n *\n * @param path - Path with potential dot segments\n * @returns Path with dot segments resolved\n */\nconst resolveDotSegments = (path: string): string => {\n // Split path into segments, preserving empty strings from leading slash\n const segments = path.split('/');\n const resolved: Array<string> = [];\n\n for (const segment of segments) {\n if (segment === '.' || segment === '') {\n // Current directory \".\" - skip completely\n // Empty segments from double slashes - also skip\n if (segment === '' && resolved.length === 0) {\n // Keep the first empty segment to maintain leading slash\n resolved.push(segment);\n }\n continue;\n }\n\n if (segment === '..') {\n // Parent directory \"..\" - go up one level\n if (resolved.length > 1) {\n // Remove last segment (go to parent)\n // But don't remove the leading empty string (which represents root \"/\")\n resolved.pop();\n }\n // If we're already at root, ignore \"..\" (can't go above root)\n } else {\n // Regular segment - keep it\n resolved.push(segment);\n }\n }\n\n // Rejoin segments\n const result = resolved.join('/');\n\n // Ensure we always have at least \"/\" for root\n return result || '/';\n};\n\n/**\n * Normalize route structure for conflict detection\n * Converts /users/:id and /users/:userId to the same structure: /users/:param\n */\nexport const normalizeRouteStructure = (path: string): string => path.replace(/:\\w+/g, ':param');\n",
|
|
35
36
|
"/**\n * Validate that parameter names are unique within a single route\n *\n * WHY THIS MATTERS:\n * - Routes like \"/users/:id/jobs/:id\" are confusing and error-prone\n * - Multiple params with same name would overwrite each other: { id: \"lastValue\" }\n * - Forces developers to use descriptive, unique names: \"/users/:userId/jobs/:jobId\"\n * - Makes code self-documenting and prevents runtime bugs\n *\n * EXAMPLES OF PROBLEMS THIS PREVENTS:\n * - Bad: \"/users/:id/posts/:id\" → unclear which :id refers to what\n * - Good: \"/users/:userId/posts/:postId\" → crystal clear intent\n *\n * @example\n * ```ts\n * validateParameterNames('/users/:id/posts/:id');\n * // Throws error: \"Route /users/:id/posts/:id has duplicate parameter names: id. Parameter names must be unique within a route for clarity and to prevent conflicts.\"\n * ```\n */\nexport const validateParameterNames = (routePath: string): void => {\n // Extract all parameter names from the route\n // \"/users/:userId/posts/:postId\" → [\":userId\", \":postId\"] → [\"userId\", \"postId\"]\n const paramMatches = routePath.match(/:\\w+/g);\n if (!paramMatches) return; // No parameters to validate\n\n const paramNames = paramMatches.map((param) => param.slice(1)); // Remove ':' prefix\n const uniqueParamNames = new Set(paramNames);\n\n // Check for duplicates\n if (paramNames.length !== uniqueParamNames.size) {\n const duplicates = paramNames.filter((name, index) => paramNames.indexOf(name) !== index);\n throw new Error(\n `Route ${routePath} has duplicate parameter names: ${duplicates.join(', ')}. ` +\n 'Parameter names must be unique within a route for clarity and to prevent conflicts.',\n );\n }\n};\n",
|
|
36
37
|
"import { compileRoutePattern } from '@core/setup/utils/compileRoutePatter.ts';\nimport { normalizePath, normalizeRouteStructure } from '@core/setup/utils/normalizeStringPatterns.ts';\nimport { validateParameterNames } from '@core/setup/utils/validateParameterNames.ts';\nimport type { InternalHttpMethod } from '@typedefs/constants/http.ts';\nimport type { InternalPreCompiledRoute, InternalRouteRegistry, InternalRouteRegistryImpl } from '@typedefs/internal/InternalRouteRegistryImpl.js';\n\n/**\n * RouteRegistry: Efficient route storage and matching\n *\n * DESIGN DECISION: Parameter extraction happens here (not in RequestImpl) because:\n * 1. We already compile regexes for route matching - reusing them for param extraction is free\n * 2. Avoids duplicate regex compilation at request time (performance critical)\n * 3. Single source of truth for route patterns and their compiled forms\n *\n * PERFORMANCE STRATEGY:\n * - Exact routes (no params): O(1) Map lookup\n * - Parameterized routes: O(n) iteration with pre-compiled regex matching\n * - Most apps have few parameterized routes, so O(n) is acceptable\n *\n * EXAMPLES:\n * - \"/users\" (exact) → stored in exactRoutes Map for instant lookup\n * - \"/users/:id\" (parameterized) → compiled to regex, stored in parameterizedRoutes Array\n */\nexport class RouteRegistryImpl implements InternalRouteRegistryImpl {\n /**\n * Fast O(1) lookup for routes without parameters\n * Example: GET /users, POST /login, etc.\n */\n readonly _exactRoutes = new Map<InternalHttpMethod, Map<string, InternalRouteRegistry>>();\n\n /**\n * Array of pre-compiled parameterized routes for O(n) matching\n * Example: GET /users/:id, POST /users/:id/posts/:postId, etc.\n *\n * We use an array because:\n * 1. Route patterns can't be used as Map keys (they're not exact matches)\n * 2. Most apps have relatively few parameterized routes\n * 3. Pre-compiled regexes make matching fast\n */\n readonly _parameterizedRoutes = new Map<InternalHttpMethod, Array<InternalPreCompiledRoute>>();\n\n /**\n * Register a new route\n *\n * PERFORMANCE NOTE: This happens at server startup, so we can afford\n * more expensive operations like regex compilation here.\n */\n _register({ method, path, handler, options }: InternalRouteRegistry): void {\n const normalizedPath = normalizePath(path);\n const isParameterized = normalizedPath.includes(':');\n\n // Validate route before registration\n if (isParameterized) {\n validateParameterNames(normalizedPath);\n }\n\n // Prevent duplicate route registration\n // We check for exact pattern duplicates, not request path matches\n if (this._hasExactRoutePattern(method, normalizedPath)) {\n throw new Error(`Route ${normalizedPath} already exists for method ${method}`);\n }\n\n const route = { method, path: normalizedPath, handler, options, params: {} };\n\n if (isParameterized) {\n // Store in parameterized routes with pre-compiled regex\n this._storeParameterizedRoute(method, route);\n } else {\n // Store in exact routes for O(1) lookup\n this._storeExactRoute(method, normalizedPath, route);\n }\n }\n\n /**\n * Find a route and extract parameters from the request path\n *\n * RUNTIME PERFORMANCE: This is called for every HTTP request, so it must be fast!\n * 1. Try exact match first (O(1) - fastest case)\n * 2. Fall back to parameterized routes (O(n) with pre-compiled regex)\n */\n _findRoute(method: InternalHttpMethod, path: string): InternalRouteRegistry | undefined {\n const normalizedPath = normalizePath(path);\n\n // FAST PATH: Try exact match first (most common case)\n const exactRoute = this._exactRoutes.get(method)?.get(normalizedPath);\n if (exactRoute) {\n return exactRoute;\n }\n\n // PARAMETERIZED PATH: Check routes with parameters\n const parameterizedRoute = this._findParameterizedRoute(method, normalizedPath);\n if (parameterizedRoute) {\n return parameterizedRoute;\n }\n\n return undefined;\n }\n\n /**\n * Check if a route pattern already exists (for conflict detection)\n * This is different from findRoute which matches request paths to patterns\n */\n private _hasExactRoutePattern(method: InternalHttpMethod, pattern: string): boolean {\n // Check exact routes\n if (this._exactRoutes.get(method)?.has(pattern)) {\n return true;\n }\n\n // For parameterized routes, check if the structure conflicts\n // Example: /users/:id conflicts with /users/:userId (same structure, different param names)\n if (pattern.includes(':')) {\n const normalizedPattern = normalizeRouteStructure(pattern);\n const paramRoutes = this._parameterizedRoutes.get(method);\n\n if (paramRoutes) {\n return paramRoutes.some((route) => normalizeRouteStructure(route.path) === normalizedPattern);\n }\n } else {\n // Check parameterized routes for exact pattern match\n const paramRoutes = this._parameterizedRoutes.get(method);\n if (paramRoutes) {\n return paramRoutes.some((route) => route.path === pattern);\n }\n }\n\n return false;\n }\n\n /**\n * Store an exact route (no parameters) for O(1) lookup\n */\n private _storeExactRoute(method: InternalHttpMethod, path: string, route: InternalRouteRegistry): void {\n if (!this._exactRoutes.has(method)) {\n this._exactRoutes.set(method, new Map());\n }\n\n this._exactRoutes.get(method)?.set(path, route);\n }\n\n /**\n * Store a parameterized route with pre-compiled regex pattern\n */\n private _storeParameterizedRoute(method: InternalHttpMethod, route: InternalRouteRegistry): void {\n if (!this._parameterizedRoutes.has(method)) {\n this._parameterizedRoutes.set(method, []);\n }\n\n /**\n * Compile a route pattern into a regex with parameter extraction\n *\n * This is the magic that converts route patterns to regexes:\n * - \"/users/:id\" → /^\\/users\\/([^\\/]+)$/\n * - \"/users/:id/posts/:postId\" → /^\\/users\\/([^\\/]+)\\/posts\\/([^\\/]+)$/\n *\n * WHY AT REGISTRATION TIME: Regex compilation is expensive, so we do it once\n * at server startup rather than on every request.\n */\n const compiled = compileRoutePattern(route);\n this._parameterizedRoutes.get(method)?.push(compiled);\n }\n\n /**\n * Find and match a parameterized route, extracting parameters\n * This is slower than the exact route match (O(n)) because it has to iterate through all the parameterized routes\n * and should only be used if the route is parameterized, otherwise it will be slower than the exact route match.\n */\n private _findParameterizedRoute(method: InternalHttpMethod, path: string): InternalRouteRegistry | undefined {\n const paramRoutes = this._parameterizedRoutes.get(method);\n if (!paramRoutes) return undefined;\n\n // Try each parameterized route until we find a match\n for (const compiledRoute of paramRoutes) {\n const match = path.match(compiledRoute.pattern);\n if (match) {\n const params: Record<string, string> = {};\n\n // Extract parameters from regex capture groups\n // match[0] is the full match, match[1+] are the captured groups\n for (let i = 0; i < compiledRoute.paramNames.length; i++) {\n const paramValue = match[i + 1];\n const paramName = compiledRoute.paramNames[i];\n\n if (paramValue !== undefined && paramName !== undefined) {\n params[paramName] = paramValue;\n }\n }\n\n return { ...compiledRoute, params };\n }\n }\n\n return undefined;\n }\n}\n",
|
|
37
38
|
"import type { InternalRouteRegistryOptions } from '@typedefs/internal/InternalRouteRegistryImpl.js';\nimport type { InternalSetupMethod } from '@typedefs/internal/InternalSetupImpl.js';\nimport type { httpMethod } from '@constants/http.ts';\nimport type { RouteGroup } from '@typedefs/public/Setup.js';\n\n/**\n * Utility type that maps HTTP methods to their handler functions\n * Ensures consistency between SetupImpl and GroupApp\n */\nexport type HttpMethodHandlers = Record<Lowercase<keyof typeof httpMethod>, InternalSetupMethod>;\n\n/**\n * Route group method signature for consistent typing across interfaces\n * Used for both main setup and nested group registration\n */\nexport type RouteGroupMethod = (prefix: string, callback: (group: RouteGroup) => void, options?: InternalRouteRegistryOptions) => RouteGroup;\n\n/**\n * Ensure route options are complete by filling in missing optional properties\n * This allows developers to specify only the hooks they need while maintaining\n * internal compatibility with the system\n */\nexport const ensureCompleteRouteOptions = (options?: InternalRouteRegistryOptions): InternalRouteRegistryOptions => ({\n beforeHooks: options?.beforeHooks ?? [],\n afterHooks: options?.afterHooks ?? [],\n});\n\n/**\n * Merge route options with proper hook ordering\n * - beforeHooks: parent hooks first, then child hooks\n * - afterHooks: child hooks first, then parent hooks\n * Handles optional hooks gracefully\n */\nexport const mergeRouteOptions = (parentOptions: InternalRouteRegistryOptions, childOptions?: InternalRouteRegistryOptions): InternalRouteRegistryOptions => ({\n beforeHooks: [...(parentOptions.beforeHooks ?? []), ...(childOptions?.beforeHooks ?? [])],\n afterHooks: [...(childOptions?.afterHooks ?? []), ...(parentOptions.afterHooks ?? [])],\n});\n\n/**\n * Build a route path by joining prefix and path segments\n * Handles leading/trailing slashes intelligently\n */\nexport const buildRoutePath = (prefix: string, path: string): string => {\n const cleanPrefix = prefix.endsWith('/') ? prefix.slice(0, -1) : prefix;\n const cleanPath = path.startsWith('/') ? path : `/${path}`;\n return `${cleanPrefix}${cleanPath}`;\n};\n",
|
|
38
39
|
"import { httpMethod } from '@constants/http.ts';\nimport type { InternalHttpMethod } from '@typedefs/constants/http.ts';\nimport type { InternalRouteRegistryOptions } from '@typedefs/internal/InternalRouteRegistryImpl.js';\nimport type { HandlerCallback } from '@typedefs/public/Context.js';\nimport type { InternalSetupImpl } from '@typedefs/internal/InternalSetupImpl.js';\nimport type { HttpMethodHandlers, RouteGroupMethod } from '@core/setup/utils/routeUtils.js';\nimport { buildRoutePath, ensureCompleteRouteOptions, mergeRouteOptions } from '@core/setup/utils/routeUtils.js';\nimport type { RouteGroup } from '@typedefs/public/Setup.js';\n\nexport interface InternalGroupApp extends HttpMethodHandlers {\n readonly group: RouteGroupMethod;\n}\n\nexport class GroupApp implements InternalGroupApp {\n private readonly _setup: InternalSetupImpl;\n private readonly _prefix: string;\n private readonly _options: InternalRouteRegistryOptions;\n\n constructor(setup: InternalSetupImpl, prefix: string, options?: InternalRouteRegistryOptions) {\n this._setup = setup;\n this._prefix = prefix;\n this._options = ensureCompleteRouteOptions(options);\n }\n\n private _createRouteHandler(method: InternalHttpMethod) {\n return (path: string, handler: HandlerCallback<any>, routeOptions?: InternalRouteRegistryOptions): void => {\n const fullPath = buildRoutePath(this._prefix, path);\n const mergedOptions = mergeRouteOptions(this._options, routeOptions);\n\n this._setup._routeRegistry._register({\n method,\n handler,\n path: fullPath,\n options: mergedOptions,\n params: {},\n });\n\n // If this is a GET route, automatically register the corresponding HEAD route\n if (method === httpMethod.get) {\n this._setup._routeRegistry._register({\n method: httpMethod.head,\n handler,\n path: fullPath,\n options: mergedOptions,\n params: {},\n });\n }\n };\n }\n\n // HTTP method handlers - using the utility type to ensure consistency\n get = this._createRouteHandler(httpMethod.get);\n head = this._createRouteHandler(httpMethod.head);\n post = this._createRouteHandler(httpMethod.post);\n put = this._createRouteHandler(httpMethod.put);\n delete = this._createRouteHandler(httpMethod.delete);\n patch = this._createRouteHandler(httpMethod.patch);\n options = this._createRouteHandler(httpMethod.options);\n\n // Nested group support\n group(prefix: string, callback: (group: RouteGroup) => void, options?: InternalRouteRegistryOptions): RouteGroup {\n const nestedPrefix = buildRoutePath(this._prefix, prefix);\n const nestedOptions = mergeRouteOptions(this._options, options);\n\n const nestedGroup = new GroupApp(this._setup, nestedPrefix, nestedOptions);\n callback(nestedGroup);\n\n return nestedGroup;\n }\n}\n",
|
|
39
|
-
"import {
|
|
40
|
+
"import { normalizePath } from '@core/setup/utils/normalizeStringPatterns.ts';\nimport type { WebSocketHandlers, WebSocketRouteOptions } from '@typedefs/public/WebSocket.js';\n\ninterface WsRoute {\n path: string;\n handlers: WebSocketHandlers;\n options: WebSocketRouteOptions | undefined;\n pattern?: RegExp;\n paramNames?: Array<string>;\n}\n\ninterface WsRouteMatch {\n handlers: WebSocketHandlers;\n options: WebSocketRouteOptions | undefined;\n params: Record<string, string>;\n}\n\n/**\n * WebSocket route registry with exact + parameterized path matching.\n * Mirrors the HTTP RouteRegistryImpl pattern but without HTTP method discrimination.\n */\nexport class WebSocketRouter {\n private readonly _exactRoutes = new Map<string, WsRoute>();\n private readonly _parameterizedRoutes: Array<WsRoute> = [];\n\n _register(path: string, handlers: WebSocketHandlers, options?: WebSocketRouteOptions): void {\n const normalizedPath = normalizePath(path);\n const isParameterized = normalizedPath.includes(':');\n\n if (isParameterized) {\n const paramNames: Array<string> = [];\n const pattern = normalizedPath\n .replace(/:\\w+/g, (match) => {\n paramNames.push(match.slice(1));\n return '([^/]+)';\n })\n .replace(/\\//g, '\\\\/');\n\n this._parameterizedRoutes.push({\n path: normalizedPath,\n handlers,\n options,\n pattern: new RegExp(`^${pattern}$`),\n paramNames,\n });\n } else {\n this._exactRoutes.set(normalizedPath, { path: normalizedPath, handlers, options });\n }\n }\n\n _match(path: string): WsRouteMatch | undefined {\n const normalizedPath = normalizePath(path);\n\n // O(1) exact match first\n const exact = this._exactRoutes.get(normalizedPath);\n if (exact) {\n return { handlers: exact.handlers, options: exact.options, params: {} };\n }\n\n // O(n) parameterized match\n for (const route of this._parameterizedRoutes) {\n if (!route.pattern) continue;\n const match = route.pattern.exec(normalizedPath);\n if (match) {\n const params: Record<string, string> = {};\n for (let i = 0; i < (route.paramNames?.length ?? 0); i++) {\n const name = route.paramNames?.[i];\n const value = match[i + 1];\n if (name && value) {\n params[name] = value;\n }\n }\n return { handlers: route.handlers, options: route.options, params };\n }\n }\n\n return undefined;\n }\n\n _hasRoutes(): boolean {\n return this._exactRoutes.size > 0 || this._parameterizedRoutes.length > 0;\n }\n}\n",
|
|
41
|
+
"import { httpMethod } from '@constants/http.ts';\nimport { handleCustomConfiguration } from '@core/setup/utils/handleCustomConfiguration.ts';\nimport type { InternalSetupImpl } from '@typedefs/internal/InternalSetupImpl.ts';\nimport { HookRegistryImpl } from '@core/execution/HookRegistryImpl.ts';\nimport type { InternalGlobalHookOptions } from '@typedefs/internal/InternalHookRegistryImpl.js';\nimport type { InternalServerOptions } from '@typedefs/internal/InternalConfiguration.js';\nimport type { ServerOptions } from '@typedefs/public/Configuration.js';\nimport type { InternalRouteRegistryOptions } from '@typedefs/internal/InternalRouteRegistryImpl.js';\nimport { RouteRegistryImpl } from '@core/setup/RouteRegistryImpl.ts';\nimport type { HandlerCallback } from '@typedefs/public/Context.js';\nimport { GroupApp } from '@core/setup/GroupApp.ts';\nimport { ensureCompleteRouteOptions } from '@core/setup/utils/routeUtils.js';\nimport type { RouteGroup } from '@typedefs/public/Setup.js';\nimport { log } from '@core/utils/log.ts';\nimport { WebSocketRouter } from '@core/modules/websocket/WebSocketRouter.ts';\nimport type { WebSocketHandlers, WebSocketMessageHook, WebSocketRouteOptions } from '@typedefs/public/WebSocket.js';\n\nexport class SetupImpl implements InternalSetupImpl {\n readonly _configuration: InternalServerOptions;\n readonly _routeRegistry = new RouteRegistryImpl();\n readonly _hooks = new HookRegistryImpl();\n readonly _wsRouter = new WebSocketRouter();\n /** Per-instance logger. Defaults to module-level `log`, replaced by `_configureLogging()` in YinzerFlow. */\n _log: typeof log = log;\n\n constructor(customConfiguration?: ServerOptions) {\n this._configuration = handleCustomConfiguration(customConfiguration);\n }\n\n // ===== Route Registration =====\n get(path: string, handler: HandlerCallback<any>, options?: InternalRouteRegistryOptions): void {\n const routeOptions = ensureCompleteRouteOptions(options);\n // Register GET route\n this._routeRegistry._register({ method: httpMethod.get, handler, path, options: routeOptions, params: {} });\n // Automatically register corresponding HEAD route\n this._routeRegistry._register({ method: httpMethod.head, handler, path, options: routeOptions, params: {} });\n }\n\n head(path: string, handler: HandlerCallback<any>, options?: InternalRouteRegistryOptions): void {\n this._routeRegistry._register({ method: httpMethod.head, handler, path, options: ensureCompleteRouteOptions(options), params: {} });\n }\n\n post(path: string, handler: HandlerCallback<any>, options?: InternalRouteRegistryOptions): void {\n this._routeRegistry._register({ method: httpMethod.post, handler, path, options: ensureCompleteRouteOptions(options), params: {} });\n }\n\n put(path: string, handler: HandlerCallback<any>, options?: InternalRouteRegistryOptions): void {\n this._routeRegistry._register({ method: httpMethod.put, handler, path, options: ensureCompleteRouteOptions(options), params: {} });\n }\n\n patch(path: string, handler: HandlerCallback<any>, options?: InternalRouteRegistryOptions): void {\n this._routeRegistry._register({ method: httpMethod.patch, handler, path, options: ensureCompleteRouteOptions(options), params: {} });\n }\n\n delete(path: string, handler: HandlerCallback<any>, options?: InternalRouteRegistryOptions): void {\n this._routeRegistry._register({ method: httpMethod.delete, handler, path, options: ensureCompleteRouteOptions(options), params: {} });\n }\n\n options(path: string, handler: HandlerCallback<any>, options?: InternalRouteRegistryOptions): void {\n this._routeRegistry._register({ method: httpMethod.options, handler, path, options: ensureCompleteRouteOptions(options), params: {} });\n }\n\n group(prefix: string, callback: (group: RouteGroup) => void, options?: InternalRouteRegistryOptions): RouteGroup {\n // Create a group app that can handle nested groups and route registration\n const groupApp = new GroupApp(this, prefix, options);\n\n // Execute callback to register routes\n callback(groupApp);\n\n return groupApp;\n }\n\n /**\n * Hook Registration\n *\n * Note these are going to be called dynamically at run time, for now\n * we are just storing them in the server object until runtime. Although\n * it is slower during lookup, it is more flexible and memory efficient\n * allowing for more flexibility to include hook modification, conditional\n * hook execution, and better debugging.\n */\n beforeRouting(handlers: Array<HandlerCallback<any>>, options?: InternalGlobalHookOptions): void {\n this._hooks._addBeforeRoutingHooks(handlers, options);\n }\n\n beforeAll(handlers: Array<HandlerCallback<any>>, options?: InternalGlobalHookOptions): void {\n this._hooks._addBeforeHooks(handlers, options);\n }\n\n afterAll(handlers: Array<HandlerCallback<any>>, options?: InternalGlobalHookOptions): void {\n this._hooks._addAfterHooks(handlers, options);\n }\n\n onError(handler: HandlerCallback<any>): void {\n this._hooks._addOnError(handler);\n }\n\n onNotFound(handler: HandlerCallback<any>): void {\n this._hooks._addOnNotFound(handler);\n }\n\n // ===== WebSocket Registration =====\n ws<T = unknown>(path: string, handlers: WebSocketHandlers<T>, options?: WebSocketRouteOptions): void {\n this._wsRouter._register(path, handlers as WebSocketHandlers, options);\n }\n\n wsBeforeMessage(handlers: Array<WebSocketMessageHook>): void {\n this._hooks._addWsBeforeMessageHooks(handlers);\n }\n\n wsAfterMessage(handlers: Array<WebSocketMessageHook>): void {\n this._hooks._addWsAfterMessageHooks(handlers);\n }\n}\n",
|
|
40
42
|
"import { logLevels } from '@constants/log.ts';\n\n/**\n * Access Log — nginx-style request/response logging.\n *\n * Separate channel from the app logger. Controlled by `logging.requests` (on/off).\n * Defaults to off. When enabled, logs one line per request in a parseable format.\n *\n * Format: {statusEmoji} {ip} \"{METHOD} {path} {proto}\" {statusCode} {bytes} \"{referer}\" \"{ua}\" {duration}ms\n *\n * The logger instance is created per YinzerFlow instance (C1 fix — no module-level singleton).\n * See YinzerFlow._configureLogging() for instance creation.\n */\n\n/** Base config for access log loggers. Personality is always off for machine-parseable output. */\nexport const accessLogBaseConfig = {\n prefix: 'ACCESS',\n level: logLevels.off,\n personality: false,\n} as const;\n\n/**\n * Get status emoji for response codes\n */\nexport const getStatusEmoji = (statusCode: number): string => {\n if (statusCode >= 200 && statusCode < 300) return '✅';\n if (statusCode >= 300 && statusCode < 400) return '🔄';\n if (statusCode >= 400 && statusCode < 500) return '❌';\n if (statusCode >= 500) return '💥';\n return '❓';\n};\n",
|
|
41
43
|
"import type { InternalRateLimitStore } from '@typedefs/internal/modules/rateLimit/index.js';\n\n/**\n * Create an in-memory store for sliding window counter data\n */\nexport const createInMemoryStore = <T>(): InternalRateLimitStore<T> => {\n const store = new Map<string, T>();\n\n return {\n get: async (key: string) => Promise.resolve(store.get(key)),\n set: async (key: string, value: T): Promise<void> => {\n store.set(key, value);\n return Promise.resolve();\n },\n delete: async (key: string): Promise<void> => {\n store.delete(key);\n return Promise.resolve();\n },\n destroy: async (): Promise<void> => {\n store.clear();\n return Promise.resolve();\n },\n };\n};\n",
|
|
42
44
|
"import { Redis } from 'ioredis';\nimport type { InternalRateLimitStore } from '@typedefs/internal/modules/rateLimit/index.js';\nimport { log } from '@core/utils/log.ts';\nimport { _convertTimeToMs } from '@core/utils/time.ts';\nimport type { RateLimitConfig } from '@core/modules/rateLimit/RateLimitConfig.ts';\nimport type { RedisClient } from '@typedefs/public/RateLimit.js';\n\n/**\n * Create a Redis-based store for rate limiting data\n *\n * This store is designed to work with any rate limiting algorithm by providing\n * a generic key-value interface. It handles serialization/deserialization\n * and provides automatic key expiration.\n *\n * ## Features\n *\n * - **Algorithm agnostic**: Works with sliding window counter, token bucket, etc.\n * - **Automatic expiration**: Keys expire automatically to prevent memory leaks\n * - **JSON serialization**: Handles complex data structures\n * - **Error handling**: Graceful fallback on Redis errors\n * - **Debug logging**: Optional detailed logging for troubleshooting\n *\n * ## Usage\n *\n * ```typescript\n * import { createRedisStore } from '@core/modules/rateLimit/stores/redis.ts';\n * import Redis from 'ioredis';\n *\n * const redis = new Redis({\n * host: 'localhost',\n * port: 6379,\n * retryDelayOnFailover: 100,\n * });\n *\n * const store = createRedisStore({\n * client: redis,\n * keyPrefix: 'myapp:rate_limit:',\n * defaultTtl: 3600\n * });\n * ```\n *\n * ## Key Format\n *\n * Keys are formatted as: `{prefix}{algorithm}:{identifier}`\n *\n * Examples:\n * - `rate_limit:sliding_window_counter:192.168.1.100`\n * - `rate_limit:token_bucket:user:12345`\n * - `myapp:rate_limit:sliding_window_counter:api_key:abc123`\n *\n * @param config - Redis store configuration\n * @returns Rate limit store instance\n */\nexport const createRedisStore = async <T>(config: RateLimitConfig): Promise<InternalRateLimitStore<T>> => {\n const { store } = config;\n if (store.type !== 'redis') throw new Error(`Expected Redis store configuration but got: ${JSON.stringify(store)}`);\n const { client, keyPrefix = 'rate_limit:', maxRetries = 3, retryDelay = 1000 } = store;\n const retryDelayMs = _convertTimeToMs(retryDelay);\n let connectionHealthy = false;\n\n // Validate Redis connection with retry logic\n const _validateConnection = async (): Promise<void> => {\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n await client.ping();\n connectionHealthy = true;\n log.info(`[RedisStore] Successfully connected to Redis (attempt ${attempt})`);\n return;\n } catch (error) {\n log.warn(`[RedisStore] Redis connection attempt ${attempt}/${maxRetries} failed:`, error);\n\n if (attempt < maxRetries) {\n log.info(`[RedisStore] Retrying connection in ${retryDelay}...`);\n await new Promise<void>((resolve) => {\n setTimeout(resolve, retryDelayMs);\n });\n } else {\n log.error('[RedisStore] All Redis connection attempts failed. Store will operate in degraded mode.');\n connectionHealthy = false;\n }\n }\n }\n };\n\n // Initialize connection validation (non-blocking)\n await _validateConnection();\n\n return {\n get: async (key: string) => _get({ client, key, keyPrefix, connectionHealthy }),\n set: async (key: string, value: T) => _set({ client, config, key, value, keyPrefix, connectionHealthy }),\n delete: async (key: string) => _delete({ client, key, keyPrefix, connectionHealthy }),\n destroy: async () => _destroy({ client, keyPrefix, connectionHealthy }),\n };\n};\n\n/**\n * Build Redis key with prefix\n */\nconst _buildKey = (key: string, keyPrefix: string): string => `${keyPrefix}${key}`;\n\n/**\n * Serialize value to JSON string\n */\nconst _serialize = <T>(value: T): string => {\n try {\n return JSON.stringify(value);\n } catch (error) {\n log.error('[RedisStore] Failed to serialize value:', error);\n throw new Error('Failed to serialize rate limit data');\n }\n};\n\n/**\n * Deserialize JSON string to value\n */\nconst _deserialize = <T>(json: string): T => {\n try {\n return JSON.parse(json) as T;\n } catch (error) {\n log.error('[RedisStore] Failed to deserialize value:', error);\n throw new Error('Failed to deserialize rate limit data');\n }\n};\n\n/**\n * Handle Redis errors gracefully\n */\nconst _handleError = (operation: string, error: unknown, connectionHealthy: boolean): void => {\n if (connectionHealthy) {\n log.warn(`[RedisStore] Redis ${operation} failed (connection was healthy):`, error);\n } else {\n log.error(`[RedisStore] Redis ${operation} failed (connection unhealthy):`, error);\n }\n // Don't throw - allow the application to continue with degraded functionality\n};\n\n/**\n * Set key with TTL, handling both ioredis and redis package differences\n */\nconst _setWithTtl = async ({ client, key, value, ttlSeconds }: { client: RedisClient; key: string; value: string; ttlSeconds: number }): Promise<void> => {\n try {\n if (client instanceof Redis) {\n await client.set(key, value, 'EX', ttlSeconds);\n } else {\n await client.set(key, value, { EX: ttlSeconds });\n }\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Unsupported Redis client or Redis operation failed: ${error.message}`);\n }\n throw error;\n }\n};\n\n/**\n * Set key while preserving TTL, handling both ioredis and redis package differences\n */\nconst _setKeepTtl = async ({ client, key, value }: { client: RedisClient; key: string; value: string }): Promise<void> => {\n try {\n if (client instanceof Redis) {\n await client.set(key, value, 'KEEPTTL'); // cspell:disable-line\n } else {\n await client.set(key, value, { KEEPTTL: true }); // cspell:disable-line\n }\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Unsupported Redis client or Redis operation failed: ${error.message}`);\n }\n throw error;\n }\n};\n\n/**\n * Get value from Redis\n */\nconst _get = async <T>({\n client,\n key,\n keyPrefix,\n connectionHealthy,\n}: {\n client: RedisClient;\n key: string;\n keyPrefix: string;\n connectionHealthy: boolean;\n}): Promise<T | undefined> => {\n try {\n const redisKey = _buildKey(key, keyPrefix);\n const value = await client.get(redisKey);\n\n if (value === null) {\n return undefined;\n }\n\n return _deserialize<T>(value);\n } catch (error) {\n _handleError('GET', error, connectionHealthy);\n return undefined;\n }\n};\n\n/**\n * Set value in Redis with TTL\n */\nconst _set = async <T>({\n client,\n config,\n key,\n value,\n keyPrefix,\n connectionHealthy,\n}: {\n client: RedisClient;\n config: RateLimitConfig;\n key: string;\n value: T;\n keyPrefix: string;\n connectionHealthy: boolean;\n}): Promise<void> => {\n try {\n const redisKey = _buildKey(key, keyPrefix);\n const serialized = _serialize(value);\n\n // Check if key exists first\n const exists = await client.exists(redisKey);\n\n if (exists) {\n // Key exists - update value but preserve TTL using KEEPTTL (cspell:disable-line)\n await _setKeepTtl({ client, key: redisKey, value: serialized });\n } else {\n // New key - set with TTL\n await _setWithTtl({ client, key: redisKey, value: serialized, ttlSeconds: Math.floor(config.window / 1000) });\n }\n } catch (error) {\n _handleError('SET', error, connectionHealthy);\n }\n};\n\n/**\n * Delete key from Redis\n */\nconst _delete = async ({\n client,\n key,\n keyPrefix,\n connectionHealthy,\n}: {\n client: RedisClient;\n key: string;\n keyPrefix: string;\n connectionHealthy: boolean;\n}): Promise<void> => {\n try {\n const redisKey = _buildKey(key, keyPrefix);\n await client.del(redisKey);\n } catch (error) {\n _handleError('DELETE', error, connectionHealthy);\n }\n};\n\n/**\n * Delete all keys related to this store\n */\nconst _destroy = async ({ client, keyPrefix, connectionHealthy }: { client: RedisClient; keyPrefix: string; connectionHealthy: boolean }): Promise<void> => {\n try {\n const pattern = `${keyPrefix}*`;\n const keys = await client.keys(pattern);\n if (keys.length > 0) {\n await Promise.all(keys.map(async (key) => client.del(key)));\n log.info(`[RedisStore] Destroyed ${keys.length} rate limit keys`);\n }\n } catch (error) {\n _handleError('DESTROY', error, connectionHealthy);\n }\n};\n",
|
|
@@ -53,9 +55,15 @@
|
|
|
53
55
|
"import type { HandlerCallback } from '@typedefs/public/Context.js';\nimport type { InternalCorsEnabledOptions } from '@typedefs/internal/InternalConfiguration.js';\nimport type { InternalContextImpl } from '@typedefs/internal/InternalContextImpl.js';\nimport { Cors } from '@core/modules/cors/Cors.ts';\n\n/**\n * Creates a CORS beforeRouting hook\n *\n * This hook handles Cross-Origin Resource Sharing (CORS) before routing.\n * It validates origins, handles preflight requests, and sets appropriate headers.\n *\n * @param config - CORS configuration (must be enabled)\n * @returns HandlerCallback that can be registered with app.beforeRouting()\n *\n * @example\n * ```typescript\n * import { YinzerFlow } from 'yinzerflow';\n * import { corsHook } from '@core/modules/cors/corsHooks.ts';\n *\n * const app = new YinzerFlow();\n *\n * // Register CORS as a beforeRouting hook\n * app.beforeRouting([\n * corsHook({\n * enabled: true,\n * origin: ['https://example.com', 'https://app.example.com'],\n * methods: ['GET', 'POST', 'PUT', 'DELETE'],\n * credentials: true,\n * })\n * ]);\n * ```\n */\nexport const corsHook = (config: InternalCorsEnabledOptions): HandlerCallback => {\n const cors = new Cors(config);\n\n return (context) => cors.handle(context as InternalContextImpl);\n};\n",
|
|
54
56
|
"import { httpStatusCode } from '@constants/http.ts';\nimport type { InternalCorsEnabledOptions, InternalCorsOptions } from '@typedefs/internal/InternalConfiguration.js';\n\n/**\n * CORS Configuration defaults and validation\n *\n * Provides sensible defaults and validates CORS configuration for security.\n */\n// eslint-disable-next-line @typescript-eslint/no-extraneous-class\nexport class CorsConfig {\n /**\n * Get default CORS configuration (disabled by default)\n */\n static getDefaults(): InternalCorsOptions {\n return {\n enabled: false,\n };\n }\n\n /**\n * Get default enabled CORS configuration\n * Used when user enables CORS but doesn't provide full config\n */\n static getEnabledDefaults(): InternalCorsEnabledOptions {\n return {\n enabled: true,\n origin: '*',\n methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],\n allowedHeaders: '*',\n exposedHeaders: [],\n credentials: false,\n maxAge: 86400, // 24 hours\n preflightContinue: false,\n optionsSuccessStatus: httpStatusCode.noContent,\n };\n }\n\n /**\n * Merge user configuration with defaults\n */\n static merge(userConfig?: Partial<InternalCorsEnabledOptions>): InternalCorsOptions {\n if (!userConfig || !userConfig.enabled) {\n return CorsConfig.getDefaults();\n }\n\n const defaults = CorsConfig.getEnabledDefaults();\n\n return {\n enabled: true,\n origin: userConfig.origin ?? defaults.origin,\n methods: userConfig.methods ?? defaults.methods,\n allowedHeaders: userConfig.allowedHeaders ?? defaults.allowedHeaders,\n exposedHeaders: userConfig.exposedHeaders ?? defaults.exposedHeaders,\n credentials: userConfig.credentials ?? defaults.credentials,\n maxAge: userConfig.maxAge ?? defaults.maxAge,\n preflightContinue: userConfig.preflightContinue ?? defaults.preflightContinue,\n optionsSuccessStatus: userConfig.optionsSuccessStatus ?? defaults.optionsSuccessStatus,\n };\n }\n\n /**\n * Validate CORS configuration for security issues\n * Throws if configuration is invalid or insecure\n */\n static validate(config: InternalCorsOptions): void {\n if (!config.enabled) return;\n\n // SECURITY: Validate wildcard + credentials combination\n if (config.origin === '*' && config.credentials) {\n throw new Error(\n 'CORS Security Error: origin: \"*\" with credentials: true is forbidden by CORS spec and creates security vulnerabilities. Use specific origins instead.',\n );\n }\n\n // Validate origin is provided when enabled\n if (!config.origin) {\n throw new Error('CORS Configuration Error: origin is required when CORS is enabled.');\n }\n\n // Validate methods array\n if (!Array.isArray(config.methods) || config.methods.length === 0) {\n throw new Error('CORS Configuration Error: methods must be a non-empty array.');\n }\n\n // Validate exposedHeaders array\n if (!Array.isArray(config.exposedHeaders)) {\n throw new Error('CORS Configuration Error: exposedHeaders must be an array.');\n }\n\n // Validate maxAge is positive\n if (typeof config.maxAge !== 'number' || config.maxAge < 0) {\n throw new Error('CORS Configuration Error: maxAge must be a non-negative number.');\n }\n }\n}\n",
|
|
55
57
|
"/**\n * Strip control characters, newlines, and Unicode BiDi overrides from attacker-controlled\n * strings before log interpolation. Prevents log injection (fake log entries via \\n),\n * ANSI escape injection, and terminal display manipulation via BiDi overrides.\n */\nconst CONTROL_CHARS_RE = /[\\r\\n\\x00-\\x1f\\x7f\\u200f\\u202a-\\u202e\\u2066-\\u2069]/g;\n\nexport const _sanitizeLogField = (value: string, maxLength = 256): string => value.replace(CONTROL_CHARS_RE, '').slice(0, maxLength);\n",
|
|
56
|
-
"import { createLogger } from '@core/utils/log.ts';\nimport { _convertTimeToMs } from '@core/utils/time.ts';\nimport { _convertBytesToBytes } from '@core/utils/bytes.ts';\nimport { _sanitizeLogField } from '@core/utils/sanitize.ts';\nimport type { InternalDiagnosticsOptions } from '@typedefs/internal/InternalConfiguration.js';\n\n/**\n * Pittsburgh-themed performance phrases for diagnostic output.\n * Moved from the old networkLog.ts `logPerformanceDetails` function.\n */\nconst DIAGNOSTIC_PHRASES = {\n slowRequest: [\n \"that's draggin' n'at\",\n 'slower than a bus on Forbes Ave',\n 'yinz might wanna optimize that',\n 'what a jagoff response time!',\n \"slowin' down a bit there\",\n ],\n largePayload: [\"that's a yuge payload n'at\", \"bigger than a Primanti's sandwich\", \"that's a lot of data, yinz\", 'hefty response there'],\n memory: [\"heap's gettin' full n'at\", 'memory usage update', \"keepin' an eye on the heap\"],\n eventLoop: [\"event loop's laggin' n'at\", \"the loop's stuck in traffic on 376\", 'yinz got a blocking operation'],\n rateLimit: [\"somebody's hammerin' the server n'at\", 'slow down there, jagoff', 'rate limit hit'],\n} as const;\n\nconst _getRandomDiagPhrase = (type: keyof typeof DIAGNOSTIC_PHRASES): string => {\n const phrases = DIAGNOSTIC_PHRASES[type];\n return phrases[Math.floor(Math.random() * phrases.length)] ?? '';\n};\n\n/**\n * Resolved diagnostics config — all thresholds converted to numbers.\n * `false` means the diagnostic is disabled.\n */\ninterface ResolvedConfig {\n slowRequestsMs: number | false;\n largeResponsesBytes: number | false;\n largeRequestsBytes: number | false;\n memoryIntervalMs: number | false;\n eventLoopThresholdMs: number | false;\n rateLimits: boolean;\n}\n\n/**\n * Framework health monitoring — independent of app log level.\n *\n * Diagnostics fire only when thresholds are exceeded. All thresholds default\n * to `false` (disabled). Even with `logging.level: 'off'`, diagnostics still\n * fire because they use their own logger instance always at 'info' level.\n *\n * Three categories:\n * - **Per-request**: Slow requests, large request/response bodies\n * - **Interval**: Memory usage, event loop lag\n * - **Event**: Rate limit hits\n */\nexport class DiagnosticsMonitor {\n _config: ResolvedConfig;\n _personality: boolean;\n _memoryTimer?: ReturnType<typeof setInterval> | undefined;\n _eventLoopTimer?: ReturnType<typeof setTimeout> | undefined;\n _log: ReturnType<typeof createLogger>;\n private _destroyed = false;\n\n constructor(config: InternalDiagnosticsOptions, personality: boolean) {\n this._config = _resolveConfig(config);\n this._personality = personality;\n // Own logger — always at 'info', bypasses the app log level\n this._log = createLogger({ level: 'info', prefix: 'DIAGNOSTIC', personality: false });\n }\n\n /** Append a Pittsburgh phrase only when personality is enabled. */\n _phrase(type: keyof typeof DIAGNOSTIC_PHRASES): string {\n return this._personality ? ` — ${_getRandomDiagPhrase(type)}` : '';\n }\n\n /**\n * Check a completed request against diagnostic thresholds.\n * Called after the response has been written to the socket.\n *\n * @param method - Pre-sanitized HTTP method (caller handles sanitization to avoid double-sanitize)\n * @param path - Pre-sanitized request path\n */\n checkRequest({ duration, reqBytes, resBytes, method, path }: { duration: number; reqBytes: number; resBytes: number; method: string; path: string }): void {\n if (this._config.slowRequestsMs !== false && duration > this._config.slowRequestsMs) {\n this._log.warn(`🐌 Slow request: ${method} ${path} took ${duration}ms (threshold: ${this._config.slowRequestsMs}ms)${this._phrase('slowRequest')}`);\n }\n\n if (this._config.largeResponsesBytes !== false && resBytes > this._config.largeResponsesBytes) {\n this._log.warn(\n `📦 Large response: ${method} ${path} ${resBytes} bytes (threshold: ${this._config.largeResponsesBytes} bytes)${this._phrase('largePayload')}`,\n );\n }\n\n if (this._config.largeRequestsBytes !== false && reqBytes > this._config.largeRequestsBytes) {\n this._log.warn(\n `📦 Large request: ${method} ${path} ${reqBytes} bytes (threshold: ${this._config.largeRequestsBytes} bytes)${this._phrase('largePayload')}`,\n );\n }\n }\n\n /**\n * Called when the rate limiter fires for an IP.\n */\n onRateLimitHit(ip: string, path: string): void {\n if (!this._config.rateLimits) return;\n this._log.warn(`🚫 Rate limit hit: ${ip} on ${_sanitizeLogField(path)}${this._phrase('rateLimit')}`);\n }\n\n /**\n * Start interval-based monitors (memory, event loop).\n * Call once after server is constructed.\n */\n start(): void {\n this._startMemoryMonitor();\n this._startEventLoopMonitor();\n }\n\n /**\n * Clean up all intervals and timers. Call on server close.\n */\n destroy(): void {\n this._destroyed = true;\n if (this._memoryTimer) {\n clearInterval(this._memoryTimer);\n this._memoryTimer = undefined;\n }\n if (this._eventLoopTimer) {\n clearTimeout(this._eventLoopTimer);\n this._eventLoopTimer = undefined;\n }\n }\n\n /**\n * Check if any diagnostics are enabled.\n */\n hasAnyEnabled(): boolean {\n return (\n this._config.slowRequestsMs !== false ||\n this._config.largeResponsesBytes !== false ||\n this._config.largeRequestsBytes !== false ||\n this._config.memoryIntervalMs !== false ||\n this._config.eventLoopThresholdMs !== false ||\n this._config.rateLimits\n );\n }\n\n /**\n * Periodic memory usage logging.\n */\n private _startMemoryMonitor(): void {\n if (this._config.memoryIntervalMs === false) return;\n\n const intervalMs = this._config.memoryIntervalMs;\n this._memoryTimer = setInterval(() => {\n const mem = process.memoryUsage();\n const toMB = (bytes: number): string => (bytes / 1024 / 1024).toFixed(1);\n this._log.info(\n `💾 Heap: ${toMB(mem.heapUsed)}MB / ${toMB(mem.heapTotal)}MB | RSS: ${toMB(mem.rss)}MB | External: ${toMB(mem.external)}MB${this._phrase('memory')}`,\n );\n }, intervalMs);\n\n // Don't prevent process exit\n this._memoryTimer.unref();\n }\n\n /**\n * Event loop lag detection via setTimeout drift.\n * If the callback fires significantly later than scheduled, the event loop is lagging.\n */\n private _startEventLoopMonitor(): void {\n if (this._config.eventLoopThresholdMs === false) return;\n\n const threshold = this._config.eventLoopThresholdMs;\n // Check every 1 second\n const checkIntervalMs = 1000;\n\n const check = (): void => {\n if (this._destroyed) return;\n const start = Date.now();\n this._eventLoopTimer = setTimeout(() => {\n if (this._destroyed) return;\n const lag = Date.now() - start - checkIntervalMs;\n if (lag > threshold) {\n this._log.warn(`⏱️ Event loop lag: ${lag}ms (threshold: ${threshold}ms)${this._phrase('eventLoop')}`);\n }\n check();\n }, checkIntervalMs);\n this._eventLoopTimer.unref();\n };\n\n check();\n }\n}\n\n/**\n * Resolve TimeString/ByteString config values to raw numbers.\n * `false` values pass through as disabled.\n */\nconst _resolveConfig = (config: InternalDiagnosticsOptions): ResolvedConfig => ({\n slowRequestsMs: config.slowRequests === false ? false : _convertTimeToMs(config.slowRequests),\n largeResponsesBytes: config.largeResponses === false ? false : _convertBytesToBytes(config.largeResponses),\n largeRequestsBytes: config.largeRequests === false ? false : _convertBytesToBytes(config.largeRequests),\n memoryIntervalMs: config.memory === false ? false : _convertTimeToMs(config.memory),\n eventLoopThresholdMs: config.eventLoop === false ? false : _convertTimeToMs(config.eventLoop),\n rateLimits: config.rateLimits,\n});\n"
|
|
58
|
+
"import { createLogger } from '@core/utils/log.ts';\nimport { _convertTimeToMs } from '@core/utils/time.ts';\nimport { _convertBytesToBytes } from '@core/utils/bytes.ts';\nimport { _sanitizeLogField } from '@core/utils/sanitize.ts';\nimport type { InternalDiagnosticsOptions } from '@typedefs/internal/InternalConfiguration.js';\n\n/**\n * Pittsburgh-themed performance phrases for diagnostic output.\n * Moved from the old networkLog.ts `logPerformanceDetails` function.\n */\nconst DIAGNOSTIC_PHRASES = {\n slowRequest: [\n \"that's draggin' n'at\",\n 'slower than a bus on Forbes Ave',\n 'yinz might wanna optimize that',\n 'what a jagoff response time!',\n \"slowin' down a bit there\",\n ],\n largePayload: [\"that's a yuge payload n'at\", \"bigger than a Primanti's sandwich\", \"that's a lot of data, yinz\", 'hefty response there'],\n memory: [\"heap's gettin' full n'at\", 'memory usage update', \"keepin' an eye on the heap\"],\n eventLoop: [\"event loop's laggin' n'at\", \"the loop's stuck in traffic on 376\", 'yinz got a blocking operation'],\n rateLimit: [\"somebody's hammerin' the server n'at\", 'slow down there, jagoff', 'rate limit hit'],\n} as const;\n\nconst _getRandomDiagPhrase = (type: keyof typeof DIAGNOSTIC_PHRASES): string => {\n const phrases = DIAGNOSTIC_PHRASES[type];\n return phrases[Math.floor(Math.random() * phrases.length)] ?? '';\n};\n\n/**\n * Resolved diagnostics config — all thresholds converted to numbers.\n * `false` means the diagnostic is disabled.\n */\ninterface ResolvedConfig {\n slowRequestsMs: number | false;\n largeResponsesBytes: number | false;\n largeRequestsBytes: number | false;\n memoryIntervalMs: number | false;\n eventLoopThresholdMs: number | false;\n rateLimits: boolean;\n}\n\n/**\n * Framework health monitoring — independent of app log level.\n *\n * Diagnostics fire only when thresholds are exceeded. All thresholds default\n * to `false` (disabled). Even with `logging.level: 'off'`, diagnostics still\n * fire because they use their own logger instance always at 'info' level.\n *\n * Three categories:\n * - **Per-request**: Slow requests, large request/response bodies\n * - **Interval**: Memory usage, event loop lag\n * - **Event**: Rate limit hits\n */\nexport class DiagnosticsMonitor {\n _config: ResolvedConfig;\n _personality: boolean;\n _memoryTimer?: ReturnType<typeof setInterval> | undefined;\n _eventLoopTimer?: ReturnType<typeof setTimeout> | undefined;\n _log: ReturnType<typeof createLogger>;\n private _destroyed = false;\n\n constructor(config: InternalDiagnosticsOptions, personality: boolean) {\n this._config = _resolveConfig(config);\n this._personality = personality;\n // Own logger — always at 'info', bypasses the app log level\n this._log = createLogger({ level: 'info', prefix: 'DIAGNOSTIC', personality: false });\n }\n\n /** Append a Pittsburgh phrase only when personality is enabled. */\n _phrase(type: keyof typeof DIAGNOSTIC_PHRASES): string {\n return this._personality ? ` — ${_getRandomDiagPhrase(type)}` : '';\n }\n\n /**\n * Check a completed request against diagnostic thresholds.\n * Called after the response has been written to the socket.\n *\n * @param method - Pre-sanitized HTTP method (caller handles sanitization to avoid double-sanitize)\n * @param path - Pre-sanitized request path\n */\n checkRequest({ duration, reqBytes, resBytes, method, path }: { duration: number; reqBytes: number; resBytes: number; method: string; path: string }): void {\n if (this._config.slowRequestsMs !== false && duration > this._config.slowRequestsMs) {\n this._log.warn(`🐌 Slow request: ${method} ${path} took ${duration}ms (threshold: ${this._config.slowRequestsMs}ms)${this._phrase('slowRequest')}`);\n }\n\n if (this._config.largeResponsesBytes !== false && resBytes > this._config.largeResponsesBytes) {\n this._log.warn(\n `📦 Large response: ${method} ${path} ${resBytes} bytes (threshold: ${this._config.largeResponsesBytes} bytes)${this._phrase('largePayload')}`,\n );\n }\n\n if (this._config.largeRequestsBytes !== false && reqBytes > this._config.largeRequestsBytes) {\n this._log.warn(\n `📦 Large request: ${method} ${path} ${reqBytes} bytes (threshold: ${this._config.largeRequestsBytes} bytes)${this._phrase('largePayload')}`,\n );\n }\n }\n\n /**\n * Called when the rate limiter fires for an IP.\n */\n onRateLimitHit(ip: string, path: string): void {\n if (!this._config.rateLimits) return;\n this._log.warn(`🚫 Rate limit hit: ${ip} on ${_sanitizeLogField(path)}${this._phrase('rateLimit')}`);\n }\n\n /**\n * Start interval-based monitors (memory, event loop).\n * Call once after server is constructed.\n */\n start(): void {\n this._startMemoryMonitor();\n this._startEventLoopMonitor();\n }\n\n /**\n * Clean up all intervals and timers. Call on server close.\n */\n destroy(): void {\n this._destroyed = true;\n if (this._memoryTimer) {\n clearInterval(this._memoryTimer);\n this._memoryTimer = undefined;\n }\n if (this._eventLoopTimer) {\n clearTimeout(this._eventLoopTimer);\n this._eventLoopTimer = undefined;\n }\n }\n\n /**\n * Check if any diagnostics are enabled.\n */\n hasAnyEnabled(): boolean {\n return (\n this._config.slowRequestsMs !== false ||\n this._config.largeResponsesBytes !== false ||\n this._config.largeRequestsBytes !== false ||\n this._config.memoryIntervalMs !== false ||\n this._config.eventLoopThresholdMs !== false ||\n this._config.rateLimits\n );\n }\n\n /**\n * Periodic memory usage logging.\n */\n private _startMemoryMonitor(): void {\n if (this._config.memoryIntervalMs === false) return;\n\n const intervalMs = this._config.memoryIntervalMs;\n this._memoryTimer = setInterval(() => {\n const mem = process.memoryUsage();\n const toMB = (bytes: number): string => (bytes / 1024 / 1024).toFixed(1);\n this._log.info(\n `💾 Heap: ${toMB(mem.heapUsed)}MB / ${toMB(mem.heapTotal)}MB | RSS: ${toMB(mem.rss)}MB | External: ${toMB(mem.external)}MB${this._phrase('memory')}`,\n );\n }, intervalMs);\n\n // Don't prevent process exit\n this._memoryTimer.unref();\n }\n\n /**\n * Event loop lag detection via setTimeout drift.\n * If the callback fires significantly later than scheduled, the event loop is lagging.\n */\n private _startEventLoopMonitor(): void {\n if (this._config.eventLoopThresholdMs === false) return;\n\n const threshold = this._config.eventLoopThresholdMs;\n // Check every 1 second\n const checkIntervalMs = 1000;\n\n const check = (): void => {\n if (this._destroyed) return;\n const start = Date.now();\n this._eventLoopTimer = setTimeout(() => {\n if (this._destroyed) return;\n const lag = Date.now() - start - checkIntervalMs;\n if (lag > threshold) {\n this._log.warn(`⏱️ Event loop lag: ${lag}ms (threshold: ${threshold}ms)${this._phrase('eventLoop')}`);\n }\n check();\n }, checkIntervalMs);\n this._eventLoopTimer.unref();\n };\n\n check();\n }\n}\n\n/**\n * Resolve TimeString/ByteString config values to raw numbers.\n * `false` values pass through as disabled.\n */\nconst _resolveConfig = (config: InternalDiagnosticsOptions): ResolvedConfig => ({\n slowRequestsMs: config.slowRequests === false ? false : _convertTimeToMs(config.slowRequests),\n largeResponsesBytes: config.largeResponses === false ? false : _convertBytesToBytes(config.largeResponses),\n largeRequestsBytes: config.largeRequests === false ? false : _convertBytesToBytes(config.largeRequests),\n memoryIntervalMs: config.memory === false ? false : _convertTimeToMs(config.memory),\n eventLoopThresholdMs: config.eventLoop === false ? false : _convertTimeToMs(config.eventLoop),\n rateLimits: config.rateLimits,\n});\n",
|
|
59
|
+
"import { createHash } from 'crypto';\nimport { wsMagicGuid } from '@constants/websocket.ts';\n\ninterface HandshakeValid {\n valid: true;\n key: string;\n origin: string | undefined;\n path: string;\n query: Record<string, string>;\n protocols: Array<string>;\n}\n\ninterface HandshakeInvalid {\n valid: false;\n reason: string;\n}\n\ntype HandshakeResult = HandshakeInvalid | HandshakeValid;\n\n/**\n * Check if raw HTTP headers contain a WebSocket upgrade request.\n * Case-insensitive match for both `Upgrade: websocket` and `Connection: Upgrade`.\n */\nexport const _isWebSocketUpgrade = (headersStr: string): boolean => {\n const lower = headersStr.toLowerCase();\n return lower.includes('upgrade: websocket') && lower.includes('connection:') && lower.includes('upgrade');\n};\n\n/**\n * Parse the request line to extract path and query parameters.\n */\nconst _parseRequestLine = (requestLine: string): { path: string; query: Record<string, string> } | null => {\n const requestMatch = /^GET\\s+(?<path>\\S+)\\s+HTTP\\/1\\.1$/i.exec(requestLine);\n if (!requestMatch?.groups?.path) {\n return null;\n }\n\n const fullPath = requestMatch.groups.path;\n const queryIndex = fullPath.indexOf('?');\n const path = queryIndex >= 0 ? fullPath.substring(0, queryIndex) : fullPath;\n const query: Record<string, string> = {};\n\n if (queryIndex >= 0) {\n const queryStr = fullPath.substring(queryIndex + 1);\n for (const pair of queryStr.split('&')) {\n const eqIndex = pair.indexOf('=');\n if (eqIndex >= 0) {\n query[decodeURIComponent(pair.substring(0, eqIndex))] = decodeURIComponent(pair.substring(eqIndex + 1));\n } else {\n query[decodeURIComponent(pair)] = '';\n }\n }\n }\n\n return { path, query };\n};\n\n/**\n * Parse HTTP headers into a case-insensitive map.\n */\nconst _parseHeaders = (lines: Array<string>): Map<string, string> => {\n const headers = new Map<string, string>();\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i];\n if (!line) continue;\n const colonIndex = line.indexOf(':');\n if (colonIndex < 0) continue;\n const [key = '', ...rest] = line.split(':');\n headers.set(key.trim().toLowerCase(), rest.join(':').trim());\n }\n return headers;\n};\n\n/**\n * Validate the Sec-WebSocket-Key header.\n */\nconst _validateSecWebSocketKey = (key: string): { valid: false; reason: string } | { valid: true } => {\n try {\n const decoded = Buffer.from(key, 'base64');\n if (decoded.length !== 16) {\n return { valid: false, reason: 'Sec-WebSocket-Key must decode to 16 bytes' };\n }\n } catch {\n return { valid: false, reason: 'Sec-WebSocket-Key is not valid base64' };\n }\n\n return { valid: true };\n};\n\n/**\n * Validate a WebSocket upgrade request per RFC 6455 §4.2.1.\n *\n * Checks:\n * - Sec-WebSocket-Key present and valid (base64, 16 bytes decoded)\n * - Sec-WebSocket-Version is 13\n * - Extracts origin, path, query string, and sub-protocol list\n */\nexport const _validateHandshake = (headersStr: string): HandshakeResult => {\n const lines = headersStr.split('\\r\\n');\n const [requestLine] = lines;\n if (!requestLine) {\n return { valid: false, reason: 'Empty request' };\n }\n\n // Parse request line: \"GET /path?query HTTP/1.1\"\n const pathQueryResult = _parseRequestLine(requestLine);\n if (!pathQueryResult) {\n return { valid: false, reason: 'Invalid request line — must be GET with HTTP/1.1' };\n }\n const { path, query } = pathQueryResult;\n\n // Parse headers into a map (case-insensitive keys)\n const headers = _parseHeaders(lines);\n\n // Sec-WebSocket-Key: required, base64-encoded 16 bytes\n const key = headers.get('sec-websocket-key');\n if (!key) {\n return { valid: false, reason: 'Missing Sec-WebSocket-Key header' };\n }\n const keyValidation = _validateSecWebSocketKey(key);\n if (!keyValidation.valid) {\n return keyValidation;\n }\n\n // Sec-WebSocket-Version: must be 13\n const version = headers.get('sec-websocket-version');\n if (version !== '13') {\n return { valid: false, reason: `Unsupported Sec-WebSocket-Version: ${version ?? 'missing'}` };\n }\n\n const origin = headers.get('origin');\n const protocolHeader = headers.get('sec-websocket-protocol');\n const protocols =\n protocolHeader ?\n protocolHeader\n .split(',')\n .map((p) => p.trim())\n .filter(Boolean)\n : [];\n\n return { valid: true, key, origin, path, query, protocols };\n};\n\n/**\n * Generate the Sec-WebSocket-Accept value per RFC 6455 §4.2.2.\n * `SHA-1(clientKey + magicGUID)` → base64\n */\nexport const _generateAcceptKey = (clientKey: string): string =>\n createHash('sha1')\n .update(clientKey + wsMagicGuid)\n .digest('base64');\n\n/**\n * Build the HTTP 101 Switching Protocols response string.\n */\nexport const _buildHandshakeResponse = (acceptKey: string, protocol?: string): string => {\n const lines = ['HTTP/1.1 101 Switching Protocols', 'Upgrade: websocket', 'Connection: Upgrade', `Sec-WebSocket-Accept: ${acceptKey}`];\n\n if (protocol) {\n lines.push(`Sec-WebSocket-Protocol: ${protocol}`);\n }\n\n return lines.join('\\r\\n').concat('\\r\\n\\r\\n');\n};\n",
|
|
60
|
+
"/**\n * WebSocket frame opcodes per RFC 6455 §5.2\n *\n * Data frames: continuation (0x0), text (0x1), binary (0x2)\n * Control frames: close (0x8), ping (0x9), pong (0xA)\n */\nexport const wsOpcode = {\n continuation: 0x0,\n text: 0x1,\n binary: 0x2,\n close: 0x8,\n ping: 0x9,\n pong: 0xa,\n} as const;\n\n/**\n * WebSocket close status codes per RFC 6455 §7.4.1\n */\nexport const wsCloseCode = {\n normal: 1000,\n goingAway: 1001,\n protocolError: 1002,\n unsupported: 1003,\n noStatus: 1005,\n abnormal: 1006,\n invalidPayload: 1007,\n policyViolation: 1008,\n tooLarge: 1009,\n missingExtension: 1010,\n internalError: 1011,\n} as const;\n\n/**\n * WebSocket connection ready states per RFC 6455 §5\n */\nexport const wsReadyState = {\n connecting: 0,\n open: 1,\n closing: 2,\n closed: 3,\n} as const;\n\n/**\n * Backpressure strategies for WebSocket connections.\n *\n * - `buffer`: Queue messages up to a configurable limit (safe default — no data loss)\n * - `drop`: Silently discard messages when the client can't keep up (ideal for\n * real-time data like trading quotes where stale data is worse than gaps)\n */\nexport const wsBackpressureStrategy = {\n buffer: 'buffer',\n drop: 'drop',\n} as const;\n\n/**\n * RFC 6455 §4.2.2 — magic GUID concatenated with Sec-WebSocket-Key for accept hash\n */\nexport const wsMagicGuid = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';\n",
|
|
61
|
+
"/* eslint-disable\n no-bitwise,\n @typescript-eslint/no-non-null-assertion\n*/\nimport { wsOpcode } from '@constants/websocket.ts';\nimport type { InternalWebSocketParseResult } from '@typedefs/internal/modules/websocket/index.js';\n\n// Pre-computed constants to avoid repeated property lookups in hot path\nconst OPCODE_CLOSE = wsOpcode.close;\n\n/**\n * XOR-unmask a payload buffer in-place using a 4-byte rotating mask key.\n * Mutates `payload` directly — zero allocation.\n *\n * Per RFC 6455 §5.3: `j = i MOD 4`, `transformed[i] = original[i] XOR maskKey[j]`\n */\nexport const _unmask = (payload: Buffer, maskKey: Buffer): void => {\n for (let i = 0; i < payload.length; i++) {\n payload[i] = payload[i]! ^ maskKey[i & 3]!;\n }\n};\n\n/**\n * Attempt to parse one WebSocket frame from a buffer starting at `offset`.\n *\n * Returns `null` if the buffer doesn't contain a complete frame (need more TCP data).\n * Otherwise returns the decoded frame and the number of bytes consumed so callers\n * can advance their offset and parse the next frame in the same buffer.\n *\n * Frame wire format (RFC 6455 §5.2):\n * ```\n * Byte 0: [FIN:1][RSV1-3:3][OPCODE:4]\n * Byte 1: [MASK:1][PAYLOAD_LEN:7]\n * if PAYLOAD_LEN == 126 → next 2 bytes are uint16 length\n * if PAYLOAD_LEN == 127 → next 8 bytes are uint64 length\n * If MASK == 1 → next 4 bytes are masking key\n * Remaining bytes: payload data\n * ```\n */\nexport const _parseFrame = (buffer: Buffer, offset: number): InternalWebSocketParseResult => {\n const available = buffer.length - offset;\n\n // Need at least 2 bytes for the minimal frame header\n if (available < 2) return null;\n\n const byte0 = buffer[offset]!;\n const byte1 = buffer[offset + 1]!;\n\n const fin = (byte0 & 0x80) !== 0;\n const opcode = byte0 & 0x0f;\n const masked = (byte1 & 0x80) !== 0;\n let payloadLength = byte1 & 0x7f;\n let headerSize = 2;\n\n // Extended payload length: 16-bit\n if (payloadLength === 126) {\n if (available < 4) return null;\n payloadLength = buffer.readUInt16BE(offset + 2);\n headerSize = 4;\n }\n // Extended payload length: 64-bit\n else if (payloadLength === 127) {\n if (available < 10) return null;\n // Read as two 32-bit values — upper 32 bits must be zero (we don't support >4GB frames)\n const upper = buffer.readUInt32BE(offset + 2);\n if (upper !== 0) {\n throw new Error('WebSocket frame payload too large (>4GB not supported)');\n }\n payloadLength = buffer.readUInt32BE(offset + 6);\n headerSize = 10;\n }\n\n // Add masking key size if present\n if (masked) {\n headerSize += 4;\n }\n\n const totalFrameSize = headerSize + payloadLength;\n\n // Not enough data for the full frame yet\n if (available < totalFrameSize) return null;\n\n const payload =\n masked ?\n ((): Buffer => {\n const maskKeyOffset = offset + headerSize - 4;\n const maskKey = buffer.subarray(maskKeyOffset, maskKeyOffset + 4);\n const unmaskedPayload = Buffer.from(buffer.subarray(offset + headerSize, offset + totalFrameSize));\n _unmask(unmaskedPayload, maskKey);\n return unmaskedPayload;\n })()\n : Buffer.from(buffer.subarray(offset + headerSize, offset + totalFrameSize));\n\n return {\n frame: {\n fin,\n opcode,\n masked,\n payloadLength,\n payload,\n },\n bytesConsumed: totalFrameSize,\n };\n};\n\n/**\n * Encode an outgoing WebSocket frame (server→client, never masked).\n * Uses `Buffer.allocUnsafe` for performance — the entire buffer is written before use.\n */\nexport const _encodeFrame = (opcode: number, payload: Buffer, fin = true): Buffer => {\n const payloadLength = payload.length;\n let headerSize = 2;\n let extendedLengthWriter: ((buf: Buffer) => void) | undefined = undefined;\n\n if (payloadLength >= 126 && payloadLength < 65536) {\n headerSize = 4;\n extendedLengthWriter = (buf: Buffer): void => {\n buf.writeUInt16BE(payloadLength, 2);\n };\n } else if (payloadLength >= 65536) {\n headerSize = 10;\n extendedLengthWriter = (buf: Buffer): void => {\n buf.writeUInt32BE(0, 2); // upper 32 bits = 0\n buf.writeUInt32BE(payloadLength, 6);\n };\n }\n\n const frame = Buffer.allocUnsafe(headerSize + payloadLength);\n\n // Byte 0: FIN + opcode\n frame[0] = (fin ? 0x80 : 0x00) | opcode;\n\n // Byte 1: MASK=0 + payload length indicator\n if (payloadLength < 126) {\n frame[1] = payloadLength;\n } else if (payloadLength < 65536) {\n frame[1] = 126;\n } else {\n frame[1] = 127;\n }\n\n // Extended length bytes\n if (extendedLengthWriter) {\n extendedLengthWriter(frame);\n }\n\n // Copy payload into frame buffer\n payload.copy(frame, headerSize);\n\n return frame;\n};\n\n/**\n * Encode a close frame with a status code and optional reason string.\n * Close frame payload: 2-byte BE status code + optional UTF-8 reason text.\n * Total payload must be ≤125 bytes (control frame limit per RFC 6455 §5.5).\n */\nexport const _encodeCloseFrame = (code: number, reason?: string): Buffer => {\n const payload =\n reason ?\n ((): Buffer => {\n const reasonBytes = Buffer.from(reason, 'utf8');\n // Truncate reason to fit within 125-byte control frame payload limit (2 bytes for code)\n const maxReasonLength = Math.min(reasonBytes.length, 123);\n const buf = Buffer.allocUnsafe(2 + maxReasonLength);\n buf.writeUInt16BE(code, 0);\n reasonBytes.copy(buf, 2, 0, maxReasonLength);\n return buf;\n })()\n : ((): Buffer => {\n const buf = Buffer.allocUnsafe(2);\n buf.writeUInt16BE(code, 0);\n return buf;\n })();\n\n return _encodeFrame(OPCODE_CLOSE, payload);\n};\n",
|
|
62
|
+
"import type { Socket } from 'net';\nimport { _encodeCloseFrame, _encodeFrame, _parseFrame } from './WebSocketFrame.ts';\nimport type { WebSocketChannelManager } from './WebSocketChannelManager.ts';\nimport { wsCloseCode, wsOpcode, wsReadyState } from '@constants/websocket.ts';\nimport type { WebSocketBackpressureOptions, WebSocketHandlers } from '@typedefs/public/WebSocket.js';\n\n/**\n * Options passed to the WebSocketConnection constructor.\n */\ninterface ConnectionOptions {\n maxPayloadLength: number;\n idleTimeout: number;\n backpressure: Required<WebSocketBackpressureOptions>;\n}\n\n/**\n * Manages a single WebSocket connection's lifecycle over a raw TCP socket.\n *\n * This is a class (per coding rules: lifecycle management + shared socket state justifies it).\n * The class owns the socket event wiring, frame-level state machine, fragment reassembly,\n * backpressure tracking, and idle timeout management.\n *\n * @template T - Per-socket data type attached during upgrade\n */\nexport class WebSocketConnection<T = unknown> {\n private _readyState: number = wsReadyState.open;\n private readonly _socket: Socket;\n private readonly _data: T;\n private readonly _handlers: WebSocketHandlers<T>;\n private readonly _options: ConnectionOptions;\n private readonly _remoteAddress: string;\n\n // TCP chunk → frame reassembly\n private _receiveBuffer = Buffer.alloc(0);\n\n // WebSocket message fragment reassembly\n private _fragmentBuffers: Array<Buffer> = [];\n private _fragmentOpcode = 0;\n\n // Backpressure state\n private _backpressured = false;\n private _bufferedAmount = 0;\n\n // Idle timeout\n private _idleTimer: ReturnType<typeof setTimeout> | undefined;\n\n // Channel manager (set externally after construction)\n private _channelManager?: WebSocketChannelManager;\n\n // eslint-disable-next-line max-params\n constructor(socket: Socket, data: T, handlers: WebSocketHandlers<T>, options: ConnectionOptions) {\n this._socket = socket;\n this._data = data;\n this._handlers = handlers;\n this._options = options;\n this._remoteAddress = socket.remoteAddress ?? 'unknown';\n\n socket.on('data', (chunk: Buffer) => this._onSocketData(chunk));\n socket.on('close', () => this._onSocketClose());\n socket.on('error', (err: Error) => this._onSocketError(err));\n socket.on('drain', () => this._onSocketDrain());\n\n this._resetIdleTimeout();\n }\n\n // ============================================\n // Public API (implements WebSocket<T> interface)\n // ============================================\n\n get readyState(): number {\n return this._readyState;\n }\n\n get data(): T {\n return this._data;\n }\n\n get remoteAddress(): string {\n return this._remoteAddress;\n }\n\n get bufferedAmount(): number {\n return this._bufferedAmount;\n }\n\n setChannelManager(manager: WebSocketChannelManager): void {\n this._channelManager = manager;\n }\n\n send(data: Buffer | string): void {\n if (this._readyState !== wsReadyState.open) return;\n\n const isString = typeof data === 'string';\n const payload = isString ? Buffer.from(data, 'utf8') : data;\n const opcode = isString ? wsOpcode.text : wsOpcode.binary;\n const frame = _encodeFrame(opcode, payload);\n\n this._writeFrame(frame);\n }\n\n sendRaw(encodedFrame: Buffer): void {\n if (this._readyState !== wsReadyState.open) return;\n this._writeFrame(encodedFrame);\n }\n\n close(code: number = wsCloseCode.normal, reason?: string): void {\n if (this._readyState !== wsReadyState.open) return;\n\n this._readyState = wsReadyState.closing;\n const frame = _encodeCloseFrame(code, reason);\n this._socket.write(frame);\n\n // Give the client 5 seconds to echo the close frame before force-destroying\n setTimeout(() => {\n if (this._readyState !== wsReadyState.closed) {\n this._readyState = wsReadyState.closed;\n if (!this._socket.destroyed) {\n this._socket.destroy();\n }\n }\n }, 5000);\n }\n\n ping(data?: Buffer): void {\n if (this._readyState !== wsReadyState.open) return;\n const payload = data ?? Buffer.alloc(0);\n const frame = _encodeFrame(wsOpcode.ping, payload);\n this._socket.write(frame);\n }\n\n subscribe(channel: string): void {\n this._channelManager?.subscribe(this as WebSocketConnection, channel);\n }\n\n unsubscribe(channel: string): void {\n this._channelManager?.unsubscribe(this as WebSocketConnection, channel);\n }\n\n publish(channel: string, data: Buffer | string): number {\n return this._channelManager?.publish(channel, data, this as WebSocketConnection) ?? 0;\n }\n\n isSubscribed(channel: string): boolean {\n return this._channelManager?.isSubscribed(this as WebSocketConnection, channel) ?? false;\n }\n\n // ============================================\n // Socket event handlers\n // ============================================\n\n private _onSocketData(chunk: Buffer): void {\n if (this._readyState === wsReadyState.closed) return;\n\n this._resetIdleTimeout();\n\n // Append chunk to receive buffer\n this._receiveBuffer = this._receiveBuffer.length === 0 ? Buffer.from(chunk) : Buffer.concat([this._receiveBuffer, chunk]);\n\n // Parse all complete frames in the buffer\n let offset = 0;\n while (offset < this._receiveBuffer.length) {\n const result = _parseFrame(this._receiveBuffer, offset);\n if (result === null) break;\n\n const { frame, bytesConsumed } = result;\n offset += bytesConsumed;\n\n // RFC 6455 §5.1: server MUST close if client frame is not masked\n if (!frame.masked) {\n this.close(wsCloseCode.protocolError, 'Client frames must be masked');\n this._destroySocket();\n return;\n }\n\n // Max payload enforcement — check before processing\n if (frame.payloadLength > this._options.maxPayloadLength) {\n this.close(wsCloseCode.tooLarge, 'Payload too large');\n this._destroySocket();\n return;\n }\n\n this._handleFrame(frame);\n\n if (this._readyState === wsReadyState.closed) return;\n }\n\n // Keep unconsumed bytes for next chunk\n this._receiveBuffer = offset > 0 ? this._receiveBuffer.subarray(offset) : this._receiveBuffer;\n }\n\n private _onSocketClose(): void {\n this._clearIdleTimeout();\n this._channelManager?.unsubscribeAll(this as WebSocketConnection);\n if (this._readyState === wsReadyState.closed) return;\n\n const prevState = this._readyState;\n this._readyState = wsReadyState.closed;\n\n if (prevState !== wsReadyState.closed) {\n this._handlers.close?.(this._asPublic(), wsCloseCode.abnormal, 'Connection closed unexpectedly');\n }\n }\n\n private _onSocketError(error: Error): void {\n this._clearIdleTimeout();\n this._handlers.error?.(this._asPublic(), error);\n\n if (!this._socket.destroyed) {\n this._socket.destroy();\n }\n }\n\n private _onSocketDrain(): void {\n this._backpressured = false;\n this._bufferedAmount = 0;\n this._handlers.drain?.(this._asPublic());\n }\n\n // ============================================\n // Frame handling\n // ============================================\n\n private _handleFrame(frame: { fin: boolean; opcode: number; payload: Buffer }): void {\n const { fin, opcode, payload } = frame;\n\n // Control frames (opcode >= 0x8) — handle immediately, even mid-fragmentation\n if (opcode >= 0x8) {\n // RFC 6455 §5.5: control frames MUST NOT be fragmented and payload ≤125 bytes\n if (!fin) {\n this.close(wsCloseCode.protocolError, 'Control frames must not be fragmented');\n this._destroySocket();\n return;\n }\n if (payload.length > 125) {\n this.close(wsCloseCode.protocolError, 'Control frame payload exceeds 125 bytes');\n this._destroySocket();\n return;\n }\n this._handleControlFrame(opcode, payload);\n return;\n }\n\n // Data frames — handle fragmentation\n if (opcode === wsOpcode.continuation) {\n // Continuation frame\n this._fragmentBuffers.push(payload);\n\n if (fin) {\n // Final fragment — reassemble and deliver\n const completePayload = Buffer.concat(this._fragmentBuffers);\n const originalOpcode = this._fragmentOpcode;\n this._fragmentBuffers = [];\n this._fragmentOpcode = 0;\n this._deliverMessage(originalOpcode, completePayload);\n }\n } else if (fin) {\n // Complete single-frame message\n this._deliverMessage(opcode, payload);\n } else {\n // Start of fragmented message\n this._fragmentOpcode = opcode;\n this._fragmentBuffers = [payload];\n }\n }\n\n private _handleControlFrame(opcode: number, payload: Buffer): void {\n if (opcode === wsOpcode.ping) {\n // Respond with pong echoing the same payload\n if (this._readyState === wsReadyState.open) {\n const pongFrame = _encodeFrame(wsOpcode.pong, payload);\n this._socket.write(pongFrame);\n }\n return;\n }\n\n if (opcode === wsOpcode.pong) {\n // No action needed — pong is just a keepalive acknowledgment\n return;\n }\n\n if (opcode === wsOpcode.close) {\n const code = payload.length >= 2 ? payload.readUInt16BE(0) : wsCloseCode.noStatus;\n const reason = payload.length > 2 ? payload.subarray(2).toString('utf8') : '';\n\n if (this._readyState === wsReadyState.open) {\n // Client initiated close — echo the close frame back\n this._readyState = wsReadyState.closed;\n const echoFrame = _encodeCloseFrame(code, reason);\n this._socket.write(echoFrame);\n this._destroySocket();\n this._handlers.close?.(this._asPublic(), code, reason);\n } else if (this._readyState === wsReadyState.closing) {\n // We initiated close, client echoed — complete the handshake\n this._readyState = wsReadyState.closed;\n this._destroySocket();\n this._handlers.close?.(this._asPublic(), code, reason);\n }\n }\n }\n\n private _deliverMessage(opcode: number, payload: Buffer): void {\n if (this._readyState === wsReadyState.closed) return;\n\n const isBinary = opcode === wsOpcode.binary;\n const data = isBinary ? payload : payload.toString('utf8');\n this._handlers.message?.(this._asPublic(), data, isBinary);\n }\n\n // ============================================\n // Write with backpressure\n // ============================================\n\n private _writeFrame(frame: Buffer): void {\n if (this._backpressured) {\n if (this._options.backpressure.strategy === 'drop') {\n return;\n }\n // Buffer strategy — check if we'd exceed the limit\n this._bufferedAmount += frame.length;\n if (this._bufferedAmount > this._options.backpressure.limit) {\n this.close(wsCloseCode.tooLarge, 'Send buffer overflow');\n this._destroySocket();\n return;\n }\n }\n\n const flushed = this._socket.write(frame);\n if (!flushed) {\n this._backpressured = true;\n this._bufferedAmount += frame.length;\n }\n }\n\n // ============================================\n // Idle timeout\n // ============================================\n\n private _resetIdleTimeout(): void {\n this._clearIdleTimeout();\n if (this._options.idleTimeout > 0) {\n this._idleTimer = setTimeout(() => {\n this.close(wsCloseCode.normal, 'Idle timeout');\n setTimeout(() => this._destroySocket(), 1000);\n }, this._options.idleTimeout * 1000);\n }\n }\n\n private _clearIdleTimeout(): void {\n if (this._idleTimer) {\n clearTimeout(this._idleTimer);\n this._idleTimer = undefined;\n }\n }\n\n // ============================================\n // Helpers\n // ============================================\n\n private _destroySocket(): void {\n this._clearIdleTimeout();\n if (!this._socket.destroyed) {\n this._socket.destroy();\n }\n }\n\n /**\n * Return `this` cast to the public WebSocket<T> interface.\n * The class implements all WebSocket<T> properties/methods, so this is safe.\n */\n private _asPublic(): WebSocketConnection<T> {\n return this;\n }\n}\n",
|
|
63
|
+
"import { _encodeFrame } from './WebSocketFrame.ts';\nimport type { WebSocketConnection } from './WebSocketConnection.ts';\nimport { wsOpcode } from '@constants/websocket.ts';\n\n/**\n * Channel-based pub/sub engine for WebSocket connections.\n *\n * The critical performance feature is **encode-once broadcast**: when publishing\n * to a channel, the WebSocket frame is encoded once into raw bytes, then those\n * exact bytes are written to every subscriber's socket via `sendRaw`. This avoids\n * per-subscriber serialization — O(messageSize + N×write) instead of O(N×messageSize).\n *\n * Two bidirectional maps ensure O(subscriptions-per-connection) cleanup on disconnect:\n * - `_channels`: channel → Set of connections (for publishing)\n * - `_subscriptions`: connection → Set of channels (for cleanup)\n */\nexport class WebSocketChannelManager {\n private readonly _channels = new Map<string, Set<WebSocketConnection>>();\n private readonly _subscriptions = new Map<WebSocketConnection, Set<string>>();\n\n subscribe(connection: WebSocketConnection, channel: string): void {\n // Channel → connections map\n let subscribers = this._channels.get(channel);\n if (!subscribers) {\n subscribers = new Set();\n this._channels.set(channel, subscribers);\n }\n subscribers.add(connection);\n\n // Connection → channels map (for fast cleanup)\n let channels = this._subscriptions.get(connection);\n if (!channels) {\n channels = new Set();\n this._subscriptions.set(connection, channels);\n }\n channels.add(channel);\n }\n\n unsubscribe(connection: WebSocketConnection, channel: string): void {\n const subscribers = this._channels.get(channel);\n if (subscribers) {\n subscribers.delete(connection);\n if (subscribers.size === 0) {\n this._channels.delete(channel);\n }\n }\n\n const channels = this._subscriptions.get(connection);\n if (channels) {\n channels.delete(channel);\n if (channels.size === 0) {\n this._subscriptions.delete(connection);\n }\n }\n }\n\n unsubscribeAll(connection: WebSocketConnection): void {\n const channels = this._subscriptions.get(connection);\n if (!channels) return;\n\n for (const channel of channels) {\n const subscribers = this._channels.get(channel);\n if (subscribers) {\n subscribers.delete(connection);\n if (subscribers.size === 0) {\n this._channels.delete(channel);\n }\n }\n }\n\n this._subscriptions.delete(connection);\n }\n\n /**\n * Publish a message to all subscribers of a channel.\n * Encodes the WebSocket frame ONCE, then writes the raw bytes to each subscriber.\n * Optionally excludes the sender (so publishers don't echo their own messages).\n */\n publish(channel: string, data: Buffer | string, sender?: WebSocketConnection): number {\n const subscribers = this._channels.get(channel);\n if (!subscribers || subscribers.size === 0) return 0;\n\n // Encode once — all subscribers get the same pre-encoded frame bytes\n const isString = typeof data === 'string';\n const payload = isString ? Buffer.from(data, 'utf8') : data;\n const opcode = isString ? wsOpcode.text : wsOpcode.binary;\n const encodedFrame = _encodeFrame(opcode, payload);\n\n let recipientCount = 0;\n for (const connection of subscribers) {\n if (connection === sender) continue;\n connection.sendRaw(encodedFrame);\n recipientCount++;\n }\n\n return recipientCount;\n }\n\n subscriberCount(channel: string): number {\n return this._channels.get(channel)?.size ?? 0;\n }\n\n isSubscribed(connection: WebSocketConnection, channel: string): boolean {\n return this._subscriptions.get(connection)?.has(channel) ?? false;\n }\n\n channels(): Array<string> {\n return [...this._channels.keys()];\n }\n}\n",
|
|
64
|
+
"/**\n * WebSocket security: origin validation and per-IP connection tracking.\n */\nexport class WebSocketSecurity {\n private readonly _connectionCounts = new Map<string, number>();\n\n /**\n * Validate the Origin header against the allowed origins list.\n * Empty allowedOrigins = allow all (including missing origin).\n * Non-empty list = case-insensitive exact match required.\n */\n validateOrigin(origin: string | undefined, allowedOrigins: Array<string>): boolean {\n if (allowedOrigins.length === 0) return true;\n if (!origin) return false;\n\n const lowerOrigin = origin.toLowerCase();\n return allowedOrigins.some((allowed) => allowed.toLowerCase() === lowerOrigin);\n }\n\n /**\n * Check if an IP can open another connection (under the per-IP limit).\n */\n canConnect(ip: string, maxPerIp: number): boolean {\n const current = this._connectionCounts.get(ip) ?? 0;\n return current < maxPerIp;\n }\n\n /**\n * Track a new connection from an IP.\n */\n trackConnect(ip: string): void {\n const current = this._connectionCounts.get(ip) ?? 0;\n this._connectionCounts.set(ip, current + 1);\n }\n\n /**\n * Track a disconnection. Only decrements if the IP was tracked.\n */\n trackDisconnect(ip: string): void {\n const current = this._connectionCounts.get(ip);\n if (current === undefined) return;\n\n if (current <= 1) {\n this._connectionCounts.delete(ip);\n } else {\n this._connectionCounts.set(ip, current - 1);\n }\n }\n\n /**\n * Get current connection count for an IP (for monitoring).\n */\n connectionCount(ip: string): number {\n return this._connectionCounts.get(ip) ?? 0;\n }\n}\n"
|
|
57
65
|
],
|
|
58
|
-
"mappings": "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",
|
|
59
|
-
"debugId": "
|
|
66
|
+
"mappings": "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",
|
|
67
|
+
"debugId": "0EF35157C891F4AC64756E2164756E21",
|
|
60
68
|
"names": []
|
|
61
69
|
}
|