blaizejs 0.5.3 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/dist/{chunk-VVEKNV22.js → chunk-CM6LIHRF.js} +3 -3
  2. package/dist/{chunk-ZBJU7ZOM.js → chunk-FLI2OVQ5.js} +3 -3
  3. package/dist/{chunk-BOFAGA5B.js → chunk-HQRQVJL6.js} +3 -3
  4. package/dist/{chunk-NXPSLUP5.js → chunk-J5FJFX2G.js} +3 -3
  5. package/dist/{chunk-JMYOXYX4.js → chunk-MZG6O7BX.js} +2 -2
  6. package/dist/{chunk-JMYOXYX4.js.map → chunk-MZG6O7BX.js.map} +1 -1
  7. package/dist/index.cjs +16 -14
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.d.cts +3014 -1689
  10. package/dist/index.d.ts +3014 -1689
  11. package/dist/index.js +17 -15
  12. package/dist/index.js.map +1 -1
  13. package/dist/{internal-server-error-MIWZOL6G.js → internal-server-error-RRNSAEYK.js} +3 -3
  14. package/dist/{payload-too-large-error-INCZ2WM7.js → payload-too-large-error-SQMCGPZ7.js} +3 -3
  15. package/dist/{unsupported-media-type-error-BVGBPGOM.js → unsupported-media-type-error-6T47SVVY.js} +3 -3
  16. package/dist/{validation-error-BQK2BTX6.js → validation-error-DRCBJ7IF.js} +3 -3
  17. package/package.json +2 -2
  18. /package/dist/{chunk-VVEKNV22.js.map → chunk-CM6LIHRF.js.map} +0 -0
  19. /package/dist/{chunk-ZBJU7ZOM.js.map → chunk-FLI2OVQ5.js.map} +0 -0
  20. /package/dist/{chunk-BOFAGA5B.js.map → chunk-HQRQVJL6.js.map} +0 -0
  21. /package/dist/{chunk-NXPSLUP5.js.map → chunk-J5FJFX2G.js.map} +0 -0
  22. /package/dist/{internal-server-error-MIWZOL6G.js.map → internal-server-error-RRNSAEYK.js.map} +0 -0
  23. /package/dist/{payload-too-large-error-INCZ2WM7.js.map → payload-too-large-error-SQMCGPZ7.js.map} +0 -0
  24. /package/dist/{unsupported-media-type-error-BVGBPGOM.js.map → unsupported-media-type-error-6T47SVVY.js.map} +0 -0
  25. /package/dist/{validation-error-BQK2BTX6.js.map → validation-error-DRCBJ7IF.js.map} +0 -0
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/middleware/execute.ts","../src/middleware/compose.ts","../src/errors/forbidden-error.ts","../src/middleware/create.ts","../src/middleware/cors/defaults.ts","../src/middleware/cors/origin-validator.ts","../src/middleware/cors/preflight.ts","../src/middleware/cors/validation.ts","../src/middleware/cors/index.ts","../src/plugins/create.ts","../src/router/create.ts","../src/config.ts","../src/router/discovery/parser.ts","../src/sse/stream.ts","../src/sse/back-pressure.ts","../src/sse/connection-registry.ts","../src/errors/sse-buffer-overflow-error.ts","../src/errors/sse-stream-closed-error.ts","../src/errors/sse-not-acceptable-error.ts","../src/sse/create.ts","../src/router/matching/params.ts","../src/router/matching/matcher.ts","../src/server/create.ts","../src/server/start.ts","../src/server/dev-certificate.ts","../src/context/errors.ts","../src/context/store.ts","../src/upload/multipart-parser.ts","../src/upload/utils.ts","../src/context/create.ts","../src/errors/not-found-error.ts","../src/errors/boundary.ts","../src/middleware/error-boundary.ts","../src/server/request-handler.ts","../src/server/stop.ts","../src/server/validation.ts","../src/plugins/lifecycle.ts","../src/plugins/errors.ts","../src/plugins/validation.ts","../src/router/discovery/cache.ts","../src/router/discovery/loader.ts","../src/router/discovery/parallel.ts","../src/router/discovery/finder.ts","../src/router/discovery/profiler.ts","../src/router/discovery/watchers.ts","../src/router/validation/schema.ts","../src/router/validation/body.ts","../src/router/validation/params.ts","../src/router/validation/query.ts","../src/router/validation/response.ts","../src/router/handlers/executor.ts","../src/router/registry/fast-registry.ts","../src/router/utils/matching-helpers.ts","../src/router/router.ts","../src/server/types.ts","../../blaize-types/src/composition.ts","../src/errors/unauthorized-error.ts","../src/errors/conflict-error.ts","../src/errors/rate-limit-error.ts","../src/errors/request-timeout-error.ts","../src/errors/unprocessable-entity-error.ts","../src/errors/service-not-available-error.ts","../src/index.ts"],"sourcesContent":["import type { Context } from '@blaize-types/context';\nimport type { Middleware, NextFunction } from '@blaize-types/middleware';\n\n/**\n * Execute a single middleware, handling both function and object forms\n */\nexport function execute(\n middleware: Middleware | undefined,\n ctx: Context,\n next: NextFunction\n): Promise<void> {\n // Handle undefined middleware (safety check)\n if (!middleware) {\n return Promise.resolve(next());\n }\n\n // Handle middleware with skip function\n if (middleware.skip && middleware.skip(ctx)) {\n return Promise.resolve(next());\n }\n\n try {\n // Execute middleware\n const result = middleware.execute(ctx, next);\n\n // Handle both Promise and non-Promise returns\n if (result instanceof Promise) {\n // Return the promise directly to allow errors to propagate\n return result;\n } else {\n // Only wrap non-Promise returns\n return Promise.resolve(result);\n }\n } catch (error) {\n // Handle synchronous errors\n return Promise.reject(error);\n }\n}\n","import { execute } from './execute';\n\nimport type { Context } from '@blaize-types/context';\nimport type { Middleware, NextFunction, MiddlewareFunction } from '@blaize-types/middleware';\n\n/**\n * Compose multiple middleware functions into a single middleware function\n */\nexport function compose(middlewareStack: Middleware[]): MiddlewareFunction {\n // No middleware? Return a pass-through function\n if (middlewareStack.length === 0) {\n return async (_, next) => {\n await Promise.resolve(next());\n };\n }\n\n // Return a function that executes the middleware stack\n return async function (ctx: Context, finalHandler: NextFunction): Promise<void> {\n // Keep track of which \"next\" functions have been called\n const called = new Set<number>();\n\n // Create dispatch function to process middleware stack\n const dispatch = async (i: number): Promise<void> => {\n // If we've reached the end of the stack, execute the final handler\n if (i >= middlewareStack.length) {\n // Ensure we're returning a Promise regardless of what finalHandler returns\n return Promise.resolve(finalHandler());\n }\n\n // Get current middleware\n const middleware = middlewareStack[i];\n\n // Create a next function that can only be called once\n const nextDispatch = () => {\n if (called.has(i)) {\n throw new Error('next() called multiple times');\n }\n\n // Mark this middleware's next as called\n called.add(i);\n\n // Move to the next middleware\n return dispatch(i + 1);\n };\n\n // Use the executeMiddleware function we defined\n return execute(middleware, ctx, nextDispatch);\n };\n\n // Start middleware chain execution\n return dispatch(0);\n };\n}\n","/**\n * ForbiddenError class for authorization failures\n *\n * This error is thrown when a user lacks permission to access a resource.\n * It provides context about required permissions and access control.\n */\n\nimport { BlaizeError, ErrorType } from '@blaize-types/errors';\n\nimport { getCorrelationId } from '../tracing/correlation';\n\nimport type { ForbiddenErrorDetails } from '@blaize-types/errors';\n\n/**\n * Error thrown when user lacks permission to access a resource\n *\n * Automatically sets HTTP status to 403 and provides permission context.\n *\n * @example Basic usage:\n * ```typescript\n * throw new ForbiddenError('Access denied');\n * ```\n *\n * @example With permission details:\n * ```typescript\n * throw new ForbiddenError('Insufficient permissions', {\n * requiredPermission: 'admin:users:delete',\n * userPermissions: ['admin:users:read'],\n * resource: 'user-123',\n * action: 'delete'\n * });\n * ```\n */\nexport class ForbiddenError extends BlaizeError<ForbiddenErrorDetails> {\n /**\n * Creates a new ForbiddenError instance\n *\n * @param title - Human-readable error message\n * @param details - Optional permission context\n * @param correlationId - Optional correlation ID (uses current context if not provided)\n */\n constructor(\n title: string,\n details: ForbiddenErrorDetails | undefined = undefined,\n correlationId: string | undefined = undefined\n ) {\n super(\n ErrorType.FORBIDDEN,\n title,\n 403, // HTTP 403 Forbidden\n correlationId ?? getCorrelationId(),\n details\n );\n }\n}\n","/* eslint-disable @typescript-eslint/no-empty-object-type */\nimport type { Middleware, MiddlewareOptions, MiddlewareFunction } from '@blaize-types/middleware';\n\n/**\n * Create a middleware\n */\nexport function create<TState = {}, TServices = {}>(\n handlerOrOptions: MiddlewareFunction | MiddlewareOptions\n): Middleware<TState, TServices> {\n // If handlerOrOptions is a function, convert it to our middleware object format\n if (typeof handlerOrOptions === 'function') {\n return {\n name: 'anonymous', // Default name for function middleware\n execute: handlerOrOptions,\n debug: false,\n } as Middleware<TState, TServices>;\n }\n\n // Otherwise, handle it as middleware options\n const { name = 'anonymous', handler, skip, debug = false } = handlerOrOptions;\n\n // Create base middleware object with required properties\n const middleware = {\n name,\n execute: handler,\n debug,\n ...(skip !== undefined && { skip }),\n } as Middleware<TState, TServices>;\n\n return middleware;\n}\n\n/**\n * Create a middleware that only contributes state (no services)\n * Convenience helper for state-only middleware\n *\n * @template T - Type of state to contribute\n * @param handler - Middleware function that adds state\n * @returns Middleware that contributes state only\n *\n */\nexport function stateMiddleware<T = {}>(handler: MiddlewareFunction): Middleware<T, {}> {\n return create<T, {}>({\n name: 'state-middleware',\n handler,\n });\n}\n\n/**\n * Create a middleware that only contributes services (no state)\n * Convenience helper for service-only middleware\n *\n * @template T - Type of services to contribute\n * @param handler - Middleware function that adds services\n * @returns Middleware that contributes services only\n *\n */\nexport function serviceMiddleware<T = {}>(handler: MiddlewareFunction): Middleware<{}, T> {\n return create<{}, T>({\n name: 'service-middleware',\n handler,\n });\n}\n","/**\n * CORS Default Configurations\n *\n * Environment-aware default configurations for CORS middleware.\n * Provides secure defaults for production and permissive defaults for development.\n *\n * SECURITY IMPLICATIONS:\n *\n * Development Mode (NODE_ENV !== 'production'):\n * - Allows ALL origins (wildcard '*')\n * - No credentials allowed with wildcard (security requirement)\n * - All common HTTP methods allowed\n * - Suitable for local development and testing\n * - WARNING: Never use in production as it allows any website to make requests\n *\n * Production Mode (NODE_ENV === 'production'):\n * - Denies all cross-origin requests by default (origin: false)\n * - Only GET and HEAD methods allowed (read-only)\n * - No credentials by default\n * - Forces explicit origin configuration for security\n * - Requires deliberate configuration of allowed origins\n *\n * @module @blaize-core/middleware/cors/defaults\n */\n\nimport type { CorsOptions } from '@blaize-types/cors';\n\n/**\n * Development environment CORS defaults\n *\n * SECURITY WARNING: These settings are ONLY for development.\n * They allow any origin to access your API, which is a security risk in production.\n *\n * Features:\n * - origin: true (allows all origins)\n * - credentials: false (prevents credential sharing with wildcard)\n * - methods: All common HTTP methods\n * - optionsSuccessStatus: 204 (standard)\n *\n * @internal\n */\nconst DEVELOPMENT_DEFAULTS: CorsOptions = {\n origin: true, // Allow all origins in development\n methods: ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'],\n credentials: false, // Cannot use credentials with wildcard origin\n optionsSuccessStatus: 204,\n};\n\n/**\n * Production environment CORS defaults\n *\n * SECURITY: These settings are restrictive by default.\n * Cross-origin requests are denied unless explicitly configured.\n *\n * Features:\n * - origin: false (denies all cross-origin requests)\n * - methods: Only GET and HEAD (read-only)\n * - credentials: false (no credential sharing)\n * - optionsSuccessStatus: 204 (standard)\n *\n * To allow cross-origin requests in production, you must explicitly set:\n * - origin: specific domain(s) or validation function\n * - methods: only the methods your API actually needs\n * - credentials: true only if necessary for authentication\n *\n * @internal\n */\nconst PRODUCTION_DEFAULTS: CorsOptions = {\n origin: false, // Deny all cross-origin requests by default\n methods: ['GET', 'HEAD'], // Only safe methods by default\n credentials: false, // No credentials by default\n optionsSuccessStatus: 204,\n};\n\n/**\n * Get default CORS options based on environment\n *\n * Automatically detects the environment and returns appropriate defaults.\n * Uses NODE_ENV environment variable to determine if in production.\n *\n * @param isDevelopment - Override environment detection (optional)\n * @returns CORS options with environment-appropriate defaults\n *\n * @example\n * ```typescript\n * // Automatic environment detection\n * const options = getDefaultCorsOptions();\n *\n * // Force development mode\n * const devOptions = getDefaultCorsOptions(true);\n *\n * // Force production mode\n * const prodOptions = getDefaultCorsOptions(false);\n * ```\n *\n * @security\n * In production, this returns restrictive defaults that deny all cross-origin\n * requests. You must explicitly configure allowed origins to enable CORS.\n *\n * Example production configuration:\n * ```typescript\n * const corsOptions = {\n * ...getDefaultCorsOptions(),\n * origin: 'https://app.example.com', // Explicit origin\n * credentials: true, // If needed for auth\n * };\n * ```\n */\nexport function getDefaultCorsOptions(isDevelopment?: boolean): CorsOptions {\n // If isDevelopment is not provided, detect from environment\n if (isDevelopment === undefined) {\n isDevelopment = process.env.NODE_ENV !== 'production';\n }\n\n return isDevelopment ? { ...DEVELOPMENT_DEFAULTS } : { ...PRODUCTION_DEFAULTS };\n}\n\n/**\n * Detect if running in development environment\n *\n * @returns True if in development mode\n */\nexport function isDevelopmentEnvironment(): boolean {\n return process.env.NODE_ENV !== 'production';\n}\n\n/**\n * Get environment name for logging\n *\n * @returns Current environment name\n */\nexport function getEnvironmentName(): string {\n return process.env.NODE_ENV || 'development';\n}\n\n/**\n * Validate that production configuration is secure\n *\n * Checks if CORS options are appropriate for production use.\n * Logs warnings if insecure configurations are detected.\n *\n * @param options - CORS options to validate\n * @returns True if configuration appears secure\n */\nexport function validateProductionConfig(options: CorsOptions): boolean {\n const warnings: string[] = [];\n\n // Check for wildcard origin in production\n if (options.origin === true || options.origin === '*') {\n warnings.push('SECURITY WARNING: Wildcard origin (*) should not be used in production');\n }\n\n // Check for credentials with permissive origin\n if (options.credentials === true && (options.origin === true || options.origin === '*')) {\n warnings.push('SECURITY ERROR: Cannot use credentials with wildcard origin');\n // Log warnings before returning false\n if (!isDevelopmentEnvironment() && warnings.length > 0) {\n warnings.forEach(warning => console.warn(`[CORS] ${warning}`));\n }\n return false; // This is a hard error\n }\n\n // Check for overly permissive methods\n const methods = options.methods || [];\n const methodsList = typeof methods === 'string' ? methods.split(',').map(m => m.trim()) : methods;\n\n if (\n methodsList.includes('DELETE') ||\n methodsList.includes('CONNECT') ||\n methodsList.includes('TRACE')\n ) {\n warnings.push('SECURITY WARNING: Dangerous HTTP methods (DELETE, CONNECT, TRACE) are allowed');\n }\n\n // Log warnings if in production\n if (!isDevelopmentEnvironment() && warnings.length > 0) {\n warnings.forEach(warning => console.warn(`[CORS] ${warning}`));\n }\n\n return warnings.length === 0;\n}\n","/**\n * Origin Validation Module for CORS\n *\n * Provides origin validation with LRU caching for performance optimization.\n * Supports string matching, regex patterns, and async function evaluation\n * with timeout protection.\n */\n\nimport type { Context } from '@blaize-types/context';\nimport type { CacheConfig, CacheEntry, CorsOrigin } from '@blaize-types/cors';\n\n/**\n * Create an LRU cache for origin validation\n *\n * Using a functional approach with closure for state management\n */\nfunction createOriginCache(ttl: number = 60000, maxSize: number = 1000) {\n const cache = new Map<string, CacheEntry>();\n const config: CacheConfig = { ttl, maxSize };\n\n /**\n * Generate cache key from origin, configured origin identifier, and optional user ID\n * We need to include a representation of the configured origin to prevent incorrect cache hits\n */\n const getCacheKey = (origin: string, configOriginId: string, userId?: string): string => {\n return `${origin}:${configOriginId}:${userId || 'anonymous'}`;\n };\n\n /**\n * Evict least recently used entry when at capacity\n */\n const evictLRU = (): void => {\n if (cache.size === 0) return;\n\n let lruKey: string | null = null;\n let lruTime = Infinity; // Start with Infinity, not Date.now()\n\n // Find least recently used entry (oldest lastAccessed time)\n for (const [key, entry] of cache.entries()) {\n if (entry.lastAccessed < lruTime) {\n lruTime = entry.lastAccessed;\n lruKey = key;\n }\n }\n\n if (lruKey) {\n cache.delete(lruKey);\n }\n };\n\n /**\n * Get cached validation result if not expired\n */\n const get = (origin: string, configOriginId: string, userId?: string): boolean | null => {\n const key = getCacheKey(origin, configOriginId, userId);\n const entry = cache.get(key);\n\n if (!entry) {\n return null;\n }\n\n // Check if expired\n const now = Date.now();\n if (now > entry.expiresAt) {\n cache.delete(key);\n return null;\n }\n\n // Update last accessed time for LRU\n entry.lastAccessed = now;\n return entry.allowed;\n };\n\n /**\n * Set validation result in cache\n */\n const set = (origin: string, allowed: boolean, configOriginId: string, userId?: string): void => {\n const key = getCacheKey(origin, configOriginId, userId);\n const now = Date.now();\n\n // If key already exists, just update it\n if (cache.has(key)) {\n cache.set(key, {\n allowed,\n expiresAt: now + config.ttl,\n lastAccessed: now,\n });\n return;\n }\n\n // Adding new key - check if we need to evict\n if (cache.size >= config.maxSize) {\n evictLRU();\n }\n\n cache.set(key, {\n allowed,\n expiresAt: now + config.ttl,\n lastAccessed: now,\n });\n };\n\n /**\n * Clear all cache entries\n */\n const clear = (): void => {\n cache.clear();\n };\n\n /**\n * Clean up expired entries\n */\n const cleanExpired = (): number => {\n const now = Date.now();\n let cleaned = 0;\n\n for (const [key, entry] of cache.entries()) {\n if (now > entry.expiresAt) {\n cache.delete(key);\n cleaned++;\n }\n }\n\n return cleaned;\n };\n\n /**\n * Get cache statistics\n */\n const getStats = () => ({\n size: cache.size,\n maxSize: config.maxSize,\n ttl: config.ttl,\n });\n\n return {\n get,\n set,\n clear,\n cleanExpired,\n getStats,\n };\n}\n\n/**\n * Default cache instance (module-level singleton)\n */\nlet defaultCache = createOriginCache();\n\n/**\n * Replace the default cache (useful for testing)\n */\nexport function setOriginCache(ttl: number = 60000, maxSize: number = 1000): void {\n defaultCache = createOriginCache(ttl, maxSize);\n}\n\n/**\n * Reset to default cache configuration\n */\nexport function resetOriginCache(): void {\n defaultCache = createOriginCache();\n}\n\n/**\n * Get cache statistics\n */\nexport function getCacheStats() {\n return defaultCache.getStats();\n}\n\n/**\n * Clean expired cache entries\n */\nexport function cleanExpiredCacheEntries(): number {\n return defaultCache.cleanExpired();\n}\n\n/**\n * Determine if a configured origin is cacheable\n * Only string and RegExp origins are cacheable\n */\nfunction isCacheable(configuredOrigin: CorsOrigin | boolean): boolean {\n // Booleans are instant - no need to cache\n if (typeof configuredOrigin === 'boolean') {\n return false;\n }\n\n // Functions are unpredictable - shouldn't cache\n if (typeof configuredOrigin === 'function') {\n return false;\n }\n\n // Arrays may contain functions - check all elements\n if (Array.isArray(configuredOrigin)) {\n return configuredOrigin.every(origin => typeof origin === 'string' || origin instanceof RegExp);\n }\n\n // String and RegExp are cacheable\n return typeof configuredOrigin === 'string' || configuredOrigin instanceof RegExp;\n}\n\n/**\n * Generate a stable identifier for a configured origin\n * This is used as part of the cache key\n * Only called for cacheable origins\n */\nfunction getConfigOriginId(configuredOrigin: CorsOrigin | boolean): string {\n if (typeof configuredOrigin === 'string') {\n return `str:${configuredOrigin}`;\n }\n if (configuredOrigin instanceof RegExp) {\n return `regex:${configuredOrigin.source}:${configuredOrigin.flags}`;\n }\n if (Array.isArray(configuredOrigin)) {\n // For arrays, create a composite ID from the elements\n return `array:[${configuredOrigin\n .map(o => {\n if (typeof o === 'string') return `str:${o}`;\n if (o instanceof RegExp) return `regex:${o.source}:${o.flags}`;\n return 'unknown';\n })\n .join(',')}]`;\n }\n // This shouldn't be reached for cacheable origins\n return 'unknown';\n}\n\n/**\n * Validate origin string against configured origin\n */\nasync function validateStringOrigin(\n requestOrigin: string,\n configuredOrigin: string\n): Promise<boolean> {\n // Handle wildcard\n if (configuredOrigin === '*') {\n return true;\n }\n\n // Exact match (case-sensitive as per spec)\n return requestOrigin === configuredOrigin;\n}\n\n/**\n * Validate origin against regex pattern\n */\nasync function validateRegExpOrigin(\n requestOrigin: string,\n configuredOrigin: RegExp\n): Promise<boolean> {\n return configuredOrigin.test(requestOrigin);\n}\n\n/**\n * Validate origin using async function with timeout\n */\nasync function validateFunctionOrigin(\n requestOrigin: string,\n configuredOrigin: (origin: string, ctx?: Context<any, any>) => boolean | Promise<boolean>,\n ctx?: Context<any, any>,\n timeoutMs: number = 100\n): Promise<boolean> {\n let timeoutId: NodeJS.Timeout | undefined;\n\n try {\n // Create a timeout promise that resolves (not rejects) with a timeout flag\n const timeoutPromise = new Promise<{ timedOut: true }>(resolve => {\n timeoutId = setTimeout(() => {\n resolve({ timedOut: true });\n }, timeoutMs);\n });\n\n // Race between the validation function and timeout\n const result = await Promise.race([\n Promise.resolve(configuredOrigin(requestOrigin, ctx)).then(r => ({ result: r })),\n timeoutPromise,\n ]);\n\n // Clear timeout if validation completed\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n\n // Check if we timed out\n if ('timedOut' in result) {\n console.warn(\n `CORS origin validation function timed out after ${timeoutMs}ms for origin: ${requestOrigin}`\n );\n return false;\n }\n\n return result.result;\n } catch (error) {\n // Clear timeout on error\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n console.error('CORS origin validation function error:', error);\n return false; // Deny on error\n }\n}\n\n/**\n * Validate origin against an array of validators\n */\nasync function validateArrayOrigin(\n requestOrigin: string,\n configuredOrigins: Array<\n string | RegExp | ((origin: string, ctx?: Context<any, any>) => boolean | Promise<boolean>)\n >,\n ctx?: Context<any, any>\n): Promise<boolean> {\n // Check each origin in parallel for performance\n const validations = configuredOrigins.map(origin =>\n validateSingleOrigin(requestOrigin, origin, ctx)\n );\n\n const results = await Promise.all(validations);\n return results.some(result => result === true);\n}\n\n/**\n * Validate a single origin (handles all non-array types)\n */\nasync function validateSingleOrigin(\n requestOrigin: string,\n configuredOrigin:\n | string\n | RegExp\n | ((origin: string, ctx?: Context<any, any>) => boolean | Promise<boolean>),\n ctx?: Context<any, any>\n): Promise<boolean> {\n if (typeof configuredOrigin === 'string') {\n return validateStringOrigin(requestOrigin, configuredOrigin);\n }\n\n if (configuredOrigin instanceof RegExp) {\n return validateRegExpOrigin(requestOrigin, configuredOrigin);\n }\n\n if (typeof configuredOrigin === 'function') {\n return validateFunctionOrigin(requestOrigin, configuredOrigin, ctx);\n }\n\n // Unknown type, deny for safety\n console.warn('Unknown CORS origin type:', typeof configuredOrigin);\n return false;\n}\n\n/**\n * Main origin validation function with caching\n *\n * @param requestOrigin - The Origin header from the request\n * @param configuredOrigin - The configured CORS origin setting\n * @param ctx - Optional context for user-based caching\n * @returns Promise resolving to whether origin is allowed\n */\nexport async function validateOrigin(\n requestOrigin: string,\n configuredOrigin: CorsOrigin | boolean,\n ctx?: Context<any, any>\n): Promise<boolean> {\n // Handle boolean shortcuts\n if (configuredOrigin === true) {\n return true; // Allow all origins\n }\n if (configuredOrigin === false) {\n return false; // Deny all origins\n }\n\n // Determine if this origin configuration is cacheable\n const cacheable = isCacheable(configuredOrigin);\n\n // Only use cache for cacheable origins (string, RegExp, or arrays of them)\n if (cacheable) {\n // Get user ID for cache key (if available)\n const userId = ctx?.state?.user?.id || ctx?.state?.userId;\n\n // Generate a stable identifier for the configured origin\n const configOriginId = getConfigOriginId(configuredOrigin);\n\n // Check cache first\n const cached = defaultCache.get(requestOrigin, configOriginId, userId);\n if (cached !== null) {\n return cached;\n }\n\n // Perform validation\n let allowed: boolean;\n\n if (Array.isArray(configuredOrigin)) {\n // Type assertion to ensure array elements are the right type\n allowed = await validateArrayOrigin(\n requestOrigin,\n configuredOrigin as Array<\n | string\n | RegExp\n | ((origin: string, ctx?: Context<any, any>) => boolean | Promise<boolean>)\n >,\n ctx\n );\n } else {\n allowed = await validateSingleOrigin(requestOrigin, configuredOrigin, ctx);\n }\n\n // Cache the result\n defaultCache.set(requestOrigin, allowed, configOriginId, userId);\n\n return allowed;\n } else {\n // Non-cacheable origin (function, boolean, or array with functions)\n // Perform validation without caching\n if (Array.isArray(configuredOrigin)) {\n return validateArrayOrigin(\n requestOrigin,\n configuredOrigin as Array<\n | string\n | RegExp\n | ((origin: string, ctx?: Context<any, any>) => boolean | Promise<boolean>)\n >,\n ctx\n );\n } else {\n return validateSingleOrigin(requestOrigin, configuredOrigin, ctx);\n }\n }\n}\n\n/**\n * Validate that credentials aren't used with wildcard origin\n * This should be called during configuration validation\n */\nexport function validateCredentialsWithOrigin(\n configuredOrigin: CorsOrigin | boolean,\n credentials: boolean\n): void {\n if (!credentials) {\n return; // No restriction when credentials are false\n }\n\n // Check for wildcard with credentials\n if (configuredOrigin === true || configuredOrigin === '*') {\n throw new Error(\n 'CORS security violation: Cannot use wildcard origin with credentials=true. ' +\n 'Specify explicit origins when credentials are enabled.'\n );\n }\n\n // Check for wildcard in array\n if (Array.isArray(configuredOrigin)) {\n const hasWildcard = configuredOrigin.some(origin => origin === '*');\n if (hasWildcard) {\n throw new Error(\n 'CORS security violation: Cannot include wildcard (*) in origin array with credentials=true.'\n );\n }\n }\n}\n\n/**\n * Performance optimization: Pre-validate common origins\n * Can be called during server startup\n */\nexport async function prevalidateOrigins(\n origins: string[],\n configuredOrigin: CorsOrigin | boolean,\n ctx?: Context<any, any>\n): Promise<void> {\n const validations = origins.map(origin => validateOrigin(origin, configuredOrigin, ctx));\n\n await Promise.all(validations);\n}\n\n/**\n * Periodically clean expired cache entries (optional)\n * Returns a cleanup function to stop the interval\n */\nexport function startCacheCleanup(intervalMs: number = 60000): () => void {\n const interval = setInterval(() => {\n const cleaned = defaultCache.cleanExpired();\n if (cleaned > 0) {\n console.debug(`Cleaned ${cleaned} expired CORS cache entries`);\n }\n }, intervalMs);\n\n return () => clearInterval(interval);\n}\n","/**\n * CORS Preflight Request Handler\n *\n * Handles OPTIONS requests for CORS preflight checks according to W3C spec.\n * Validates requested methods and headers, sets appropriate response headers,\n * and returns 403 Forbidden on validation failures.\n */\n\nimport { validateOrigin } from './origin-validator';\nimport { ValidationError } from '../../errors/validation-error';\n\nimport type { Context } from '@blaize-types/context';\nimport type { CorsOptions } from '@blaize-types/cors';\n\n/**\n * Extract Access-Control-Request-* headers from OPTIONS request\n */\ninterface PreflightRequest {\n origin: string | undefined;\n requestedMethod: string | undefined;\n requestedHeaders: string[] | undefined;\n}\n\n/**\n * Parse preflight request headers\n */\nfunction parsePreflightRequest(ctx: Context): PreflightRequest {\n // Extract origin using the context's header method\n const origin = ctx.request.header('origin') || ctx.request.header('Origin');\n\n // Extract requested method (case-insensitive header name)\n const requestedMethod =\n ctx.request.header('access-control-request-method') ||\n ctx.request.header('Access-Control-Request-Method');\n\n // Extract requested headers (comma-delimited string)\n const requestedHeadersRaw =\n ctx.request.header('access-control-request-headers') ||\n ctx.request.header('Access-Control-Request-Headers');\n\n const requestedHeaders = requestedHeadersRaw\n ? requestedHeadersRaw.split(',').map(h => h.trim().toLowerCase())\n : undefined;\n\n return {\n origin,\n requestedMethod,\n requestedHeaders,\n };\n}\n\n/**\n * Normalize method names for comparison\n * HTTP methods are case-sensitive per spec\n */\nfunction normalizeMethod(method: string): string {\n return method.toUpperCase();\n}\n\n/**\n * Check if a method is allowed\n */\nfunction isMethodAllowed(\n requestedMethod: string,\n allowedMethods: string[] | string | undefined\n): boolean {\n if (!allowedMethods) {\n // Default allowed methods per W3C spec\n const defaults = ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'];\n return defaults.includes(normalizeMethod(requestedMethod));\n }\n\n // Convert to array if string\n const methodsArray =\n typeof allowedMethods === 'string'\n ? allowedMethods.split(',').map(m => m.trim())\n : allowedMethods;\n\n return methodsArray.map(m => normalizeMethod(m)).includes(normalizeMethod(requestedMethod));\n}\n\n/**\n * Check if headers are allowed\n * Headers are case-insensitive per HTTP spec\n */\nfunction areHeadersAllowed(\n requestedHeaders: string[] | undefined,\n allowedHeaders: string[] | string | undefined\n): boolean {\n // If no headers requested, always allowed\n if (!requestedHeaders || requestedHeaders.length === 0) {\n return true;\n }\n\n // If allowedHeaders is undefined, mirror the requested headers (permissive)\n if (allowedHeaders === undefined) {\n return true;\n }\n\n // Convert to array if string\n const allowedArray =\n typeof allowedHeaders === 'string'\n ? allowedHeaders.split(',').map(h => h.trim().toLowerCase())\n : allowedHeaders.map(h => h.toLowerCase());\n\n // Check if all requested headers are in allowed list\n return requestedHeaders.every(header => allowedArray.includes(header.toLowerCase()));\n}\n\n/**\n * Set CORS response headers for preflight\n */\nfunction setPreflightHeaders(\n ctx: Context,\n options: CorsOptions,\n origin: string,\n originAllowed: boolean\n): void {\n // Set origin header based on validation result\n if (originAllowed) {\n if (options.origin === true && !options.credentials) {\n // Wildcard allowed when credentials not enabled\n ctx.response.header('Access-Control-Allow-Origin', '*');\n } else {\n // Reflect the specific origin\n ctx.response.header('Access-Control-Allow-Origin', origin);\n // Add Vary header when origin is dynamic\n ctx.response.header('Vary', 'Origin');\n }\n }\n\n // Set credentials header if enabled\n if (options.credentials && originAllowed) {\n ctx.response.header('Access-Control-Allow-Credentials', 'true');\n }\n\n // Set allowed methods\n const methods = options.methods || ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'];\n const methodsString = typeof methods === 'string' ? methods : methods.join(', ');\n ctx.response.header('Access-Control-Allow-Methods', methodsString);\n\n // Set allowed headers\n if (options.allowedHeaders) {\n const headers =\n typeof options.allowedHeaders === 'string'\n ? options.allowedHeaders\n : options.allowedHeaders.join(', ');\n ctx.response.header('Access-Control-Allow-Headers', headers);\n } else {\n // Mirror requested headers if not specified\n const requestedHeaders =\n ctx.request.header('access-control-request-headers') ||\n ctx.request.header('Access-Control-Request-Headers');\n if (requestedHeaders) {\n ctx.response.header('Access-Control-Allow-Headers', requestedHeaders);\n }\n }\n\n // Set max age if specified\n if (options.maxAge !== undefined && options.maxAge >= 0) {\n ctx.response.header('Access-Control-Max-Age', String(options.maxAge));\n }\n}\n\n/**\n * Handle CORS preflight request\n *\n * @param ctx - The request context\n * @param options - CORS configuration options\n * @returns Promise that resolves when preflight is handled\n * @throws ValidationError with 400 status on validation failure (403 behavior via response.status)\n */\nexport async function handlePreflight(ctx: Context, options: CorsOptions): Promise<void> {\n const preflight = parsePreflightRequest(ctx);\n\n // Preflight requires both origin and method headers\n if (!preflight.origin || !preflight.requestedMethod) {\n // Set 403 status directly\n ctx.response.status(403);\n\n throw new ValidationError('Invalid preflight request: missing required headers', {\n fields: [\n {\n field: preflight.origin ? 'Access-Control-Request-Method' : 'Origin',\n messages: ['Required header is missing'],\n },\n ],\n errorCount: 1,\n section: 'body', // Using valid section type\n });\n }\n\n // Validate origin\n const originAllowed = await validateOrigin(preflight.origin, options.origin || false, ctx);\n\n if (!originAllowed) {\n // Set 403 status directly\n ctx.response.status(403);\n\n throw new ValidationError('CORS origin not allowed', {\n fields: [\n {\n field: 'Origin',\n messages: [`Origin '${preflight.origin}' is not allowed`],\n rejectedValue: preflight.origin,\n },\n ],\n errorCount: 1,\n section: 'body',\n });\n }\n\n // Validate requested method\n if (!isMethodAllowed(preflight.requestedMethod, options.methods)) {\n // Set 403 status directly\n ctx.response.status(403);\n\n throw new ValidationError('CORS method not allowed', {\n fields: [\n {\n field: 'Access-Control-Request-Method',\n messages: [`Method '${preflight.requestedMethod}' is not allowed`],\n rejectedValue: preflight.requestedMethod,\n expectedType:\n typeof options.methods === 'string' ? options.methods : options.methods?.join(', '),\n },\n ],\n errorCount: 1,\n section: 'body',\n });\n }\n\n // Validate requested headers\n if (!areHeadersAllowed(preflight.requestedHeaders, options.allowedHeaders)) {\n const rejectedHeaders = preflight.requestedHeaders?.filter(h => {\n const allowed = options.allowedHeaders;\n if (!allowed) return false;\n const allowedArray =\n typeof allowed === 'string'\n ? allowed.split(',').map(h => h.trim().toLowerCase())\n : allowed.map(h => h.toLowerCase());\n return !allowedArray.includes(h.toLowerCase());\n });\n\n // Set 403 status directly\n ctx.response.status(403);\n\n throw new ValidationError('CORS headers not allowed', {\n fields: [\n {\n field: 'Access-Control-Request-Headers',\n messages: [`Headers not allowed: ${rejectedHeaders?.join(', ')}`],\n rejectedValue: rejectedHeaders,\n },\n ],\n errorCount: 1,\n section: 'body',\n });\n }\n\n // All validations passed - set response headers\n setPreflightHeaders(ctx, options, preflight.origin, originAllowed);\n\n // Set response status\n const successStatus = options.optionsSuccessStatus || 204;\n ctx.response.status(successStatus);\n\n // If preflightContinue is false (default), end the response here\n if (!options.preflightContinue) {\n // Send empty response body\n ctx.response.text('');\n }\n}\n\n/**\n * Check if a request is a preflight request\n *\n * @param ctx - The request context\n * @returns True if this is a CORS preflight request\n */\nexport function isPreflightRequest(ctx: Context): boolean {\n return (\n ctx.request.method === 'OPTIONS' &&\n !!(\n ctx.request.header('access-control-request-method') ||\n ctx.request.header('Access-Control-Request-Method')\n )\n );\n}\n\n/**\n * Create a standalone preflight handler for router mounting\n *\n * @param options - CORS configuration options\n * @returns Async handler function for preflight requests\n */\nexport function createPreflightHandler(options: CorsOptions) {\n return async (ctx: Context) => {\n await handlePreflight(ctx, options);\n };\n}\n","/**\n * CORS Validation Schemas\n *\n * Zod schemas for validating CORS configuration options\n * following BlaizeJS validation patterns.\n */\n\nimport { z } from 'zod';\n\nimport type { Context } from '@blaize-types/context';\nimport type { CorsOptions, CorsOrigin, CorsHttpMethod } from '@blaize-types/cors';\n\n/**\n * Validation for CORS HTTP methods\n * Includes all standard HTTP methods plus CONNECT and TRACE\n */\nconst corsHttpMethodSchema = z.enum([\n 'GET',\n 'POST',\n 'PUT',\n 'DELETE',\n 'PATCH',\n 'HEAD',\n 'OPTIONS',\n 'CONNECT',\n 'TRACE',\n]) as z.ZodType<CorsHttpMethod>;\n\n/**\n * Validation for methods field - can be array or comma-delimited string\n */\nconst corsMethodsSchema = z\n .union([\n z.array(corsHttpMethodSchema),\n z.string().transform(val => {\n // Transform comma-delimited string to array\n return val.split(',').map(m => m.trim()) as CorsHttpMethod[];\n }),\n ])\n .optional();\n\n/**\n * Validation for headers - can be array or comma-delimited string\n * Note: Headers are case-insensitive per HTTP spec. Node.js handles\n * normalization automatically (lowercase for HTTP/2, case-preserving for HTTP/1.1)\n */\nconst corsHeadersSchema = z\n .union([\n z.array(z.string()),\n z.string().transform(val => {\n // Transform comma-delimited string to array\n return val.split(',').map(h => h.trim());\n }),\n ])\n .optional();\n\n/**\n * Custom validation for origin functions\n * Zod doesn't have built-in function validation with specific signatures\n */\nconst corsOriginFunctionSchema = z.custom<\n (origin: string, ctx?: Context<any, any>) => boolean | Promise<boolean>\n>(\n data => {\n return typeof data === 'function' && data.length <= 2;\n },\n {\n message: 'Origin validator must be a function accepting (origin, ctx?) parameters',\n }\n);\n\n/**\n * Validation for single origin value\n * Can be string, RegExp, or validation function\n */\nconst singleOriginSchema = z.union([z.string(), z.instanceof(RegExp), corsOriginFunctionSchema]);\n\n/**\n * Full origin validation schema\n * Supports boolean, single origin, or array of origins\n */\nconst corsOriginSchema: z.ZodType<boolean | CorsOrigin> = z.union([\n z.boolean(),\n singleOriginSchema,\n z.array(singleOriginSchema),\n]);\n\n/**\n * Main CORS options validation schema\n */\nexport const corsOptionsSchema = z\n .object({\n /**\n * Origin configuration\n * - true: allow all origins\n * - false: disable CORS\n * - string/RegExp/function: specific origin validation\n * - array: multiple origin validators\n */\n origin: corsOriginSchema.optional(),\n\n /**\n * Allowed HTTP methods\n * Default: ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE']\n */\n methods: corsMethodsSchema,\n\n /**\n * Allowed request headers\n * Default: mirror Access-Control-Request-Headers\n */\n allowedHeaders: corsHeadersSchema,\n\n /**\n * Headers exposed to the client\n * Default: []\n */\n exposedHeaders: corsHeadersSchema,\n\n /**\n * Allow credentials (cookies, auth headers)\n * Default: false\n */\n credentials: z.boolean().optional(),\n\n /**\n * Preflight cache duration in seconds\n * -1 disables caching\n */\n maxAge: z.number().int().optional(),\n\n /**\n * Pass preflight to next handler\n * Default: false\n */\n preflightContinue: z.boolean().optional(),\n\n /**\n * Success status for OPTIONS requests\n * Default: 204\n */\n optionsSuccessStatus: z.number().int().min(200).max(299).optional(),\n })\n .strict() as z.ZodType<CorsOptions>;\n\n/**\n * Schema for server options CORS field\n * Can be boolean or CorsOptions\n */\nexport const serverCorsSchema = z.union([z.boolean(), corsOptionsSchema]).optional();\n\n/**\n * Validate CORS options with detailed error messages\n */\nexport function validateCorsOptions(options: unknown): CorsOptions {\n try {\n // Handle boolean shortcuts\n if (typeof options === 'boolean') {\n if (options === false) {\n // CORS disabled\n return { origin: false };\n }\n // true means allow all origins (dev mode)\n return { origin: true };\n }\n\n // Validate as CorsOptions\n return corsOptionsSchema.parse(options);\n } catch (error) {\n if (error instanceof z.ZodError) {\n const formattedErrors = formatCorsValidationErrors(error);\n throw new Error(`Invalid CORS options:\\n${formattedErrors}`);\n }\n throw new Error(`Invalid CORS options: ${String(error)}`);\n }\n}\n\n/**\n * Format Zod validation errors for CORS options\n */\nfunction formatCorsValidationErrors(error: z.ZodError): string {\n const errors = error.errors.map(err => {\n const path = err.path.join('.');\n return ` - ${path || 'root'}: ${err.message}`;\n });\n return errors.join('\\n');\n}\n\n/**\n * Type guards for origin types\n * Note: These guards work with the union type, not recursive arrays\n */\nexport function isOriginString(origin: unknown): origin is string {\n return typeof origin === 'string';\n}\n\nexport function isOriginRegExp(origin: unknown): origin is RegExp {\n return origin instanceof RegExp;\n}\n\nexport function isOriginFunction(\n origin: unknown\n): origin is (origin: string, ctx?: Context<any, any>) => boolean | Promise<boolean> {\n return typeof origin === 'function';\n}\n\nexport function isOriginArray(\n origin: unknown\n): origin is Array<\n string | RegExp | ((origin: string, ctx?: Context<any, any>) => boolean | Promise<boolean>)\n> {\n return Array.isArray(origin);\n}\n\n/**\n * Validate that wildcard (*) is not used with credentials\n * This is a security requirement per W3C CORS specification\n */\nexport function validateOriginSecurity(options: CorsOptions): void {\n if (options.credentials === true && options.origin !== undefined) {\n if (options.origin === true || options.origin === '*') {\n throw new Error(\n 'CORS security violation: Cannot use wildcard origin (*) with credentials. ' +\n 'When credentials are enabled, you must specify explicit origins.'\n );\n }\n\n // Check for wildcard in array\n if (isOriginArray(options.origin)) {\n const hasWildcard = options.origin.some(o => o === '*');\n if (hasWildcard) {\n throw new Error(\n 'CORS security violation: Cannot include wildcard origin (*) in array when credentials are enabled.'\n );\n }\n }\n }\n}\n\n/**\n * Merge user options with defaults\n */\nexport function mergeCorsOptions(\n userOptions: CorsOptions | boolean | undefined,\n defaults: CorsOptions\n): CorsOptions {\n // Handle boolean shortcuts\n if (userOptions === true) {\n return { ...defaults, origin: true };\n }\n if (userOptions === false) {\n return { origin: false };\n }\n if (!userOptions) {\n return defaults;\n }\n\n // Merge with defaults\n return {\n ...defaults,\n ...userOptions,\n // Special handling for methods and headers to avoid overwriting with undefined\n methods: userOptions.methods ?? defaults.methods,\n allowedHeaders: userOptions.allowedHeaders ?? defaults.allowedHeaders,\n exposedHeaders: userOptions.exposedHeaders ?? defaults.exposedHeaders,\n };\n}\n","/**\n * CORS Middleware for BlaizeJS\n *\n * W3C-compliant CORS implementation with origin validation, preflight handling,\n * and proper error responses. Must run early in middleware chain before SSE.\n */\nimport { ForbiddenError } from '../../errors/forbidden-error';\nimport { create as createMiddleware } from '../create';\nimport { getDefaultCorsOptions } from './defaults';\nimport { validateOrigin } from './origin-validator';\nimport { handlePreflight, isPreflightRequest } from './preflight';\nimport { validateCorsOptions, mergeCorsOptions, validateOriginSecurity } from './validation';\n\nimport type { Context } from '@blaize-types/context';\nimport type { CorsOptions } from '@blaize-types/cors';\nimport type { Middleware, NextFunction } from '@blaize-types/middleware';\n\n/**\n * Set CORS headers for simple (non-preflight) requests\n */\nfunction setCorsHeaders(\n ctx: Context,\n options: CorsOptions,\n origin: string | undefined,\n originAllowed: boolean\n): void {\n // Only set headers if origin is allowed\n if (!originAllowed || !origin) {\n return;\n }\n\n // Set origin header\n if (options.origin === true && !options.credentials) {\n // Wildcard allowed when credentials not enabled\n ctx.response.header('Access-Control-Allow-Origin', '*');\n } else {\n // Reflect the specific origin\n ctx.response.header('Access-Control-Allow-Origin', origin);\n // Add Vary header when origin is dynamic\n ctx.response.header('Vary', 'Origin');\n }\n\n // Set credentials header if enabled\n if (options.credentials) {\n ctx.response.header('Access-Control-Allow-Credentials', 'true');\n }\n\n // Set exposed headers if specified\n if (options.exposedHeaders) {\n const headers =\n typeof options.exposedHeaders === 'string'\n ? options.exposedHeaders\n : options.exposedHeaders.join(', ');\n ctx.response.header('Access-Control-Expose-Headers', headers);\n }\n}\n\n/**\n * Create CORS middleware with the specified options\n *\n * @param userOptions - CORS configuration options or boolean\n * @returns Middleware function that handles CORS\n *\n * @example\n * ```typescript\n * import { cors } from '@blaize-core/middleware/cors';\n *\n * // Development mode - allow all origins\n * server.use(cors(true));\n *\n * // Production - specific origin\n * server.use(cors({\n * origin: 'https://app.example.com',\n * credentials: true,\n * maxAge: 86400\n * }));\n *\n * // Multiple origins with regex\n * server.use(cors({\n * origin: [\n * 'https://app.example.com',\n * /^https:\\/\\/.*\\.example\\.com$/\n * ]\n * }));\n *\n * // Dynamic origin validation\n * server.use(cors({\n * origin: async (origin, ctx) => {\n * return await checkOriginAllowed(origin, ctx.state.user);\n * }\n * }));\n * ```\n */\nexport function cors(userOptions?: CorsOptions | boolean): Middleware {\n // Determine environment\n const isDevelopment = process.env.NODE_ENV === 'development';\n\n // Get defaults based on environment\n const defaults = getDefaultCorsOptions(isDevelopment);\n\n // Merge and validate options\n const options = mergeCorsOptions(userOptions, defaults);\n const validatedOptions = validateCorsOptions(options);\n\n // Security validation\n validateOriginSecurity(validatedOptions);\n\n // Create the middleware using createMiddleware\n return createMiddleware({\n name: 'cors',\n handler: async (ctx: Context, next: NextFunction) => {\n // Extract origin from request\n const origin = ctx.request.header('origin') || ctx.request.header('Origin');\n\n // Check if this is a preflight request\n if (isPreflightRequest(ctx)) {\n // Handle preflight - this may throw ValidationError\n await handlePreflight(ctx, validatedOptions);\n\n // If preflightContinue is false, we're done\n if (!validatedOptions.preflightContinue) {\n return; // Don't call next()\n }\n } else {\n // Simple request - validate origin and set headers\n\n // Skip CORS for same-origin requests (no Origin header)\n if (!origin) {\n // No origin header means same-origin request or non-browser client\n // Continue without CORS headers\n await next();\n return;\n }\n\n // Validate the origin\n const originAllowed = await validateOrigin(origin, validatedOptions.origin || false, ctx);\n\n // If origin is not allowed, return 403 Forbidden\n if (!originAllowed) {\n // Set 403 status\n ctx.response.status(403);\n\n throw new ForbiddenError('CORS validation failed', {\n reason: 'origin_not_allowed',\n origin,\n allowedOrigins: validatedOptions.origin,\n });\n }\n\n // Origin is allowed - set CORS headers\n setCorsHeaders(ctx, validatedOptions, origin, originAllowed);\n }\n\n // Continue to next middleware\n await next();\n },\n debug: process.env.DEBUG?.includes('cors'),\n });\n}\n\n/**\n * Create a strict CORS middleware that denies all cross-origin requests\n * Useful for internal APIs that should never be accessed cross-origin\n */\nexport function corsStrict(): Middleware {\n return cors({ origin: false });\n}\n\n/**\n * Create a permissive CORS middleware for development\n * Allows all origins but logs warnings\n */\nexport function corsDevelopment(): Middleware {\n const baseMiddleware = cors({\n origin: true,\n credentials: false, // Don't allow credentials with wildcard\n methods: ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'],\n maxAge: 3600,\n });\n\n // Create a wrapper middleware that adds the warning\n return createMiddleware({\n name: 'cors-development',\n handler: async (ctx: Context, next: NextFunction) => {\n console.warn('[CORS] Running in development mode - all origins allowed');\n // Execute the base CORS middleware\n await baseMiddleware.execute(ctx, next);\n },\n debug: baseMiddleware.debug,\n });\n}\n\n/**\n * Create CORS middleware for specific allowed origins\n * Convenience function for common production use case\n */\nexport function corsForOrigins(\n origins: string[],\n options?: Omit<CorsOptions, 'origin'>\n): Middleware {\n return cors({\n ...options,\n origin: origins,\n });\n}\n\n// Re-export types and utilities for convenience\nexport { validateOrigin } from './origin-validator';\nexport { isPreflightRequest } from './preflight';\n","/* eslint-disable @typescript-eslint/no-empty-object-type */\nimport type { Plugin, PluginFactory, PluginHooks, UnknownServer } from '@blaize-types/index';\n\n/**\n * Create a plugin with the given name, version, and setup function\n */\nexport function create<TConfig = any, TState = {}, TServices = {}>(\n name: string,\n version: string,\n setup: (\n app: UnknownServer,\n options: TConfig\n ) => void | Partial<PluginHooks> | Promise<void> | Promise<Partial<PluginHooks>>,\n defaultOptions: Partial<TConfig> = {}\n): PluginFactory<TConfig, TState, TServices> {\n // Input validation\n if (!name || typeof name !== 'string') {\n throw new Error('Plugin name must be a non-empty string');\n }\n\n if (!version || typeof version !== 'string') {\n throw new Error('Plugin version must be a non-empty string');\n }\n\n if (typeof setup !== 'function') {\n throw new Error('Plugin setup must be a function');\n }\n\n // Return the factory function\n return function pluginFactory(userOptions?: Partial<TConfig>) {\n // Merge default options with user options\n const mergedOptions = { ...defaultOptions, ...userOptions } as TConfig;\n\n // Create the base plugin object\n const plugin: Plugin<TState, TServices> = {\n name,\n version,\n\n // The register hook calls the user's setup function\n register: async (app: UnknownServer) => {\n const result = await setup(app, mergedOptions);\n\n // If setup returns hooks, merge them into this plugin\n if (result && typeof result === 'object') {\n // Now we explicitly assign to our plugin object\n Object.assign(plugin, result);\n }\n },\n };\n\n return plugin;\n };\n}\n","import { fileURLToPath } from 'node:url';\n\nimport { getRoutesDir } from '../config';\nimport { parseRoutePath } from './discovery/parser';\nimport { createSSERoute } from '../sse/create';\n\nimport type {\n CreateGetRoute,\n CreatePostRoute,\n CreatePutRoute,\n CreateDeleteRoute,\n CreatePatchRoute,\n CreateHeadRoute,\n CreateOptionsRoute,\n State,\n Services,\n} from '@blaize-types/index';\n\n/**\n * Get the file path of the function that called createXRoute\n */\nfunction getCallerFilePath(): string {\n const originalPrepareStackTrace = Error.prepareStackTrace;\n\n try {\n Error.prepareStackTrace = (_, stack) => stack;\n const stack = new Error().stack as unknown as NodeJS.CallSite[];\n\n // Stack: getCallerFilePath -> createXRoute -> route file\n const callerFrame = stack[3];\n if (!callerFrame || typeof callerFrame.getFileName !== 'function') {\n throw new Error('Unable to determine caller file frame');\n }\n const fileName = callerFrame.getFileName();\n\n if (!fileName) {\n throw new Error('Unable to determine caller file name');\n }\n\n if (fileName.startsWith('file://')) {\n return fileURLToPath(fileName);\n }\n\n return fileName;\n } finally {\n Error.prepareStackTrace = originalPrepareStackTrace;\n }\n}\n\n/**\n * Convert caller file path to route path using existing parsing logic\n */\nexport function getRoutePath(): string {\n const callerPath = getCallerFilePath();\n const routesDir = getRoutesDir();\n\n const parsedRoute = parseRoutePath(callerPath, routesDir);\n console.log(`🔎 Parsed route path: ${parsedRoute.routePath} from file: ${callerPath}`);\n\n return parsedRoute.routePath;\n}\n\n/**\n * Create a GET route\n * SIMPLER FIX: Just pass the config through, TypeScript will handle the types\n */\nexport const createGetRoute: CreateGetRoute = <\n _TState extends State = State,\n _TServices extends Services = Services,\n>() => {\n return (config: any) => {\n validateMethodConfig('GET', config);\n const path = getRoutePath();\n\n return {\n GET: config,\n path,\n };\n };\n};\n\n/**\n * Create a POST route\n */\nexport const createPostRoute: CreatePostRoute = <\n _TState extends State = State,\n _TServices extends Services = Services,\n>() => {\n return (config: any) => {\n validateMethodConfig('POST', config);\n const path = getRoutePath();\n\n return {\n POST: config,\n path,\n };\n };\n};\n\n/**\n * Create a PUT route\n */\nexport const createPutRoute: CreatePutRoute = <\n _TState extends State = State,\n _TServices extends Services = Services,\n>() => {\n return (config: any) => {\n validateMethodConfig('PUT', config);\n const path = getRoutePath();\n\n return {\n PUT: config,\n path,\n };\n };\n};\n\n/**\n * Create a DELETE route\n */\nexport const createDeleteRoute: CreateDeleteRoute = <\n _TState extends State = State,\n _TServices extends Services = Services,\n>() => {\n return (config: any) => {\n validateMethodConfig('DELETE', config);\n const path = getRoutePath();\n\n return {\n DELETE: config,\n path,\n };\n };\n};\n\n/**\n * Create a PATCH route\n */\nexport const createPatchRoute: CreatePatchRoute = <\n _TState extends State = State,\n _TServices extends Services = Services,\n>() => {\n return (config: any) => {\n validateMethodConfig('PATCH', config);\n const path = getRoutePath();\n\n return {\n PATCH: config,\n path,\n };\n };\n};\n\n/**\n * Create a HEAD route (same signature as GET - no body)\n */\nexport const createHeadRoute: CreateHeadRoute = <\n _TState extends State = State,\n _TServices extends Services = Services,\n>() => {\n return (config: any) => {\n validateMethodConfig('HEAD', config);\n const path = getRoutePath();\n\n return {\n HEAD: config,\n path,\n };\n };\n};\n\n/**\n * Create an OPTIONS route (same signature as GET - no body)\n */\nexport const createOptionsRoute: CreateOptionsRoute = <\n _TState extends State = State,\n _TServices extends Services = Services,\n>() => {\n return (config: any) => {\n validateMethodConfig('OPTIONS', config);\n const path = getRoutePath();\n\n return {\n OPTIONS: config,\n path,\n };\n };\n};\n\n/**\n * Validate a method configuration\n */\nfunction validateMethodConfig(method: string, config: any): void {\n if (!config.handler || typeof config.handler !== 'function') {\n throw new Error(`Handler for method ${method} must be a function`);\n }\n\n if (config.middleware && !Array.isArray(config.middleware)) {\n throw new Error(`Middleware for method ${method} must be an array`);\n }\n\n // Validate schema if provided\n if (config.schema) {\n validateSchema(method, config.schema);\n }\n\n // Method-specific warnings\n switch (method) {\n case 'GET':\n case 'HEAD':\n case 'DELETE':\n if (config.schema?.body) {\n console.warn(`Warning: ${method} requests typically don't have request bodies`);\n }\n break;\n }\n}\n\n/**\n * Validate schema structure\n */\nfunction validateSchema(method: string, schema: any): void {\n const { params, query, body, response } = schema;\n\n // Basic validation - ensure they look like Zod schemas if provided\n if (params && (!params._def || typeof params.parse !== 'function')) {\n throw new Error(`Params schema for ${method} must be a valid Zod schema`);\n }\n\n if (query && (!query._def || typeof query.parse !== 'function')) {\n throw new Error(`Query schema for ${method} must be a valid Zod schema`);\n }\n\n if (body && (!body._def || typeof body.parse !== 'function')) {\n throw new Error(`Body schema for ${method} must be a valid Zod schema`);\n }\n\n if (response && (!response._def || typeof response.parse !== 'function')) {\n throw new Error(`Response schema for ${method} must be a valid Zod schema`);\n }\n}\n\n/**\n * Factory that creates all route methods with consistent types\n * This is the RECOMMENDED approach for most applications\n *\n * Usage in server.ts:\n * ```typescript\n * export const route = createRouteFactory<AppState, AppServices>();\n * ```\n *\n * Usage in route files:\n * ```typescript\n * import { route } from '../server';\n *\n * export const GET = route.get({\n * handler: async (ctx) => {\n * // ctx.state and ctx.services are fully typed!\n * }\n * });\n * ```\n */\nexport function createRouteFactory<\n TState extends State = State,\n TServices extends Services = Services,\n>() {\n return {\n get: createGetRoute<TState, TServices>(),\n post: createPostRoute<TState, TServices>(),\n put: createPutRoute<TState, TServices>(),\n delete: createDeleteRoute<TState, TServices>(),\n patch: createPatchRoute<TState, TServices>(),\n head: createHeadRoute<TState, TServices>(),\n options: createOptionsRoute<TState, TServices>(),\n sse: createSSERoute<TState, TServices>(),\n } as const;\n}\n\n/**\n * Type guard to check if a value is a route factory\n */\nexport function isRouteFactory(value: any): value is ReturnType<typeof createRouteFactory> {\n return (\n value &&\n typeof value === 'object' &&\n 'get' in value &&\n 'post' in value &&\n 'put' in value &&\n 'delete' in value &&\n 'patch' in value &&\n 'head' in value &&\n 'options' in value\n );\n}\n","// config/runtime-config.ts\ninterface RuntimeConfig {\n routesDir?: string;\n basePath?: string;\n // Add other runtime configuration as needed\n}\n\n// Internal state - not exported\nlet config: RuntimeConfig = {};\n\n/**\n * Set runtime configuration\n */\nexport function setRuntimeConfig(newConfig: Partial<RuntimeConfig>): void {\n config = { ...config, ...newConfig };\n}\n\n/**\n * Get full runtime configuration\n */\nexport function getRuntimeConfig(): RuntimeConfig {\n return { ...config };\n}\n\n/**\n * Get the configured routes directory\n */\nexport function getRoutesDir(): string {\n if (!config.routesDir) {\n throw new Error('Routes directory not configured. Make sure server is properly initialized.');\n }\n return config.routesDir;\n}\n\n/**\n * Get the configured base path\n */\nexport function getBasePath(): string {\n return config.basePath || '';\n}\n\n/**\n * Clear configuration (useful for testing)\n */\nexport function clearRuntimeConfig(): void {\n config = {};\n}\n","import * as path from 'node:path';\n\nimport type { ParsedRoute } from '@blaize-types/router';\n\n/**\n * Parse a file path into a route path\n * Works consistently across Windows and Unix-like file systems\n */\nexport function parseRoutePath(filePath: string, basePath: string): ParsedRoute {\n // Clean file:// URLs if present\n if (filePath.startsWith('file://')) {\n filePath = filePath.replace('file://', '');\n }\n if (basePath.startsWith('file://')) {\n basePath = basePath.replace('file://', '');\n }\n\n // Convert all backslashes to forward slashes for consistent handling\n const forwardSlashFilePath = filePath.replace(/\\\\/g, '/');\n const forwardSlashBasePath = basePath.replace(/\\\\/g, '/');\n\n // Ensure the base path ends with a slash for proper prefix removal\n const normalizedBasePath = forwardSlashBasePath.endsWith('/')\n ? forwardSlashBasePath\n : `${forwardSlashBasePath}/`;\n\n // Remove the base path to get the relative path\n let relativePath = forwardSlashFilePath;\n if (forwardSlashFilePath.startsWith(normalizedBasePath)) {\n relativePath = forwardSlashFilePath.substring(normalizedBasePath.length);\n } else if (forwardSlashFilePath.startsWith(forwardSlashBasePath)) {\n relativePath = forwardSlashFilePath.substring(forwardSlashBasePath.length);\n // If base path didn't end with a slash but we still matched, ensure relative path doesn't start with a slash\n if (relativePath.startsWith('/')) {\n relativePath = relativePath.substring(1);\n }\n } else {\n // If base path isn't a prefix of file path, use path.relative as a fallback\n // But convert to forward slashes for consistency\n relativePath = path.relative(forwardSlashBasePath, forwardSlashFilePath).replace(/\\\\/g, '/');\n }\n\n // Remove file extension (anything after the last dot)\n relativePath = relativePath.replace(/\\.[^.]+$/, '');\n\n // Split the path into segments\n const segments = relativePath.split('/').filter(Boolean);\n const params: string[] = [];\n\n // Transform file path segments to route path segments\n const routeSegments = segments.map(segment => {\n // Handle dynamic parameters ([param])\n if (segment.startsWith('[') && segment.endsWith(']')) {\n const paramName = segment.slice(1, -1);\n params.push(paramName);\n return `:${paramName}`;\n }\n return segment;\n });\n\n // Create the final route path\n let routePath = routeSegments.length > 0 ? `/${routeSegments.join('/')}` : '/';\n\n // Handle index routes\n if (routePath.endsWith('/index')) {\n routePath = routePath.slice(0, -6) || '/';\n }\n\n return {\n filePath,\n routePath,\n params,\n };\n}\n","/**\n * @module sse/stream\n * @description SSE Stream implementation with backpressure management\n *\n * Provides a functional SSE stream implementation with:\n * - Automatic connection registry integration\n * - Configurable buffer management strategies\n * - Memory-efficient event handling\n * - Automatic cleanup on disconnect\n */\n\nimport { EventEmitter } from 'node:events';\n\nimport { BackpressureConfigSchema, type BackpressureConfig } from './back-pressure';\nimport { getConnectionRegistry } from './connection-registry';\nimport { SSEBufferOverflowError } from '../errors/sse-buffer-overflow-error';\nimport { SSEStreamClosedError } from '../errors/sse-stream-closed-error';\nimport { getCorrelationId } from '../tracing/correlation';\n\nimport type { Context } from '@blaize-types/context';\nimport type {\n SSEStreamExtended,\n SSEConnectionState,\n SSEOptions,\n SSEBufferStrategy,\n BufferedEvent,\n StreamMetrics,\n} from '@blaize-types/sse';\n\n/**\n * Default SSE options with production-ready defaults\n */\nconst DEFAULT_OPTIONS: Required<SSEOptions> = {\n heartbeatInterval: 30000, // 30 seconds - prevents proxy/firewall timeouts\n maxEventSize: 1024 * 1024, // 1MB - generous but prevents memory attacks\n autoClose: true, // Clean up resources on disconnect\n maxBufferSize: 1000, // 1000 events - reasonable for most use cases\n bufferStrategy: 'drop-oldest' as SSEBufferStrategy, // Prefer fresh data\n};\n\n/**\n * Format SSE event for wire protocol\n * @internal\n */\nfunction formatSSEEvent(event: string, data: unknown, id?: string, retry?: number): string {\n const lines: string[] = [];\n\n if (id) {\n lines.push(`id: ${id}`);\n }\n\n if (retry !== undefined) {\n lines.push(`retry: ${retry}`);\n }\n\n lines.push(`event: ${event}`);\n\n // Handle multi-line data - handle null/undefined gracefully\n const dataStr =\n data === null\n ? 'null'\n : data === undefined\n ? 'undefined'\n : typeof data === 'string'\n ? data\n : JSON.stringify(data);\n const dataLines = dataStr.split('\\n');\n for (const line of dataLines) {\n lines.push(`data: ${line}`);\n }\n\n lines.push(''); // Empty line to terminate event\n return lines.join('\\n') + '\\n';\n}\n\n/**\n * Create event ID\n * @internal\n */\nfunction createEventId(): string {\n const timestamp = Date.now().toString(36);\n const random = Math.random().toString(36).substr(2, 9);\n return `${timestamp}-${random}`;\n}\n\n/**\n * Estimate event size in bytes\n * @internal\n */\nfunction estimateEventSize(event: string, data: unknown): number {\n const dataStr =\n data === null\n ? 'null'\n : data === undefined\n ? 'undefined'\n : typeof data === 'string'\n ? data\n : JSON.stringify(data);\n // Rough estimate: event name + data + SSE formatting overhead\n return event.length + dataStr.length + 50; // 50 bytes for SSE protocol overhead\n}\n\n/**\n * Apply buffer strategy when buffer is full\n * @internal\n */\nfunction applyBufferStrategy(\n buffer: BufferedEvent[],\n strategy: SSEBufferStrategy,\n newEvent: BufferedEvent,\n maxSize: number\n): { buffer: BufferedEvent[]; dropped: number } {\n let dropped = 0;\n\n switch (strategy) {\n case 'drop-oldest': {\n // Remove oldest events to make room\n while (buffer.length >= maxSize && buffer.length > 0) {\n buffer.shift();\n dropped++;\n }\n buffer.push(newEvent);\n break;\n }\n\n case 'drop-newest': {\n // Reject the new event if buffer is full\n if (buffer.length >= maxSize) {\n dropped = 1;\n // Don't add the new event\n } else {\n buffer.push(newEvent);\n }\n break;\n }\n\n case 'close': {\n // This strategy will be handled by the caller\n // by throwing an error\n break;\n }\n\n default:\n // Default to drop-oldest\n while (buffer.length >= maxSize && buffer.length > 0) {\n buffer.shift();\n dropped++;\n }\n buffer.push(newEvent);\n }\n\n return { buffer, dropped };\n}\n\n/**\n * SSE Stream implementation using functional patterns\n */\nclass SSEStreamImpl implements SSEStreamExtended {\n readonly id: string;\n private _state: SSEConnectionState = 'connecting';\n private _buffer: BufferedEvent[] = [];\n private _closeCallbacks: Array<() => void | Promise<void>> = [];\n private _errorCallbacks: Array<(error: Error) => void> = [];\n private _emitter = new EventEmitter();\n private _metrics: StreamMetrics;\n private _options: Required<SSEOptions>;\n private _response: Context['response'];\n private _request: Context['request'];\n private _writable: boolean = true;\n private _cleanupExecuted = false;\n private _eventCounter = 0;\n private _lastEventId: string | null = null;\n private _heartbeatTimer?: NodeJS.Timeout;\n private _backpressureConfig?: BackpressureConfig;\n private _disconnectHandlers: {\n req: { close: () => void; error: () => void };\n res: { close: () => void; error: () => void };\n } | null = null;\n\n constructor(ctx: Context, options: SSEOptions = {}) {\n this.id = `sse-${createEventId()}`;\n this._options = { ...DEFAULT_OPTIONS, ...options };\n this._response = ctx.response;\n this._request = ctx.request;\n\n // Parse and validate backpressure config if provided\n if ((options as any).backpressure) {\n const result = BackpressureConfigSchema.safeParse((options as any).backpressure);\n if (result.success) {\n this._backpressureConfig = result.data;\n // Override simple options with backpressure config values\n this._options.maxBufferSize = result.data.limits.maxMessages;\n this._options.bufferStrategy = result.data.strategy;\n }\n }\n\n // Handle Last-Event-ID header for reconnection\n const lastEventId = ctx.request.header('last-event-id');\n if (lastEventId) {\n this._eventCounter = parseInt(lastEventId) || 0;\n this._lastEventId = lastEventId;\n }\n\n // Initialize metrics\n this._metrics = {\n eventsSent: 0,\n eventsDropped: 0,\n bytesWritten: 0,\n bufferHighWatermark: 0,\n lastEventTime: Date.now(),\n };\n\n // CRITICAL: Do all operations that might throw BEFORE setting headers\n\n // 1. Try to register with connection registry FIRST\n // This can throw if connection limits are exceeded\n try {\n const registry = getConnectionRegistry();\n const metadata = {\n clientIp:\n this._request.header('x-forwarded-for') ||\n this._request.header('x-real-ip') ||\n (this._request.raw as any).socket?.remoteAddress,\n userAgent: this._request.header('user-agent'),\n };\n\n registry.add(this.id, this, metadata);\n } catch (error) {\n // If registration fails (e.g., connection limit), fail immediately\n // BEFORE setting any headers\n this._state = 'closed';\n this._writable = false;\n console.error('[SSE] Failed to register connection:', error);\n throw error;\n }\n\n // 2. Set up disconnect handling (shouldn't throw, but do it before headers)\n this._setupDisconnectHandling();\n\n // 3. NOW we can safely set SSE headers\n // If anything above threw, we haven't sent headers yet\n this._response\n .status(200)\n .header('Content-Type', 'text/event-stream')\n .header('Cache-Control', 'no-cache')\n .header('X-Accel-Buffering', 'no'); // Disable Nginx buffering\n\n // Only set Connection header for HTTP/1.x\n if (!this._request.raw.httpVersionMajor || this._request.raw.httpVersionMajor < 2) {\n this._response.header('Connection', 'keep-alive');\n }\n\n // 4. Set up heartbeat if configured (after headers are sent)\n if (this._options.heartbeatInterval && this._options.heartbeatInterval > 0) {\n this._setupHeartbeat(this._options.heartbeatInterval);\n }\n\n // 5. Transition to connected state\n this._state = 'connected';\n\n // 6. Send initial comment to establish connection\n this._writeRaw(`: SSE connection established\\n\\n`);\n }\n\n /**\n * Register connection with the internal registry\n * @internal\n */\n private _registerConnection(): void {\n try {\n const registry = getConnectionRegistry();\n const metadata = {\n clientIp:\n this._request.header('x-forwarded-for') ||\n this._request.header('x-real-ip') ||\n (this._request.raw as any).socket?.remoteAddress,\n userAgent: this._request.header('user-agent'),\n };\n\n registry.add(this.id, this, metadata);\n } catch (error) {\n // If registration fails (e.g., connection limit), close immediately\n this._state = 'closed';\n this._writable = false;\n throw error;\n }\n }\n\n /**\n * Set up heartbeat timer\n * @internal\n */\n private _setupHeartbeat(interval: number): void {\n this._heartbeatTimer = global.setInterval(() => {\n if (this.isWritable) {\n const idleTime = Date.now() - this._metrics.lastEventTime;\n // Only send heartbeat if no recent activity\n if (idleTime > interval * 0.9) {\n this.ping(`heartbeat ${new Date().toISOString()}`);\n }\n }\n }, interval);\n\n // Ensure timer doesn't prevent process exit\n if (this._heartbeatTimer.unref) {\n this._heartbeatTimer.unref();\n }\n }\n\n /**\n * Set up automatic disconnect detection\n * @internal\n */\n private _setupDisconnectHandling(): void {\n const req = this._request.raw;\n const res = this._response.raw;\n\n // Handle client disconnect\n const handleDisconnect = () => {\n if (this._options.autoClose && this._state !== 'closed') {\n this.close();\n }\n };\n\n // Store handlers for cleanup\n this._disconnectHandlers = {\n req: { close: handleDisconnect, error: handleDisconnect },\n res: { close: handleDisconnect, error: handleDisconnect },\n };\n\n // Listen for various disconnect signals\n req.on('close', this._disconnectHandlers.req.close);\n req.on('error', this._disconnectHandlers.req.error);\n res.on('close', this._disconnectHandlers.res.close);\n res.on('error', this._disconnectHandlers.res.error);\n }\n\n /**\n * Write raw data to the response stream\n * @internal\n */\n private _writeRaw(data: string): boolean {\n if (!this._writable || this._state === 'closed') {\n return false;\n }\n\n try {\n const res = this._response.raw;\n // Handle the write method with proper typing for both HTTP/1.1 and HTTP/2\n let written: boolean;\n\n if ('write' in res && typeof res.write === 'function') {\n // Call write with just the data parameter to avoid signature conflicts\n written = (res as any).write(data);\n } else {\n throw new Error('Response stream does not support write operation');\n }\n\n if (written) {\n this._metrics.bytesWritten += Buffer.byteLength(data);\n }\n\n return written;\n } catch (error) {\n this._writable = false;\n this._handleError(error as Error);\n return false;\n }\n }\n\n /**\n * Process and send buffered events\n * @internal\n */\n private async _flushBuffer(): Promise<void> {\n while (this._buffer.length > 0 && this._writable) {\n const event = this._buffer.shift();\n if (!event) break;\n\n const formatted = formatSSEEvent(event.event, event.data, event.id);\n\n if (!this._writeRaw(formatted)) {\n // If write failed, put event back and wait for drain\n this._buffer.unshift(event);\n await this._waitForDrain();\n } else {\n this._metrics.eventsSent++;\n this._metrics.lastEventTime = Date.now();\n }\n }\n }\n\n /**\n * Wait for the response stream to drain\n * @internal\n */\n private _waitForDrain(): Promise<void> {\n return new Promise(resolve => {\n const res = this._response.raw;\n res.once('drain', resolve);\n });\n }\n\n /**\n * Handle internal errors\n * @internal\n */\n private _handleError(error: Error): void {\n this._errorCallbacks.forEach(cb => {\n try {\n cb(error);\n } catch (err) {\n console.error('Error in error callback:', err);\n }\n });\n\n // Send error event if still writable\n if (this._writable) {\n this.sendError(error);\n }\n }\n\n /**\n * Execute cleanup operations\n * @internal\n */\n private _executeCleanup(): void {\n if (this._cleanupExecuted) return;\n this._cleanupExecuted = true;\n\n // Clear heartbeat timer\n if (this._heartbeatTimer) {\n global.clearInterval(this._heartbeatTimer);\n this._heartbeatTimer = undefined;\n }\n\n // Remove event listeners\n if (this._disconnectHandlers) {\n const req = this._request.raw;\n const res = this._response.raw;\n\n req.removeListener('close', this._disconnectHandlers.req.close);\n req.removeListener('error', this._disconnectHandlers.req.error);\n res.removeListener('close', this._disconnectHandlers.res.close);\n res.removeListener('error', this._disconnectHandlers.res.error);\n\n this._disconnectHandlers = null;\n }\n\n // Deregister from connection registry\n try {\n const registry = getConnectionRegistry();\n registry.remove(this.id);\n } catch (error) {\n // Ignore registry errors during cleanup\n console.error('Registry cleanup error:', error);\n }\n\n // Execute close callbacks synchronously\n // Make a copy to avoid modification during iteration\n const callbacks = [...this._closeCallbacks];\n for (const cb of callbacks) {\n try {\n const result = cb();\n // If it's a promise, catch any errors but don't await\n if (result && typeof result.then === 'function') {\n result.catch((error: Error) => {\n console.error('Error in async close callback:', error);\n });\n }\n } catch (error) {\n console.error('Error in close callback:', error);\n }\n }\n\n // Clear callbacks and buffer\n this._closeCallbacks = [];\n this._errorCallbacks = [];\n this._buffer = [];\n this._emitter.removeAllListeners();\n }\n\n // Public API Implementation\n\n get state(): SSEConnectionState {\n return this._state;\n }\n\n get bufferSize(): number {\n return this._buffer.length;\n }\n\n get isWritable(): boolean {\n return this._writable && this._state === 'connected';\n }\n\n send<T>(event: string, data: T): void {\n if (!this.isWritable) {\n throw new SSEStreamClosedError('Cannot send event to closed stream', {\n clientId: this.id,\n closedAt: new Date().toISOString(),\n closeReason: 'server-close',\n canReconnect: false,\n });\n }\n\n // Use sequential event IDs for proper reconnection support\n const eventId = String(++this._eventCounter);\n this._lastEventId = eventId;\n const correlationId = getCorrelationId();\n const size = estimateEventSize(event, data);\n\n // Validate event size to prevent memory attacks\n const maxEventSize = this._options.maxEventSize;\n if (size > maxEventSize) {\n throw new SSEBufferOverflowError('Event size exceeds maximum allowed', {\n currentSize: size,\n maxSize: maxEventSize,\n strategy: 'close',\n clientId: this.id,\n eventsDropped: 0,\n triggeringEvent: event,\n });\n }\n\n // Create buffered event\n const bufferedEvent: BufferedEvent = {\n id: eventId,\n event,\n data,\n size,\n timestamp: Date.now(),\n correlationId,\n };\n\n // Check buffer limit (use backpressure config if available)\n const maxBuffer = this._backpressureConfig\n ? this._backpressureConfig.watermarks.high\n : this._options.maxBufferSize;\n\n if (this._buffer.length >= maxBuffer) {\n if (this._options.bufferStrategy === 'close') {\n const currentSize = this._buffer.length;\n\n // Close the stream on buffer overflow\n this.close();\n throw new SSEBufferOverflowError('Buffer overflow - stream closed', {\n currentSize,\n maxSize: maxBuffer,\n strategy: 'close',\n clientId: this.id,\n });\n }\n\n // Apply buffer strategy\n const result = applyBufferStrategy(\n this._buffer,\n this._options.bufferStrategy,\n bufferedEvent,\n maxBuffer\n );\n\n this._buffer = result.buffer;\n this._metrics.eventsDropped += result.dropped;\n\n if (result.dropped > 0) {\n console.warn(\n `SSE stream ${this.id}: Dropped ${result.dropped} events due to buffer overflow`\n );\n }\n } else {\n this._buffer.push(bufferedEvent);\n }\n\n // Update high watermark\n this._metrics.bufferHighWatermark = Math.max(\n this._metrics.bufferHighWatermark,\n this._buffer.length\n );\n\n // Emit event for async iterator\n this._emitter.emit('event');\n\n // Try to flush immediately\n this._flushBuffer().catch(error => {\n this._handleError(error as Error);\n });\n }\n\n sendError(error: Error): void {\n if (!this.isWritable) return;\n\n const errorData = {\n message: error.message,\n name: error.name,\n correlationId: getCorrelationId(),\n timestamp: new Date().toISOString(),\n stack: process.env.NODE_ENV === 'development' ? error.stack : undefined,\n };\n\n try {\n this.send('error', errorData);\n } catch (sendError) {\n // If we can't send the error event, just log it\n console.error('Failed to send error event:', sendError);\n }\n }\n\n close(): void {\n if (this._state === 'closed') return;\n\n this._state = 'closed';\n this._writable = false;\n\n // Emit close event for async iterator\n this._emitter.emit('close');\n\n // Send close event if possible\n try {\n const closeEvent = formatSSEEvent('close', {\n reason: 'stream-closed',\n reconnect: false,\n });\n const res = this._response.raw;\n // Use type assertion to handle union type\n if ('write' in res && typeof res.write === 'function') {\n (res as any).write(closeEvent);\n }\n } catch {\n // Ignore errors when sending close event\n }\n\n // End the response\n try {\n const res = this._response.raw;\n if (!res.writableEnded && typeof res.end === 'function') {\n res.end();\n }\n } catch (error) {\n console.error('Error ending response:', error);\n }\n\n // Execute cleanup synchronously\n this._executeCleanup();\n }\n\n onClose(cb: () => void | Promise<void>): void {\n if (this._state === 'closed') {\n // If already closed, execute immediately\n try {\n const result = cb();\n if (result && typeof result.then === 'function') {\n result.catch((error: Error) => {\n console.error('Error in close callback:', error);\n });\n }\n } catch (error) {\n console.error('Error in close callback:', error);\n }\n } else {\n this._closeCallbacks.push(cb);\n }\n }\n\n ping(comment?: string): void {\n if (!this.isWritable) return;\n\n const message = comment ? `: ${comment}\\n\\n` : `: ping\\n\\n`;\n this._writeRaw(message);\n }\n\n setRetry(milliseconds: number): void {\n if (!this.isWritable) return;\n\n if (milliseconds < 0 || !Number.isFinite(milliseconds)) {\n throw new Error('Retry interval must be a positive number');\n }\n\n this._writeRaw(`retry: ${Math.floor(milliseconds)}\\n\\n`);\n }\n\n flush(): void {\n if (!this.isWritable) return;\n\n // Force flush all buffered events\n this._flushBuffer().catch(error => {\n this._handleError(error as Error);\n });\n }\n\n /**\n * Get stream metrics for monitoring\n */\n getMetrics(): StreamMetrics {\n return { ...this._metrics };\n }\n\n /**\n * Create async iterator for generator-based streaming\n * Enables using the stream with for-await-of loops\n */\n async *[Symbol.asyncIterator](): AsyncGenerator<BufferedEvent, void, unknown> {\n while (this.isWritable) {\n // Yield buffered events\n while (this._buffer.length > 0) {\n const event = this._buffer.shift();\n if (event) {\n yield event;\n }\n }\n\n // Wait for next event or close\n await new Promise<void>(resolve => {\n const checkBuffer = () => {\n if (this._buffer.length > 0 || !this.isWritable) {\n this._emitter.off('event', checkBuffer);\n this._emitter.off('close', checkBuffer);\n resolve();\n }\n };\n\n this._emitter.on('event', checkBuffer);\n this._emitter.on('close', checkBuffer);\n });\n }\n }\n}\n\n/**\n * Create an SSE stream with backpressure management\n *\n * This factory function creates a fully-featured SSE stream that:\n * - Automatically registers with the connection registry\n * - Manages buffer overflow with configurable strategies\n * - Handles client disconnections gracefully\n * - Provides async iteration support\n * - Supports reconnection with event ID sequencing\n * - Optional heartbeat for connection health monitoring\n * - Prevents memory attacks via event size validation\n *\n * @param ctx - The request context\n * @param options - Stream configuration options\n * @returns A new SSE stream instance\n *\n * @example Basic usage:\n * ```typescript\n * const stream = createSSEStream(ctx);\n * stream.send('message', { text: 'Hello SSE!' });\n * stream.close();\n * ```\n *\n * @example With custom configuration:\n * ```typescript\n * const stream = createSSEStream(ctx, {\n * heartbeatInterval: 30000, // 30s heartbeat\n * maxEventSize: 512 * 1024, // 512KB max event size\n * maxBufferSize: 100,\n * bufferStrategy: 'drop-oldest',\n * autoClose: true\n * });\n *\n * // Send events with automatic size validation\n * try {\n * stream.send('data', largePayload); // Throws if > maxEventSize\n * } catch (error) {\n * console.error('Event too large:', error);\n * }\n * ```\n *\n * @example Using async iteration:\n * ```typescript\n * const stream = createSSEStream(ctx);\n *\n * // Process events using async generator\n * for await (const event of stream) {\n * console.log('Processing event:', event);\n * }\n * ```\n *\n * @example Handling reconnection:\n * ```typescript\n * // Client sends Last-Event-ID header on reconnection\n * // Stream automatically resumes from that ID\n * const stream = createSSEStream(ctx);\n * // If Last-Event-ID: \"42\" was sent, next event will be \"43\"\n * stream.send('message', { text: 'Continuing from where we left off' });\n * ```\n */\nexport function createSSEStream(ctx: Context, options?: SSEOptions): SSEStreamExtended {\n return new SSEStreamImpl(ctx, options);\n}\n","/**\n * Backpressure strategy types and validation schemas for SSE streaming.\n * Provides runtime type checking and sensible defaults for buffer management.\n */\n\nimport { z } from 'zod';\n\n/**\n * Buffer overflow strategies when high watermark is reached.\n * Aligned with SSEBufferStrategy from @blaize-types/sse\n */\nexport const BufferStrategySchema = z.enum([\n 'drop-oldest', // Drop oldest messages from buffer (FIFO)\n 'drop-newest', // Drop newest messages (reject new)\n 'close', // Close the stream when buffer limit is reached\n]);\n\nexport type BufferStrategy = z.infer<typeof BufferStrategySchema>;\n\n/**\n * Watermark configuration for buffer management.\n * Low watermark resumes flow, high watermark triggers strategy.\n */\nexport const WatermarkConfigSchema = z\n .object({\n low: z.number().int().positive().describe('Resume threshold in messages'),\n high: z.number().int().positive().describe('Trigger threshold in messages'),\n })\n .refine(data => data.low < data.high, {\n message: 'Low watermark must be less than high watermark',\n path: ['low'],\n });\n\nexport type WatermarkConfig = z.infer<typeof WatermarkConfigSchema>;\n\n/**\n * Size limits for buffer management.\n */\nexport const SizeLimitsSchema = z.object({\n maxMessages: z\n .number()\n .int()\n .positive()\n .max(100000)\n .describe('Maximum number of messages in buffer'),\n maxBytes: z\n .number()\n .int()\n .positive()\n .max(100 * 1024 * 1024) // 100MB max\n .optional()\n .describe('Maximum buffer size in bytes'),\n messageTimeout: z\n .number()\n .int()\n .nonnegative()\n .max(300000) // 5 minutes max\n .optional()\n .describe('Message TTL in milliseconds'),\n});\n\nexport type SizeLimits = z.infer<typeof SizeLimitsSchema>;\n\n/**\n * Complete backpressure configuration.\n */\nexport const BackpressureConfigSchema = z\n .object({\n enabled: z.boolean().default(true).describe('Enable backpressure management'),\n\n strategy: BufferStrategySchema.default('drop-oldest').describe(\n 'Strategy when buffer reaches high watermark'\n ),\n\n watermarks: WatermarkConfigSchema.default({\n low: 100,\n high: 1000,\n }).describe('Buffer watermark thresholds'),\n\n limits: SizeLimitsSchema.default({\n maxMessages: 10000,\n }).describe('Buffer size constraints'),\n\n metrics: z\n .object({\n enabled: z.boolean().default(false),\n interval: z.number().int().positive().default(5000),\n })\n .optional()\n .describe('Metrics collection configuration'),\n })\n .refine(\n data => {\n // Ensure watermarks are within limits\n return data.watermarks.high <= data.limits.maxMessages;\n },\n {\n message: 'High watermark cannot exceed maxMessages limit',\n path: ['watermarks', 'high'],\n }\n );\n\nexport type BackpressureConfig = z.infer<typeof BackpressureConfigSchema>;\n\n/**\n * Factory for creating default configurations.\n */\nexport const createDefaultConfig = (\n overrides?: Partial<BackpressureConfig>\n): BackpressureConfig => {\n return BackpressureConfigSchema.parse(overrides || {});\n};\n\n/**\n * Validation helper with detailed error messages.\n */\nexport const validateConfig = (\n config: unknown\n): { success: true; data: BackpressureConfig } | { success: false; errors: string[] } => {\n const result = BackpressureConfigSchema.safeParse(config);\n\n if (result.success) {\n return { success: true, data: result.data };\n }\n\n const errors = result.error.issues.map(issue => {\n const path = issue.path.join('.');\n return path ? `${path}: ${issue.message}` : issue.message;\n });\n\n return { success: false, errors };\n};\n\n/**\n * Type guards for runtime checks.\n */\nexport const isValidStrategy = (value: unknown): value is BufferStrategy => {\n return BufferStrategySchema.safeParse(value).success;\n};\n\nexport const isValidWatermarks = (value: unknown): value is WatermarkConfig => {\n return WatermarkConfigSchema.safeParse(value).success;\n};\n\nexport const isValidConfig = (value: unknown): value is BackpressureConfig => {\n return BackpressureConfigSchema.safeParse(value).success;\n};\n","/**\n * Internal SSE Connection Registry\n *\n * This module is INTERNAL ONLY and not exposed in the public API.\n * It manages active SSE connections, enforces limits, and handles cleanup.\n * The registry is created lazily on first SSE route initialization.\n *\n */\n\nimport type { ConnectionEntry, ConnectionRegistry, RegistryConfig } from '@blaize-types/sse';\n\n/**\n *\n * Default configuration values\n *\n */\nconst DEFAULT_CONFIG: Required<RegistryConfig> = {\n maxConnections: 10000,\n maxConnectionsPerClient: 100,\n inactiveTimeout: 30 * 60 * 1000, // 30 minutes\n cleanupInterval: 60 * 1000, // 1 minute\n};\n\n/**\n * Creates a connection registry using functional patterns with closure-based state\n * @internal\n */\nfunction createConnectionRegistry(config?: RegistryConfig): ConnectionRegistry {\n // Merge with defaults\n const settings = { ...DEFAULT_CONFIG, ...config };\n\n // Private state using closure\n const connections = new Map<string, ConnectionEntry>();\n const clientConnectionCounts = new Map<string, number>();\n let cleanupTimer: NodeJS.Timeout | null = null;\n\n // Create the registry object first so we can reference its methods\n const registry: ConnectionRegistry = {} as ConnectionRegistry;\n\n /**\n * Start periodic cleanup if not already running\n */\n const startCleanupTimer = (cleanupFn: () => void): void => {\n if (!cleanupTimer && settings.cleanupInterval > 0) {\n cleanupTimer = setInterval(() => {\n cleanupFn();\n }, settings.cleanupInterval);\n\n // Ensure cleanup timer doesn't prevent process exit\n if (cleanupTimer.unref) {\n cleanupTimer.unref();\n }\n }\n };\n\n /**\n * Stop the cleanup timer\n */\n const stopCleanupTimer = (): void => {\n if (cleanupTimer) {\n clearInterval(cleanupTimer);\n cleanupTimer = null;\n }\n };\n\n /**\n * Update client connection count\n */\n const updateClientCount = (clientIp: string | undefined, delta: number): void => {\n if (!clientIp) return;\n\n const current = clientConnectionCounts.get(clientIp) || 0;\n const newCount = current + delta;\n\n if (newCount <= 0) {\n clientConnectionCounts.delete(clientIp);\n } else {\n clientConnectionCounts.set(clientIp, newCount);\n }\n };\n\n /**\n * Add a connection to the registry\n * @throws {Error} If connection ID already exists or limits exceeded\n */\n const add: ConnectionRegistry['add'] = (id, stream, metadata) => {\n // Check if ID already exists\n if (connections.has(id)) {\n throw new Error(`Connection with ID ${id} already exists`);\n }\n\n // Check total connection limit\n if (connections.size >= settings.maxConnections) {\n throw new Error(`Maximum connection limit reached (${settings.maxConnections})`);\n }\n\n // Check per-client limit\n if (metadata?.clientIp) {\n const clientCount = clientConnectionCounts.get(metadata.clientIp) || 0;\n if (clientCount >= settings.maxConnectionsPerClient) {\n throw new Error(\n `Maximum connections per client reached (${settings.maxConnectionsPerClient})`\n );\n }\n }\n\n // Add the connection\n const now = Date.now();\n connections.set(id, {\n stream,\n connectedAt: now,\n lastActivity: now,\n clientIp: metadata?.clientIp,\n userAgent: metadata?.userAgent,\n });\n\n // Update client count\n updateClientCount(metadata?.clientIp, 1);\n\n // Start cleanup timer on first connection\n if (connections.size === 1) {\n startCleanupTimer(registry.cleanup);\n }\n\n // Register cleanup callback on stream close\n stream.onClose(() => {\n remove(id);\n });\n };\n\n /**\n * Remove a connection from the registry\n */\n const remove: ConnectionRegistry['remove'] = id => {\n const entry = connections.get(id);\n if (!entry) return;\n\n // Remove from registry\n connections.delete(id);\n\n // Update client count\n updateClientCount(entry.clientIp, -1);\n\n // Stop cleanup timer if no connections\n if (connections.size === 0) {\n stopCleanupTimer();\n }\n };\n\n /**\n * Get current connection count\n */\n const count: ConnectionRegistry['count'] = () => {\n return connections.size;\n };\n\n /**\n * Clean up inactive or closed connections\n */\n const cleanup: ConnectionRegistry['cleanup'] = () => {\n const now = Date.now();\n const idsToRemove: string[] = [];\n\n connections.forEach((entry, id) => {\n // Check if connection is inactive\n const isInactive = now - entry.lastActivity > settings.inactiveTimeout;\n\n // Check if stream is closed (assuming SSEStream has an isWritable property)\n // Since we don't have the actual implementation yet, we'll check if the stream\n // has been explicitly closed by checking a hypothetical state\n const isClosed =\n !entry.stream ||\n (entry.stream as any).state === 'closed' ||\n !(entry.stream as any).isWritable;\n\n if (isInactive || isClosed) {\n idsToRemove.push(id);\n\n // Close the stream if it's still open\n if (entry.stream && typeof entry.stream.close === 'function') {\n try {\n entry.stream.close();\n } catch {\n // Ignore errors during cleanup\n }\n }\n }\n });\n\n // Remove marked connections\n idsToRemove.forEach(id => remove(id));\n };\n\n /**\n * Get a connection by ID\n */\n const get: ConnectionRegistry['get'] = id => {\n const entry = connections.get(id);\n return entry?.stream;\n };\n\n /**\n * Check if a connection exists\n */\n const has: ConnectionRegistry['has'] = id => {\n return connections.has(id);\n };\n\n /**\n * Get all connection IDs\n */\n const getIds: ConnectionRegistry['getIds'] = () => {\n return Array.from(connections.keys());\n };\n\n /**\n * Shutdown the registry and close all connections\n */\n const shutdown: ConnectionRegistry['shutdown'] = () => {\n // Stop cleanup timer\n stopCleanupTimer();\n\n // Close all connections\n connections.forEach(entry => {\n if (entry.stream && typeof entry.stream.close === 'function') {\n try {\n entry.stream.close();\n } catch {\n // Ignore errors during shutdown\n }\n }\n });\n\n // Clear all state\n connections.clear();\n clientConnectionCounts.clear();\n };\n\n // Assign methods to the registry object\n registry.add = add;\n registry.remove = remove;\n registry.count = count;\n registry.cleanup = cleanup;\n registry.get = get;\n registry.has = has;\n registry.getIds = getIds;\n registry.shutdown = shutdown;\n\n // Return the registry interface\n return registry;\n}\n\n/**\n *\n * Singleton instance holder using closure\n *\n */\nlet registryInstance: ConnectionRegistry | null = null;\n\n/**\n * Get or create the singleton registry instance (lazy initialization)\n * This is the only function that should be used by other SSE modules\n *\n * @param config - Optional configuration (only used on first initialization)\n * @returns The singleton connection registry\n */\nexport function getConnectionRegistry(config?: RegistryConfig): ConnectionRegistry {\n if (!registryInstance) {\n registryInstance = createConnectionRegistry(config);\n }\n return registryInstance;\n}\n\n/**\n *\n * Reset the singleton instance (for testing purposes only)\n *\n */\nexport function resetRegistry(): void {\n if (registryInstance) {\n registryInstance.shutdown();\n registryInstance = null;\n }\n}\n","/**\n * SSEBufferOverflowError class for SSE buffer overflow conditions\n *\n * This error is thrown when an SSE stream buffer exceeds its configured limits.\n * It provides context about the overflow and the strategy applied.\n */\n\nimport { BlaizeError, ErrorType } from '@blaize-types/errors';\n\nimport { getCorrelationId } from '../tracing/correlation';\n\nimport type { SSEBufferOverflowErrorDetails } from '@blaize-types/errors';\n\n/**\n * Error thrown when SSE buffer overflows\n *\n * Automatically sets HTTP status to 503 (Service Unavailable) indicating\n * the server cannot handle the request due to overload.\n *\n * @example Basic usage with required details:\n * ```typescript\n * throw new SSEBufferOverflowError('SSE buffer limit exceeded', {\n * currentSize: 1000,\n * maxSize: 1000,\n * strategy: 'drop-oldest'\n * });\n * ```\n *\n * @example With full context:\n * ```typescript\n * throw new SSEBufferOverflowError('Buffer overflow on high-frequency stream', {\n * clientId: 'client-123',\n * currentSize: 5000,\n * maxSize: 5000,\n * eventsDropped: 25,\n * strategy: 'drop-oldest',\n * triggeringEvent: 'market-data-update'\n * });\n * ```\n *\n * @example Stream closed due to overflow:\n * ```typescript\n * throw new SSEBufferOverflowError('Stream closed due to buffer overflow', {\n * clientId: 'client-456',\n * currentSize: 1000,\n * maxSize: 1000,\n * strategy: 'close',\n * eventsDropped: 0\n * });\n * ```\n */\nexport class SSEBufferOverflowError extends BlaizeError<SSEBufferOverflowErrorDetails> {\n /**\n * Creates a new SSEBufferOverflowError instance\n *\n * @param title - Human-readable error message\n * @param details - Required context about the buffer overflow\n * @param correlationId - Optional correlation ID (uses current context if not provided)\n */\n constructor(\n title: string,\n details: SSEBufferOverflowErrorDetails,\n correlationId: string | undefined = undefined\n ) {\n super(\n ErrorType.SSE_BUFFER_OVERFLOW,\n title,\n 503, // HTTP 503 Service Unavailable - server cannot handle the request\n correlationId ?? getCorrelationId(),\n details\n );\n }\n}\n","/**\n * SSEStreamClosedError class for operations on closed SSE streams\n *\n * This error is thrown when attempting to perform operations on a closed SSE stream.\n * It provides context about when and why the stream was closed.\n */\n\nimport { BlaizeError, ErrorType } from '@blaize-types/errors';\n\nimport { getCorrelationId } from '../tracing/correlation';\n\nimport type { SSEStreamClosedErrorDetails } from '@blaize-types/errors';\n\n/**\n * Error thrown when attempting operations on a closed SSE stream\n *\n * Automatically sets HTTP status to 410 (Gone) indicating\n * the resource is no longer available.\n *\n * @example Basic usage:\n * ```typescript\n * throw new SSEStreamClosedError('Cannot send event to closed stream');\n * ```\n *\n * @example With closure context:\n * ```typescript\n * throw new SSEStreamClosedError('Stream closed by client', {\n * clientId: 'client-123',\n * closedAt: new Date().toISOString(),\n * closeReason: 'client-disconnect',\n * canReconnect: true,\n * retryAfter: 5000\n * });\n * ```\n *\n * @example Timeout closure:\n * ```typescript\n * throw new SSEStreamClosedError('Stream closed due to inactivity', {\n * clientId: 'client-456',\n * closedAt: new Date().toISOString(),\n * closeReason: 'timeout',\n * canReconnect: true,\n * retryAfter: 1000\n * });\n * ```\n *\n * @example Permanent closure:\n * ```typescript\n * throw new SSEStreamClosedError('Stream permanently closed', {\n * clientId: 'client-789',\n * closedAt: new Date().toISOString(),\n * closeReason: 'error',\n * canReconnect: false\n * });\n * ```\n */\nexport class SSEStreamClosedError extends BlaizeError<SSEStreamClosedErrorDetails> {\n /**\n * Creates a new SSEStreamClosedError instance\n *\n * @param title - Human-readable error message\n * @param details - Optional context about the stream closure\n * @param correlationId - Optional correlation ID (uses current context if not provided)\n */\n constructor(\n title: string,\n details: SSEStreamClosedErrorDetails | undefined = undefined,\n correlationId: string | undefined = undefined\n ) {\n super(\n ErrorType.SSE_STREAM_CLOSED,\n title,\n 410, // HTTP 410 Gone - resource no longer available\n correlationId ?? getCorrelationId(),\n details\n );\n }\n}\n","import { BlaizeError, ErrorType } from '@blaize-types/errors';\nimport { getCorrelationId } from 'src/tracing/correlation';\n\nexport class SSENotAcceptableError extends BlaizeError<{\n acceptHeader: string;\n requiredHeader: string;\n endpoint: string;\n}> {\n constructor(message: string, details: any, correlationId?: string) {\n super(\n ErrorType.SSE_NOT_ACCEPTABLE,\n message,\n 406, // Not Acceptable status\n correlationId || getCorrelationId(),\n details\n );\n }\n}\n","/**\n * @module sse/route-creator\n * @description SSE route creator following BlaizeJS v0.4.x patterns\n */\n\nimport { z } from 'zod';\n\nimport { createSSEStream } from './stream';\nimport { SSENotAcceptableError } from '../errors/sse-not-acceptable-error';\nimport { getRoutePath } from '../router/create';\n\nimport type { State, Services, Context } from '@blaize-types/context';\nimport type { CreateSSERoute, SSEStreamExtended, TypedSSEStream } from '@blaize-types/sse';\n\n/**\n * Validate an SSE configuration\n */\nfunction validateSSEConfig(config: any): void {\n if (!config.handler || typeof config.handler !== 'function') {\n throw new Error('SSE route handler must be a function');\n }\n\n if (config.middleware && !Array.isArray(config.middleware)) {\n throw new Error('Middleware for SSE route must be an array');\n }\n\n // Validate schema if provided\n if (config.schema) {\n const { params, query, events } = config.schema;\n\n if (params && (!params._def || typeof params.parse !== 'function')) {\n throw new Error('Params schema for SSE must be a valid Zod schema');\n }\n\n if (query && (!query._def || typeof query.parse !== 'function')) {\n throw new Error('Query schema for SSE must be a valid Zod schema');\n }\n\n // Events can be either a Zod schema or an object of Zod schemas\n if (events) {\n if (typeof events === 'object' && !events._def) {\n // It's an event map, validate each event schema\n for (const [eventName, eventSchema] of Object.entries(events)) {\n if (\n !eventSchema ||\n typeof eventSchema !== 'object' ||\n !(eventSchema as any)._def ||\n typeof (eventSchema as any).parse !== 'function'\n ) {\n throw new Error(`Event schema for '${eventName}' must be a valid Zod schema`);\n }\n }\n } else if (events._def && typeof events.parse === 'function') {\n // Single schema - that's fine too\n } else {\n throw new Error('Events schema for SSE must be a valid Zod schema or event map');\n }\n }\n }\n}\n\n/**\n * Create a typed SSE stream wrapper if event schemas are provided\n */\nfunction createTypedStream<TEvents extends Record<string, z.ZodType>>(\n stream: SSEStreamExtended,\n eventSchemas: TEvents\n): TypedSSEStream<TEvents> {\n const typedStream = Object.create(stream) as TypedSSEStream<TEvents>;\n\n // Override send method with validation\n const originalSend = stream.send.bind(stream);\n typedStream.send = function <K extends keyof TEvents>(\n event: K & string,\n data: z.infer<TEvents[K]>\n ): void {\n // Validate the data against the schema if it exists\n const schema = eventSchemas[event];\n if (schema) {\n try {\n const validated = schema.parse(data);\n originalSend(event, validated);\n } catch (error) {\n stream.sendError(\n new Error(\n `Event '${event}' validation failed: ${error instanceof Error ? error.message : String(error)}`\n )\n );\n }\n } else {\n // No schema for this event, send as-is\n originalSend(event, data);\n }\n };\n\n return typedStream;\n}\n\n/**\n * Create an SSE route following BlaizeJS patterns\n *\n * SSE routes use a stream-first handler signature: (stream, ctx, params)\n * This makes sense because SSE is fundamentally about streaming events.\n *\n * @example Basic usage:\n * ```typescript\n * export default createSSERoute<AppState, AppServices>()({\n * handler: async (stream, ctx, params) => {\n * stream.send('message', { text: 'Hello SSE!' });\n *\n * // Access state and services as usual\n * const user = ctx.state.user;\n * const db = ctx.services.database;\n * }\n * });\n * ```\n *\n * @example With typed events (automatic type inference!):\n * ```typescript\n * export default createSSERoute<AppState, AppServices>()({\n * schema: {\n * params: z.object({ roomId: z.string() }),\n * events: {\n * message: z.object({ content: z.string(), author: z.string() }),\n * typing: z.object({ userId: z.string(), isTyping: z.boolean() }),\n * presence: z.object({ users: z.array(z.string()) })\n * }\n * },\n * handler: async (stream, ctx, params) => {\n * // stream is automatically typed as TypedSSEStream!\n * stream.send('message', { content: 'Hi', author: 'bot' }); // ✅ Type-safe!\n * stream.send('typing', { userId: params.roomId, isTyping: true }); // ✅ Type-safe!\n * // stream.send('unknown', {}); // ❌ TypeScript error!\n * }\n * });\n * ```\n */\nexport const createSSERoute: CreateSSERoute = <\n _TState extends State = State,\n _TServices extends Services = Services,\n>() => {\n return (config: any) => {\n // Validate the configuration\n validateSSEConfig(config);\n\n // Get the route path\n const path = getRoutePath();\n\n // Create a wrapped handler that manages the SSE stream lifecycle\n const wrappedHandler = async (ctx: Context, params: any) => {\n // Validate SSE accept header\n const accept = ctx.request.header('accept');\n if (accept && !accept.includes('text/event-stream') && !accept.includes('*/*')) {\n throw new SSENotAcceptableError('This endpoint requires Server-Sent Events support', {\n acceptHeader: accept,\n requiredHeader: 'text/event-stream',\n endpoint: ctx.request.path,\n });\n }\n\n if (config.schema) {\n try {\n if (config.schema.params) {\n params = config.schema.params.parse(params);\n }\n if (config.schema.query) {\n ctx.request.query = config.schema.query.parse(ctx.request.query);\n }\n } catch (validationError) {\n // Validation failed BEFORE SSE started - safe to throw\n console.error('[SSE] Validation error:', validationError);\n throw validationError;\n }\n }\n\n // Create the SSE stream\n // CRITICAL FIX: Mark the response as sent immediately\n // This prevents the framework from trying to send any additional response\n const baseStream = createSSEStream(ctx, config.options);\n\n // Create typed stream if event schemas provided\n const stream =\n config.schema?.events &&\n typeof config.schema.events === 'object' &&\n !config.schema.events._def\n ? createTypedStream(baseStream, config.schema.events)\n : baseStream;\n\n // Handle client disconnect\n ctx.request.raw.on('close', () => stream.close());\n\n try {\n // Execute the original handler with (stream, ctx, params) signature\n await config.handler(stream, ctx, params);\n } catch (error) {\n console.error('[SSE] Handler error - THIS IS THE REAL ERROR:', error);\n console.error('[SSE] Stack trace:', error instanceof Error ? error.stack : 'No stack');\n // Send error to stream if still writable\n if (stream.isWritable) {\n stream.sendError(error instanceof Error ? error : new Error(String(error)));\n }\n stream.close();\n\n throw error;\n }\n };\n\n // Return the route definition with GET method (SSE uses GET)\n return {\n GET: {\n handler: wrappedHandler,\n schema:\n config.schema?.params || config.schema?.query\n ? {\n params: config.schema?.params,\n query: config.schema?.query,\n }\n : undefined,\n middleware: config.middleware,\n options: config.options,\n },\n path,\n };\n };\n};\n","/**\n * Extract parameter values from a URL path\n */\nexport function extractParams(\n path: string,\n pattern: RegExp,\n paramNames: string[]\n): Record<string, string> {\n const match = pattern.exec(path);\n if (!match) {\n return {};\n }\n\n const params: Record<string, string> = {};\n\n // Extract parameter values from regex match groups\n for (let i = 0; i < paramNames.length; i++) {\n // Add 1 to index since the first capture group is at index 1\n params[paramNames[i]!] = match[i + 1] || '';\n }\n\n return params;\n}\n\n/**\n * Compile a path pattern with parameters\n */\nexport function compilePathPattern(path: string): { pattern: RegExp; paramNames: string[] } {\n const paramNames: string[] = [];\n\n // Special case for root path\n if (path === '/') {\n return {\n pattern: /^\\/$/,\n paramNames: [],\n };\n }\n\n // First escape special regex characters (except for : and [ ] which we process specially)\n let patternString = path.replace(/([.+*?^$(){}|\\\\])/g, '\\\\$1');\n\n // Replace route parameters with regex capture groups\n patternString = patternString\n // Replace :param syntax with capture groups\n .replace(/\\/:([^/]+)/g, (_, paramName) => {\n paramNames.push(paramName);\n return '/([^/]+)';\n })\n // Replace [param] syntax (for file-based routing)\n .replace(/\\/\\[([^\\]]+)\\]/g, (_, paramName) => {\n paramNames.push(paramName);\n return '/([^/]+)';\n });\n\n // Make the trailing slash optional (if not already the root path)\n // This adds an optional trailing slash to the end of the pattern\n patternString = `${patternString}(?:/)?`;\n\n // Create the regex pattern\n // This is safe because we've escaped special RegExp characters and\n // we're using developer-defined routes, not user input\n const pattern = new RegExp(`^${patternString}$`);\n\n return {\n pattern,\n paramNames,\n };\n}\n\n/**\n * Convert parameters object to URL query string\n */\nexport function paramsToQuery(params: Record<string, string | number | boolean>): string {\n const parts: string[] = [];\n\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n const encodedKey = encodeURIComponent(key);\n const encodedValue = encodeURIComponent(String(value));\n parts.push(`${encodedKey}=${encodedValue}`);\n }\n }\n\n return parts.length > 0 ? `?${parts.join('&')}` : '';\n}\n\n/**\n * Build a URL with path parameters\n */\nexport function buildUrl(\n pathPattern: string,\n params: Record<string, string | number | boolean> = {},\n query: Record<string, string | number | boolean> = {}\n): string {\n // Extract path parameters and query parameters\n const pathParams: Record<string, string | number | boolean> = {};\n const queryParams: Record<string, string | number | boolean> = { ...query };\n\n // Find all parameter names in the path\n const paramNames: string[] = [];\n pathPattern.replace(/\\/:([^/]+)/g, (_, paramName) => {\n paramNames.push(paramName);\n return '/';\n });\n\n // Separate params into path params and additional query params\n for (const [key, value] of Object.entries(params)) {\n if (paramNames.includes(key)) {\n pathParams[key] = value;\n } else {\n queryParams[key] = value;\n }\n }\n\n // Replace path parameters\n let url = pathPattern;\n for (const [key, value] of Object.entries(pathParams)) {\n url = url.replace(`:${key}`, encodeURIComponent(String(value)));\n }\n\n // Add query string if needed\n const queryString = paramsToQuery(queryParams);\n\n return url + queryString;\n}\n","import { compilePathPattern, extractParams } from './params';\n\nimport type {\n HttpMethod,\n RouteMethodOptions,\n RouteMatch,\n Matcher,\n RouteEntry,\n Route,\n} from '../../index';\n\n/**\n * Create a route matcher\n */\nexport function createMatcher(): Matcher {\n // Private state\n const routes: RouteEntry[] = [];\n\n return {\n /**\n * Add a route to the matcher\n */\n add(path: string, method: HttpMethod, routeOptions: RouteMethodOptions) {\n const { pattern, paramNames } = compilePathPattern(path);\n\n const newRoute: RouteEntry = {\n path,\n method,\n pattern,\n paramNames,\n routeOptions,\n };\n\n // Find the insertion point using findIndex\n const insertIndex = routes.findIndex(route => paramNames.length < route.paramNames.length);\n\n // If no insertion point found, append to end\n if (insertIndex === -1) {\n routes.push(newRoute);\n } else {\n routes.splice(insertIndex, 0, newRoute);\n }\n },\n\n /**\n * Remove a route from the matcher by path\n */\n remove(path: string) {\n // Remove all routes that match the given path\n for (let i = routes.length - 1; i >= 0; i--) {\n if ((routes[i] as Route).path === path) {\n routes.splice(i, 1);\n }\n }\n },\n\n /**\n * Clear all routes from the matcher\n */\n clear() {\n routes.length = 0;\n },\n\n /**\n * Match a URL path to a route\n */\n match(path: string, method: HttpMethod): RouteMatch | null {\n // First, try to find an exact match for the method\n const pathname = path.split('?')[0];\n if (!pathname) return null;\n\n for (const route of routes) {\n // Skip routes that don't match the method\n if (route.method !== method) continue;\n\n // Try to match the path\n const match = route.pattern.exec(pathname);\n if (match) {\n // Extract parameters from the match\n const params = extractParams(path, route.pattern, route.paramNames);\n\n return {\n route: route.routeOptions,\n params,\n };\n }\n }\n\n // If no exact method match, check if path exists but method is different\n // This allows returning 405 Method Not Allowed instead of 404 Not Found\n const matchingPath = routes.find(\n route => route.method !== method && route.pattern.test(path)\n );\n\n if (matchingPath) {\n // Return null but with allowedMethods to indicate method not allowed\n return {\n route: null,\n params: {},\n methodNotAllowed: true,\n allowedMethods: routes\n .filter(route => route.pattern.test(path))\n .map(route => route.method),\n } as unknown as RouteMatch; // Type assertion for the extended return type\n }\n\n return null; // No match found\n },\n\n /**\n * Get all registered routes\n */\n getRoutes(): { path: string; method: HttpMethod }[] {\n return routes.map(route => ({\n path: route.path,\n method: route.method,\n }));\n },\n\n /**\n * Find routes matching a specific path\n */\n findRoutes(\n path: string\n ): { path: string; method: HttpMethod; params: Record<string, string> }[] {\n return routes\n .filter(route => route.pattern.test(path))\n .map(route => ({\n path: route.path,\n method: route.method,\n params: extractParams(path, route.pattern, route.paramNames),\n }));\n },\n };\n}\n","/* eslint-disable @typescript-eslint/no-empty-object-type */\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport EventEmitter from 'node:events';\n\nimport { setRuntimeConfig } from '../config';\nimport { startServer } from './start';\nimport { registerSignalHandlers, stopServer } from './stop';\nimport { validateServerOptions } from './validation';\nimport { createPluginLifecycleManager } from '../plugins/lifecycle';\nimport { validatePlugin } from '../plugins/validation';\nimport { createRouter } from '../router/router';\nimport { _setCorrelationConfig } from '../tracing/correlation';\n\nimport type {\n ComposeMiddlewareStates,\n ComposeMiddlewareServices,\n ComposePluginStates,\n ComposePluginServices,\n} from '@blaize-types/composition';\nimport type { Context } from '@blaize-types/context';\nimport type { Middleware } from '@blaize-types/middleware';\nimport type { Plugin } from '@blaize-types/plugins';\nimport type {\n Server,\n ServerOptions,\n ServerOptionsInput,\n StopOptions,\n UnknownServer,\n} from '@blaize-types/server';\n\nexport const DEFAULT_OPTIONS: ServerOptions = {\n port: 3000,\n host: 'localhost',\n routesDir: './routes',\n http2: {\n enabled: true,\n },\n middleware: [],\n plugins: [],\n bodyLimits: {\n // 🆕 NEW\n json: 512 * 1024,\n form: 1024 * 1024,\n text: 5 * 1024 * 1024,\n raw: 10 * 1024 * 1024,\n multipart: {\n maxFileSize: 50 * 1024 * 1024,\n maxTotalSize: 100 * 1024 * 1024,\n maxFiles: 10,\n maxFieldSize: 1024 * 1024,\n },\n },\n};\n\n/**\n * Creates the configuration options by merging defaults with user-provided options\n */\nfunction createServerOptions(options: ServerOptionsInput = {}): ServerOptions {\n const mergedOptions: ServerOptions = {\n port: options.port ?? DEFAULT_OPTIONS.port,\n host: options.host ?? DEFAULT_OPTIONS.host,\n routesDir: options.routesDir ?? DEFAULT_OPTIONS.routesDir,\n http2: {\n enabled: options.http2?.enabled ?? DEFAULT_OPTIONS.http2!.enabled,\n keyFile: options.http2?.keyFile,\n certFile: options.http2?.certFile,\n },\n middleware: options.middleware ?? DEFAULT_OPTIONS.middleware,\n plugins: options.plugins ?? DEFAULT_OPTIONS.plugins,\n correlation: options.correlation,\n cors: options.cors,\n bodyLimits: options.bodyLimits\n ? {\n json: options.bodyLimits.json ?? DEFAULT_OPTIONS.bodyLimits.json,\n form: options.bodyLimits.form ?? DEFAULT_OPTIONS.bodyLimits.form,\n text: options.bodyLimits.text ?? DEFAULT_OPTIONS.bodyLimits.text,\n raw: options.bodyLimits.raw ?? DEFAULT_OPTIONS.bodyLimits.raw,\n multipart: {\n maxFileSize:\n options.bodyLimits.multipart?.maxFileSize ??\n DEFAULT_OPTIONS.bodyLimits.multipart.maxFileSize,\n maxTotalSize:\n options.bodyLimits.multipart?.maxTotalSize ??\n DEFAULT_OPTIONS.bodyLimits.multipart.maxTotalSize,\n maxFiles:\n options.bodyLimits.multipart?.maxFiles ??\n DEFAULT_OPTIONS.bodyLimits.multipart.maxFiles,\n maxFieldSize:\n options.bodyLimits.multipart?.maxFieldSize ??\n DEFAULT_OPTIONS.bodyLimits.multipart.maxFieldSize,\n },\n }\n : DEFAULT_OPTIONS.bodyLimits,\n };\n try {\n const validated = validateServerOptions(mergedOptions);\n\n // Set runtime config after successful validation\n setRuntimeConfig({ routesDir: validated.routesDir });\n return validated;\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Failed to create server: ${error.message}`);\n }\n throw new Error(`Failed to create server: ${String(error)}`);\n }\n}\n\n/**\n * Configures the correlation ID system based on server options\n *\n * @param options - The validated server options\n */\nfunction configureCorrelation(options: ServerOptions): void {\n if (options.correlation) {\n // Apply correlation configuration if provided\n _setCorrelationConfig(options.correlation.headerName, options.correlation.generator);\n }\n // If no correlation options provided, the system uses defaults\n}\n\n/**\n * Creates the server listen method\n */\nfunction createListenMethod(\n serverInstance: UnknownServer,\n validatedOptions: ServerOptions\n): UnknownServer['listen'] {\n return async () => {\n // Configure correlation before starting the server\n configureCorrelation(validatedOptions);\n // Initialize middleware and plugins\n await initializePlugins(serverInstance);\n\n // Use the functional manager\n await serverInstance.pluginManager.initializePlugins(serverInstance);\n\n // Start the server\n await startServer(serverInstance, validatedOptions);\n\n await serverInstance.pluginManager.onServerStart(serverInstance, serverInstance.server);\n\n // Setup signal handlers and emit events\n setupServerLifecycle(serverInstance);\n\n return serverInstance;\n };\n}\n\n/**\n * Initializes plugins\n */\nasync function initializePlugins(serverInstance: UnknownServer): Promise<void> {\n // Register plugins from options\n for (const p of serverInstance.plugins) {\n await p.register(serverInstance);\n }\n}\n\n/**\n * Sets up server lifecycle (signal handlers, events)\n */\nfunction setupServerLifecycle(serverInstance: UnknownServer): void {\n // Register signal handlers for graceful shutdown\n const signalHandlers = registerSignalHandlers(() => serverInstance.close());\n\n // Store handlers to unregister when server closes\n serverInstance._signalHandlers = signalHandlers;\n\n // Emit started event\n serverInstance.events.emit('started');\n}\n\n/**\n * Creates the server close method\n */\nfunction createCloseMethod(serverInstance: UnknownServer): UnknownServer['close'] {\n return async (stopOptions?: StopOptions) => {\n if (!serverInstance.server) {\n return;\n }\n\n // Prepare options\n const options: StopOptions = { ...stopOptions };\n\n // Unregister signal handlers if they exist\n if (serverInstance._signalHandlers) {\n serverInstance._signalHandlers.unregister();\n delete serverInstance._signalHandlers;\n }\n\n // Call stopServer with the server instance\n await stopServer(serverInstance, options);\n };\n}\n\n/**\n * Creates the server use method for adding middleware\n * This version properly handles type accumulation for both single and array middleware\n */\nfunction createUseMethod<TState, TServices>(\n serverInstance: Server<TState, TServices>\n): Server<TState, TServices>['use'] {\n return ((middleware: Middleware | Middleware[]) => {\n const middlewareArray = Array.isArray(middleware) ? middleware : [middleware];\n serverInstance.middleware.push(...middlewareArray);\n // Return the server instance with accumulated types\n // TypeScript will infer the correct return type based on the overload\n return serverInstance;\n }) as Server<TState, TServices>['use'];\n}\n\n/**\n * Creates the server register method for plugins\n * This version properly handles type accumulation for both single and array plugins\n */\nfunction createRegisterMethod<TState, TServices>(\n serverInstance: Server<TState, TServices>\n): Server<TState, TServices>['register'] {\n return (async (plugin: Plugin | Plugin[]) => {\n if (Array.isArray(plugin)) {\n // Handle array of plugins\n for (const p of plugin) {\n validatePlugin(p);\n serverInstance.plugins.push(p);\n await p.register(serverInstance);\n }\n } else {\n // Handle single plugin\n validatePlugin(plugin);\n serverInstance.plugins.push(plugin);\n await plugin.register(serverInstance);\n }\n // Return the server instance with accumulated types\n return serverInstance;\n }) as Server<TState, TServices>['register'];\n}\n\n/**\n * Creates a BlaizeJS server instance\n */\nexport function create<\n const TMw extends readonly Middleware<any, any>[] = [],\n const TP extends readonly Plugin<any, any>[] = [],\n>(\n options: ServerOptionsInput & {\n middleware?: TMw;\n plugins?: TP;\n } = {}\n): Server<\n ComposeMiddlewareStates<TMw> & ComposePluginStates<TP>,\n ComposeMiddlewareServices<TMw> & ComposePluginServices<TP>\n> {\n // Create and validate options\n const validatedOptions = createServerOptions(options);\n\n // Extract options and prepare initial components\n const { port, host, middleware, plugins, cors, bodyLimits } = validatedOptions;\n\n // TODO: create registries to manage middleware and plugins\n const initialMiddleware = Array.isArray(middleware) ? [...middleware] : [];\n const initialPlugins = Array.isArray(plugins) ? [...plugins] : [];\n\n // Initialize core server components\n const contextStorage = new AsyncLocalStorage<Context>();\n const router = createRouter({\n routesDir: validatedOptions.routesDir,\n watchMode: process.env.NODE_ENV === 'development',\n });\n // Create plugin lifecycle manager\n const pluginManager = createPluginLifecycleManager({\n debug: process.env.NODE_ENV === 'development',\n continueOnError: true,\n });\n const events = new EventEmitter();\n\n // Type alias for the accumulated types\n type AccumulatedState = ComposeMiddlewareStates<TMw> & ComposePluginStates<TP>;\n type AccumulatedServices = ComposeMiddlewareServices<TMw> & ComposePluginServices<TP>;\n\n // Create server instance with minimal properties\n const serverInstance: Server<AccumulatedState, AccumulatedServices> = {\n server: null as any,\n port,\n host,\n context: contextStorage,\n events,\n plugins: [...initialPlugins],\n middleware: [...initialMiddleware],\n corsOptions: cors,\n bodyLimits,\n _signalHandlers: { unregister: () => {} },\n use: () => serverInstance,\n register: async () => serverInstance,\n listen: async () => serverInstance,\n close: async () => {},\n router,\n pluginManager,\n };\n\n // Add methods to the server instance\n serverInstance.listen = createListenMethod(serverInstance, validatedOptions);\n serverInstance.close = createCloseMethod(serverInstance);\n serverInstance.use = createUseMethod(serverInstance);\n serverInstance.register = createRegisterMethod(serverInstance);\n\n return serverInstance;\n}\n","import * as fs from 'node:fs';\nimport * as http from 'node:http';\nimport * as http2 from 'node:http2';\n\nimport { generateDevCertificates } from './dev-certificate';\nimport { createRequestHandler } from './request-handler';\n\nimport type { Http2Options, ServerOptions, UnknownServer } from '@blaize-types/server';\n\n// Extract certificate handling to a separate function\nasync function prepareCertificates(\n http2Options: Http2Options\n): Promise<{ keyFile?: string; certFile?: string }> {\n // Not using HTTP/2? No certificates needed\n if (!http2Options.enabled) {\n return {};\n }\n\n const { keyFile, certFile } = http2Options;\n\n // If certificates are missing and in development, generate them\n const isDevMode = process.env.NODE_ENV === 'development';\n const certificatesMissing = !keyFile || !certFile;\n\n if (certificatesMissing && isDevMode) {\n const devCerts = await generateDevCertificates();\n return devCerts;\n }\n\n // If certificates are still missing, throw error\n if (certificatesMissing) {\n throw new Error(\n 'HTTP/2 requires SSL certificates. Provide keyFile and certFile in http2 options. ' +\n 'In development, set NODE_ENV=development to generate them automatically.'\n );\n }\n\n return { keyFile, certFile };\n}\n\n// Create server based on protocol\nfunction createServerInstance(\n isHttp2: boolean,\n certOptions: { keyFile?: string; certFile?: string }\n): http.Server | http2.Http2SecureServer {\n if (!isHttp2) {\n return http.createServer();\n }\n\n // Create HTTP/2 server options\n const http2ServerOptions: http2.SecureServerOptions = {\n allowHTTP1: true, // Allow fallback to HTTP/1.1\n };\n\n // Read certificate files\n try {\n if (certOptions.keyFile) {\n http2ServerOptions.key = fs.readFileSync(certOptions.keyFile);\n }\n if (certOptions.certFile) {\n http2ServerOptions.cert = fs.readFileSync(certOptions.certFile);\n }\n } catch (err) {\n throw new Error(\n `Failed to read certificate files: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n\n return http2.createSecureServer(http2ServerOptions);\n}\n\n// Start listening on the specified port and host\nfunction listenOnPort(\n server: http.Server | http2.Http2SecureServer,\n port: number,\n host: string,\n isHttp2: boolean\n): Promise<void> {\n return new Promise((resolve, reject) => {\n server.listen(port, host, () => {\n const protocol = isHttp2 ? 'https' : 'http';\n const url = `${protocol}://${host}:${port}`;\n console.log(`\n🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥\n\n ⚡ BlaizeJS DEVELOPMENT SERVER HOT AND READY ⚡\n \n 🚀 Server: ${url}\n 🔥 Hot Reload: Enabled\n 🛠️ Mode: Development\n \n Time to build something amazing! 🚀\n\n🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥\n`);\n resolve();\n });\n\n server.on('error', err => {\n console.error('Server error:', err);\n reject(err);\n });\n });\n}\n\nasync function initializePlugins(serverInstance: UnknownServer): Promise<void> {\n for (const plugin of serverInstance.plugins) {\n if (typeof plugin.initialize === 'function') {\n await plugin.initialize(serverInstance);\n }\n }\n}\n\n// Main server start function - now with much lower complexity\nexport async function startServer(\n serverInstance: UnknownServer,\n serverOptions: ServerOptions\n): Promise<void> {\n // Server already running? Do nothing.\n if (serverInstance.server) {\n return;\n }\n\n try {\n // Get effective port and host\n const port = serverOptions.port;\n const host = serverOptions.host;\n\n // Initialize all registered plugins\n await initializePlugins(serverInstance);\n\n // Determine if using HTTP/2\n const http2Options = serverOptions.http2 || { enabled: true };\n const isHttp2 = !!http2Options.enabled;\n\n // Prepare certificates if needed\n const certOptions = await prepareCertificates(http2Options);\n\n // Update the server options if we generated certificates\n if (serverOptions.http2 && certOptions.keyFile && certOptions.certFile) {\n serverOptions.http2.keyFile = certOptions.keyFile;\n serverOptions.http2.certFile = certOptions.certFile;\n }\n\n // Create the server instance\n const server = createServerInstance(isHttp2, certOptions);\n\n // Store the server in the instance\n serverInstance.server = server;\n\n // Update server instance properties\n serverInstance.port = port;\n serverInstance.host = host;\n\n // Configure request handling\n const requestHandler = createRequestHandler(serverInstance);\n server.on('request', requestHandler);\n\n // Start listening\n await listenOnPort(server, port, host, isHttp2);\n } catch (error) {\n console.error('Failed to start server:', error);\n throw error;\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport * as selfsigned from 'selfsigned';\n\nexport interface DevCertificates {\n keyFile: string;\n certFile: string;\n}\n\nexport async function generateDevCertificates(): Promise<DevCertificates> {\n const certDir = path.join(process.cwd(), '.blaizejs', 'certs');\n const keyPath = path.join(certDir, 'dev.key');\n const certPath = path.join(certDir, 'dev.cert');\n \n // Check if certificates already exist\n if (fs.existsSync(keyPath) && fs.existsSync(certPath)) {\n return {\n keyFile: keyPath,\n certFile: certPath\n };\n }\n \n // Create directory if it doesn't exist\n if (!fs.existsSync(certDir)) {\n fs.mkdirSync(certDir, { recursive: true });\n }\n \n // Generate self-signed certificate\n const attrs = [{ name: 'commonName', value: 'localhost' }];\n const options = {\n days: 365,\n algorithm: 'sha256',\n keySize: 2048,\n extensions: [\n { name: 'basicConstraints', cA: true },\n {\n name: 'keyUsage',\n keyCertSign: true,\n digitalSignature: true,\n nonRepudiation: true,\n keyEncipherment: true,\n dataEncipherment: true\n },\n {\n name: 'extKeyUsage',\n serverAuth: true,\n clientAuth: true\n },\n {\n name: 'subjectAltName',\n altNames: [\n { type: 2, value: 'localhost' },\n { type: 7, ip: '127.0.0.1' }\n ]\n }\n ]\n };\n \n // Generate the certificates\n const pems = selfsigned.generate(attrs, options);\n \n // Write the key and certificate to files\n fs.writeFileSync(keyPath, Buffer.from(pems.private, 'utf-8'));\n fs.writeFileSync(certPath, Buffer.from(pems.cert, 'utf-8'));\n \n console.log(`\\n🔒 Generated self-signed certificates for development at ${certDir}\\n`);\n \n return {\n keyFile: keyPath,\n certFile: certPath\n };\n}","export class ResponseSentError extends Error {\n constructor(message: string = '❌ Response has already been sent') {\n super(message);\n this.name = 'ResponseSentError';\n }\n}\n\nexport class ResponseSentHeaderError extends ResponseSentError {\n constructor(message: string = 'Cannot set header after response has been sent') {\n super(message);\n }\n}\n\nexport class ResponseSentContentError extends ResponseSentError {\n constructor(message: string = 'Cannot set content type after response has been sent') {\n super(message);\n }\n}\n\nexport class ParseUrlError extends ResponseSentError {\n constructor(message: string = 'Invalide URL') {\n super(message);\n }\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\n\nimport type { Context, QueryParams, Services, State, UnknownFunction } from '@blaize-types/context';\n\n/**\n * AsyncLocalStorage instance for storing request context\n */\nexport const contextStorage = new AsyncLocalStorage<Context>();\n\n/**\n * Returns the current context from AsyncLocalStorage\n */\nexport function getContext<\n S extends State = State,\n Svc extends Services = Services,\n TBody = unknown,\n TQuery = QueryParams,\n>(): Context<S, Svc, TBody, TQuery> | undefined {\n return contextStorage.getStore() as Context<S, Svc, TBody, TQuery> | undefined;\n}\n\n/**\n * Wraps a callback function with a context\n */\nexport function runWithContext<T>(\n context: Context,\n callback: () => T | Promise<T>\n): T | Promise<T> {\n return contextStorage.run(context, callback);\n}\n\n/**\n * Middleware function that ensures a context is available in AsyncLocalStorage\n */\nexport async function contextMiddleware(\n context: Context,\n next: () => Promise<void>\n): Promise<void> {\n return runWithContext(context, next);\n}\n\n/**\n * Utility to check if code is running within a context\n */\nexport function hasContext(): boolean {\n return contextStorage.getStore() !== undefined;\n}\n\n/**\n * Creates a function that will run with the current context\n *\n * @param fn The function to bind to the current context\n * @returns A function that will execute with the bound context\n */\nexport function bindContext<TFunction extends UnknownFunction>(fn: TFunction): TFunction {\n const context = getContext();\n if (!context) {\n return fn;\n }\n\n // Using function instead of arrow function to preserve 'this'\n return function (this: unknown, ...args: Parameters<TFunction>): ReturnType<TFunction> {\n return runWithContext(context, () => fn.apply(this, args)) as ReturnType<TFunction>;\n } as TFunction;\n}\n","import * as crypto from 'node:crypto';\nimport { createWriteStream, type WriteStream } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { Readable } from 'node:stream';\n\nimport { extractBoundary, parseContentDisposition, parseContentType } from './utils';\n\nimport type { UnifiedRequest } from '@blaize-types/context';\nimport type { UploadedFile, MultipartData, ParseOptions, ParserState } from '@blaize-types/upload';\n\n// Default options with sensible defaults\nconst DEFAULT_OPTIONS: Required<ParseOptions> = {\n maxFileSize: 10 * 1024 * 1024, // 10MB\n maxFiles: 10,\n maxFieldSize: 1 * 1024 * 1024, // 1MB\n allowedMimeTypes: [],\n allowedExtensions: [],\n strategy: 'stream',\n tempDir: tmpdir(),\n computeHash: false,\n};\n\n/**\n * Create initial parser state\n */\nfunction createParserState(boundary: string, options: Partial<ParseOptions> = {}): ParserState {\n return {\n boundary: Buffer.from(`--${boundary}`),\n options: { ...DEFAULT_OPTIONS, ...options },\n fields: new Map(),\n files: new Map(),\n buffer: Buffer.alloc(0),\n stage: 'boundary',\n currentHeaders: '',\n currentField: null,\n currentFilename: undefined,\n currentMimetype: 'application/octet-stream',\n currentContentLength: 0,\n fileCount: 0,\n fieldCount: 0,\n currentBufferChunks: [],\n currentStream: null,\n currentTempPath: null,\n currentWriteStream: null,\n streamController: null,\n cleanupTasks: [],\n // Track validation state\n hasFoundValidBoundary: false,\n hasProcessedAnyPart: false,\n isFinished: false,\n };\n}\n\n/**\n * Process a chunk of data through the parser state machine\n */\nasync function processChunk(state: ParserState, chunk: Buffer): Promise<ParserState> {\n const newBuffer = Buffer.concat([state.buffer, chunk]);\n let currentState = { ...state, buffer: newBuffer };\n\n // Process buffer until no more progress can be made\n while (currentState.buffer.length > 0 && !currentState.isFinished) {\n const nextState = await processCurrentStage(currentState);\n if (nextState === currentState) break; // No progress made, need more data\n currentState = nextState;\n }\n\n return currentState;\n}\n\n/**\n * Process current stage of parsing\n */\nasync function processCurrentStage(state: ParserState): Promise<ParserState> {\n switch (state.stage) {\n case 'boundary':\n return processBoundary(state);\n case 'headers':\n return processHeaders(state);\n case 'content':\n return processContent(state);\n default: {\n const { InternalServerError } = await import('../errors/internal-server-error');\n throw new InternalServerError(`Invalid parser stage`, {\n operation: state.stage,\n });\n }\n }\n}\n\n/**\n * Process boundary detection\n */\nfunction processBoundary(state: ParserState): ParserState {\n const boundaryIndex = state.buffer.indexOf(state.boundary);\n if (boundaryIndex === -1) return state;\n\n // Mark that we found at least one boundary\n const hasFoundValidBoundary = true;\n\n // Consume boundary and check for end\n let buffer = state.buffer.subarray(boundaryIndex + state.boundary.length);\n\n // Check for end boundary (-- after boundary)\n if (buffer.length >= 2 && buffer.subarray(0, 2).equals(Buffer.from('--'))) {\n return {\n ...state,\n buffer,\n hasFoundValidBoundary,\n isFinished: true,\n stage: 'boundary',\n };\n }\n\n // Skip CRLF after boundary\n if (buffer.length >= 2 && buffer.subarray(0, 2).equals(Buffer.from('\\r\\n'))) {\n buffer = buffer.subarray(2);\n }\n\n return {\n ...state,\n buffer,\n hasFoundValidBoundary,\n stage: 'headers',\n currentHeaders: '',\n };\n}\n\n/**\n * Process headers section\n */\nasync function processHeaders(state: ParserState): Promise<ParserState> {\n const headerEnd = state.buffer.indexOf('\\r\\n\\r\\n');\n if (headerEnd === -1) return state;\n\n const headers = state.buffer.subarray(0, headerEnd).toString('utf8');\n const buffer = state.buffer.subarray(headerEnd + 4);\n\n const disposition = parseContentDisposition(headers);\n if (!disposition) {\n // ✅ HTTP 400 - Bad Request for malformed headers\n const { ValidationError } = await import('../errors/validation-error');\n throw new ValidationError('Missing or invalid Content-Disposition header');\n }\n\n const mimetype = parseContentType(headers);\n const isFile = disposition.filename !== undefined;\n\n // Validation\n if (isFile && state.fileCount >= state.options.maxFiles) {\n const { PayloadTooLargeError } = await import('../errors/payload-too-large-error');\n throw new PayloadTooLargeError('Too many files in upload', {\n fileCount: state.fileCount + 1,\n maxFiles: state.options.maxFiles,\n filename: disposition.filename,\n });\n }\n\n if (\n isFile &&\n state.options.allowedMimeTypes.length > 0 &&\n !state.options.allowedMimeTypes.includes(mimetype)\n ) {\n const { UnsupportedMediaTypeError } = await import('../errors/unsupported-media-type-error');\n throw new UnsupportedMediaTypeError('File type not allowed', {\n receivedMimeType: mimetype,\n allowedMimeTypes: state.options.allowedMimeTypes,\n filename: disposition.filename,\n });\n }\n\n return {\n ...state,\n buffer,\n stage: 'content',\n currentHeaders: headers,\n currentField: disposition.name,\n currentFilename: disposition.filename,\n currentMimetype: mimetype,\n currentContentLength: 0,\n fileCount: isFile ? state.fileCount + 1 : state.fileCount,\n fieldCount: isFile ? state.fieldCount : state.fieldCount + 1,\n currentBufferChunks: [],\n };\n}\n\n/**\n * Process content section\n */\nasync function processContent(state: ParserState): Promise<ParserState> {\n const nextBoundaryIndex = state.buffer.indexOf(state.boundary);\n\n let contentChunk: Buffer;\n let isComplete = false;\n let buffer = state.buffer;\n\n if (nextBoundaryIndex === -1) {\n // No boundary found, process safely\n const safeLength = Math.max(0, state.buffer.length - state.boundary.length);\n if (safeLength === 0) return state; // Need more data\n\n contentChunk = state.buffer.subarray(0, safeLength);\n buffer = state.buffer.subarray(safeLength);\n } else {\n // Found boundary, process content before it (minus CRLF)\n const contentEnd = Math.max(0, nextBoundaryIndex - 2);\n contentChunk = state.buffer.subarray(0, contentEnd);\n buffer = state.buffer.subarray(nextBoundaryIndex);\n isComplete = true;\n }\n\n let updatedState = { ...state, buffer };\n\n if (contentChunk.length > 0) {\n updatedState = await processContentChunk(updatedState, contentChunk);\n }\n\n if (isComplete) {\n updatedState = await finalizeCurrentPart(updatedState);\n updatedState = {\n ...updatedState,\n stage: 'boundary' as const,\n hasProcessedAnyPart: true, // Mark that we've processed at least one part\n };\n }\n\n return updatedState;\n}\n\n/**\n * Process a chunk of content data\n */\nasync function processContentChunk(state: ParserState, chunk: Buffer): Promise<ParserState> {\n const newContentLength = state.currentContentLength + chunk.length;\n\n // Size validation\n const maxSize =\n state.currentFilename !== undefined ? state.options.maxFileSize : state.options.maxFieldSize;\n\n if (newContentLength > maxSize) {\n const isFile = state.currentFilename !== undefined;\n const { PayloadTooLargeError } = await import('../errors/payload-too-large-error');\n const payloadErrorDetals = state.currentField\n ? {\n contentType: isFile ? 'file' : 'field',\n currentSize: newContentLength,\n maxSize,\n field: state.currentField,\n filename: state.currentFilename,\n }\n : {\n contentType: isFile ? 'file' : 'field',\n currentSize: newContentLength,\n maxSize,\n filename: state.currentFilename,\n };\n throw new PayloadTooLargeError(\n `${isFile ? 'File' : 'Field'} size exceeds limit`,\n payloadErrorDetals\n );\n }\n\n if (state.currentFilename !== undefined) {\n return processFileChunk(state, chunk, newContentLength);\n } else {\n return {\n ...state,\n currentContentLength: newContentLength,\n currentBufferChunks: [...state.currentBufferChunks, chunk],\n };\n }\n}\n\n/**\n * Process file chunk based on strategy\n */\nasync function processFileChunk(\n state: ParserState,\n chunk: Buffer,\n newContentLength: number\n): Promise<ParserState> {\n switch (state.options.strategy) {\n case 'memory':\n return {\n ...state,\n currentContentLength: newContentLength,\n currentBufferChunks: [...state.currentBufferChunks, chunk],\n };\n\n case 'stream':\n if (state.streamController) {\n state.streamController.enqueue(chunk);\n }\n return { ...state, currentContentLength: newContentLength };\n\n case 'temp':\n if (state.currentWriteStream) {\n await writeToStream(state.currentWriteStream, chunk);\n }\n return { ...state, currentContentLength: newContentLength };\n\n default: {\n const { ValidationError } = await import('../errors/validation-error');\n throw new ValidationError(`Invalid parsing strategy`);\n // TODO: create new error type to support \"strategy\" + \"supportedStrategies\"\n // throw new ValidationError(`Invalid parsing strategy`, {\n // strategy: state.options.strategy,\n // supportedStrategies: ['memory', 'stream', 'temp'],\n // });\n }\n }\n}\n\n/**\n * Initialize file processing for current part\n */\nasync function initializeFileProcessing(state: ParserState): Promise<ParserState> {\n if (state.currentFilename === undefined) return state;\n\n switch (state.options.strategy) {\n case 'memory':\n return { ...state, currentBufferChunks: [] };\n\n case 'stream': {\n let streamController: ReadableStreamDefaultController<Uint8Array> | null = null;\n const stream = new ReadableStream<Uint8Array>({\n start: controller => {\n streamController = controller;\n },\n });\n\n return {\n ...state,\n currentStream: stream as any, // Type cast for Node.js compatibility\n streamController,\n };\n }\n\n case 'temp': {\n const tempPath = join(state.options.tempDir, `upload-${crypto.randomUUID()}`);\n const writeStream = createWriteStream(tempPath);\n const cleanupTask = async () => {\n try {\n const { unlink } = await import('node:fs/promises');\n await unlink(tempPath);\n } catch (error) {\n console.warn(`Failed to cleanup temp file: ${tempPath}`, error);\n }\n };\n\n return {\n ...state,\n currentTempPath: tempPath,\n currentWriteStream: writeStream,\n cleanupTasks: [...state.cleanupTasks, cleanupTask],\n };\n }\n\n default: {\n const { ValidationError } = await import('../errors/validation-error');\n throw new ValidationError(`Invalid file processing strategy`);\n // throw new ValidationError(`Invalid file processing strategy`, {\n // strategy: state.options.strategy,\n // });\n }\n }\n}\n\n/**\n * Finalize current part and add to collections\n */\nasync function finalizeCurrentPart(state: ParserState): Promise<ParserState> {\n if (!state.currentField) return resetCurrentPart(state);\n\n if (state.currentFilename !== undefined) {\n return finalizeFile(state);\n } else {\n return finalizeField(state);\n }\n}\n\n/**\n * Finalize file processing\n */\nasync function finalizeFile(state: ParserState): Promise<ParserState> {\n if (!state.currentField || state.currentFilename === undefined) {\n return resetCurrentPart(state);\n }\n\n let stream: Readable;\n let buffer: Buffer | undefined;\n let tempPath: string | undefined;\n\n switch (state.options.strategy) {\n case 'memory':\n buffer = Buffer.concat(state.currentBufferChunks);\n stream = Readable.from(buffer);\n break;\n\n case 'stream':\n if (state.streamController) {\n state.streamController.close();\n }\n stream = state.currentStream!;\n break;\n\n case 'temp':\n if (state.currentWriteStream) {\n await closeStream(state.currentWriteStream);\n }\n tempPath = state.currentTempPath!;\n stream = Readable.from(Buffer.alloc(0)); // Placeholder\n break;\n\n default: {\n // ✅ HTTP 400 - Bad Request for invalid strategy\n const { ValidationError } = await import('../errors/validation-error');\n throw new ValidationError(`Invalid file finalization strategy`);\n // throw new ValidationError(`Invalid file finalization strategy`, {\n // strategy: state.options.strategy,\n // });\n }\n }\n\n const file: UploadedFile = {\n filename: state.currentFilename,\n fieldname: state.currentField,\n mimetype: state.currentMimetype,\n size: state.currentContentLength,\n stream,\n buffer,\n tempPath,\n };\n\n const updatedFiles = addToCollection(state.files, state.currentField, file);\n\n return {\n ...resetCurrentPart(state),\n files: updatedFiles,\n };\n}\n\n/**\n * Finalize field processing\n */\nfunction finalizeField(state: ParserState): ParserState {\n if (!state.currentField) return resetCurrentPart(state);\n\n const value = Buffer.concat(state.currentBufferChunks).toString('utf8');\n const updatedFields = addToCollection(state.fields, state.currentField, value);\n\n return {\n ...resetCurrentPart(state),\n fields: updatedFields,\n };\n}\n\n/**\n * Reset current part state\n */\nfunction resetCurrentPart(state: ParserState): ParserState {\n return {\n ...state,\n currentField: null,\n currentFilename: undefined,\n currentContentLength: 0,\n currentBufferChunks: [],\n currentStream: null,\n streamController: null,\n currentTempPath: null,\n currentWriteStream: null,\n };\n}\n\n/**\n * Add item to collection immutably\n */\nfunction addToCollection<T>(collection: Map<string, T[]>, key: string, value: T): Map<string, T[]> {\n const newCollection = new Map(collection);\n const existing = newCollection.get(key) || [];\n newCollection.set(key, [...existing, value]);\n return newCollection;\n}\n\n/**\n * Finalize parsing and return results\n */\nasync function finalize(state: ParserState): Promise<MultipartData> {\n // Validate that we found valid multipart data\n if (!state.hasFoundValidBoundary) {\n const { ValidationError } = await import('../errors/validation-error');\n throw new ValidationError('No valid multipart boundary found');\n // throw new ValidationError('No valid multipart boundary found', {\n // errorType: 'invalid_multipart',\n // reason: 'Missing or malformed boundary markers',\n // });`\n }\n\n // If we found boundaries but didn't process any parts, it's empty/invalid\n if (state.hasFoundValidBoundary && !state.hasProcessedAnyPart) {\n const { ValidationError } = await import('../errors/validation-error');\n throw new ValidationError('Empty multipart request');\n // throw new ValidationError('Empty multipart request', {\n // errorType: 'empty_multipart',\n // reason: 'Valid boundaries found but no data parts processed',\n // });\n }\n\n const fields: Record<string, string | string[]> = {};\n for (const [key, values] of state.fields.entries()) {\n fields[key] = values.length === 1 ? values[0]! : values;\n }\n\n const files: Record<string, UploadedFile | UploadedFile[]> = {};\n for (const [key, fileList] of state.files.entries()) {\n files[key] = fileList.length === 1 ? fileList[0]! : fileList;\n }\n\n return { fields, files };\n}\n\n/**\n * Cleanup resources\n */\nasync function cleanup(state: ParserState): Promise<void> {\n // Execute all cleanup tasks\n await Promise.allSettled(state.cleanupTasks.map(task => task()));\n\n // Close any open streams\n if (state.streamController) {\n state.streamController.close();\n }\n\n if (state.currentWriteStream) {\n await closeStream(state.currentWriteStream);\n }\n}\n\n// Helper functions\nasync function writeToStream(stream: WriteStream, chunk: Buffer): Promise<void> {\n return new Promise((resolve, reject) => {\n stream.write(chunk, error => {\n if (error) reject(error);\n else resolve();\n });\n });\n}\n\nasync function closeStream(stream: WriteStream): Promise<void> {\n return new Promise(resolve => {\n stream.end(() => resolve());\n });\n}\n\n/**\n * Main parsing function (functional interface)\n */\nexport async function parseMultipartRequest(\n request: UnifiedRequest,\n options: Partial<ParseOptions> = {}\n): Promise<MultipartData> {\n const contentType = (request.headers['content-type'] as string) || '';\n const boundary = extractBoundary(contentType);\n\n if (!boundary) {\n const { UnsupportedMediaTypeError } = await import('../errors/unsupported-media-type-error');\n throw new UnsupportedMediaTypeError('Missing boundary in multipart content-type', {\n receivedContentType: contentType,\n expectedFormat: 'multipart/form-data; boundary=...',\n });\n }\n\n let state = createParserState(boundary, options);\n\n // Initialize file processing if needed\n if (state.currentFilename !== undefined) {\n state = await initializeFileProcessing(state);\n }\n\n try {\n // Process request stream\n for await (const chunk of request) {\n state = await processChunk(state, chunk as Buffer);\n }\n\n return finalize(state);\n } finally {\n await cleanup(state);\n }\n}\n","// Hoisted regex patterns\nconst BOUNDARY_REGEX = /boundary=([^;]+)/i;\nconst CONTENT_DISPOSITION_REGEX =\n /Content-Disposition:\\s*form-data;\\s*name=\"([^\"]+)\"(?:;[\\s\\r\\n]*filename=\"([^\"]*)\")?/i;\nconst CONTENT_TYPE_REGEX = /Content-Type:\\s*([^\\r\\n]+)/i;\nconst MULTIPART_REGEX = /multipart\\/form-data/i;\n\n/**\n * Extract boundary from Content-Type header\n */\nexport function extractBoundary(contentType: string): string | null {\n const match = contentType.match(BOUNDARY_REGEX);\n if (!match || !match[1]) return null;\n\n let boundary = match[1].trim();\n if (boundary.startsWith('\"') && boundary.endsWith('\"')) {\n boundary = boundary.slice(1, -1);\n }\n\n return boundary || null;\n}\n\n/**\n * Parse Content-Disposition header\n */\nexport function parseContentDisposition(\n headers: string\n): { name: string; filename?: string } | null {\n const match = headers.match(CONTENT_DISPOSITION_REGEX);\n if (!match || !match[1]) return null;\n\n return {\n name: match[1],\n filename: match[2] !== undefined ? match[2] : undefined,\n };\n}\n\n/**\n * Parse Content-Type header\n */\nexport function parseContentType(headers: string): string {\n const match = headers.match(CONTENT_TYPE_REGEX);\n return match && match[1]?.trim() ? match[1].trim() : 'application/octet-stream';\n}\n\n/**\n * Check if content type is multipart\n */\nexport function isMultipartContent(contentType: string): boolean {\n return MULTIPART_REGEX.test(contentType);\n}\n","import {\n ParseUrlError,\n ResponseSentContentError,\n ResponseSentError,\n ResponseSentHeaderError,\n} from './errors';\nimport { hasContext, getContext } from './store';\nimport { PayloadTooLargeError } from '../errors/payload-too-large-error';\nimport { UnsupportedMediaTypeError } from '../errors/unsupported-media-type-error';\nimport { ValidationError } from '../errors/validation-error';\nimport { getCorrelationHeaderName, getCorrelationId } from '../tracing/correlation';\nimport { parseMultipartRequest } from '../upload/multipart-parser';\nimport { isMultipartContent } from '../upload/utils';\n\nimport type {\n Context,\n ContextOptions,\n MultipartLimits,\n QueryParams,\n RequestParams,\n State,\n StreamOptions,\n UnifiedRequest,\n UnifiedResponse,\n Services,\n} from '@blaize-types/context';\n\nconst CONTENT_TYPE_HEADER = 'Content-Type';\n\n/**\n * Parse URL and extract path and query parameters using modern URL API\n */\nfunction parseRequestUrl(req: UnifiedRequest): {\n path: string;\n url: URL | null;\n query: QueryParams;\n} {\n const originalUrl = (req as any).url || '/';\n\n // Construct full URL for parsing\n const host = req.headers.host || 'localhost';\n const protocol = req.socket && (req.socket as any).encrypted ? 'https' : 'http';\n const fullUrl = `${protocol}://${host}${originalUrl.startsWith('/') ? '' : '/'}${originalUrl}`;\n try {\n const url = new URL(fullUrl);\n\n // Extract path\n const path = url.pathname;\n\n // Parse query parameters using URLSearchParams\n const query: QueryParams = {};\n url.searchParams.forEach((value, key) => {\n // Handle array parameters (key=value1&key=value2)\n if (query[key] !== undefined) {\n if (Array.isArray(query[key])) {\n (query[key] as string[]).push(value);\n } else {\n query[key] = [query[key] as string, value];\n }\n } else {\n query[key] = value;\n }\n });\n\n return { path, url, query };\n } catch (error) {\n // Fallback for invalid URLs\n console.warn(`Invalid URL: ${fullUrl}`, error);\n throw new ParseUrlError(`Invalid URL: ${fullUrl}`);\n }\n}\n\n/**\n * Determine if the request is using HTTP/2\n */\nfunction isHttp2Request(req: UnifiedRequest): boolean {\n // Check for HTTP/2 specific properties\n return 'stream' in req || ('httpVersionMajor' in req && (req as any).httpVersionMajor === 2);\n}\n\n/**\n * Get the HTTP protocol (http or https)\n */\nfunction getProtocol(req: UnifiedRequest): string {\n // Check for encrypted socket\n const encrypted = req.socket && (req.socket as any).encrypted;\n // Check for X-Forwarded-Proto header (common in proxy environments)\n const forwardedProto = req.headers['x-forwarded-proto'];\n\n if (forwardedProto) {\n if (Array.isArray(forwardedProto)) {\n // Handle array of header values (uncommon but possible)\n return forwardedProto[0]?.split(',')[0]?.trim() || 'http';\n } else {\n // Handle string header value (typical case)\n return forwardedProto.split(',')[0]?.trim() || 'http';\n }\n }\n\n // Default protocol based on socket encryption\n return encrypted ? 'https' : 'http';\n}\n\n/**\n * Create a new context object for a request/response cycle\n */\nexport async function createContext<\n S extends State = State,\n Svc extends Services = Services,\n TBody = unknown,\n TQuery = QueryParams,\n>(\n req: UnifiedRequest,\n res: UnifiedResponse,\n options: ContextOptions\n): Promise<Context<S, Svc, TBody, TQuery>> {\n // Extract basic request information\n const { path, url, query } = parseRequestUrl(req);\n const method = req.method || 'GET';\n const isHttp2 = isHttp2Request(req);\n const protocol = getProtocol(req);\n\n // Initialize state\n const params: RequestParams = {};\n const state = { ...(options.initialState || {}) } as S;\n const services = { ...(options.initialServices || {}) } as Svc;\n\n // Track response status\n const responseState = { sent: false };\n\n // Create the context object with its components\n const ctx: Context<S, Svc, TBody, TQuery> = {\n request: createRequestObject<TBody, TQuery>(req, {\n path,\n url,\n query: query as TQuery,\n params,\n method,\n isHttp2,\n protocol,\n }),\n response: {} as Context<S, Svc, TBody, TQuery>['response'],\n state,\n services,\n };\n\n ctx.response = createResponseObject(res, responseState, ctx);\n\n // Parse body if requested\n if (options.parseBody) {\n await parseBodyIfNeeded(req, ctx, options);\n }\n\n return ctx;\n}\n\n/**\n * Create the request object portion of the context\n */\nfunction createRequestObject<TBody = unknown, TQuery = QueryParams>(\n req: UnifiedRequest,\n info: {\n path: string;\n url: URL | null;\n query: TQuery;\n params: RequestParams;\n method: string;\n isHttp2: boolean;\n protocol: string;\n }\n): Context<State, Services, TBody, TQuery>['request'] {\n return {\n raw: req,\n ...info,\n header: createRequestHeaderGetter(req),\n headers: createRequestHeadersGetter(req),\n body: undefined as unknown as TBody,\n };\n}\n\n/**\n * Create a function to get a single request header\n */\nfunction createRequestHeaderGetter(req: UnifiedRequest) {\n return (name: string): string | undefined => {\n const value = req.headers[name.toLowerCase()];\n if (Array.isArray(value)) {\n return value.join(', ');\n }\n return value || undefined;\n };\n}\n\n/**\n * Create a function to get multiple request headers\n */\nfunction createRequestHeadersGetter(req: UnifiedRequest) {\n const headerGetter = createRequestHeaderGetter(req);\n\n return (names?: string[]): Record<string, string | undefined> => {\n if (names && Array.isArray(names) && names.length > 0) {\n return names.reduce<Record<string, string | undefined>>((acc, name) => {\n acc[name] = headerGetter(name);\n return acc;\n }, {});\n } else {\n return Object.entries(req.headers).reduce<Record<string, string | undefined>>(\n (acc, [key, value]) => {\n acc[key] = Array.isArray(value) ? value.join(', ') : value || undefined;\n return acc;\n },\n {}\n );\n }\n };\n}\n\n/**\n * Helper to add correlation header if available in state\n * Works for both HTTP/1.1 and HTTP/2 by using the context's setHeader abstraction\n */\nfunction addCorrelationHeader(res: UnifiedResponse, state: State): void {\n // Only add if correlation ID exists in state\n if (state.correlationId) {\n const headerName = getCorrelationHeaderName();\n const correlationValue = String(state.correlationId);\n res.setHeader(headerName, correlationValue);\n }\n}\n\n/**\n * Create the response object portion of the context\n */\nfunction createResponseObject<\n S extends State = State,\n Svc extends Services = Services,\n TBody = unknown,\n TQuery = QueryParams,\n>(\n res: UnifiedResponse,\n responseState: { sent: boolean },\n ctx: Context<S, Svc, TBody, TQuery>\n): Context<S, Svc, TBody, TQuery>['response'] {\n return {\n raw: res,\n\n // TODO: this does not work well and should be enhanced\n get statusCode() {\n return res.statusCode || 200;\n },\n\n get sent() {\n return responseState.sent;\n },\n\n status: createStatusSetter(res, responseState, ctx),\n header: createHeaderSetter(res, responseState, ctx),\n headers: createHeadersSetter(res, responseState, ctx),\n type: createContentTypeSetter(res, responseState, ctx),\n\n json: createJsonResponder(res, responseState, ctx.state),\n text: createTextResponder(res, responseState, ctx.state),\n html: createHtmlResponder(res, responseState, ctx.state),\n redirect: createRedirectResponder(res, responseState, ctx.state),\n stream: createStreamResponder(res, responseState, ctx.state),\n };\n}\n\n/**\n * Create a function to set response status\n */\nfunction createStatusSetter<\n S extends State = State,\n Svc extends Services = Services,\n TBody = unknown,\n TQuery = QueryParams,\n>(res: UnifiedResponse, responseState: { sent: boolean }, ctx: Context<S, Svc, TBody, TQuery>) {\n return function statusSetter(code: number): Context['response'] {\n if (responseState.sent) {\n throw new ResponseSentError();\n }\n res.statusCode = code;\n return ctx.response;\n };\n}\n\n/**\n * Create a function to set a response header\n */\nfunction createHeaderSetter<\n S extends State = State,\n Svc extends Services = Services,\n TBody = unknown,\n TQuery = QueryParams,\n>(res: UnifiedResponse, responseState: { sent: boolean }, ctx: Context<S, Svc, TBody, TQuery>) {\n return function headerSetter(name: string, value: string) {\n if (responseState.sent) {\n throw new ResponseSentHeaderError();\n }\n res.setHeader(name, value);\n return ctx.response;\n };\n}\n\n/**\n * Create a function to set multiple response headers\n */\nfunction createHeadersSetter<\n S extends State = State,\n Svc extends Services = Services,\n TBody = unknown,\n TQuery = QueryParams,\n>(res: UnifiedResponse, responseState: { sent: boolean }, ctx: Context<S, Svc, TBody, TQuery>) {\n return function headersSetter(headers: Record<string, string>) {\n if (responseState.sent) {\n throw new ResponseSentHeaderError();\n }\n for (const [name, value] of Object.entries(headers)) {\n res.setHeader(name, value);\n }\n return ctx.response;\n };\n}\n\n/**\n * Create a function to set content type header\n */\nfunction createContentTypeSetter<\n S extends State = State,\n Svc extends Services = Services,\n TBody = unknown,\n TQuery = QueryParams,\n>(res: UnifiedResponse, responseState: { sent: boolean }, ctx: Context<S, Svc, TBody, TQuery>) {\n return function typeSetter(type: string) {\n if (responseState.sent) {\n throw new ResponseSentContentError();\n }\n res.setHeader(CONTENT_TYPE_HEADER, type);\n return ctx.response;\n };\n}\n\n/**\n * Create a function to send JSON response\n */\nfunction createJsonResponder(res: UnifiedResponse, responseState: { sent: boolean }, state: State) {\n return function jsonResponder(body: unknown, status?: number) {\n if (responseState.sent) {\n throw new ResponseSentError();\n }\n\n if (status !== undefined) {\n res.statusCode = status;\n }\n\n addCorrelationHeader(res, state);\n res.setHeader(CONTENT_TYPE_HEADER, 'application/json');\n res.end(JSON.stringify(body));\n responseState.sent = true;\n };\n}\n\n/**\n * Create a function to send text response\n */\nfunction createTextResponder(res: UnifiedResponse, responseState: { sent: boolean }, state: State) {\n return function textResponder(body: string, status?: number) {\n if (responseState.sent) {\n throw new ResponseSentError();\n }\n\n if (status !== undefined) {\n res.statusCode = status;\n }\n\n addCorrelationHeader(res, state);\n res.setHeader(CONTENT_TYPE_HEADER, 'text/plain');\n res.end(body);\n responseState.sent = true;\n };\n}\n\n/**\n * Create a function to send HTML response\n */\nfunction createHtmlResponder(res: UnifiedResponse, responseState: { sent: boolean }, state: State) {\n return function htmlResponder(body: string, status?: number) {\n if (responseState.sent) {\n throw new ResponseSentError();\n }\n\n if (status !== undefined) {\n res.statusCode = status;\n }\n\n addCorrelationHeader(res, state);\n res.setHeader(CONTENT_TYPE_HEADER, 'text/html');\n res.end(body);\n responseState.sent = true;\n };\n}\n\n/**\n * Create a function to send redirect response\n */\nfunction createRedirectResponder(\n res: UnifiedResponse,\n responseState: { sent: boolean },\n state: State\n) {\n return function redirectResponder(url: string, status = 302) {\n if (responseState.sent) {\n throw new ResponseSentError();\n }\n\n addCorrelationHeader(res, state);\n res.statusCode = status;\n res.setHeader('Location', url);\n res.end();\n responseState.sent = true;\n };\n}\n\n/**\n * Create a function to stream response\n */\nfunction createStreamResponder(\n res: UnifiedResponse,\n responseState: { sent: boolean },\n state: State\n) {\n return function streamResponder(readable: NodeJS.ReadableStream, options: StreamOptions = {}) {\n if (responseState.sent) {\n throw new ResponseSentError();\n }\n\n if (options.status !== undefined) {\n res.statusCode = options.status;\n }\n\n addCorrelationHeader(res, state);\n if (options.contentType) {\n res.setHeader(CONTENT_TYPE_HEADER, options.contentType);\n }\n\n if (options.headers) {\n for (const [name, value] of Object.entries(options.headers)) {\n res.setHeader(name, value);\n }\n }\n\n // Handle streaming\n readable.pipe(res);\n\n // Mark as sent when the stream ends\n readable.on('end', () => {\n responseState.sent = true;\n });\n\n // Handle errors\n readable.on('error', err => {\n console.error('Stream error:', err);\n if (!responseState.sent) {\n res.statusCode = 500;\n res.end('Stream error');\n responseState.sent = true;\n }\n });\n };\n}\n\n/**\n * Parse request body if enabled in options\n *\n * Throws appropriate errors on parsing failures:\n * - ValidationError (400) for malformed data\n * - PayloadTooLargeError (413) for size limit violations\n * - UnsupportedMediaTypeError (415) for unsupported content types\n */\nasync function parseBodyIfNeeded<TBody = unknown, TQuery = QueryParams>(\n req: UnifiedRequest,\n ctx: Context<State, Services, TBody, TQuery>,\n options: ContextOptions\n): Promise<void> {\n // Skip parsing for methods that typically don't have bodies\n if (shouldSkipParsing(req.method)) {\n return;\n }\n\n const contentType = req.headers['content-type'] || '';\n const contentLength = parseInt(req.headers['content-length'] || '0', 10);\n\n // Skip if no content\n if (contentLength === 0) {\n return;\n }\n\n const limits = options.bodyLimits;\n\n // ✅ Check size limits BEFORE parsing and throw immediately\n if (contentType.includes('application/json')) {\n if (contentLength > limits.json) {\n throw new PayloadTooLargeError(\n 'JSON body exceeds size limit',\n {\n currentSize: contentLength,\n maxSize: limits.json,\n contentType: 'application/json',\n },\n getCorrelationId()\n );\n }\n await parseJsonBody(req, ctx); // Throws ValidationError on malformed JSON\n } else if (contentType.includes('application/x-www-form-urlencoded')) {\n if (contentLength > limits.form) {\n throw new PayloadTooLargeError(\n 'Form body exceeds size limit',\n {\n currentSize: contentLength,\n maxSize: limits.form,\n contentType: 'application/x-www-form-urlencoded',\n },\n getCorrelationId()\n );\n }\n await parseFormUrlEncodedBody(req, ctx); // Throws ValidationError on malformed form\n } else if (contentType.includes('text/')) {\n if (contentLength > limits.text) {\n throw new PayloadTooLargeError(\n 'Text body exceeds size limit',\n {\n currentSize: contentLength,\n maxSize: limits.text,\n contentType,\n },\n getCorrelationId()\n );\n }\n await parseTextBody(req, ctx);\n } else if (isMultipartContent(contentType)) {\n // Multipart has its own size validation in parseMultipartRequest\n // Throws PayloadTooLargeError or UnsupportedMediaTypeError\n await parseMultipartBody(req, ctx, limits.multipart);\n } else {\n // Unknown content type - apply raw limit\n if (contentLength > limits.raw) {\n throw new PayloadTooLargeError(\n 'Request body exceeds size limit',\n {\n currentSize: contentLength,\n maxSize: limits.raw,\n contentType: contentType || 'unknown',\n },\n getCorrelationId()\n );\n }\n // Don't parse unknown content types, but allow them through\n return;\n }\n\n // ✅ No try/catch - let errors bubble up to error boundary\n}\n\n/**\n * Determine if body parsing should be skipped based on HTTP method\n */\nfunction shouldSkipParsing(method?: string): boolean {\n const skipMethods = ['GET', 'HEAD', 'OPTIONS'];\n return skipMethods.includes(method || 'GET');\n}\n\n/**\n * Parse JSON request body\n */\nasync function parseJsonBody<TBody = unknown, TQuery = QueryParams>(\n req: UnifiedRequest,\n ctx: Context<State, Services, TBody, TQuery>\n): Promise<void> {\n const body = await readRequestBody(req);\n\n if (!body) {\n console.warn('Empty body, skipping JSON parsing');\n return;\n }\n\n // Check if the body is actually \"null\" string\n if (body.trim() === 'null') {\n console.warn('Body is the string \"null\"');\n ctx.request.body = null as TBody;\n return;\n }\n\n try {\n const json = JSON.parse(body);\n ctx.request.body = json as TBody;\n } catch (error) {\n throw new ValidationError(\n 'Invalid JSON in request body',\n {\n fields: [\n {\n field: 'body',\n messages: [\n 'Request body contains malformed JSON',\n error instanceof Error ? error.message : 'JSON parse failed',\n ],\n },\n ],\n errorCount: 1,\n section: 'body',\n },\n getCorrelationId()\n );\n }\n}\n\n/**\n * Parse URL-encoded form data\n */\nasync function parseFormUrlEncodedBody<TBody = unknown, TQuery = QueryParams>(\n req: UnifiedRequest,\n ctx: Context<State, Services, TBody, TQuery>\n): Promise<void> {\n const body = await readRequestBody(req);\n if (!body) return;\n\n try {\n ctx.request.body = parseUrlEncodedData(body) as TBody;\n } catch (error) {\n throw new ValidationError(\n 'Request body contains malformed form data',\n {\n fields: [\n {\n field: 'body',\n messages: [\n 'Invalid URL-encoded form data',\n error instanceof Error ? error.message : 'Form parse failed',\n ],\n },\n ],\n errorCount: 1,\n section: 'body',\n },\n getCorrelationId()\n );\n }\n}\n\n/**\n * Parse URL-encoded data into an object\n */\nfunction parseUrlEncodedData(body: string): Record<string, string | string[]> {\n const params = new URLSearchParams(body);\n const formData: Record<string, string | string[]> = {};\n\n params.forEach((value, key) => {\n if (formData[key] !== undefined) {\n if (Array.isArray(formData[key])) {\n (formData[key] as string[]).push(value);\n } else {\n formData[key] = [formData[key] as string, value];\n }\n } else {\n formData[key] = value;\n }\n });\n\n return formData;\n}\n\n/**\n * Parse plain text body\n */\nasync function parseTextBody<TBody = null, TQuery = QueryParams>(\n req: UnifiedRequest,\n ctx: Context<State, Services, TBody, TQuery>\n): Promise<void> {\n const body = await readRequestBody(req);\n if (body) {\n ctx.request.body = body as TBody;\n }\n}\n\n/**\n * Parse multipart/form-data request body with improved error handling\n */\nasync function parseMultipartBody<TBody = unknown, TQuery = QueryParams>(\n req: UnifiedRequest,\n ctx: Context<State, Services, TBody, TQuery>,\n multipartLimits: MultipartLimits\n): Promise<void> {\n try {\n const limits = multipartLimits;\n const multipartData = await parseMultipartRequest(req, {\n strategy: 'stream',\n maxFileSize: limits.maxFileSize,\n maxFiles: limits.maxFiles,\n maxFieldSize: limits.maxFieldSize,\n // Could add total size validation here\n });\n\n // Extend context with multipart data (type-safe assignments)\n (ctx.request as any).multipart = multipartData;\n (ctx.request as any).files = multipartData.files;\n\n // Set body to fields for backward compatibility with existing form handling\n ctx.request.body = multipartData.fields as TBody;\n } catch (error) {\n if (error instanceof PayloadTooLargeError) {\n throw error; // Already correct type\n }\n if (error instanceof UnsupportedMediaTypeError) {\n throw error; // Already correct type\n }\n // Generic multipart errors\n throw new UnsupportedMediaTypeError(\n 'Failed to parse multipart/form-data',\n {\n receivedContentType: req.headers['content-type'],\n expectedFormat: 'multipart/form-data; boundary=...',\n },\n getCorrelationId()\n );\n }\n}\n\n/**\n * Read the entire request body as a string\n */\nasync function readRequestBody(req: UnifiedRequest): Promise<string> {\n return new Promise<string>((resolve, reject) => {\n const chunks: Buffer[] = [];\n\n req.on('data', (chunk: Buffer | string) => {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n });\n\n req.on('end', () => {\n resolve(Buffer.concat(chunks).toString('utf8'));\n });\n\n req.on('error', err => {\n reject(err);\n });\n });\n}\n\n/**\n * Get the current context or throw an error if none exists\n */\nexport function getCurrentContext<\n S extends State = State,\n Svc extends Services = Services,\n TBody = unknown,\n TQuery = QueryParams,\n>(): Context<S, Svc, TBody, TQuery> {\n const ctx = getContext<S, Svc, TBody, TQuery>();\n if (!ctx) {\n throw new Error(\n 'No context found. Ensure this function is called within a request handler, ' +\n 'middleware, or function wrapped with runWithContext().'\n );\n }\n return ctx;\n}\n\n/**\n * Check if we're currently in a request context\n */\nexport function isInRequestContext(): boolean {\n return hasContext();\n}\n","/**\n * NotFoundError class for resource not found errors\n *\n * This error is thrown when a requested resource cannot be found.\n * It provides context about what resource was being looked for and how.\n */\n\nimport { BlaizeError, ErrorType } from '@blaize-types/errors';\n\nimport { getCorrelationId } from '../tracing/correlation';\n\nimport type { NotFoundErrorDetails } from '@blaize-types/errors';\n/**\n * Error thrown when a requested resource cannot be found\n *\n * Automatically sets HTTP status to 404 and provides context\n * about the missing resource for better debugging and user experience.\n *\n * @example Basic usage:\n * ```typescript\n * throw new NotFoundError('User not found');\n * ```\n *\n * @example With resource context:\n * ```typescript\n * throw new NotFoundError('User not found', {\n * resourceType: 'User',\n * resourceId: 'user-123',\n * suggestion: 'Check if the user ID is correct'\n * });\n * ```\n *\n * @example API endpoint not found:\n * ```typescript\n * throw new NotFoundError('Endpoint not found', {\n * path: '/api/v1/unknown',\n * method: 'GET',\n * suggestion: 'Check the API documentation'\n * });\n * ```\n */\nexport class NotFoundError extends BlaizeError<NotFoundErrorDetails> {\n /**\n * Creates a new NotFoundError instance\n *\n * @param title - Human-readable error message\n * @param details - Optional context about the missing resource\n * @param correlationId - Optional correlation ID (uses current context if not provided)\n */\n constructor(\n title: string,\n details: NotFoundErrorDetails | undefined = undefined,\n correlationId: string | undefined = undefined\n ) {\n super(\n ErrorType.NOT_FOUND,\n title,\n 404, // HTTP 404 Not Found\n correlationId ?? getCorrelationId(),\n details\n );\n }\n}\n","import { BlaizeError } from '@blaize-types/errors';\n\nimport { InternalServerError } from './internal-server-error';\nimport {\n getCorrelationId,\n createCorrelationIdFromHeaders,\n getCorrelationHeaderName,\n} from '../tracing/correlation';\n\nimport type { BlaizeErrorResponse } from '@blaize-types/errors';\n\n/**\n * Checks if an error is a handled BlaizeError instance\n */\nexport function isHandledError(error: unknown): error is BlaizeError {\n return error instanceof BlaizeError;\n}\n\n/**\n * Formats any error into a standardized BlaizeErrorResponse\n */\nexport function formatErrorResponse(error: unknown): BlaizeErrorResponse {\n // Handle BlaizeError instances - they're already properly formatted\n if (isHandledError(error)) {\n return {\n type: error.type,\n title: error.title,\n status: error.status,\n correlationId: error.correlationId,\n timestamp: error.timestamp.toISOString(),\n details: error.details,\n };\n }\n\n // Handle unexpected errors by wrapping them in InternalServerError\n const correlationId = getCorrelationId();\n let originalMessage: string;\n\n if (error instanceof Error) {\n originalMessage = error.message;\n } else if (error === null || error === undefined) {\n originalMessage = 'Unknown error occurred';\n } else {\n originalMessage = String(error);\n }\n\n // Create InternalServerError for unexpected errors\n const wrappedError = new InternalServerError(\n 'Internal Server Error',\n { originalMessage },\n correlationId\n );\n\n return {\n type: wrappedError.type,\n title: wrappedError.title,\n status: wrappedError.status,\n correlationId: wrappedError.correlationId,\n timestamp: wrappedError.timestamp.toISOString(),\n details: wrappedError.details,\n };\n}\n\n/**\n * Extracts correlation ID from request headers or generates a new one\n *\n * Uses the configured header name (default: 'x-correlation-id') to extract\n * the correlation ID from request headers. If not found, generates a new one.\n *\n * @param headerGetter - Function to retrieve header values by name\n * @returns Correlation ID (extracted or generated)\n */\nexport function extractOrGenerateCorrelationId(\n headerGetter: (name: string) => string | undefined\n): string {\n // Get the configured header name\n const headerName = getCorrelationHeaderName();\n\n // Build a headers object that the correlation module expects\n const headers: Record<string, string | undefined> = {\n [headerName]: headerGetter(headerName),\n };\n\n // Use the correlation module's function which handles the configured header\n return createCorrelationIdFromHeaders(headers);\n}\n\n/**\n * Sets response headers for error responses\n *\n * Sets the correlation ID header using the configured header name\n * (default: 'x-correlation-id'). This ensures error responses always\n * include the correlation ID for tracing.\n *\n * @param headerSetter - Function to set response headers\n * @param correlationId - The correlation ID to include in the response\n */\nexport function setErrorResponseHeaders(\n headerSetter: (name: string, value: string) => void,\n correlationId: string\n): void {\n // Get the configured header name\n const headerName = getCorrelationHeaderName();\n\n // Set the correlation header with the configured name\n headerSetter(headerName, correlationId);\n\n // Add any other standard error headers here if needed\n // For example: headerSetter('content-type', 'application/json');\n}\n","import {\n formatErrorResponse,\n extractOrGenerateCorrelationId,\n setErrorResponseHeaders,\n} from '../errors/boundary';\n\nimport type { Context } from '@blaize-types/context';\nimport type { Middleware, MiddlewareFunction, NextFunction } from '@blaize-types/middleware';\n\n/**\n * Options for configuring the error boundary middleware\n */\nexport interface ErrorBoundaryOptions {\n /** Enable debug logging of caught errors */\n debug?: boolean;\n}\n\n/**\n * Creates an error boundary middleware that catches all errors and converts them to proper HTTP responses\n *\n * This middleware should be placed early in the middleware chain to catch all downstream errors.\n * It ensures that:\n * - All BlaizeError instances are properly formatted as HTTP responses\n * - Unexpected errors are wrapped in InternalServerError and logged\n * - Correlation IDs are preserved and added to response headers\n * - No unhandled errors escape the middleware chain\n */\nexport function createErrorBoundary(options: ErrorBoundaryOptions = {}): Middleware {\n const { debug = false } = options;\n\n const middlewareFn: MiddlewareFunction = async (ctx: Context, next: NextFunction) => {\n try {\n await next();\n } catch (error) {\n // Don't handle errors if response was already sent\n if (ctx.response.sent) {\n if (debug) {\n console.error('Error occurred after response was sent:', error);\n }\n return;\n }\n\n // Log error in debug mode\n if (debug) {\n console.error('Error boundary caught error:', error);\n }\n\n // Extract or generate correlation ID from request\n const correlationId = extractOrGenerateCorrelationId(ctx.request.header);\n\n // Format the error as a proper response\n const errorResponse = formatErrorResponse(error);\n\n // Ensure correlation ID is consistent\n errorResponse.correlationId = correlationId;\n\n // Set appropriate response headers\n setErrorResponseHeaders(ctx.response.header, correlationId);\n\n // Send the formatted error response\n ctx.response.status(errorResponse.status).json(errorResponse);\n }\n };\n\n return {\n name: 'ErrorBoundary',\n execute: middlewareFn,\n debug,\n };\n}\n","import { createContext } from '../context/create';\nimport { runWithContext } from '../context/store';\nimport { NotFoundError } from '../errors/not-found-error';\nimport { compose } from '../middleware/compose';\nimport { cors } from '../middleware/cors';\nimport { createErrorBoundary } from '../middleware/error-boundary';\nimport {\n createCorrelationIdFromHeaders,\n getCorrelationHeaderName,\n withCorrelationId,\n} from '../tracing/correlation';\n\nimport type { Middleware } from '@blaize-types/middleware';\nimport type { RequestHandler, UnknownServer } from '@blaize-types/server';\n\nexport function createRequestHandler(serverInstance: UnknownServer): RequestHandler {\n return async (req, res) => {\n const correlationId = createCorrelationIdFromHeaders(\n req.headers as Record<string, string | string[] | undefined>\n );\n\n try {\n await withCorrelationId(correlationId, async () => {\n // Create context for this request\n const context = await createContext(req, res, {\n parseBody: true, // Enable automatic body parsing\n initialState: {\n correlationId,\n },\n bodyLimits: serverInstance.bodyLimits,\n });\n\n // Create error boundary middleware that catches all thrown error classes\n const errorBoundary = createErrorBoundary();\n const middlewareChain: Middleware[] = [errorBoundary];\n\n if ('corsOptions' in serverInstance && serverInstance.corsOptions !== false) {\n middlewareChain.push(cors(serverInstance.corsOptions));\n }\n\n // Compose all middleware with error boundary first (to catch all errors)\n middlewareChain.push(...serverInstance.middleware);\n\n // Compose all middleware into a single function\n const handler = compose(middlewareChain);\n\n // Run the request with context in AsyncLocalStorage\n await runWithContext(context, async () => {\n await handler(context, async () => {\n if (!context.response.sent) {\n // Let the router handle the request\n await serverInstance.router.handleRequest(context);\n // If router didn't handle it either, send a 404\n if (!res.headersSent && !context.response.sent) {\n throw new NotFoundError(\n `Route not found: ${context.request.method} ${context.request.path}`\n );\n }\n }\n });\n });\n });\n } catch (error) {\n // Fixed to handle HTTP/2 and check if headers already sent (SSE case)\n console.error('Error creating context:', error);\n const headerName = getCorrelationHeaderName();\n\n // Check if headers have already been sent (happens with SSE after stream starts)\n if (res.headersSent || (res as any).stream?.headersSent) {\n // Can't send HTTP error response after headers are sent\n // For SSE, the stream's error handling will take care of it\n console.error('Headers already sent, cannot send error response');\n return;\n }\n\n if ('stream' in res && typeof (res as any).stream?.respond === 'function') {\n // HTTP/2\n (res as any).stream.respond({\n ':status': 500,\n 'content-type': 'application/json',\n [headerName.toLowerCase()]: correlationId,\n });\n (res as any).stream.end(\n JSON.stringify({\n error: 'Internal Server Error',\n message: 'Failed to process request',\n correlationId,\n })\n );\n } else {\n // HTTP/1.1\n res.setHeader(headerName, correlationId);\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n error: 'Internal Server Error',\n message: 'Failed to process request',\n correlationId,\n })\n );\n }\n }\n };\n}\n","import type { StopOptions, UnknownServer } from '@blaize-types/server';\n\n// Add a global flag to prevent multiple shutdowns\nlet isShuttingDown = false;\n\n// Replace the stopServer function in stop.ts with this version:\n\nexport async function stopServer(\n serverInstance: UnknownServer,\n options: StopOptions = {}\n): Promise<void> {\n const server = serverInstance.server;\n const events = serverInstance.events;\n\n if (isShuttingDown) {\n console.log('⚠️ Shutdown already in progress, ignoring duplicate shutdown request');\n return;\n }\n\n if (!server) {\n return;\n }\n\n isShuttingDown = true;\n const timeout = options.timeout || 5000; // Reduced to 5 seconds for faster restarts\n\n try {\n if (options.onStopping) {\n await options.onStopping();\n }\n\n events.emit('stopping');\n\n // Close router watchers with timeout\n if (serverInstance.router && typeof serverInstance.router.close === 'function') {\n console.log('🔌 Closing router watchers...');\n try {\n // Add timeout to router close\n await Promise.race([\n serverInstance.router.close(),\n new Promise((_, reject) =>\n setTimeout(() => reject(new Error('Router close timeout')), 2000)\n ),\n ]);\n console.log('✅ Router watchers closed');\n } catch (error) {\n console.error('❌ Error closing router watchers:', error);\n // Continue with shutdown\n }\n }\n\n // Notify plugins with timeout\n try {\n await Promise.race([\n serverInstance.pluginManager.onServerStop(serverInstance, server),\n new Promise((_, reject) =>\n setTimeout(() => reject(new Error('Plugin stop timeout')), 2000)\n ),\n ]);\n } catch (error) {\n console.error('❌ Plugin stop timeout:', error);\n // Continue with shutdown\n }\n\n // Create server close promise with shorter timeout\n const closePromise = new Promise<void>((resolve, reject) => {\n server.close((err?: Error) => {\n if (err) return reject(err);\n resolve();\n });\n });\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => {\n reject(new Error('Server shutdown timeout'));\n }, timeout);\n });\n\n await Promise.race([closePromise, timeoutPromise]);\n\n // Terminate plugins with timeout\n try {\n await Promise.race([\n serverInstance.pluginManager.terminatePlugins(serverInstance),\n new Promise((_, reject) =>\n setTimeout(() => reject(new Error('Plugin terminate timeout')), 1000)\n ),\n ]);\n } catch (error) {\n console.error('❌ Plugin terminate timeout:', error);\n // Continue with shutdown\n }\n\n if (options.onStopped) {\n await options.onStopped();\n }\n\n events.emit('stopped');\n serverInstance.server = null as any;\n\n console.log('✅ Graceful shutdown completed');\n isShuttingDown = false;\n } catch (error) {\n isShuttingDown = false;\n console.error('⚠️ Shutdown error (forcing exit):', error);\n\n // Force close the server if graceful shutdown fails\n if (server && typeof server.close === 'function') {\n server.close();\n }\n\n // In development, force exit to allow tsx to restart\n if (process.env.NODE_ENV === 'development') {\n console.log('🔄 Forcing exit for development restart...');\n process.exit(0);\n }\n\n events.emit('error', error);\n throw error;\n }\n}\n\n/**\n * Register signal handlers for graceful shutdown\n */\nexport function registerSignalHandlers(stopFn: () => Promise<void>): { unregister: () => void } {\n const isDevelopment = process.env.NODE_ENV === 'development';\n\n if (isDevelopment) {\n // Development: Force exit for fast restarts\n const sigintHandler = () => {\n console.log('📤 SIGINT received, forcing exit for development restart...');\n process.exit(0);\n };\n\n const sigtermHandler = () => {\n console.log('📤 SIGTERM received, forcing exit for development restart...');\n process.exit(0);\n };\n\n process.on('SIGINT', sigintHandler);\n process.on('SIGTERM', sigtermHandler);\n\n return {\n unregister: () => {\n process.removeListener('SIGINT', sigintHandler);\n process.removeListener('SIGTERM', sigtermHandler);\n },\n };\n } else {\n // Production: Graceful shutdown\n const sigintHandler = () => {\n console.log('📤 SIGINT received, starting graceful shutdown...');\n stopFn().catch(console.error);\n };\n\n const sigtermHandler = () => {\n console.log('📤 SIGTERM received, starting graceful shutdown...');\n stopFn().catch(console.error);\n };\n\n process.on('SIGINT', sigintHandler);\n process.on('SIGTERM', sigtermHandler);\n\n return {\n unregister: () => {\n process.removeListener('SIGINT', sigintHandler);\n process.removeListener('SIGTERM', sigtermHandler);\n },\n };\n }\n}\n","import { z } from 'zod';\n\nimport { serverCorsSchema } from '../middleware/cors/validation';\n\nimport type { Middleware } from '@blaize-types/middleware';\nimport type { Plugin } from '@blaize-types/plugins';\nimport type { ServerOptions } from '@blaize-types/server';\n\n// Create a more flexible validation for the middleware function type\nconst middlewareSchema = z.custom<Middleware>(\n data =>\n data !== null &&\n typeof data === 'object' &&\n 'execute' in data &&\n typeof data.execute === 'function',\n {\n message: 'Expected middleware to have an execute function',\n }\n);\n\n// Create a schema for plugins\nconst pluginSchema = z.custom<Plugin>(\n data =>\n data !== null &&\n typeof data === 'object' &&\n 'register' in data &&\n typeof data.register === 'function',\n {\n message: 'Expected a valid plugin object with a register method',\n }\n);\n\n// Create a schema for HTTP/2 options with conditional validation\nconst http2Schema = z\n .object({\n enabled: z.boolean().optional().default(true),\n keyFile: z.string().optional(),\n certFile: z.string().optional(),\n })\n .refine(\n data => {\n // If HTTP/2 is enabled and not in development mode,\n // both keyFile and certFile must be provided\n if (data.enabled && process.env.NODE_ENV === 'production') {\n return data.keyFile && data.certFile;\n }\n return true;\n },\n {\n message:\n 'When HTTP/2 is enabled (outside of development mode), both keyFile and certFile must be provided',\n }\n );\n\n// Create a schema for correlation options\nconst correlationSchema = z\n .object({\n /**\n * HTTP header name for correlation IDs\n * Must be a valid HTTP header name (lowercase, alphanumeric with hyphens)\n */\n headerName: z\n .string()\n .regex(/^[a-z][a-z0-9-]*$/, {\n message:\n 'Header name must start with a letter and contain only lowercase letters, numbers, and hyphens',\n })\n .optional(),\n\n /**\n * Custom generator function for correlation IDs\n * Must be a function that returns a string\n */\n generator: z.function().args().returns(z.string()).optional(),\n })\n .optional();\n\nconst multipartLimitsSchema = z.object({\n maxFileSize: z\n .number()\n .positive()\n .default(50 * 1024 * 1024),\n maxTotalSize: z\n .number()\n .positive()\n .default(100 * 1024 * 1024),\n maxFiles: z.number().positive().int().default(10),\n maxFieldSize: z\n .number()\n .positive()\n .default(1024 * 1024),\n});\n\nconst bodyLimitsSchema = z.object({\n json: z\n .number()\n .positive()\n .default(512 * 1024),\n form: z\n .number()\n .positive()\n .default(1024 * 1024),\n text: z\n .number()\n .positive()\n .default(5 * 1024 * 1024),\n raw: z\n .number()\n .positive()\n .default(10 * 1024 * 1024),\n multipart: multipartLimitsSchema,\n});\n\n// Validation schema for server options\nexport const serverOptionsSchema = z.object({\n port: z.number().int().positive().optional().default(3000),\n host: z.string().optional().default('localhost'),\n routesDir: z.string().optional().default('./routes'),\n http2: http2Schema.optional().default({\n enabled: true,\n }),\n middleware: z.array(middlewareSchema).optional().default([]),\n plugins: z.array(pluginSchema).optional().default([]),\n correlation: correlationSchema,\n cors: serverCorsSchema,\n bodyLimits: bodyLimitsSchema,\n});\n\nexport function validateServerOptions(options: ServerOptions): ServerOptions {\n try {\n return serverOptionsSchema.parse(options);\n } catch (error) {\n // Properly type the error as Zod validation error\n if (error instanceof z.ZodError) {\n // Format the Zod error for better readability\n const formattedError = error.format();\n throw new Error(`Invalid server options: ${JSON.stringify(formattedError, null, 2)}`);\n }\n // For other types of errors\n throw new Error(`Invalid server options: ${String(error)}`);\n }\n}\n","import type { Plugin, PluginLifecycleManager, PluginLifecycleOptions } from '@blaize-types/plugins';\nimport type { UnknownServer } from '@blaize-types/server';\n\n/**\n * Create a plugin lifecycle manager\n */\nexport function createPluginLifecycleManager(\n options: PluginLifecycleOptions = {}\n): PluginLifecycleManager {\n const { continueOnError = true, debug = false, onError } = options;\n\n /**\n * Log debug messages if enabled\n */\n function log(message: string, ...args: any[]) {\n if (debug) {\n console.log(`[PluginLifecycle] ${message}`, ...args);\n }\n }\n\n /**\n * Handle plugin errors\n */\n function handleError(plugin: Plugin, phase: string, error: Error) {\n const errorMessage = `Plugin ${plugin.name} failed during ${phase}: ${error.message}`;\n\n if (onError) {\n onError(plugin, phase, error);\n } else {\n console.error(errorMessage, error);\n }\n\n if (!continueOnError) {\n throw new Error(errorMessage);\n }\n }\n\n return {\n /**\n * Initialize all plugins\n */\n async initializePlugins(server: UnknownServer): Promise<void> {\n log('Initializing plugins...');\n\n for (const plugin of server.plugins) {\n if (plugin.initialize) {\n try {\n log(`Initializing plugin: ${plugin.name}`);\n await plugin.initialize(server);\n } catch (error) {\n handleError(plugin, 'initialize', error as Error);\n }\n }\n }\n\n log(`Initialized ${server.plugins.length} plugins`);\n },\n\n /**\n * Terminate all plugins in reverse order\n */\n async terminatePlugins(server: UnknownServer): Promise<void> {\n log('Terminating plugins...');\n\n const pluginsToTerminate = [...server.plugins].reverse();\n\n for (const plugin of pluginsToTerminate) {\n if (plugin.terminate) {\n try {\n log(`Terminating plugin: ${plugin.name}`);\n await plugin.terminate(server);\n } catch (error) {\n handleError(plugin, 'terminate', error as Error);\n }\n }\n }\n\n log(`Terminated ${pluginsToTerminate.length} plugins`);\n },\n\n /**\n * Notify plugins that the server has started\n */\n async onServerStart(server: UnknownServer, httpServer: any): Promise<void> {\n log('Notifying plugins of server start...');\n\n for (const plugin of server.plugins) {\n if (plugin.onServerStart) {\n try {\n log(`Notifying plugin of server start: ${plugin.name}`);\n await plugin.onServerStart(httpServer);\n } catch (error) {\n handleError(plugin, 'onServerStart', error as Error);\n }\n }\n }\n },\n\n /**\n * Notify plugins that the server is stopping\n */\n async onServerStop(server: UnknownServer, httpServer: any): Promise<void> {\n log('Notifying plugins of server stop...');\n\n const pluginsToNotify = [...server.plugins].reverse();\n\n for (const plugin of pluginsToNotify) {\n if (plugin.onServerStop) {\n try {\n log(`Notifying plugin of server stop: ${plugin.name}`);\n await plugin.onServerStop(httpServer);\n } catch (error) {\n handleError(plugin, 'onServerStop', error as Error);\n }\n }\n }\n },\n };\n}\n","export class PluginError extends Error {\n constructor(\n public pluginName: string,\n message: string,\n public cause?: Error\n ) {\n super(`Plugin \"${pluginName}\": ${message}`);\n this.name = 'PluginError';\n }\n}\n\nexport class PluginLifecycleError extends PluginError {\n constructor(\n pluginName: string,\n public phase: 'register' | 'initialize' | 'terminate' | 'start' | 'stop',\n cause: Error\n ) {\n super(pluginName, `Failed during ${phase} phase: ${cause.message}`, cause);\n this.name = 'PluginLifecycleError';\n }\n}\n\nexport class PluginDependencyError extends PluginError {\n constructor(\n pluginName: string,\n public missingDependency: string\n ) {\n super(pluginName, `Missing dependency: ${missingDependency}`);\n this.name = 'PluginDependencyError';\n }\n}\n\n// packages/blaizejs/src/plugins/errors.ts (or add to existing errors file)\n\nexport class PluginValidationError extends Error {\n constructor(\n public pluginName: string,\n message: string\n ) {\n super(`Plugin validation error${pluginName ? ` for \"${pluginName}\"` : ''}: ${message}`);\n this.name = 'PluginValidationError';\n }\n}\n\nexport class PluginRegistrationError extends Error {\n constructor(\n public pluginName: string,\n message: string\n ) {\n super(`Plugin registration error for \"${pluginName}\": ${message}`);\n this.name = 'PluginRegistrationError';\n }\n}\n","import { PluginValidationError } from './errors';\n\nimport type { Plugin } from '@blaize-types/plugins';\n\nexport interface PluginValidationOptions {\n /** Require specific plugin properties */\n requireVersion?: boolean;\n /** Validate plugin name format */\n validateNameFormat?: boolean;\n /** Check for reserved plugin names */\n checkReservedNames?: boolean;\n}\n\n/**\n * Reserved plugin names that cannot be used\n */\nconst RESERVED_NAMES = new Set([\n 'core',\n 'server',\n 'router',\n 'middleware',\n 'context',\n 'blaize',\n 'blaizejs',\n]);\n\n/**\n * Valid plugin name pattern (lowercase, letters, numbers, hyphens)\n */\nconst VALID_NAME_PATTERN = /^[a-z]([a-z0-9-]*[a-z0-9])?$/;\n\n/**\n * Valid semantic version pattern\n */\nconst VALID_VERSION_PATTERN = /^\\d+\\.\\d+\\.\\d+(?:-[a-zA-Z0-9-.]+)?(?:\\+[a-zA-Z0-9-.]+)?$/;\n\n/**\n * Validate a plugin object\n */\nexport function validatePlugin(\n plugin: unknown,\n options: PluginValidationOptions = {}\n): asserts plugin is Plugin {\n const { requireVersion = true, validateNameFormat = true, checkReservedNames = true } = options;\n\n // Basic type validation\n if (!plugin || typeof plugin !== 'object') {\n throw new PluginValidationError('', 'Plugin must be an object');\n }\n\n const p = plugin as any;\n\n // Validate name\n if (!p.name || typeof p.name !== 'string') {\n throw new PluginValidationError('', 'Plugin must have a name (string)');\n }\n\n // Validate name format\n if (validateNameFormat && !VALID_NAME_PATTERN.test(p.name)) {\n throw new PluginValidationError(\n p.name,\n 'Plugin name must be lowercase letters, numbers, and hyphens only'\n );\n }\n\n // Check reserved names\n if (checkReservedNames && RESERVED_NAMES.has(p.name.toLowerCase())) {\n throw new PluginValidationError(p.name, `Plugin name \"${p.name}\" is reserved`);\n }\n\n // Validate version\n if (requireVersion) {\n if (!p.version || typeof p.version !== 'string') {\n throw new PluginValidationError(p.name, 'Plugin must have a version (string)');\n }\n\n if (!VALID_VERSION_PATTERN.test(p.version)) {\n throw new PluginValidationError(\n p.name,\n 'Plugin version must follow semantic versioning (e.g., \"1.0.0\")'\n );\n }\n }\n\n // Validate register method\n if (!p.register || typeof p.register !== 'function') {\n throw new PluginValidationError(p.name, 'Plugin must have a register method (function)');\n }\n\n // Validate optional lifecycle methods\n const lifecycleMethods = ['initialize', 'terminate', 'onServerStart', 'onServerStop'];\n\n for (const method of lifecycleMethods) {\n if (p[method] && typeof p[method] !== 'function') {\n throw new PluginValidationError(p.name, `Plugin ${method} must be a function if provided`);\n }\n }\n\n // Validate dependencies if present\n // if (p.dependencies) {\n // if (!Array.isArray(p.dependencies) && typeof p.dependencies !== 'string') {\n // throw new PluginValidationError(\n // p.name,\n // 'Plugin dependencies must be a string or array of strings'\n // );\n // }\n\n // const deps = Array.isArray(p.dependencies) ? p.dependencies : [p.dependencies];\n // for (const dep of deps) {\n // if (typeof dep !== 'string') {\n // throw new PluginValidationError(p.name, 'Plugin dependencies must be strings');\n // }\n // }\n // }\n}\n\n/**\n * Validate plugin options object\n */\nexport function validatePluginOptions(pluginName: string, options: unknown, schema?: any): void {\n // Basic validation\n if (options !== undefined && typeof options !== 'object') {\n throw new PluginValidationError(pluginName, 'Plugin options must be an object');\n }\n\n // If a schema is provided, validate against it\n if (schema && options) {\n try {\n schema.parse(options);\n } catch (error) {\n throw new PluginValidationError(\n pluginName,\n `Plugin options validation failed: ${(error as Error).message}`\n );\n }\n }\n}\n\n/**\n * Validate plugin factory function\n */\nexport function validatePluginFactory(\n factory: unknown\n): asserts factory is (...args: any[]) => any {\n if (typeof factory !== 'function') {\n throw new PluginValidationError('', 'Plugin factory must be a function');\n }\n}\n\n/**\n * Check if a plugin name is valid\n */\nexport function isValidPluginName(name: string): boolean {\n return (\n typeof name === 'string' &&\n name.length > 0 &&\n VALID_NAME_PATTERN.test(name) &&\n !RESERVED_NAMES.has(name.toLowerCase())\n );\n}\n\n/**\n * Check if a version string is valid\n */\nexport function isValidVersion(version: string): boolean {\n return typeof version === 'string' && VALID_VERSION_PATTERN.test(version);\n}\n\n/**\n * Sanitize plugin name (remove invalid characters)\n */\nexport function sanitizePluginName(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9-]/g, '-')\n .replace(/^-+|-+$/g, '')\n .replace(/-+/g, '-');\n}\n","// packages/blaize-core/src/router/discovery/cache.ts\nimport * as crypto from 'node:crypto';\nimport * as fs from 'node:fs/promises';\n\nimport { loadRouteModule } from './loader';\n\nimport type { FileCache, Route } from '@blaize-types/router';\n\nconst fileRouteCache = new Map<string, FileCache>();\n\nexport async function processChangedFile(\n filePath: string,\n routesDir: string,\n updateCache: boolean = true\n): Promise<Route[]> {\n const stat = await fs.stat(filePath);\n const lastModified = stat.mtime.getTime();\n const cachedEntry = fileRouteCache.get(filePath);\n\n // Skip if file hasn't changed by timestamp (only when updating cache)\n if (updateCache && cachedEntry && cachedEntry.timestamp === lastModified) {\n return cachedEntry.routes;\n }\n\n // Load only this file\n const routes = await loadRouteModule(filePath, routesDir);\n\n // Only update cache if requested\n if (updateCache) {\n // Calculate content hash for change detection\n const hash = hashRoutes(routes);\n\n // Update cache\n fileRouteCache.set(filePath, {\n routes,\n timestamp: lastModified,\n hash,\n });\n }\n\n return routes;\n}\n\nexport function hasRouteContentChanged(filePath: string, newRoutes: Route[]): boolean {\n const cachedEntry = fileRouteCache.get(filePath);\n if (!cachedEntry) {\n return true;\n }\n\n const newHash = hashRoutes(newRoutes);\n\n return cachedEntry.hash !== newHash;\n}\n\nexport function clearFileCache(filePath?: string): void {\n if (filePath) {\n fileRouteCache.delete(filePath);\n } else {\n fileRouteCache.clear();\n }\n}\n\nfunction hashRoutes(routes: Route[]): string {\n const routeData = routes.map(route => ({\n path: route.path,\n methods: Object.keys(route)\n .filter(key => key !== 'path')\n .sort()\n .map(method => {\n const methodDef = route[method as keyof Route] as any;\n const handlerString = methodDef?.handler ? methodDef.handler.toString() : null;\n return {\n method,\n // Include handler function string for change detection\n handler: handlerString,\n // Include middleware if present\n middleware: methodDef?.middleware ? methodDef.middleware.length : 0,\n // Include schema structure (but not full serialization which can be unstable)\n hasSchema: !!methodDef?.schema,\n schemaKeys: methodDef?.schema ? Object.keys(methodDef.schema).sort() : [],\n };\n }),\n }));\n\n const dataString = JSON.stringify(routeData);\n const hash = crypto.createHash('md5').update(dataString).digest('hex');\n\n return hash;\n}\n","import { parseRoutePath } from './parser';\n\nimport type { Route, RouteDefinition } from '@blaize-types/router';\n\nexport async function dynamicImport(filePath: string) {\n // Add a cache-busting query parameter for ESM\n const cacheBuster = `?t=${Date.now()}`;\n const importPath = filePath + cacheBuster;\n\n try {\n const module = await import(importPath);\n console.log(`✅ Successfully imported module`);\n return module;\n } catch (error) {\n // Type guard to ensure resolveError is an Error object\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.log(`⚠️ Error importing with cache buster, trying original path:`, errorMessage);\n // Fallback to original path\n return import(filePath);\n }\n}\n\n/**\n * Load route modules from a file - supports both default export and named exports\n */\nexport async function loadRouteModule(filePath: string, basePath: string): Promise<Route[]> {\n try {\n // Parse the route path from the file path\n const parsedRoute = parseRoutePath(filePath, basePath);\n // Dynamically import the module\n const module = await dynamicImport(filePath);\n console.log('📦 Module exports:', Object.keys(module));\n\n const routes: Route[] = [];\n\n // Method 1: Check for default export (existing pattern)\n if (module.default && typeof module.default === 'object') {\n const route: Route = {\n ...(module.default as RouteDefinition),\n path: parsedRoute.routePath,\n };\n\n routes.push(route);\n }\n\n // Method 2: Check for named exports that look like routes\n Object.entries(module).forEach(([exportName, exportValue]) => {\n // Skip default export (already handled) and non-objects\n if (exportName === 'default' || !exportValue || typeof exportValue !== 'object') {\n return;\n }\n\n // Check if this export looks like a route (has path property and HTTP methods)\n const potentialRoute = exportValue as any;\n\n if (isValidRoute(potentialRoute)) {\n // For named exports, we might want to use the export name or the route's path\n const route: Route = {\n ...potentialRoute,\n // Use the route's own path if it has one, otherwise derive from file\n path: parsedRoute.routePath,\n };\n\n routes.push(route);\n }\n });\n\n if (routes.length === 0) {\n console.warn(`Route file ${filePath} does not export any valid route definitions`);\n return [];\n }\n\n console.log(`✅ Successfully Loaded ${routes.length} route(s)`);\n return routes;\n } catch (error) {\n console.error(`Failed to load route module ${filePath}:`, error);\n return [];\n }\n}\n\n/**\n * Check if an object looks like a valid route\n */\nfunction isValidRoute(obj: any): boolean {\n if (!obj || typeof obj !== 'object') {\n return false;\n }\n\n // Check if it has at least one HTTP method\n const httpMethods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'];\n const hasHttpMethod = httpMethods.some(\n method => obj[method] && typeof obj[method] === 'object' && obj[method].handler\n );\n\n return hasHttpMethod;\n}\n","import * as os from 'node:os';\n\nimport { processChangedFile } from './cache';\nimport { findRouteFiles } from './finder';\n\nimport type { Route } from '@blaize-types/router';\n\nexport async function processFilesInParallel(\n filePaths: string[],\n processor: (filePath: string) => Promise<Route[]>,\n concurrency: number = Math.max(1, Math.floor(os.cpus().length / 2))\n): Promise<Route[][]> {\n const chunks = chunkArray(filePaths, concurrency);\n const results: Route[][] = [];\n\n for (const chunk of chunks) {\n const chunkResults = await Promise.allSettled(chunk.map(filePath => processor(filePath)));\n\n const successfulResults = chunkResults\n .filter(result => result.status === 'fulfilled')\n .map(result => (result as PromiseFulfilledResult<Route[]>).value);\n\n results.push(...successfulResults);\n }\n\n return results;\n}\n\nexport async function loadInitialRoutesParallel(routesDir: string): Promise<Route[]> {\n const files = await findRouteFiles(routesDir);\n const routeArrays = await processFilesInParallel(files, filePath =>\n processChangedFile(filePath, routesDir)\n );\n\n return routeArrays.flat();\n}\n\nfunction chunkArray<T>(array: T[], chunkSize: number): T[][] {\n const chunks: T[][] = [];\n for (let i = 0; i < array.length; i += chunkSize) {\n chunks.push(array.slice(i, i + chunkSize));\n }\n return chunks;\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\nimport type { FindRouteFilesOptions } from '@blaize-types/router';\n\n/**\n * Find all route files in the specified directory\n */\nexport async function findRouteFiles(\n routesDir: string,\n options: FindRouteFilesOptions = {}\n): Promise<string[]> {\n // Convert to absolute path if it's relative\n const absoluteDir = path.isAbsolute(routesDir)\n ? routesDir\n : path.resolve(process.cwd(), routesDir);\n\n console.log('Creating router with routes directory:', absoluteDir);\n\n // Check if directory exists\n try {\n const stats = await fs.stat(absoluteDir);\n if (!stats.isDirectory()) {\n throw new Error(`Route directory is not a directory: ${absoluteDir}`);\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new Error(`Route directory not found: ${absoluteDir}`);\n }\n throw error;\n }\n\n const routeFiles: string[] = [];\n const ignore = options.ignore || ['node_modules', '.git'];\n\n async function scanDirectory(dir: string) {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n\n // Skip ignored directories\n if (entry.isDirectory() && ignore.includes(entry.name)) {\n continue;\n }\n\n if (entry.isDirectory()) {\n await scanDirectory(fullPath);\n } else if (isRouteFile(entry.name)) {\n routeFiles.push(fullPath);\n }\n }\n }\n\n await scanDirectory(absoluteDir);\n return routeFiles;\n}\n\n/**\n * Check if a file is a valid route file\n */\nfunction isRouteFile(filename: string): boolean {\n // Route files are TypeScript/JavaScript files that don't start with underscore\n return !filename.startsWith('_') && (filename.endsWith('.ts') || filename.endsWith('.js'));\n}\n","import type { ReloadMetrics } from '@blaize-types/router';\n\nconst profilerState: ReloadMetrics = {\n fileChanges: 0,\n totalReloadTime: 0,\n averageReloadTime: 0,\n slowReloads: [],\n};\n\nexport function trackReloadPerformance(filePath: string, startTime: number): void {\n const duration = Date.now() - startTime;\n\n profilerState.fileChanges++;\n profilerState.totalReloadTime += duration;\n profilerState.averageReloadTime = profilerState.totalReloadTime / profilerState.fileChanges;\n\n if (duration > 100) {\n profilerState.slowReloads.push({ file: filePath, time: duration });\n if (profilerState.slowReloads.length > 10) {\n profilerState.slowReloads.shift();\n }\n }\n\n if (process.env.NODE_ENV === 'development') {\n const emoji = duration < 50 ? '⚡' : duration < 100 ? '🔄' : '🐌';\n console.log(`${emoji} Route reload: ${filePath} (${duration}ms)`);\n }\n}\n\nexport function getReloadMetrics(): Readonly<ReloadMetrics> {\n return { ...profilerState };\n}\n\nexport function resetReloadMetrics(): void {\n profilerState.fileChanges = 0;\n profilerState.totalReloadTime = 0;\n profilerState.averageReloadTime = 0;\n profilerState.slowReloads = [];\n}\n\nexport function withPerformanceTracking<T extends (...args: any[]) => Promise<any>>(\n fn: T,\n filePath: string\n): T {\n console.log(`Tracking performance for: ${filePath}`);\n return (async (...args: Parameters<T>) => {\n const startTime = Date.now();\n try {\n const result = await fn(...args);\n trackReloadPerformance(filePath, startTime);\n return result;\n } catch (error) {\n trackReloadPerformance(filePath, startTime);\n throw error;\n }\n }) as T;\n}\n","import * as path from 'node:path';\n\nimport { watch } from 'chokidar';\n\nimport { hasRouteContentChanged, processChangedFile } from './cache';\n\nimport type { Route, WatchOptions } from '@blaize-types/router';\n\n/**\n * Watch for route file changes\n */\nexport function watchRoutes(routesDir: string, options: WatchOptions = {}) {\n // Debounce rapid file changes\n const debounceMs = options.debounceMs || 16;\n const debouncedCallbacks = new Map<string, NodeJS.Timeout>();\n\n function createDebouncedCallback<T extends (...args: any[]) => void>(\n fn: T,\n filePath: string\n ): (...args: Parameters<T>) => void {\n return (...args: Parameters<T>) => {\n // Clear existing timeout for this file\n const existingTimeout = debouncedCallbacks.get(filePath);\n if (existingTimeout) {\n clearTimeout(existingTimeout);\n }\n\n // Set new timeout\n const timeoutId = setTimeout(() => {\n fn(...args);\n debouncedCallbacks.delete(filePath);\n }, debounceMs);\n\n debouncedCallbacks.set(filePath, timeoutId);\n };\n }\n // Track loaded routes by file path - now stores arrays of routes\n const routesByPath = new Map<string, Route[]>();\n\n // Optimized load and notify function\n async function loadAndNotify(filePath: string) {\n try {\n const existingRoutes = routesByPath.get(filePath);\n\n // Step 1: Load new routes WITHOUT updating cache\n const newRoutes = await processChangedFile(filePath, routesDir, false);\n\n if (!newRoutes || newRoutes.length === 0) {\n return;\n }\n\n // Step 2: Check if content has actually changed (cache still has old data)\n if (existingRoutes && !hasRouteContentChanged(filePath, newRoutes)) {\n return;\n }\n\n // Step 3: Content changed! Now update the cache\n await processChangedFile(filePath, routesDir, true);\n\n const normalizedPath = path.normalize(filePath);\n\n if (existingRoutes) {\n routesByPath.set(filePath, newRoutes);\n if (options.onRouteChanged) {\n options.onRouteChanged(normalizedPath, newRoutes);\n }\n } else {\n routesByPath.set(filePath, newRoutes);\n if (options.onRouteAdded) {\n options.onRouteAdded(normalizedPath, newRoutes);\n }\n }\n } catch (error) {\n console.log(`⚠️ Error processing file ${filePath}:`, error);\n handleError(error);\n }\n }\n\n // Handle route file removal\n function handleRemoved(filePath: string) {\n const normalizedPath = path.normalize(filePath);\n const routes = routesByPath.get(normalizedPath);\n\n if (routes && routes.length > 0 && options.onRouteRemoved) {\n options.onRouteRemoved(normalizedPath, routes);\n }\n\n routesByPath.delete(normalizedPath);\n }\n\n // Handle errors\n function handleError(error: unknown) {\n if (options.onError && error instanceof Error) {\n options.onError(error);\n } else {\n console.error('⚠️ Route watcher error:', error);\n }\n }\n\n // Start file watcher\n // Create optimized watcher\n const watcher = watch(routesDir, {\n ignoreInitial: true,\n // Much faster response times\n awaitWriteFinish: {\n stabilityThreshold: 50, // Reduced from 300ms\n pollInterval: 10, // Reduced from 100ms\n },\n\n // Performance optimizations\n usePolling: false,\n atomic: true,\n followSymlinks: false,\n depth: 10,\n\n // More aggressive ignoring\n ignored: [\n /(^|[/\\\\])\\../,\n /node_modules/,\n /\\.git/,\n /\\.DS_Store/,\n /Thumbs\\.db/,\n /\\.(test|spec)\\.(ts|js)$/,\n /\\.d\\.ts$/,\n /\\.map$/,\n /~$/,\n ...(options.ignore || []),\n ],\n });\n\n // Set up event handlers\n watcher\n .on('add', filePath => {\n const debouncedLoad = createDebouncedCallback(loadAndNotify, filePath);\n debouncedLoad(filePath);\n })\n .on('change', filePath => {\n const debouncedLoad = createDebouncedCallback(loadAndNotify, filePath);\n\n // Call debounced load for changed file\n debouncedLoad(filePath);\n })\n .on('unlink', filePath => {\n const debouncedRemove = createDebouncedCallback(handleRemoved, filePath);\n debouncedRemove(filePath);\n })\n .on('error', handleError);\n\n // Return control methods\n return {\n close: () => {\n // Clear any pending debounced callbacks\n debouncedCallbacks.forEach(timeout => clearTimeout(timeout));\n debouncedCallbacks.clear();\n\n return watcher.close();\n },\n getRoutes: () => {\n const allRoutes: Route[] = [];\n for (const routes of routesByPath.values()) {\n allRoutes.push(...routes);\n }\n return allRoutes;\n },\n getRoutesByFile: () => new Map(routesByPath),\n };\n}\n","import { z } from 'zod';\n\nimport { validateBody } from './body';\nimport { validateParams } from './params';\nimport { validateQuery } from './query';\nimport { validateResponse } from './response';\nimport { InternalServerError } from '../../errors/internal-server-error';\nimport { ValidationError } from '../../errors/validation-error';\n\nimport type { Context } from '@blaize-types/context';\nimport type { Middleware, MiddlewareFunction, NextFunction } from '@blaize-types/middleware';\nimport type { RouteSchema } from '@blaize-types/router';\n\n/**\n * Create a validation middleware for request data\n */\nexport function createRequestValidator(schema: RouteSchema, debug: boolean = false): Middleware {\n const middlewareFn: MiddlewareFunction = async (ctx: Context, next: NextFunction) => {\n // Validate params if schema exists - throw immediately on failure\n if (schema.params && ctx.request.params) {\n try {\n ctx.request.params = validateParams(ctx.request.params, schema.params);\n } catch (error) {\n const fieldErrors = extractZodFieldErrors(error);\n const errorCount = fieldErrors.reduce((sum, fe) => sum + fe.messages.length, 0);\n\n throw new ValidationError('Request validation failed', {\n fields: fieldErrors,\n errorCount,\n section: 'params',\n });\n }\n }\n\n // Validate query if schema exists - throw immediately on failure\n if (schema.query && ctx.request.query) {\n try {\n ctx.request.query = validateQuery(ctx.request.query, schema.query);\n } catch (error) {\n const fieldErrors = extractZodFieldErrors(error);\n const errorCount = fieldErrors.reduce((sum, fe) => sum + fe.messages.length, 0);\n\n throw new ValidationError('Request validation failed', {\n fields: fieldErrors,\n errorCount,\n section: 'query',\n });\n }\n }\n\n // Validate body if schema exists - throw immediately on failure\n if (schema.body) {\n try {\n ctx.request.body = validateBody(ctx.request.body, schema.body);\n } catch (error) {\n const fieldErrors = extractZodFieldErrors(error);\n const errorCount = fieldErrors.reduce((sum, fe) => sum + fe.messages.length, 0);\n\n throw new ValidationError('Request validation failed', {\n fields: fieldErrors,\n errorCount,\n section: 'body',\n });\n }\n }\n // Continue if validation passed\n await next();\n };\n\n return {\n name: 'RequestValidator',\n execute: middlewareFn,\n debug,\n };\n}\n\n/**\n * Type guard to detect error responses\n * Error responses have: type, status, correlationId, timestamp\n */\nfunction isErrorResponse(body: unknown): boolean {\n return (\n body !== null &&\n typeof body === 'object' &&\n 'type' in body &&\n 'status' in body &&\n 'correlationId' in body &&\n 'timestamp' in body\n );\n}\n\n/**\n * Create a validation middleware for response data\n */\nexport function createResponseValidator<T>(\n responseSchema: z.ZodType<T, z.ZodTypeDef, unknown>,\n debug: boolean = false\n): Middleware {\n const middlewareFn: MiddlewareFunction = async (ctx, next) => {\n const originalJson = ctx.response.json;\n let validatorActive = true; // Track if validator should run\n\n // Override json method to validate responses\n ctx.response.json = (body: unknown, status?: number) => {\n // If validator was deactivated (error occurred), skip validation\n if (!validatorActive) {\n return originalJson.call(ctx.response, body, status);\n }\n\n // Don't validate error responses - they have their own schema\n // This allows NotFoundError, ValidationError, etc. to pass through\n if (isErrorResponse(body)) {\n return originalJson.call(ctx.response, body, status);\n }\n\n // Validate success responses\n try {\n const validatedBody = validateResponse(body, responseSchema);\n return originalJson.call(ctx.response, validatedBody, status);\n } catch (error) {\n // Deactivate validator to prevent recursion when error is thrown\n validatorActive = false;\n\n // Throw validation error for error boundary to catch\n throw new InternalServerError('Response validation failed', {\n validationError: extractZodFieldErrors(error),\n hint: 'The handler returned data that does not match the response schema',\n });\n }\n };\n\n try {\n // Execute the handler and downstream middleware\n await next();\n } catch (error) {\n // On any error, deactivate validator and restore original method\n validatorActive = false;\n ctx.response.json = originalJson;\n // Re-throw for error boundary to handle\n throw error;\n } finally {\n // Always restore original json method when middleware completes\n ctx.response.json = originalJson;\n }\n };\n\n return {\n name: 'ResponseValidator',\n execute: middlewareFn,\n debug,\n };\n}\n\n/**\n * Extract structured field errors from Zod validation errors\n *\n * Converts Zod errors into a clean array of error messages per field.\n *\n * @param error - The validation error (typically a ZodError)\n * @returns Array of error messages for the field\n *\n * @example\n * ```typescript\n * const zodError = new z.ZodError([\n * { path: ['email'], message: 'Invalid email' },\n * { path: ['email'], message: 'Email is required' }\n * ]);\n *\n * const fieldErrors = extractZodFieldErrors(zodError);\n * // Returns: ['Invalid email', 'Email is required']\n * ```\n */\nfunction extractZodFieldErrors(error: unknown): { field: string; messages: string[] }[] {\n if (error instanceof z.ZodError) {\n // Group errors by field path\n const fieldErrorMap = new Map<string, string[]>();\n\n for (const issue of error.issues) {\n // Get the field path (e.g., ['user', 'email'] becomes 'user.email')\n const fieldPath = issue.path.length > 0 ? issue.path.join('.') : 'root';\n\n if (!fieldErrorMap.has(fieldPath)) {\n fieldErrorMap.set(fieldPath, []);\n }\n fieldErrorMap.get(fieldPath)!.push(issue.message);\n }\n\n // Convert map to array of field errors\n return Array.from(fieldErrorMap.entries()).map(([field, messages]) => ({\n field,\n messages,\n }));\n }\n\n if (error instanceof Error) {\n return [{ field: 'unknown', messages: [error.message] }];\n }\n\n return [{ field: 'unknown', messages: [String(error)] }];\n}\n\n/**\n * 🔄 DEPRECATED: Keep for backward compatibility but mark as deprecated\n *\n * This function maintains the old API for any existing code that might depend on it.\n * New code should use extractZodFieldErrors for better structured error handling.\n *\n * @deprecated Use extractZodFieldErrors instead for better structured error details\n * @param error - The validation error to format\n * @returns Formatted error object (maintains old structure)\n */\nexport function formatValidationError(error: unknown): unknown {\n // Handle Zod errors\n if (\n error &&\n typeof error === 'object' &&\n 'format' in error &&\n typeof error.format === 'function'\n ) {\n return error.format();\n }\n\n // Handle other error types\n return error instanceof Error ? error.message : String(error);\n}\n","import { z } from 'zod';\n\n/**\n * Validate request body\n */\nexport function validateBody<T>(body: unknown, schema: z.ZodType<T>): T {\n if (schema instanceof z.ZodObject) {\n return schema.strict().parse(body) as T;\n }\n // Parse and validate with the provided schema\n return schema.parse(body);\n}\n","import { z } from 'zod';\n\n/**\n * Validate request parameters\n */\nexport function validateParams<T>(\n params: Record<string, string>,\n schema: z.ZodType<T, z.ZodTypeDef, unknown>\n): T {\n if (schema instanceof z.ZodObject) {\n // If schema is an object, ensure strict parsing\n return schema.strict().parse(params) as T;\n }\n // Parse and validate with the provided schema\n return schema.parse(params);\n}\n","import { z } from 'zod';\n\n/**\n * Validate query parameters\n */\nexport function validateQuery<T>(\n query: Record<string, string | string[] | undefined>,\n schema: z.ZodType<T, z.ZodTypeDef, unknown>\n): T {\n if (schema instanceof z.ZodObject) {\n // If schema is an object, ensure strict parsing\n return schema.strict().parse(query) as T;\n }\n // Parse and validate with the provided schema\n return schema.parse(query);\n}\n","import { z } from 'zod';\n\n/**\n * Validate response body\n */\nexport function validateResponse<T>(\n response: unknown,\n schema: z.ZodType<T, z.ZodTypeDef, unknown>\n): T {\n if (schema instanceof z.ZodObject) {\n return schema.strict().parse(response) as T;\n }\n // Parse and validate with the provided schema\n return schema.parse(response);\n}\n","import { compose } from '../../middleware/compose';\nimport { createRequestValidator, createResponseValidator } from '../validation';\n\nimport type { Context } from '@blaize-types/context';\nimport type { RouteMethodOptions } from '@blaize-types/router';\n\n/**\n * Execute a route handler with its middleware\n */\nexport async function executeHandler(\n ctx: Context,\n routeOptions: RouteMethodOptions,\n params: Record<string, string>\n): Promise<void> {\n // Set up middleware chain\n const middleware = [...(routeOptions.middleware || [])];\n\n // Add validation middleware if schemas are defined\n if (routeOptions.schema) {\n if (routeOptions.schema.params || routeOptions.schema.query || routeOptions.schema.body) {\n middleware.unshift(createRequestValidator(routeOptions.schema));\n }\n\n if (routeOptions.schema.response) {\n middleware.push(createResponseValidator(routeOptions.schema.response));\n }\n }\n\n // Compose middleware with the final handler\n const handler = compose([...middleware]);\n\n // Execute the middleware chain\n await handler(ctx, async () => {\n // Execute the handler with the new argument style\n const result = await routeOptions.handler(ctx, params);\n\n // Handle the result if it wasn't already handled by the handler\n if (!ctx.response.sent && result !== undefined) {\n ctx.response.json(result);\n }\n });\n}\n","import type { Route, RouteRegistry } from '@blaize-types/router';\n\nexport function createRouteRegistry(): RouteRegistry {\n return {\n routesByPath: new Map(),\n routesByFile: new Map(),\n pathToFile: new Map(),\n };\n}\n\nexport function updateRoutesFromFile(\n registry: RouteRegistry,\n filePath: string,\n newRoutes: Route[]\n): { added: Route[]; removed: string[]; changed: Route[] } {\n console.log(`Updating routes from file: ${filePath}`);\n const oldPaths = registry.routesByFile.get(filePath) || new Set();\n const newPaths = new Set(newRoutes.map(r => r.path));\n\n // Fast diff calculation\n const added = newRoutes.filter(r => !oldPaths.has(r.path));\n const removed = Array.from(oldPaths).filter(p => !newPaths.has(p));\n const potentiallyChanged = newRoutes.filter(r => oldPaths.has(r.path));\n\n // Check for actual content changes\n const changed = potentiallyChanged.filter(route => {\n const existingRoute = registry.routesByPath.get(route.path);\n return !existingRoute || !routesEqual(existingRoute, route);\n });\n\n // Apply updates\n applyRouteUpdates(registry, filePath, { added, removed, changed });\n\n return { added, removed, changed };\n}\n\nexport function getRouteFromRegistry(registry: RouteRegistry, path: string): Route | undefined {\n return registry.routesByPath.get(path);\n}\n\nexport function getAllRoutesFromRegistry(registry: RouteRegistry): Route[] {\n return Array.from(registry.routesByPath.values());\n}\n\nexport function getFileRoutes(registry: RouteRegistry, filePath: string): Route[] {\n const paths = registry.routesByFile.get(filePath) || new Set();\n return Array.from(paths)\n .map(path => registry.routesByPath.get(path)!)\n .filter(Boolean);\n}\n\nfunction applyRouteUpdates(\n registry: RouteRegistry,\n filePath: string,\n updates: { added: Route[]; removed: string[]; changed: Route[] }\n): void {\n const { added, removed, changed } = updates;\n\n // Remove old routes\n removed.forEach(path => {\n registry.routesByPath.delete(path);\n registry.pathToFile.delete(path);\n });\n\n // Add/update routes\n [...added, ...changed].forEach(route => {\n registry.routesByPath.set(route.path, route);\n registry.pathToFile.set(route.path, filePath);\n });\n\n // Update file -> paths mapping\n const allPathsForFile = new Set([\n ...added.map(r => r.path),\n ...changed.map(r => r.path),\n ...Array.from(registry.routesByFile.get(filePath) || []).filter(p => !removed.includes(p)),\n ]);\n\n if (allPathsForFile.size > 0) {\n registry.routesByFile.set(filePath, allPathsForFile);\n } else {\n registry.routesByFile.delete(filePath);\n }\n}\n\nfunction routesEqual(route1: Route, route2: Route): boolean {\n if (route1.path !== route2.path) return false;\n\n const methods1 = Object.keys(route1)\n .filter(k => k !== 'path')\n .sort();\n const methods2 = Object.keys(route2)\n .filter(k => k !== 'path')\n .sort();\n\n if (methods1.length !== methods2.length) return false;\n\n return methods1.every(method => {\n const handler1 = route1[method as keyof Route];\n const handler2 = route2[method as keyof Route];\n\n // Compare handler signatures/structure rather than function references\n return typeof handler1 === typeof handler2;\n });\n}\n","import type { Route, HttpMethod, RouteMethodOptions, Matcher } from '@blaize-types/router';\n\nexport function addRouteToMatcher(route: Route, matcher: Matcher): void {\n Object.entries(route).forEach(([method, methodOptions]) => {\n if (method === 'path' || !methodOptions) return;\n matcher.add(route.path, method as HttpMethod, methodOptions as RouteMethodOptions);\n });\n}\n\nexport function removeRouteFromMatcher(path: string, matcher: Matcher): void {\n // Use matcher's remove method if available, otherwise fallback to clear/rebuild\n if ('remove' in matcher && typeof matcher.remove === 'function') {\n matcher.remove(path);\n } else {\n // This requires rebuilding the matcher - could be optimized\n console.warn('Matcher does not support selective removal, consider adding remove() method');\n }\n}\n\nexport function updateRouteInMatcher(route: Route, matcher: Matcher): void {\n removeRouteFromMatcher(route.path, matcher);\n addRouteToMatcher(route, matcher);\n}\n\nexport function rebuildMatcherWithRoutes(routes: Route[], matcher: Matcher): void {\n if ('clear' in matcher && typeof matcher.clear === 'function') {\n matcher.clear();\n }\n\n routes.forEach(route => addRouteToMatcher(route, matcher));\n}\n","import { NotFoundError } from '../errors/not-found-error';\nimport { clearFileCache } from './discovery/cache';\nimport { loadInitialRoutesParallel } from './discovery/parallel';\nimport { withPerformanceTracking } from './discovery/profiler';\nimport { watchRoutes } from './discovery/watchers';\nimport { executeHandler } from './handlers';\nimport { createMatcher } from './matching';\nimport {\n createRouteRegistry,\n updateRoutesFromFile,\n getAllRoutesFromRegistry,\n} from './registry/fast-registry';\nimport {\n addRouteToMatcher,\n removeRouteFromMatcher,\n updateRouteInMatcher,\n} from './utils/matching-helpers';\n\nimport type { Context } from '@blaize-types/context';\nimport type { HttpMethod, Route, RouterOptions, Router } from '@blaize-types/router';\n\nconst DEFAULT_ROUTER_OPTIONS = {\n routesDir: './routes',\n basePath: '/',\n watchMode: process.env.NODE_ENV === 'development',\n};\n\n/**\n * Create an optimized router instance with fast hot reload\n */\nexport function createRouter(options: RouterOptions): Router {\n // Merge with default options\n const routerOptions = {\n ...DEFAULT_ROUTER_OPTIONS,\n ...options,\n };\n\n if (options.basePath && !options.basePath.startsWith('/')) {\n console.warn('Base path does nothing');\n }\n\n // Use optimized registry instead of simple array\n const registry = createRouteRegistry();\n const matcher = createMatcher();\n\n // Initialize routes\n let initialized = false;\n let initializationPromise: Promise<void> | null = null;\n let _watchers: Map<string, ReturnType<typeof watchRoutes>> | null = null;\n\n const routeDirectories = new Set<string>([routerOptions.routesDir]);\n\n /**\n * Apply registry changes to matcher efficiently\n */\n function applyMatcherChanges(changes: { added: Route[]; removed: string[]; changed: Route[] }) {\n console.log('\\n🔧 APPLYING MATCHER CHANGES:');\n console.log(` Adding ${changes.added.length} routes`);\n console.log(` Removing ${changes.removed.length} routes`);\n console.log(` Updating ${changes.changed.length} routes`);\n\n // Remove routes first\n changes.removed.forEach(routePath => {\n console.log(` ➖ Removing: ${routePath}`);\n removeRouteFromMatcher(routePath, matcher);\n });\n\n // Add new routes\n changes.added.forEach(route => {\n const methods = Object.keys(route).filter(key => key !== 'path');\n console.log(` ➕ Adding: ${route.path} [${methods.join(', ')}]`);\n addRouteToMatcher(route, matcher);\n });\n\n // Update changed routes\n changes.changed.forEach(route => {\n const methods = Object.keys(route).filter(key => key !== 'path');\n console.log(` 🔄 Updating: ${route.path} [${methods.join(', ')}]`);\n updateRouteInMatcher(route, matcher);\n });\n\n console.log('✅ Matcher changes applied\\n');\n }\n\n /**\n * Add multiple routes with batch processing\n */\n function addRoutesWithSource(routes: Route[], source: string) {\n try {\n // Use registry for batch conflict detection and management\n const changes = updateRoutesFromFile(registry, source, routes);\n\n // Apply all changes to matcher in one operation\n applyMatcherChanges(changes);\n\n return changes;\n } catch (error) {\n console.error(`⚠️ Route conflicts from ${source}:`, error);\n throw error;\n }\n }\n\n /**\n * Optimized route loading with parallel processing\n */\n async function loadRoutesFromDirectory(directory: string, source: string, prefix?: string) {\n try {\n // Use parallel loading for better performance\n const discoveredRoutes = await loadInitialRoutesParallel(directory);\n\n // Apply prefix if provided\n const finalRoutes = discoveredRoutes.map(route =>\n prefix ? { ...route, path: `${prefix}${route.path}` } : route\n );\n\n // Batch add all routes from this directory\n const changes = addRoutesWithSource(finalRoutes, source);\n\n console.log(\n `Loaded ${discoveredRoutes.length} routes from ${source}${prefix ? ` with prefix ${prefix}` : ''} ` +\n `(${changes.added.length} added, ${changes.changed.length} changed, ${changes.removed.length} removed)`\n );\n } catch (error) {\n console.error(`⚠️ Failed to load routes from ${source}:`, error);\n throw error;\n }\n }\n\n /**\n * Initialize the router with parallel route loading\n */\n async function initialize() {\n if (initialized || initializationPromise) {\n return initializationPromise;\n }\n\n initializationPromise = (async () => {\n try {\n // Load routes from all directories in parallel\n await Promise.all(\n Array.from(routeDirectories).map(directory =>\n loadRoutesFromDirectory(directory, directory)\n )\n );\n\n // Set up optimized watching\n if (routerOptions.watchMode) {\n setupOptimizedWatching();\n }\n\n initialized = true;\n } catch (error) {\n console.error('⚠️ Failed to initialize router:', error);\n throw error;\n }\n })();\n\n return initializationPromise;\n }\n\n /**\n * Setup optimized file watching with fast updates\n */\n function setupOptimizedWatching() {\n if (!_watchers) {\n _watchers = new Map();\n }\n\n for (const directory of routeDirectories) {\n if (!_watchers.has(directory)) {\n const watcher = watchRoutes(directory, {\n debounceMs: 16, // ~60fps debouncing\n ignore: ['node_modules', '.git'],\n\n onRouteAdded: (filepath: string, addedRoutes: Route[]) => {\n // Batch process all added routes\n try {\n const changes = updateRoutesFromFile(registry, filepath, addedRoutes);\n applyMatcherChanges(changes);\n } catch (error) {\n console.error(`Error adding routes from ${directory}:`, error);\n }\n },\n\n onRouteChanged: withPerformanceTracking(\n async (filepath: string, changedRoutes: Route[]) => {\n // console.log(`${changedRoutes.length} route(s) changed in ${directory}`);\n\n try {\n console.log(`Processing changes for ${filepath}`);\n // Process all changed routes in one batch operation\n const changes = updateRoutesFromFile(registry, filepath, changedRoutes);\n\n console.log(\n `Changes detected: ${changes.added.length} added, ` +\n `${changes.changed.length} changed, ${changes.removed.length} removed`\n );\n\n // Apply matcher updates efficiently\n applyMatcherChanges(changes);\n\n console.log(\n `Route changes applied: ${changes.added.length} added, ` +\n `${changes.changed.length} changed, ${changes.removed.length} removed`\n );\n } catch (error) {\n console.error(`⚠️ Error updating routes from ${directory}:`, error);\n }\n },\n directory\n ),\n\n onRouteRemoved: (filePath: string, removedRoutes: Route[]) => {\n console.log(`File removed: ${filePath} with ${removedRoutes.length} routes`);\n\n try {\n // Remove all routes from this file\n removedRoutes.forEach(route => {\n removeRouteFromMatcher(route.path, matcher);\n });\n\n // Clear cache for removed file\n clearFileCache(filePath);\n } catch (error) {\n console.error(`⚠️ Error removing routes from ${filePath}:`, error);\n }\n },\n\n onError: (error: Error) => {\n console.error(`⚠️ Route watcher error for ${directory}:`, error);\n },\n });\n\n _watchers.set(directory, watcher);\n }\n }\n }\n\n /**\n * Setup watcher for newly added directory\n */\n function setupWatcherForNewDirectory(directory: string, prefix?: string) {\n if (!_watchers) {\n _watchers = new Map();\n }\n\n const watcher = watchRoutes(directory, {\n debounceMs: 16,\n ignore: ['node_modules', '.git'],\n\n onRouteAdded: (filePath: string, addedRoutes: Route[]) => {\n try {\n // Apply prefix to all routes\n const finalRoutes = addedRoutes.map(route =>\n prefix ? { ...route, path: `${prefix}${route.path}` } : route\n );\n\n // Batch process all added routes\n const changes = updateRoutesFromFile(registry, filePath, finalRoutes);\n applyMatcherChanges(changes);\n } catch (error) {\n console.error(`⚠️ Error adding routes from ${directory}:`, error);\n }\n },\n\n onRouteChanged: withPerformanceTracking(async (filePath: string, changedRoutes: Route[]) => {\n try {\n // Apply prefix to all routes\n const finalRoutes = changedRoutes.map(route =>\n prefix ? { ...route, path: `${prefix}${route.path}` } : route\n );\n\n // Process all changed routes in one batch operation\n const changes = updateRoutesFromFile(registry, filePath, finalRoutes);\n applyMatcherChanges(changes);\n } catch (error) {\n console.error(`⚠️ Error updating routes from ${directory}:`, error);\n }\n }, directory),\n\n onRouteRemoved: (filePath: string, removedRoutes: Route[]) => {\n try {\n removedRoutes.forEach(route => {\n const finalPath = prefix ? `${prefix}${route.path}` : route.path;\n removeRouteFromMatcher(finalPath, matcher);\n });\n clearFileCache(filePath);\n } catch (error) {\n console.error(`Error removing routes from ${filePath}:`, error);\n }\n },\n\n onError: (error: Error) => {\n console.error(`⚠️ Route watcher error for ${directory}:`, error);\n },\n });\n\n _watchers.set(directory, watcher);\n return watcher;\n }\n\n // Initialize router on creation\n initialize().catch(error => {\n console.error('⚠️ Failed to initialize router on creation:', error);\n });\n\n // Public API\n return {\n /**\n * Handle an incoming request\n */\n async handleRequest(ctx: Context) {\n // Ensure router is initialized\n if (!initialized) {\n console.log('🔄 Router not initialized, initializing...');\n await initialize();\n }\n\n const { method, path } = ctx.request;\n console.log(`\\n📥 Handling request: ${method} ${path}`);\n\n // Find matching route\n const match = matcher.match(path, method as HttpMethod);\n\n if (!match) {\n console.log(`❌ No match found for: ${method} ${path}`);\n // Handle 404 Not Found\n throw new NotFoundError('Not found');\n }\n\n console.log(`✅ Route matched: ${method} ${path}`);\n console.log(` Params: ${JSON.stringify(match.params)}`);\n\n // Check for method not allowed\n if (match.methodNotAllowed) {\n // Handle 405 Method Not Allowed\n // TODO: Add support for Method Not Allowed Error\n ctx.response.status(405).json({\n error: '❌ Method Not Allowed',\n allowed: match.allowedMethods,\n });\n\n // Set Allow header with allowed methods\n if (match.allowedMethods && match.allowedMethods.length > 0) {\n ctx.response.header('Allow', match.allowedMethods.join(', '));\n }\n\n return;\n }\n\n // Extract route parameters\n ctx.request.params = match.params;\n\n // Execute the route handler with middleware\n await executeHandler(ctx, match.route!, match.params);\n },\n\n /**\n * Get all registered routes (using optimized registry)\n */\n getRoutes() {\n return getAllRoutesFromRegistry(registry);\n },\n\n /**\n * Add a route programmatically\n */\n addRoute(route: Route) {\n const changes = updateRoutesFromFile(registry, 'programmatic', [route]);\n applyMatcherChanges(changes);\n },\n\n /**\n * Add multiple routes programmatically with batch processing\n */\n addRoutes(routes: Route[]) {\n const changes = updateRoutesFromFile(registry, 'programmatic', routes);\n applyMatcherChanges(changes);\n return changes;\n },\n\n /**\n * Add a route directory (for plugins) with optimized loading\n */\n async addRouteDirectory(directory: string, options: { prefix?: string } = {}) {\n if (routeDirectories.has(directory)) {\n console.warn(`Route directory ${directory} already registered`);\n return;\n }\n\n routeDirectories.add(directory);\n\n // If already initialized, load routes immediately\n if (initialized) {\n await loadRoutesFromDirectory(directory, directory, options.prefix);\n\n // Set up watching for this directory if in watch mode\n if (routerOptions.watchMode) {\n setupWatcherForNewDirectory(directory, options.prefix);\n }\n }\n },\n\n /**\n * Get route conflicts (using registry)\n */\n getRouteConflicts() {\n // Registry handles conflict detection internally\n // This could be enhanced to expose more detailed conflict info\n const conflicts: Array<{ path: string; sources: string[] }> = [];\n // Implementation would depend on registry's conflict tracking\n return conflicts;\n },\n\n /**\n * Close watchers and cleanup (useful for testing)\n */\n async close() {\n if (_watchers) {\n for (const watcher of _watchers.values()) {\n await watcher.close();\n }\n _watchers.clear();\n }\n },\n };\n}\n","/**\n * Type inference utilities for BlaizeJS\n * Minimal set of utilities needed for type-safe routing\n */\n\nimport type { Server, Context, State, Services } from '@blaize-types/index';\n\n/**\n * Infers the context type from a server instance\n *\n * @example\n * ```typescript\n * const server = createServer().use(authMiddleware);\n * type AppContext = InferContext<typeof server>;\n * ```\n */\nexport type InferContext<T> =\n T extends Server<infer TState, infer TServices>\n ? TState extends State\n ? TServices extends Services\n ? Context<TState, TServices, any, any>\n : Context<State, Services, any, any>\n : Context<State, Services, any, any>\n : Context<State, Services, any, any>;\n\n/**\n * Extracts just the state type from a server\n */\nexport type InferServerState<T> =\n T extends Server<infer TState, any> ? (TState extends State ? TState : State) : State;\n\n/**\n * Extracts just the services type from a server\n */\nexport type InferServerServices<T> =\n T extends Server<any, infer TServices>\n ? TServices extends Services\n ? TServices\n : Services\n : Services;\n\n/**\n * Runtime helper that provides type hints for development\n * Returns an empty object but gives TypeScript the correct context type\n *\n * @param _server - The server instance (not used at runtime)\n * @returns An empty object typed as the server's context\n */\nexport function inferContext<TState extends State, TServices extends Services>(\n _server: Server<TState, TServices>\n): InferContext<Server<TState, TServices>> {\n return {} as InferContext<Server<TState, TServices>>;\n}\n","/* eslint-disable @typescript-eslint/no-empty-object-type */\n/**\n * Type composition utilities for extracting and composing middleware type contributions\n * @module composition\n * @since v0.4.0\n */\n\nimport type { Middleware } from './middleware';\nimport type { Plugin } from './plugins';\n\n/**\n * Extracts the State type contribution from a middleware\n * @template T - The middleware type to extract from\n * @returns The state type if present, empty object otherwise\n */\nexport type ExtractMiddlewareState<T> = T extends Middleware<infer S, any> ? S : {};\n\n/**\n * Extracts the State type contribution from a plugin\n * @template T - The plugin type to extract from\n * @returns The state type if present, empty object otherwise\n */\nexport type ExtractPluginState<T> = T extends Plugin<infer S, any> ? S : {};\n\n/**\n * Extracts the Services type contribution from a middleware\n * @template T - The middleware type to extract from\n * @returns The services type if present, empty object otherwise\n */\nexport type ExtractMiddlewareServices<T> = T extends Middleware<any, infer S> ? S : {};\n\n/**\n * Extracts the Services type contribution from a plugin\n * @template T - The plugin type to extract from\n * @returns The services type if present, empty object otherwise\n */\nexport type ExtractPluginServices<T> = T extends Plugin<any, infer S> ? S : {};\n\n/**\n * Utility type to convert a union type to an intersection type\n * This is the magic that allows us to compose multiple middleware contributions\n *\n * @example\n * type U = { a: string } | { b: number }\n * type I = UnionToIntersection<U> // { a: string } & { b: number }\n *\n */\nexport type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (\n k: infer I\n) => void\n ? I\n : never;\n\n/**\n * Composes state contributions from an array of middleware\n * Merges all state types into a single intersection type\n *\n * @template T - ReadonlyArray of Middleware\n * @returns Intersection of all state contributions\n *\n * @example\n * const middlewares = [authMiddleware, loggerMiddleware] as const;\n * type ComposedState = ComposeStates<typeof middlewares>;\n * // Result: { user: User } & { requestId: string }\n */\nexport type ComposeMiddlewareStates<T extends ReadonlyArray<Middleware>> = T extends readonly []\n ? {}\n : UnionToIntersection<ExtractMiddlewareState<T[number]>>;\n\n/**\n * Composes state contributions from an array of plugins\n * Merges all state types into a single intersection type\n *\n * @template T - ReadonlyArray of Plugin\n * @returns Intersection of all state contributions\n *\n * @example\n * const plugins = [authPlugin, dbPlugin] as const;\n * type ComposedState = ComposePluginStates<typeof plugins>;\n * // Result: { config: AuthConfig } & { dbConnected: boolean }\n */\nexport type ComposePluginStates<T extends ReadonlyArray<Plugin<any, any>>> = T extends readonly []\n ? {}\n : UnionToIntersection<ExtractPluginState<T[number]>>;\n\n/**\n * Composes service contributions from an array of middleware\n * Merges all service types into a single intersection type\n *\n * @template T - ReadonlyArray of Middleware\n * @returns Intersection of all service contributions\n *\n * @example\n * const middlewares = [dbMiddleware, cacheMiddleware] as const;\n * type ComposedServices = ComposeServices<typeof middlewares>;\n * // Result: { db: Database } & { cache: Cache }\n */\nexport type ComposeMiddlewareServices<T extends ReadonlyArray<Middleware>> = T extends readonly []\n ? {}\n : UnionToIntersection<ExtractMiddlewareServices<T[number]>>;\n\n/**\n * Composes service contributions from an array of plugins\n * Merges all service types into a single intersection type\n *\n * @template T - ReadonlyArray of Plugin\n * @returns Intersection of all service contributions\n *\n * @example\n * const plugins = [dbPlugin, cachePlugin] as const;\n * type ComposedServices = ComposePluginServices<typeof plugins>;\n * // Result: { db: Database } & { cache: Cache }\n */\nexport type ComposePluginServices<T extends ReadonlyArray<Plugin<any, any>>> = T extends readonly []\n ? {}\n : UnionToIntersection<ExtractPluginServices<T[number]>>;\n\n/**\n * Helper type to check if a type is never\n * @internal\n */\ntype IsNever<T> = [T] extends [never] ? true : false;\n\n/**\n * Helper type to check if a type is any\n * @internal\n */\ntype IsAny<T> = 0 extends 1 & T ? true : false;\n\n/**\n * Safe version of ExtractState that handles edge cases\n * @template T - The middleware type to extract from\n * @returns The state type, handling never/any/unknown gracefully\n */\nexport type SafeExtractMiddlewareState<T> =\n IsNever<T> extends true\n ? {}\n : IsAny<T> extends true\n ? {}\n : T extends Middleware<infer S, any>\n ? unknown extends S\n ? {}\n : S\n : {};\n\n/**\n * Safe version of ExtractPluginState that handles edge cases\n * @template T - The plugin type to extract from\n * @returns The state type, handling never/any/unknown gracefully\n */\nexport type SafeExtractPluginState<T> =\n IsNever<T> extends true\n ? {}\n : IsAny<T> extends true\n ? {}\n : T extends Plugin<infer S, any>\n ? unknown extends S\n ? {}\n : S\n : {};\n\n/**\n * Safe version of ExtractServices that handles edge cases\n * @template T - The middleware type to extract from\n * @returns The services type, handling never/any/unknown gracefully\n */\nexport type SafeExtractMiddlewareServices<T> =\n IsNever<T> extends true\n ? {}\n : IsAny<T> extends true\n ? {}\n : T extends Middleware<any, infer S>\n ? unknown extends S\n ? {}\n : S\n : {};\n\n/**\n * Safe version of ExtractPluginServices that handles edge cases\n * @template T - The plugin type to extract from\n * @returns The services type, handling never/any/unknown gracefully\n */\nexport type SafeExtractPluginServices<T> =\n IsNever<T> extends true\n ? {}\n : IsAny<T> extends true\n ? {}\n : T extends Plugin<any, infer S>\n ? unknown extends S\n ? {}\n : S\n : {};\n\n/**\n * Composes state with better edge case handling\n * @template T - ReadonlyArray of Middleware\n * @returns Safely composed state types\n */\nexport type SafeComposeMiddlewareStates<T extends ReadonlyArray<Middleware>> = T extends readonly []\n ? {}\n : T extends readonly [infer First, ...infer Rest]\n ? First extends Middleware\n ? Rest extends ReadonlyArray<Middleware>\n ? SafeExtractMiddlewareState<First> & SafeComposeMiddlewareStates<Rest>\n : SafeExtractMiddlewareState<First>\n : {}\n : UnionToIntersection<SafeExtractMiddlewareState<T[number]>>;\n\n/**\n * Composes plugin state with better edge case handling\n * @template T - ReadonlyArray of Plugin\n * @returns Safely composed state types\n */\nexport type SafeComposePluginStates<T extends ReadonlyArray<Plugin<any, any>>> =\n T extends readonly []\n ? {}\n : T extends readonly [infer First, ...infer Rest]\n ? First extends Plugin<any, any>\n ? Rest extends ReadonlyArray<Plugin<any, any>>\n ? SafeExtractPluginState<First> & SafeComposePluginStates<Rest>\n : SafeExtractPluginState<First>\n : {}\n : UnionToIntersection<SafeExtractPluginState<T[number]>>;\n\n/**\n * Composes services with better edge case handling\n * @template T - ReadonlyArray of Middleware\n * @returns Safely composed service types\n */\nexport type SafeComposeMiddlewareServices<T extends ReadonlyArray<Middleware>> =\n T extends readonly []\n ? {}\n : T extends readonly [infer First, ...infer Rest]\n ? First extends Middleware\n ? Rest extends ReadonlyArray<Middleware>\n ? SafeExtractMiddlewareServices<First> & SafeComposeMiddlewareServices<Rest>\n : SafeExtractMiddlewareServices<First>\n : {}\n : UnionToIntersection<SafeExtractMiddlewareServices<T[number]>>;\n\n/**\n * Composes plugin services with better edge case handling\n * @template T - ReadonlyArray of Plugin\n * @returns Safely composed service types\n */\nexport type SafeComposePluginServices<T extends ReadonlyArray<Plugin<any, any>>> =\n T extends readonly []\n ? {}\n : T extends readonly [infer First, ...infer Rest]\n ? First extends Plugin<any, any>\n ? Rest extends ReadonlyArray<Plugin<any, any>>\n ? SafeExtractPluginServices<First> & SafeComposePluginServices<Rest>\n : SafeExtractPluginServices<First>\n : {}\n : UnionToIntersection<SafeExtractPluginServices<T[number]>>;\n\n/**\n * Utility to merge two state types\n * Handles conflicts by using the rightmost (latest) type\n *\n * @template A - First state type\n * @template B - Second state type\n * @returns Merged state with B taking precedence\n */\nexport type MergeStates<A, B> = Omit<A, keyof B> & B;\n\n/**\n * Utility to merge two service types\n * Handles conflicts by using the rightmost (latest) type\n *\n * @template A - First services type\n * @template B - Second services type\n * @returns Merged services with B taking precedence\n */\nexport type MergeServices<A, B> = Omit<A, keyof B> & B;\n\n/**\n * Extract both state and services from a middleware at once\n * @template T - The middleware type\n * @returns Object with state and services types\n */\nexport type ExtractMiddlewareTypes<T> = {\n state: ExtractMiddlewareState<T>;\n services: ExtractMiddlewareServices<T>;\n};\n\n/**\n * Extract both state and services from a plugin at once\n * @template T - The plugin type\n * @returns Object with state and services types\n */\nexport type ExtractPluginTypes<T> = {\n state: ExtractPluginState<T>;\n services: ExtractPluginServices<T>;\n};\n\n/**\n * Compose both state and services from middleware array at once\n * @template T - ReadonlyArray of Middleware\n * @returns Object with composed state and services\n */\nexport type ComposeMiddlewareTypes<T extends ReadonlyArray<Middleware>> = {\n state: ComposeMiddlewareStates<T>;\n services: ComposeMiddlewareServices<T>;\n};\n\n/**\n * Compose both state and services from plugin array at once\n * @template T - ReadonlyArray of Plugin\n * @returns Object with composed state and services\n */\nexport type ComposePluginTypes<T extends ReadonlyArray<Plugin<any, any>>> = {\n state: ComposePluginStates<T>;\n services: ComposePluginServices<T>;\n};\n\n/**\n * Type guard to check if a value is a Middleware\n * @param value - Value to check\n * @returns True if value is a Middleware\n */\nexport function isMiddleware(value: unknown): value is Middleware {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'name' in value &&\n 'execute' in value &&\n typeof (value as any).name === 'string' &&\n typeof (value as any).execute === 'function'\n );\n}\n\n/**\n * Type guard to check if a value is a Plugin\n * @param value - Value to check\n * @returns True if value is a Plugin\n */\nexport function isPlugin(value: unknown): value is Plugin {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'name' in value &&\n 'version' in value &&\n 'register' in value &&\n typeof (value as any).name === 'string' &&\n typeof (value as any).version === 'string' &&\n typeof (value as any).register === 'function'\n );\n}\n\n/**\n * Type helper for middleware arrays\n * Ensures proper readonly array typing for composition\n *\n * @example\n * const middlewares = asMiddlewareArray([auth, logger, cache]);\n * type State = ComposeStates<typeof middlewares>;\n */\nexport function asMiddlewareArray<T extends ReadonlyArray<Middleware>>(middlewares: T): T {\n return middlewares;\n}\n\n/**\n * Type helper for plugin arrays\n * Ensures proper readonly array typing for composition\n *\n * @example\n * const plugins = asPluginArray([dbPlugin, cachePlugin]);\n * type Services = ComposePluginServices<typeof plugins>;\n */\nexport function asPluginArray<T extends ReadonlyArray<Plugin<any, any>>>(plugins: T): T {\n return plugins;\n}\n\n/**\n * Create a typed middleware array with inferred types\n * Useful for getting proper const assertions\n *\n * @example\n * const middlewares = createMiddlewareArray(auth, logger, cache);\n * type State = ComposeStates<typeof middlewares>;\n */\nexport function createMiddlewareArray<T extends ReadonlyArray<Middleware>>(...middlewares: T): T {\n return middlewares;\n}\n\n/**\n * Create a typed plugin array with inferred types\n * Useful for getting proper const assertions\n *\n * @example\n * const plugins = createPluginArray(dbPlugin, cachePlugin);\n * type Services = ComposePluginServices<typeof plugins>;\n */\nexport function createPluginArray<T extends ReadonlyArray<Plugin<any, any>>>(...plugins: T): T {\n return plugins;\n}\n","/**\n * UnauthorizedError class for authentication failures\n *\n * This error is thrown when authentication is required or has failed.\n * It provides context about authentication requirements and failure reasons.\n */\n\nimport { ErrorType, BlaizeError } from '@blaize-types/errors';\n\nimport { getCorrelationId } from '../tracing/correlation';\n\nimport type { UnauthorizedErrorDetails } from '@blaize-types/errors';\n\n/**\n * Error thrown when authentication is required or has failed\n *\n * Automatically sets HTTP status to 401 and provides authentication context.\n *\n * @example Basic usage:\n * ```typescript\n * throw new UnauthorizedError('Authentication required');\n * ```\n *\n * @example With authentication details:\n * ```typescript\n * throw new UnauthorizedError('Token expired', {\n * reason: 'expired_token',\n * authScheme: 'Bearer',\n * loginUrl: '/auth/login'\n * });\n * ```\n */\nexport class UnauthorizedError extends BlaizeError<UnauthorizedErrorDetails> {\n /**\n * Creates a new UnauthorizedError instance\n *\n * @param title - Human-readable error message\n * @param details - Optional authentication context\n * @param correlationId - Optional correlation ID (uses current context if not provided)\n */\n constructor(\n title: string,\n details: UnauthorizedErrorDetails | undefined = undefined,\n correlationId: string | undefined = undefined\n ) {\n super(\n ErrorType.UNAUTHORIZED,\n title,\n 401, // HTTP 401 Unauthorized\n correlationId ?? getCorrelationId(),\n details\n );\n }\n}\n","/**\n * ConflictError class for resource conflicts\n *\n * This error is thrown when a resource conflict occurs, such as duplicate keys,\n * version mismatches, or concurrent modifications.\n */\n\nimport { BlaizeError, ErrorType } from '@blaize-types/errors';\n\nimport { getCorrelationId } from '../tracing/correlation';\n\nimport type { ConflictErrorDetails } from '@blaize-types/errors';\n\n/**\n * Error thrown when a resource conflict occurs\n *\n * Automatically sets HTTP status to 409 and provides conflict context.\n *\n * @example Basic usage:\n * ```typescript\n * throw new ConflictError('Email already exists');\n * ```\n *\n * @example With conflict details:\n * ```typescript\n * throw new ConflictError('Version conflict', {\n * conflictType: 'version_mismatch',\n * currentVersion: '2',\n * expectedVersion: '1',\n * resolution: 'Fetch the latest version and retry'\n * });\n * ```\n */\nexport class ConflictError extends BlaizeError<ConflictErrorDetails> {\n /**\n * Creates a new ConflictError instance\n *\n * @param title - Human-readable error message\n * @param details - Optional conflict context\n * @param correlationId - Optional correlation ID (uses current context if not provided)\n */\n constructor(\n title: string,\n details: ConflictErrorDetails | undefined = undefined,\n correlationId: string | undefined = undefined\n ) {\n super(\n ErrorType.CONFLICT,\n title,\n 409, // HTTP 409 Conflict\n correlationId ?? getCorrelationId(),\n details\n );\n }\n}\n","/**\n * RateLimitError class for rate limiting violations\n *\n * This error is thrown when rate limits are exceeded.\n * It provides context about the rate limit and when requests can resume.\n */\n\nimport { BlaizeError, ErrorType } from '@blaize-types/errors';\n\nimport { getCorrelationId } from '../tracing/correlation';\n\nimport type { RateLimitErrorDetails } from '@blaize-types/errors';\n\n/**\n * Error thrown when rate limits are exceeded\n *\n * Automatically sets HTTP status to 429 and provides rate limit context.\n *\n * @example Basic usage:\n * ```typescript\n * throw new RateLimitError('Too many requests');\n * ```\n *\n * @example With rate limit details:\n * ```typescript\n * throw new RateLimitError('Rate limit exceeded', {\n * limit: 100,\n * remaining: 0,\n * retryAfter: 3600,\n * window: 'hour',\n * identifier: 'user-123'\n * });\n * ```\n */\nexport class RateLimitError extends BlaizeError<RateLimitErrorDetails> {\n /**\n * Creates a new RateLimitError instance\n *\n * @param title - Human-readable error message\n * @param details - Optional rate limit context\n * @param correlationId - Optional correlation ID (uses current context if not provided)\n */\n constructor(\n title: string,\n details: RateLimitErrorDetails | undefined = undefined,\n correlationId: string | undefined = undefined\n ) {\n super(\n ErrorType.RATE_LIMITED,\n title,\n 429, // HTTP 429 Too Many Requests\n correlationId ?? getCorrelationId(),\n details\n );\n }\n}\n","import { BlaizeError, ErrorType } from '../../../blaize-types/src/errors';\nimport { getCorrelationId } from '../tracing/correlation';\n\nexport class RequestTimeoutError extends BlaizeError {\n constructor(title: string, details?: unknown, correlationId?: string) {\n super(\n ErrorType.UPLOAD_TIMEOUT,\n title,\n 408,\n correlationId ?? getCorrelationId(),\n details\n );\n }\n}\n","import { BlaizeError, ErrorType } from '../../../blaize-types/src/errors';\nimport { getCorrelationId } from '../tracing/correlation';\n\nexport class UnprocessableEntityError extends BlaizeError {\n constructor(title: string, details?: unknown, correlationId?: string) {\n super(\n ErrorType.UNPROCESSABLE_ENTITY,\n title,\n 422,\n correlationId ?? getCorrelationId(),\n details\n );\n }\n}\n","// ============================================\n// packages/blaize-core/src/errors/service-unavailable-error.ts\n// ============================================\n\nimport { BlaizeError, ErrorType } from '@blaize-types/errors';\n\nimport { getCorrelationId } from '../tracing/correlation';\n\nimport type { ServiceNotAvailableDetails } from '@blaize-types/errors';\n\n/**\n * Error thrown when a service is temporarily unavailable\n *\n * Automatically sets HTTP status to 503 and optionally includes Retry-After.\n *\n * @example Basic usage:\n * ```typescript\n * throw new ServiceNotAvailableError('Database unavailable');\n * ```\n *\n * @example With retry guidance:\n * ```typescript\n * throw new ServiceNotAvailableError('Payment service down', {\n * service: 'stripe',\n * retryAfter: 30,\n * reason: 'circuit_breaker'\n * });\n * ```\n */\nexport class ServiceNotAvailableError extends BlaizeError<ServiceNotAvailableDetails> {\n constructor(\n title: string,\n details: ServiceNotAvailableDetails | undefined = undefined,\n correlationId: string | undefined = undefined\n ) {\n super(ErrorType.SERVICE_UNAVAILABLE, title, 503, correlationId ?? getCorrelationId(), details);\n }\n}\n","/**\n * BlaizeJS Core\n *\n * A blazing-fast, type-safe Node.js framework with file-based routing,\n * powerful middleware, and end-to-end type safety.\n *\n * @package blaizejs\n */\n// Middleware System\nimport { compose } from './middleware/compose';\nimport { cors } from './middleware/cors';\nimport {\n create as createMiddleware,\n serviceMiddleware as createServiceMiddleware,\n stateMiddleware as createStateMiddleware,\n} from './middleware/create';\n// Plugin System\nimport { create as createPlugin } from './plugins/create';\n// Router System\nimport {\n createDeleteRoute,\n createGetRoute,\n createHeadRoute,\n createOptionsRoute,\n createPatchRoute,\n createPostRoute,\n createPutRoute,\n createRouteFactory,\n} from './router/create';\nimport { createMatcher } from './router/matching/matcher';\nimport {\n extractParams,\n compilePathPattern,\n paramsToQuery,\n buildUrl,\n} from './router/matching/params';\n// Server\nimport { create as createServer } from './server/create';\nimport { inferContext, type InferContext } from './server/types';\n// Tracing\nimport { getCorrelationId } from './tracing/correlation';\n\n// TODO: ideally this could be import as an npm package, but for now we use a relative path\n// Explicit imports to avoid using values without importing\nexport * from '../../blaize-types/src/index';\n\n// Re-export everything\n\nexport {\n // Server module exports\n createServer,\n inferContext,\n type InferContext,\n\n // Router module exports\n createDeleteRoute,\n createGetRoute,\n createHeadRoute,\n createOptionsRoute,\n createPatchRoute,\n createPostRoute,\n createPutRoute,\n createRouteFactory,\n createMatcher,\n extractParams,\n compilePathPattern,\n paramsToQuery,\n buildUrl,\n\n // Middleware module exports\n createMiddleware,\n createServiceMiddleware,\n createStateMiddleware,\n compose,\n cors,\n\n // Plugins module exports\n createPlugin,\n\n // Tracing module exports\n getCorrelationId,\n};\n\n// Version information\nexport const VERSION = '0.1.0';\n\n// Namespaced exports with different names to avoid conflicts\nexport const ServerAPI = { createServer, inferContext };\nexport const RouterAPI = {\n createDeleteRoute,\n createGetRoute,\n createHeadRoute,\n createOptionsRoute,\n createPatchRoute,\n createPostRoute,\n createPutRoute,\n createRouteFactory,\n createMatcher,\n extractParams,\n compilePathPattern,\n paramsToQuery,\n buildUrl,\n};\nexport const MiddlewareAPI = {\n createMiddleware,\n createServiceMiddleware,\n createStateMiddleware,\n compose,\n cors,\n};\nexport const PluginsAPI = { createPlugin };\n\n// Server-side error classes\nexport { ValidationError } from './errors/validation-error';\nexport { NotFoundError } from './errors/not-found-error';\nexport { UnauthorizedError } from './errors/unauthorized-error';\nexport { ForbiddenError } from './errors/forbidden-error';\nexport { ConflictError } from './errors/conflict-error';\nexport { RateLimitError } from './errors/rate-limit-error';\nexport { InternalServerError } from './errors/internal-server-error';\nexport { PayloadTooLargeError } from './errors/payload-too-large-error';\nexport { RequestTimeoutError } from './errors/request-timeout-error';\nexport { UnprocessableEntityError } from './errors/unprocessable-entity-error';\nexport { UnsupportedMediaTypeError } from './errors/unsupported-media-type-error';\nexport { ServiceNotAvailableError } from './errors/service-not-available-error';\n\n// Default export\nconst Blaize = {\n // Core functions\n createServer,\n createMiddleware,\n createServiceMiddleware,\n createStateMiddleware,\n createPlugin,\n getCorrelationId,\n\n // Namespaces (using the non-conflicting names)\n Server: ServerAPI,\n Router: RouterAPI,\n Middleware: MiddlewareAPI,\n Plugins: PluginsAPI,\n\n // Constants\n VERSION,\n};\n\nexport { Blaize };\n"],"mappings":"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","names":["execute","middleware","ctx","next","result","error","compose","middlewareStack","_","next","ctx","finalHandler","called","dispatch","middleware","execute","ForbiddenError","BlaizeError","title","details","correlationId","getCorrelationId","create","handlerOrOptions","name","handler","skip","debug","stateMiddleware","serviceMiddleware","DEVELOPMENT_DEFAULTS","PRODUCTION_DEFAULTS","getDefaultCorsOptions","isDevelopment","createOriginCache","ttl","maxSize","cache","config","getCacheKey","origin","configOriginId","userId","evictLRU","lruKey","lruTime","key","entry","now","allowed","cleaned","defaultCache","isCacheable","configuredOrigin","origin","getConfigOriginId","o","validateStringOrigin","requestOrigin","validateRegExpOrigin","validateFunctionOrigin","ctx","timeoutMs","timeoutId","timeoutPromise","resolve","result","r","error","validateArrayOrigin","configuredOrigins","validations","validateSingleOrigin","validateOrigin","userId","configOriginId","cached","defaultCache","allowed","parsePreflightRequest","ctx","origin","requestedMethod","requestedHeadersRaw","requestedHeaders","h","normalizeMethod","method","isMethodAllowed","allowedMethods","m","areHeadersAllowed","allowedHeaders","allowedArray","header","setPreflightHeaders","options","originAllowed","methods","methodsString","headers","handlePreflight","preflight","ValidationError","validateOrigin","rejectedHeaders","allowed","successStatus","isPreflightRequest","z","corsHttpMethodSchema","corsMethodsSchema","val","m","corsHeadersSchema","h","corsOriginFunctionSchema","data","singleOriginSchema","corsOriginSchema","corsOptionsSchema","serverCorsSchema","validateCorsOptions","options","error","formattedErrors","formatCorsValidationErrors","err","isOriginArray","origin","validateOriginSecurity","options","o","mergeCorsOptions","userOptions","defaults","setCorsHeaders","ctx","options","origin","originAllowed","headers","cors","userOptions","isDevelopment","defaults","getDefaultCorsOptions","mergeCorsOptions","validatedOptions","validateCorsOptions","validateOriginSecurity","create","next","isPreflightRequest","handlePreflight","validateOrigin","ForbiddenError","create","name","version","setup","defaultOptions","userOptions","mergedOptions","plugin","app","result","fileURLToPath","config","setRuntimeConfig","newConfig","getRoutesDir","config","path","parseRoutePath","filePath","basePath","forwardSlashFilePath","forwardSlashBasePath","normalizedBasePath","relativePath","segments","params","routeSegments","segment","paramName","routePath","EventEmitter","z","BufferStrategySchema","WatermarkConfigSchema","data","SizeLimitsSchema","BackpressureConfigSchema","DEFAULT_CONFIG","createConnectionRegistry","config","settings","connections","clientConnectionCounts","cleanupTimer","registry","startCleanupTimer","cleanupFn","stopCleanupTimer","updateClientCount","clientIp","delta","newCount","add","id","stream","metadata","now","remove","entry","count","cleanup","idsToRemove","isInactive","isClosed","get","has","getIds","shutdown","registryInstance","getConnectionRegistry","SSEBufferOverflowError","BlaizeError","title","details","correlationId","getCorrelationId","SSEStreamClosedError","BlaizeError","title","details","correlationId","getCorrelationId","DEFAULT_OPTIONS","formatSSEEvent","event","data","id","retry","lines","dataLines","line","createEventId","timestamp","random","estimateEventSize","dataStr","applyBufferStrategy","buffer","strategy","newEvent","maxSize","dropped","SSEStreamImpl","EventEmitter","ctx","options","result","BackpressureConfigSchema","lastEventId","registry","getConnectionRegistry","metadata","error","interval","req","res","handleDisconnect","written","formatted","resolve","cb","err","callbacks","SSEStreamClosedError","eventId","correlationId","getCorrelationId","size","maxEventSize","SSEBufferOverflowError","bufferedEvent","maxBuffer","currentSize","errorData","sendError","closeEvent","comment","message","milliseconds","checkBuffer","createSSEStream","SSENotAcceptableError","BlaizeError","message","details","correlationId","getCorrelationId","validateSSEConfig","config","params","query","events","eventName","eventSchema","createTypedStream","stream","eventSchemas","typedStream","originalSend","event","data","schema","validated","error","createSSERoute","path","getRoutePath","ctx","accept","SSENotAcceptableError","validationError","baseStream","createSSEStream","getCallerFilePath","originalPrepareStackTrace","_","stack","callerFrame","fileName","fileURLToPath","getRoutePath","callerPath","routesDir","getRoutesDir","parsedRoute","parseRoutePath","createGetRoute","config","validateMethodConfig","path","createPostRoute","createPutRoute","createDeleteRoute","createPatchRoute","createHeadRoute","createOptionsRoute","method","validateSchema","schema","params","query","body","response","createRouteFactory","createSSERoute","extractParams","path","pattern","paramNames","match","params","compilePathPattern","patternString","_","paramName","paramsToQuery","parts","key","value","encodedKey","encodedValue","buildUrl","pathPattern","query","pathParams","queryParams","url","queryString","createMatcher","routes","path","method","routeOptions","pattern","paramNames","compilePathPattern","newRoute","insertIndex","route","i","pathname","params","extractParams","AsyncLocalStorage","EventEmitter","fs","http","http2","fs","path","selfsigned","generateDevCertificates","certDir","keyPath","certPath","pems","ResponseSentError","message","ResponseSentHeaderError","ResponseSentContentError","ParseUrlError","AsyncLocalStorage","contextStorage","runWithContext","context","callback","contextStorage","crypto","createWriteStream","tmpdir","join","Readable","BOUNDARY_REGEX","CONTENT_DISPOSITION_REGEX","CONTENT_TYPE_REGEX","MULTIPART_REGEX","extractBoundary","contentType","match","boundary","parseContentDisposition","headers","parseContentType","isMultipartContent","DEFAULT_OPTIONS","tmpdir","createParserState","boundary","options","processChunk","state","chunk","newBuffer","currentState","nextState","processCurrentStage","processBoundary","processHeaders","processContent","InternalServerError","boundaryIndex","hasFoundValidBoundary","buffer","headerEnd","headers","disposition","parseContentDisposition","ValidationError","mimetype","parseContentType","isFile","PayloadTooLargeError","UnsupportedMediaTypeError","nextBoundaryIndex","contentChunk","isComplete","safeLength","contentEnd","updatedState","processContentChunk","finalizeCurrentPart","newContentLength","maxSize","payloadErrorDetals","processFileChunk","writeToStream","initializeFileProcessing","streamController","stream","controller","tempPath","join","writeStream","createWriteStream","cleanupTask","unlink","error","finalizeFile","finalizeField","resetCurrentPart","Readable","closeStream","file","updatedFiles","addToCollection","value","updatedFields","collection","key","newCollection","existing","finalize","fields","values","files","fileList","cleanup","task","resolve","reject","parseMultipartRequest","request","contentType","extractBoundary","CONTENT_TYPE_HEADER","parseRequestUrl","req","originalUrl","host","fullUrl","url","path","query","value","key","error","ParseUrlError","isHttp2Request","getProtocol","encrypted","forwardedProto","createContext","res","options","method","isHttp2","protocol","params","state","services","responseState","ctx","createRequestObject","createResponseObject","parseBodyIfNeeded","info","createRequestHeaderGetter","createRequestHeadersGetter","name","headerGetter","names","acc","addCorrelationHeader","headerName","getCorrelationHeaderName","correlationValue","createStatusSetter","createHeaderSetter","createHeadersSetter","createContentTypeSetter","createJsonResponder","createTextResponder","createHtmlResponder","createRedirectResponder","createStreamResponder","code","ResponseSentError","ResponseSentHeaderError","headers","type","ResponseSentContentError","body","status","readable","err","shouldSkipParsing","contentType","contentLength","limits","PayloadTooLargeError","getCorrelationId","parseJsonBody","parseFormUrlEncodedBody","parseTextBody","isMultipartContent","parseMultipartBody","readRequestBody","json","ValidationError","parseUrlEncodedData","formData","multipartLimits","multipartData","parseMultipartRequest","UnsupportedMediaTypeError","resolve","reject","chunks","chunk","NotFoundError","BlaizeError","title","details","correlationId","getCorrelationId","isHandledError","error","BlaizeError","formatErrorResponse","correlationId","getCorrelationId","originalMessage","wrappedError","InternalServerError","extractOrGenerateCorrelationId","headerGetter","headerName","getCorrelationHeaderName","headers","createCorrelationIdFromHeaders","setErrorResponseHeaders","headerSetter","createErrorBoundary","options","debug","ctx","next","error","correlationId","extractOrGenerateCorrelationId","errorResponse","formatErrorResponse","setErrorResponseHeaders","createRequestHandler","serverInstance","req","res","correlationId","createCorrelationIdFromHeaders","withCorrelationId","context","createContext","middlewareChain","createErrorBoundary","cors","handler","compose","runWithContext","NotFoundError","error","headerName","getCorrelationHeaderName","prepareCertificates","http2Options","keyFile","certFile","isDevMode","certificatesMissing","generateDevCertificates","createServerInstance","isHttp2","certOptions","http2ServerOptions","err","listenOnPort","server","port","host","resolve","reject","url","initializePlugins","serverInstance","plugin","startServer","serverOptions","requestHandler","createRequestHandler","error","isShuttingDown","stopServer","serverInstance","options","server","events","timeout","_","reject","error","closePromise","resolve","err","timeoutPromise","registerSignalHandlers","stopFn","sigintHandler","sigtermHandler","z","middlewareSchema","z","data","pluginSchema","http2Schema","correlationSchema","multipartLimitsSchema","bodyLimitsSchema","serverOptionsSchema","serverCorsSchema","validateServerOptions","options","error","formattedError","createPluginLifecycleManager","options","continueOnError","debug","onError","log","message","args","handleError","plugin","phase","error","errorMessage","server","pluginsToTerminate","httpServer","pluginsToNotify","PluginValidationError","pluginName","message","RESERVED_NAMES","VALID_NAME_PATTERN","VALID_VERSION_PATTERN","validatePlugin","plugin","options","requireVersion","validateNameFormat","checkReservedNames","PluginValidationError","p","lifecycleMethods","method","crypto","fs","dynamicImport","filePath","cacheBuster","importPath","module","error","errorMessage","loadRouteModule","basePath","parsedRoute","parseRoutePath","routes","route","exportName","exportValue","potentialRoute","isValidRoute","obj","method","fileRouteCache","processChangedFile","filePath","routesDir","updateCache","lastModified","cachedEntry","routes","loadRouteModule","hash","hashRoutes","hasRouteContentChanged","newRoutes","newHash","clearFileCache","routeData","route","key","method","methodDef","handlerString","dataString","os","fs","path","findRouteFiles","routesDir","options","absoluteDir","error","routeFiles","ignore","scanDirectory","dir","entries","entry","fullPath","isRouteFile","filename","processFilesInParallel","filePaths","processor","concurrency","chunks","chunkArray","results","chunk","successfulResults","filePath","result","loadInitialRoutesParallel","routesDir","files","findRouteFiles","processChangedFile","array","chunkSize","i","profilerState","trackReloadPerformance","filePath","startTime","duration","emoji","withPerformanceTracking","fn","filePath","args","startTime","result","trackReloadPerformance","error","path","watch","watchRoutes","routesDir","options","debounceMs","debouncedCallbacks","createDebouncedCallback","fn","filePath","args","existingTimeout","timeoutId","routesByPath","loadAndNotify","existingRoutes","newRoutes","processChangedFile","hasRouteContentChanged","normalizedPath","error","handleError","handleRemoved","routes","watcher","watch","timeout","allRoutes","z","z","validateBody","body","schema","z","validateParams","params","schema","z","validateQuery","query","schema","z","validateResponse","response","schema","createRequestValidator","schema","debug","ctx","next","validateParams","error","fieldErrors","extractZodFieldErrors","errorCount","sum","fe","ValidationError","validateQuery","validateBody","isErrorResponse","body","createResponseValidator","responseSchema","originalJson","validatorActive","status","validatedBody","validateResponse","InternalServerError","z","fieldErrorMap","issue","fieldPath","field","messages","executeHandler","ctx","routeOptions","params","middleware","createRequestValidator","createResponseValidator","compose","result","createRouteRegistry","updateRoutesFromFile","registry","filePath","newRoutes","oldPaths","newPaths","r","added","removed","p","changed","route","existingRoute","routesEqual","applyRouteUpdates","getAllRoutesFromRegistry","registry","applyRouteUpdates","registry","filePath","updates","added","removed","changed","path","route","allPathsForFile","r","p","routesEqual","route1","route2","methods1","k","methods2","method","handler1","handler2","addRouteToMatcher","route","matcher","method","methodOptions","removeRouteFromMatcher","path","updateRouteInMatcher","DEFAULT_ROUTER_OPTIONS","createRouter","options","routerOptions","registry","createRouteRegistry","matcher","createMatcher","initialized","initializationPromise","_watchers","routeDirectories","applyMatcherChanges","changes","routePath","removeRouteFromMatcher","route","methods","key","addRouteToMatcher","updateRouteInMatcher","addRoutesWithSource","routes","source","updateRoutesFromFile","error","loadRoutesFromDirectory","directory","prefix","discoveredRoutes","loadInitialRoutesParallel","finalRoutes","initialize","setupOptimizedWatching","watcher","watchRoutes","filepath","addedRoutes","withPerformanceTracking","changedRoutes","filePath","removedRoutes","clearFileCache","setupWatcherForNewDirectory","finalPath","ctx","method","path","match","NotFoundError","executeHandler","getAllRoutesFromRegistry","DEFAULT_OPTIONS","createServerOptions","options","mergedOptions","validated","validateServerOptions","setRuntimeConfig","error","configureCorrelation","_setCorrelationConfig","createListenMethod","serverInstance","validatedOptions","initializePlugins","startServer","setupServerLifecycle","p","signalHandlers","registerSignalHandlers","createCloseMethod","stopOptions","stopServer","createUseMethod","middleware","middlewareArray","createRegisterMethod","plugin","validatePlugin","create","port","host","plugins","cors","bodyLimits","initialMiddleware","initialPlugins","contextStorage","AsyncLocalStorage","router","createRouter","pluginManager","createPluginLifecycleManager","events","EventEmitter","inferContext","_server","isMiddleware","value","isPlugin","asMiddlewareArray","middlewares","asPluginArray","plugins","createMiddlewareArray","createPluginArray","UnauthorizedError","BlaizeError","title","details","correlationId","getCorrelationId","ConflictError","BlaizeError","title","details","correlationId","getCorrelationId","RateLimitError","BlaizeError","title","details","correlationId","getCorrelationId","RequestTimeoutError","BlaizeError","title","details","correlationId","getCorrelationId","UnprocessableEntityError","BlaizeError","title","details","correlationId","getCorrelationId","ServiceNotAvailableError","BlaizeError","title","details","correlationId","getCorrelationId","VERSION","ServerAPI","create","inferContext","RouterAPI","createDeleteRoute","createGetRoute","createHeadRoute","createOptionsRoute","createPatchRoute","createPostRoute","createPutRoute","createRouteFactory","createMatcher","extractParams","compilePathPattern","paramsToQuery","buildUrl","MiddlewareAPI","serviceMiddleware","stateMiddleware","compose","cors","PluginsAPI","Blaize","getCorrelationId"]}
1
+ {"version":3,"sources":["../src/logger/transports/console.ts","../src/logger/utils.ts","../src/logger/transports/json.ts","../src/logger/logger.ts","../src/logger/transports/null.ts","../src/logger/index.ts","../src/middleware/execute.ts","../src/middleware/compose.ts","../src/errors/forbidden-error.ts","../src/middleware/create.ts","../src/middleware/cors/defaults.ts","../src/middleware/cors/origin-validator.ts","../src/middleware/cors/preflight.ts","../src/middleware/cors/validation.ts","../src/middleware/cors/index.ts","../src/middleware/logger/request-logger.ts","../src/plugins/create.ts","../src/router/create.ts","../src/config.ts","../src/router/discovery/parser.ts","../src/sse/stream.ts","../src/sse/back-pressure.ts","../src/sse/connection-registry.ts","../src/errors/sse-buffer-overflow-error.ts","../src/errors/sse-stream-closed-error.ts","../src/errors/sse-not-acceptable-error.ts","../src/sse/create.ts","../src/router/matching/params.ts","../src/router/matching/matcher.ts","../src/server/create.ts","../src/server/start.ts","../src/server/dev-certificate.ts","../src/context/errors.ts","../src/context/store.ts","../src/upload/multipart-parser.ts","../src/upload/utils.ts","../src/context/create.ts","../src/errors/not-found-error.ts","../src/errors/boundary.ts","../src/middleware/error-boundary/create.ts","../src/server/request-handler.ts","../src/server/stop.ts","../src/server/validation.ts","../src/plugins/lifecycle.ts","../src/plugins/errors.ts","../src/plugins/validation.ts","../src/router/discovery/cache.ts","../src/router/discovery/loader.ts","../src/router/discovery/parallel.ts","../src/router/discovery/finder.ts","../src/router/discovery/profiler.ts","../src/router/discovery/watchers.ts","../src/router/validation/schema.ts","../src/router/validation/body.ts","../src/router/validation/params.ts","../src/router/validation/query.ts","../src/router/validation/response.ts","../src/router/handlers/executor.ts","../src/router/registry/fast-registry.ts","../src/router/utils/matching-helpers.ts","../src/router/router.ts","../src/server/types.ts","../../blaize-types/src/composition.ts","../src/errors/unauthorized-error.ts","../src/errors/conflict-error.ts","../src/errors/rate-limit-error.ts","../src/errors/request-timeout-error.ts","../src/errors/unprocessable-entity-error.ts","../src/errors/service-not-available-error.ts","../src/index.ts"],"sourcesContent":["/**\n * Console Transport for Development\n *\n * Pretty-prints logs with colors for human-readable development output.\n * Uses Node.js built-in util.inspect for metadata formatting.\n *\n * @packageDocumentation\n */\n\nimport { inspect } from 'node:util';\n\nimport { serializeMetadata } from '../utils';\n\nimport type { BlaizeLogTransport, LogLevel, LogMetadata } from '@blaize-types/logger';\n\n/**\n * ANSI color codes for log levels\n */\nconst LEVEL_COLORS: Record<LogLevel, string> = {\n debug: '\\x1b[36m', // Cyan\n info: '\\x1b[32m', // Green\n warn: '\\x1b[33m', // Yellow\n error: '\\x1b[31m', // Red\n};\n\nconst RESET = '\\x1b[0m';\nconst BOLD = '\\x1b[1m';\n\n/**\n * Console transport for development logging\n *\n * Outputs colorized, human-readable logs to the console.\n * Uses console.log/warn/error appropriately based on log level.\n *\n * Features:\n * - Colorized log levels (debug=gray, info=blue, warn=yellow, error=red)\n * - Pretty-printed metadata with util.inspect\n * - Error objects automatically serialized with stack traces\n * - Stateless - safe for concurrent logging\n *\n * @example\n * ```typescript\n * import { ConsoleTransport } from './transports';\n *\n * const transport = new ConsoleTransport();\n *\n * transport.write('info', 'User login', {\n * userId: '123',\n * method: 'oauth',\n * timestamp: '2025-10-20T15:30:00Z'\n * });\n *\n * // Output:\n * // [INFO] User login\n * // {\n * // userId: '123',\n * // method: 'oauth',\n * // timestamp: '2025-10-20T15:30:00Z'\n * // }\n * ```\n */\nexport class ConsoleTransport implements BlaizeLogTransport {\n /**\n * Write a log entry to the console\n *\n * @param level - Log level\n * @param message - Log message\n * @param meta - Structured metadata\n */\n write(level: LogLevel, message: string, meta: LogMetadata): void {\n // Serialize errors in metadata\n const serializedMeta = serializeMetadata(meta);\n\n // Format level with color\n const levelColor = LEVEL_COLORS[level];\n const levelText = `${levelColor}${BOLD}[${level.toUpperCase()}]${RESET}`;\n\n // Format message\n const formattedMessage = `${levelText} ${message}`;\n\n // Pretty-print metadata if present\n const hasMetadata = Object.keys(serializedMeta).length > 0;\n const metadataText = hasMetadata\n ? `\\n\n ${inspect(serializedMeta, {\n colors: true,\n depth: 3,\n compact: false,\n breakLength: 80,\n })}`\n : '';\n\n // Use appropriate console method based on level\n switch (level) {\n case 'error':\n console.error(formattedMessage + metadataText);\n break;\n case 'warn':\n console.warn(formattedMessage + metadataText);\n break;\n case 'debug':\n case 'info':\n default:\n console.log(formattedMessage + metadataText);\n break;\n }\n }\n}\n","/**\n * Transport utility functions\n *\n * Shared utilities for error serialization and metadata processing.\n *\n * @internal\n */\n\nimport type { LogMetadata, SerializedError } from '@blaize-types/logger';\n\n/**\n * Check if a value is an Error object\n *\n * @param value - Value to check\n * @returns true if value is an Error\n */\nfunction isError(value: unknown): value is Error {\n return value instanceof Error;\n}\n\n/**\n * Serialize an Error object to a plain object\n *\n * Extracts message, name, and stack trace for logging.\n *\n * @param error - Error object to serialize\n * @returns Serialized error object\n */\nfunction serializeError(error: Error): SerializedError {\n return {\n message: error.message,\n name: error.name,\n stack: error.stack,\n };\n}\n\n/**\n * Serialize metadata, handling Error objects and circular references\n *\n * Recursively processes metadata to convert Error objects to plain objects\n * with message, name, and stack properties. Dates and other primitives pass through.\n *\n * @param meta - Metadata to serialize\n * @returns Serialized metadata safe for JSON.stringify\n */\nexport function serializeMetadata(meta: LogMetadata): LogMetadata {\n const serialized: LogMetadata = {};\n\n for (const [key, value] of Object.entries(meta)) {\n if (isError(value)) {\n // Serialize Error objects\n serialized[key] = serializeError(value);\n } else if (Array.isArray(value)) {\n // Handle arrays (may contain errors)\n serialized[key] = value.map(item => (isError(item) ? serializeError(item) : item));\n } else if (value instanceof Date) {\n // Dates pass through - JSON.stringify will convert to ISO string\n serialized[key] = value;\n } else if (value && typeof value === 'object') {\n // Handle nested objects (shallow check only for errors)\n // Deep recursion avoided to keep performance predictable\n const nested: Record<string, unknown> = {};\n for (const [nestedKey, nestedValue] of Object.entries(value as Record<string, unknown>)) {\n if (isError(nestedValue)) {\n nested[nestedKey] = serializeError(nestedValue);\n } else {\n // Let other values (including nested Dates) pass through\n nested[nestedKey] = nestedValue;\n }\n }\n serialized[key] = nested;\n } else {\n // Primitive values pass through\n serialized[key] = value;\n }\n }\n\n return serialized;\n}\n\n/**\n * JSON replacer function to handle circular references\n *\n * Replaces circular references with '[Circular]' marker.\n *\n * @returns Replacer function for JSON.stringify\n */\nexport function createCircularReplacer() {\n const seen = new WeakSet();\n\n return (_key: string, value: unknown) => {\n if (typeof value === 'object' && value !== null) {\n if (seen.has(value)) {\n return '[Circular]';\n }\n seen.add(value);\n }\n return value;\n };\n}\n","/**\n * JSON Transport for Production\n *\n * Outputs single-line JSON logs for log aggregators and monitoring systems.\n * Handles circular references and serializes Error objects.\n *\n * @packageDocumentation\n */\n\nimport { serializeMetadata, createCircularReplacer } from '../utils';\n\nimport type { BlaizeLogTransport, LogLevel, LogMetadata } from '@blaize-types/logger';\n\n/**\n * JSON log entry structure\n */\ninterface JSONLogEntry {\n level: LogLevel;\n message: string;\n [key: string]: unknown;\n}\n\n/**\n * JSON transport for production logging\n *\n * Outputs single-line JSON to stdout for log aggregators (CloudWatch,\n * Datadog, Splunk, etc.). Handles circular references safely and\n * serializes Error objects with stack traces.\n *\n * Features:\n * - Single-line JSON output (no pretty-printing)\n * - Circular reference handling via replacer function\n * - Error objects serialized with message, name, and stack\n * - Stateless - safe for concurrent logging\n * - All metadata flattened into top-level JSON object\n *\n * @example\n * ```typescript\n * import { JSONTransport } from './transports';\n *\n * const transport = new JSONTransport();\n *\n * transport.write('info', 'User login', {\n * userId: '123',\n * method: 'oauth',\n * timestamp: '2025-10-20T15:30:00Z',\n * correlationId: 'req_abc123'\n * });\n *\n * // Output (single line):\n * // {\"level\":\"info\",\"message\":\"User login\",\"userId\":\"123\",\"method\":\"oauth\",\"timestamp\":\"2025-10-20T15:30:00Z\",\"correlationId\":\"req_abc123\"}\n * ```\n *\n * @example With Error Object\n * ```typescript\n * const error = new Error('Database connection failed');\n *\n * transport.write('error', 'Operation failed', {\n * error,\n * retryCount: 3\n * });\n *\n * // Output:\n * // {\"level\":\"error\",\"message\":\"Operation failed\",\"error\":{\"message\":\"Database connection failed\",\"name\":\"Error\",\"stack\":\"Error: Database...\"},\"retryCount\":3}\n * ```\n */\nexport class JSONTransport implements BlaizeLogTransport {\n /**\n * Write a log entry as single-line JSON to stdout\n *\n * @param level - Log level\n * @param message - Log message\n * @param meta - Structured metadata\n */\n write(level: LogLevel, message: string, meta: LogMetadata): void {\n // Serialize errors in metadata\n const serializedMeta = serializeMetadata(meta);\n\n // Create log entry with flattened structure\n // Level and message are top-level fields, metadata is spread\n const logEntry: JSONLogEntry = {\n level,\n message,\n ...serializedMeta,\n };\n\n // Stringify with circular reference handling\n // No indentation - single line for log aggregators\n const json = JSON.stringify(logEntry, createCircularReplacer());\n\n // Write to stdout (console.log adds newline automatically)\n console.log(json);\n }\n\n /**\n * Flush any buffered logs (optional)\n *\n * Currently a no-op since we write directly to stdout.\n * Can be implemented for batching in the future if needed.\n *\n * @returns Promise that resolves immediately\n */\n async flush(): Promise<void> {\n // No buffering currently, so nothing to flush\n // This method exists to satisfy the ILogTransport interface\n // and allow for future batching implementations\n return Promise.resolve();\n }\n}\n","/**\n * Core Logger Implementation\n *\n * Production-ready structured logger with level filtering, metadata redaction,\n * child loggers, and zero-overhead filtering for disabled log levels.\n *\n * @packageDocumentation\n */\n\nimport { ConsoleTransport } from './transports/console';\nimport { JSONTransport } from './transports/json';\n\nimport type {\n BlaizeLogger,\n BlaizeLogTransport,\n LogLevel,\n LogMetadata,\n ResolvedLoggerConfig,\n} from '@blaize-types/logger';\n\n/**\n * Log level priority values for filtering\n * Higher number = higher priority\n */\nconst LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\n/**\n * Core Logger class implementing ILogger interface\n *\n * Thread-safe via immutable inherited metadata. Supports zero-overhead\n * filtering - logs below the configured level return immediately with\n * no processing overhead.\n *\n * @example Basic Usage\n * ```typescript\n * const logger = new Logger({\n * level: 'info',\n * transport: new ConsoleTransport(),\n * redactKeys: ['password', 'apiKey'],\n * includeTimestamp: true\n * });\n *\n * logger.info('User login', { userId: '123', method: 'oauth' });\n * ```\n *\n * @example Child Logger\n * ```typescript\n * const parentLogger = createLogger({ level: 'info' });\n * const childLogger = parentLogger.child({ component: 'auth' });\n *\n * childLogger.info('Token verified');\n * // Output includes inherited metadata: { component: 'auth', ... }\n * ```\n */\nexport class Logger implements BlaizeLogger {\n private readonly config: ResolvedLoggerConfig;\n private readonly inheritedMeta: Readonly<LogMetadata>;\n private readonly minLevelPriority: number;\n\n /**\n * Create a new Logger instance\n *\n * @param config - Resolved logger configuration\n * @param inheritedMeta - Metadata inherited from parent logger (optional)\n */\n constructor(config: ResolvedLoggerConfig, inheritedMeta?: LogMetadata) {\n this.config = config;\n\n // Freeze inherited metadata for immutability (thread-safety)\n this.inheritedMeta = inheritedMeta ? Object.freeze({ ...inheritedMeta }) : Object.freeze({});\n\n // Cache min level priority for fast filtering\n this.minLevelPriority = LOG_LEVEL_PRIORITY[config.level];\n }\n\n /**\n * Log a debug message\n *\n * @param message - The log message\n * @param meta - Optional metadata to attach\n */\n debug(message: string, meta?: LogMetadata): void {\n this.log('debug', message, meta);\n }\n\n /**\n * Log an info message\n *\n * @param message - The log message\n * @param meta - Optional metadata to attach\n */\n info(message: string, meta?: LogMetadata): void {\n this.log('info', message, meta);\n }\n\n /**\n * Log a warning message\n *\n * @param message - The log message\n * @param meta - Optional metadata to attach\n */\n warn(message: string, meta?: LogMetadata): void {\n this.log('warn', message, meta);\n }\n\n /**\n * Log an error message\n *\n * @param message - The log message\n * @param meta - Optional metadata to attach\n */\n error(message: string, meta?: LogMetadata): void {\n this.log('error', message, meta);\n }\n\n /**\n * Create a child logger with additional metadata\n *\n * Child loggers inherit all parent metadata and add their own.\n * Child metadata overrides parent metadata for the same keys.\n *\n * @param meta - Additional metadata for the child logger\n * @returns A new logger instance with merged metadata\n *\n * @example\n * ```typescript\n * const parent = createLogger({ level: 'info' });\n * const child = parent.child({ component: 'database' });\n *\n * child.info('Query executed');\n * // Output includes: { component: 'database', ...parent metadata }\n * ```\n */\n child(meta: LogMetadata): BlaizeLogger {\n // Merge parent and child metadata (child overrides parent)\n const mergedMeta: LogMetadata = {\n ...this.inheritedMeta,\n ...meta,\n };\n\n // Create new logger instance with merged metadata\n return new Logger(this.config, mergedMeta);\n }\n\n /**\n * Flush any buffered logs and wait for completion\n *\n * Delegates to the transport's flush method if it exists.\n * Use this during graceful shutdown to ensure all logs are written.\n *\n * @returns Promise that resolves when all logs are flushed\n *\n * @example\n * ```typescript\n * process.on('SIGTERM', async () => {\n * await logger.flush();\n * process.exit(0);\n * });\n * ```\n */\n async flush(): Promise<void> {\n await this.config.transport.flush?.();\n }\n\n /**\n * Internal log method that handles all log levels\n *\n * Fast-path: Returns immediately if log level is filtered.\n * This ensures zero overhead for disabled log levels.\n *\n * @param level - The log level\n * @param message - The log message\n * @param meta - Optional metadata to attach\n */\n private log(level: LogLevel, message: string, meta?: LogMetadata): void {\n // Fast-path: Check level filter first (zero overhead for filtered logs)\n if (!this.shouldLog(level)) {\n return;\n }\n\n // Merge inherited metadata with call-site metadata\n // Call-site metadata overrides inherited metadata\n const mergedMeta: LogMetadata = {\n ...this.inheritedMeta,\n ...(meta || {}),\n };\n\n // Add timestamp if configured\n let finalMeta = mergedMeta;\n if (this.config.includeTimestamp) {\n finalMeta = {\n timestamp: new Date().toISOString(),\n ...mergedMeta,\n };\n }\n\n // Redact sensitive keys\n const redactedMeta = this.redact(finalMeta);\n\n // Write to transport (synchronous, non-blocking)\n this.config.transport.write(level, message, redactedMeta);\n }\n\n /**\n * Check if a log level should be output\n *\n * @param level - The log level to check\n * @returns true if the level should be logged\n */\n private shouldLog(level: LogLevel): boolean {\n return LOG_LEVEL_PRIORITY[level] >= this.minLevelPriority;\n }\n\n /**\n * Redact sensitive keys from metadata\n *\n * Performs case-insensitive shallow redaction. Only top-level keys\n * are checked and redacted - nested objects are not traversed.\n *\n * Matching keys are replaced with the string '[REDACTED]'.\n *\n * @param meta - The metadata to redact\n * @returns New metadata object with sensitive values redacted\n */\n private redact(meta: LogMetadata): LogMetadata {\n // Fast-path: No redaction keys configured\n if (this.config.redactKeys.length === 0) {\n return meta;\n }\n\n // Create lowercase lookup set for case-insensitive matching\n const redactKeysLower = new Set(this.config.redactKeys.map(key => key.toLowerCase()));\n\n // Shallow redaction - only check top-level keys\n const redacted: LogMetadata = {};\n for (const [key, value] of Object.entries(meta)) {\n if (redactKeysLower.has(key.toLowerCase())) {\n redacted[key] = '[REDACTED]';\n } else {\n redacted[key] = value;\n }\n }\n\n return redacted;\n }\n}\n\n/**\n * Get default transport based on environment\n *\n * Lazy-loads transports to avoid circular dependencies and unnecessary imports.\n *\n * @returns Default transport instance for current environment\n * @internal\n */\nfunction getDefaultTransport(): BlaizeLogTransport {\n const isDevelopment = process.env.NODE_ENV !== 'production';\n\n if (isDevelopment) {\n // Development: ConsoleTransport with colors\n return new ConsoleTransport();\n } else {\n // Production: JSONTransport for log aggregators\n return new JSONTransport();\n }\n}\n\n/**\n * Create a logger with default configuration\n *\n * Resolves defaults based on environment:\n * - Development: debug level, ConsoleTransport\n * - Production: info level, JSONTransport\n *\n * Core transports (ConsoleTransport, JSONTransport) are lazy-loaded by\n * the logger itself. Custom transports should be provided by application code.\n *\n * @param config - Partial logger configuration (all fields optional)\n * @returns A new Logger instance\n *\n * @example Development Logger (Default)\n * ```typescript\n * const logger = createLogger();\n * // Uses: level='debug', ConsoleTransport, timestamp=true, no redaction\n *\n * logger.debug('Starting application');\n * ```\n *\n * @example Production Logger (Default)\n * ```typescript\n * process.env.NODE_ENV = 'production';\n *\n * const logger = createLogger({\n * redactKeys: ['password', 'apiKey', 'secret']\n * });\n * // Uses: level='info', JSONTransport, timestamp=true, redaction enabled\n * ```\n *\n * @example Custom Transport (Application Code)\n * ```typescript\n * import { CustomTransport } from './my-transports';\n *\n * const logger = createLogger({\n * level: 'warn',\n * transport: new CustomTransport(), // Application provides custom transport\n * redactKeys: ['ssn', 'creditCard'],\n * includeTimestamp: false\n * });\n * ```\n */\nexport function createLogger(config?: Partial<ResolvedLoggerConfig>): Logger {\n const isDevelopment = process.env.NODE_ENV !== 'production';\n\n // Resolve defaults\n // Core transports are lazy-loaded by getDefaultTransport()\n // Custom transports must be provided by application code\n const resolvedConfig: ResolvedLoggerConfig = {\n level: config?.level ?? (isDevelopment ? 'debug' : 'info'),\n transport: config?.transport ?? getDefaultTransport(),\n redactKeys: config?.redactKeys ?? [],\n includeTimestamp: config?.includeTimestamp ?? true,\n };\n\n return new Logger(resolvedConfig);\n}\n","/**\n * Null Transport for Testing\n *\n * Silent transport that discards all logs. Used in tests to suppress output.\n *\n * @packageDocumentation\n */\n\nimport type { BlaizeLogTransport, LogLevel, LogMetadata } from '@blaize-types/logger';\n\n/**\n * Null transport for testing and silent logging\n *\n * Discards all log entries without producing any output. Useful for:\n * - Unit tests that don't care about log output\n * - Benchmarks where logging overhead should be minimal\n * - Temporarily disabling logging without changing code\n *\n * Features:\n * - Zero overhead - no processing or I/O\n * - Stateless - safe for concurrent logging\n * - No output to stdout, stderr, or files\n *\n * @example In Tests\n * ```typescript\n * import { NullTransport } from './transports';\n * import { createLogger } from './Logger';\n *\n * describe('MyService', () => {\n * const logger = createLogger({\n * transport: new NullTransport() // Suppress logs in tests\n * });\n *\n * test('performs operation', () => {\n * const service = new MyService(logger);\n * service.doWork(); // No log output\n * });\n * });\n * ```\n *\n * @example Temporary Disable\n * ```typescript\n * // Temporarily disable logging without changing business logic\n * const logger = createLogger({\n * transport: new NullTransport()\n * });\n *\n * logger.info('This message is discarded');\n * logger.error('This error is discarded');\n * ```\n */\nexport class NullTransport implements BlaizeLogTransport {\n /**\n * Discard a log entry (no-op)\n *\n * @param _level - Log level (unused)\n * @param _message - Log message (unused)\n * @param _meta - Structured metadata (unused)\n */\n write(_level: LogLevel, _message: string, _meta: LogMetadata): void {\n // Intentional no-op - discard all logs\n }\n\n /**\n * Flush any buffered logs (no-op)\n *\n * Since no logs are written, there's nothing to flush.\n *\n * @returns Promise that resolves immediately\n */\n async flush(): Promise<void> {\n // Intentional no-op - nothing to flush\n return Promise.resolve();\n }\n}\n","import { createLogger, Logger } from './logger';\nimport { ConsoleTransport } from './transports/console';\n\nimport type { BlaizeLogger, LoggerConfig } from '@blaize-types/index';\n\n// ==========================================\n// GLOBAL LOGGER INSTANCE\n// ==========================================\n\n/**\n * Global logger singleton instance\n *\n * This instance is available before server creation and can be used\n * anywhere in your application. When the server starts, it will be\n * configured with the server's logging options.\n *\n * @example\n * ```typescript\n * import { logger } from '@blaizejs/logger';\n *\n * logger.info('Application starting');\n * ```\n */\nexport const logger: BlaizeLogger = createLogger({\n level: process.env.NODE_ENV === 'development' ? 'debug' : 'info',\n transport: new ConsoleTransport(),\n includeTimestamp: true,\n redactKeys: [],\n});\n\n// Keep internal reference for update\nlet _globalLoggerInstance = logger as Logger;\n\n/**\n * Configure the global logger instance\n *\n * This function updates the global logger in-place so that all existing\n * imports automatically receive the new configuration. Called internally\n * by the server during creation.\n *\n * @param config - Partial logger configuration\n *\n * @example\n * ```typescript\n * import { configureGlobalLogger } from '@blaizejs/logger';\n *\n * configureGlobalLogger({\n * level: 'warn',\n * redactKeys: ['password', 'apiKey']\n * });\n * ```\n */\nexport function configureGlobalLogger(config: Partial<LoggerConfig>): void {\n // Create new logger with config\n const newLogger = createLogger(config);\n\n // Update internal reference\n _globalLoggerInstance = newLogger;\n\n // Update the exported logger object in-place\n // This ensures all existing imports get the new config\n Object.assign(logger, newLogger);\n}\n\n/**\n * Get a reference to the current global logger instance\n *\n * @internal - For testing purposes only\n */\nexport function _getGlobalLogger(): Logger {\n return _globalLoggerInstance;\n}\n\nexport { ConsoleTransport } from './transports/console';\nexport { JSONTransport } from './transports/json';\nexport { NullTransport } from './transports/null';\n\nexport { createLogger, Logger } from './logger';\n","import type { Context } from '@blaize-types/context';\nimport type { BlaizeLogger } from '@blaize-types/logger';\nimport type { Middleware, NextFunction } from '@blaize-types/middleware';\n\n/**\n * Execute a single middleware, handling both function and object forms\n *\n * handle undefined middleware and skip logic\n *\n * @param middleware - The middleware to execute (or undefined)\n * @param ctx - The Blaize context object\n * @param next - Function to invoke the next middleware in the chain\n * @param logger - Logger instance for logging within the middleware\n *\n * @returns A Promise that resolves when middleware execution is complete\n *\n * @example\n * ```typescript\n * const logger = createLogger();\n * await execute(myMiddleware, ctx, next, logger);\n * ```\n */\nexport function execute(\n middleware: Middleware | undefined,\n ctx: Context,\n next: NextFunction,\n logger: BlaizeLogger\n): Promise<void> {\n // Handle undefined middleware (safety check)\n if (!middleware) {\n return Promise.resolve(next());\n }\n\n // Handle middleware with skip function\n if (middleware.skip && middleware.skip(ctx)) {\n return Promise.resolve(next());\n }\n\n try {\n // Execute middleware\n const result = middleware.execute(ctx, next, logger);\n\n // Handle both Promise and non-Promise returns\n if (result instanceof Promise) {\n // Return the promise directly to allow errors to propagate\n return result;\n } else {\n // Only wrap non-Promise returns\n return Promise.resolve(result);\n }\n } catch (error) {\n // Handle synchronous errors\n return Promise.reject(error);\n }\n}\n","\nimport { execute } from './execute';\n\nimport type { Context } from '@blaize-types/context';\nimport type { BlaizeLogger } from '@blaize-types/logger';\nimport type { Middleware, NextFunction, MiddlewareFunction } from '@blaize-types/middleware';\n\n/**\n * Compose multiple middleware functions into a single middleware function\n */\nexport function compose(middlewareStack: Middleware[]): MiddlewareFunction {\n // No middleware? Return a pass-through function\n if (middlewareStack.length === 0) {\n return async (_, next, __) => {\n await Promise.resolve(next());\n };\n }\n\n // Return a function that executes the middleware stack\n return async function (\n ctx: Context,\n finalHandler: NextFunction,\n baseLogger: BlaizeLogger\n ): Promise<void> {\n // Keep track of which \"next\" functions have been called\n const called = new Set<number>();\n\n // Create dispatch function to process middleware stack\n const dispatch = async (i: number): Promise<void> => {\n // If we've reached the end of the stack, execute the final handler\n if (i >= middlewareStack.length) {\n // Ensure we're returning a Promise regardless of what finalHandler returns\n return Promise.resolve(finalHandler());\n }\n\n // Get current middleware\n const middleware = middlewareStack[i];\n\n // Create a next function that can only be called once\n const nextDispatch = () => {\n if (called.has(i)) {\n throw new Error('next() called multiple times');\n }\n\n // Mark this middleware's next as called\n called.add(i);\n\n // Move to the next middleware\n return dispatch(i + 1);\n };\n\n const middlewareLogger = baseLogger.child({\n middleware: middleware?.name || 'anonymous',\n });\n\n // Use the executeMiddleware function we defined\n return execute(middleware, ctx, nextDispatch, middlewareLogger);\n };\n\n // Start middleware chain execution\n return dispatch(0);\n };\n}\n","/**\n * ForbiddenError class for authorization failures\n *\n * This error is thrown when a user lacks permission to access a resource.\n * It provides context about required permissions and access control.\n */\n\nimport { BlaizeError, ErrorType } from '@blaize-types/errors';\n\nimport { getCorrelationId } from '../tracing/correlation';\n\nimport type { ForbiddenErrorDetails } from '@blaize-types/errors';\n\n/**\n * Error thrown when user lacks permission to access a resource\n *\n * Automatically sets HTTP status to 403 and provides permission context.\n *\n * @example Basic usage:\n * ```typescript\n * throw new ForbiddenError('Access denied');\n * ```\n *\n * @example With permission details:\n * ```typescript\n * throw new ForbiddenError('Insufficient permissions', {\n * requiredPermission: 'admin:users:delete',\n * userPermissions: ['admin:users:read'],\n * resource: 'user-123',\n * action: 'delete'\n * });\n * ```\n */\nexport class ForbiddenError extends BlaizeError<ForbiddenErrorDetails> {\n /**\n * Creates a new ForbiddenError instance\n *\n * @param title - Human-readable error message\n * @param details - Optional permission context\n * @param correlationId - Optional correlation ID (uses current context if not provided)\n */\n constructor(\n title: string,\n details: ForbiddenErrorDetails | undefined = undefined,\n correlationId: string | undefined = undefined\n ) {\n super(\n ErrorType.FORBIDDEN,\n title,\n 403, // HTTP 403 Forbidden\n correlationId ?? getCorrelationId(),\n details\n );\n }\n}\n","/* eslint-disable @typescript-eslint/no-empty-object-type */\nimport type { Middleware, MiddlewareOptions, MiddlewareFunction } from '@blaize-types/middleware';\n\n/**\n * Create a middleware\n */\nexport function create<TState = {}, TServices = {}>(\n handlerOrOptions: MiddlewareFunction | MiddlewareOptions\n): Middleware<TState, TServices> {\n // If handlerOrOptions is a function, convert it to our middleware object format\n if (typeof handlerOrOptions === 'function') {\n return {\n name: 'anonymous', // Default name for function middleware\n execute: handlerOrOptions,\n debug: false,\n } as Middleware<TState, TServices>;\n }\n\n // Otherwise, handle it as middleware options\n const { name = 'anonymous', handler, skip, debug = false } = handlerOrOptions;\n\n // Create base middleware object with required properties\n const middleware = {\n name,\n execute: handler,\n debug,\n ...(skip !== undefined && { skip }),\n } as Middleware<TState, TServices>;\n\n return middleware;\n}\n\n/**\n * Create a middleware that only contributes state (no services)\n * Convenience helper for state-only middleware\n *\n * @template T - Type of state to contribute\n * @param handler - Middleware function that adds state\n * @returns Middleware that contributes state only\n *\n */\nexport function stateMiddleware<T = {}>(handler: MiddlewareFunction): Middleware<T, {}> {\n return create<T, {}>({\n name: 'state-middleware',\n handler,\n });\n}\n\n/**\n * Create a middleware that only contributes services (no state)\n * Convenience helper for service-only middleware\n *\n * @template T - Type of services to contribute\n * @param handler - Middleware function that adds services\n * @returns Middleware that contributes services only\n *\n */\nexport function serviceMiddleware<T = {}>(handler: MiddlewareFunction): Middleware<{}, T> {\n return create<{}, T>({\n name: 'service-middleware',\n handler,\n });\n}\n","/**\n * CORS Default Configurations\n *\n * Environment-aware default configurations for CORS middleware.\n * Provides secure defaults for production and permissive defaults for development.\n *\n * SECURITY IMPLICATIONS:\n *\n * Development Mode (NODE_ENV !== 'production'):\n * - Allows ALL origins (wildcard '*')\n * - No credentials allowed with wildcard (security requirement)\n * - All common HTTP methods allowed\n * - Suitable for local development and testing\n * - WARNING: Never use in production as it allows any website to make requests\n *\n * Production Mode (NODE_ENV === 'production'):\n * - Denies all cross-origin requests by default (origin: false)\n * - Only GET and HEAD methods allowed (read-only)\n * - No credentials by default\n * - Forces explicit origin configuration for security\n * - Requires deliberate configuration of allowed origins\n *\n * @module @blaize-core/middleware/cors/defaults\n */\n\nimport type { CorsOptions } from '@blaize-types/cors';\n\n/**\n * Development environment CORS defaults\n *\n * SECURITY WARNING: These settings are ONLY for development.\n * They allow any origin to access your API, which is a security risk in production.\n *\n * Features:\n * - origin: true (allows all origins)\n * - credentials: false (prevents credential sharing with wildcard)\n * - methods: All common HTTP methods\n * - optionsSuccessStatus: 204 (standard)\n *\n * @internal\n */\nconst DEVELOPMENT_DEFAULTS: CorsOptions = {\n origin: true, // Allow all origins in development\n methods: ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'],\n credentials: false, // Cannot use credentials with wildcard origin\n optionsSuccessStatus: 204,\n};\n\n/**\n * Production environment CORS defaults\n *\n * SECURITY: These settings are restrictive by default.\n * Cross-origin requests are denied unless explicitly configured.\n *\n * Features:\n * - origin: false (denies all cross-origin requests)\n * - methods: Only GET and HEAD (read-only)\n * - credentials: false (no credential sharing)\n * - optionsSuccessStatus: 204 (standard)\n *\n * To allow cross-origin requests in production, you must explicitly set:\n * - origin: specific domain(s) or validation function\n * - methods: only the methods your API actually needs\n * - credentials: true only if necessary for authentication\n *\n * @internal\n */\nconst PRODUCTION_DEFAULTS: CorsOptions = {\n origin: false, // Deny all cross-origin requests by default\n methods: ['GET', 'HEAD'], // Only safe methods by default\n credentials: false, // No credentials by default\n optionsSuccessStatus: 204,\n};\n\n/**\n * Get default CORS options based on environment\n *\n * Automatically detects the environment and returns appropriate defaults.\n * Uses NODE_ENV environment variable to determine if in production.\n *\n * @param isDevelopment - Override environment detection (optional)\n * @returns CORS options with environment-appropriate defaults\n *\n * @example\n * ```typescript\n * // Automatic environment detection\n * const options = getDefaultCorsOptions();\n *\n * // Force development mode\n * const devOptions = getDefaultCorsOptions(true);\n *\n * // Force production mode\n * const prodOptions = getDefaultCorsOptions(false);\n * ```\n *\n * @security\n * In production, this returns restrictive defaults that deny all cross-origin\n * requests. You must explicitly configure allowed origins to enable CORS.\n *\n * Example production configuration:\n * ```typescript\n * const corsOptions = {\n * ...getDefaultCorsOptions(),\n * origin: 'https://app.example.com', // Explicit origin\n * credentials: true, // If needed for auth\n * };\n * ```\n */\nexport function getDefaultCorsOptions(isDevelopment?: boolean): CorsOptions {\n // If isDevelopment is not provided, detect from environment\n if (isDevelopment === undefined) {\n isDevelopment = process.env.NODE_ENV !== 'production';\n }\n\n return isDevelopment ? { ...DEVELOPMENT_DEFAULTS } : { ...PRODUCTION_DEFAULTS };\n}\n\n/**\n * Detect if running in development environment\n *\n * @returns True if in development mode\n */\nexport function isDevelopmentEnvironment(): boolean {\n return process.env.NODE_ENV !== 'production';\n}\n\n/**\n * Get environment name for logging\n *\n * @returns Current environment name\n */\nexport function getEnvironmentName(): string {\n return process.env.NODE_ENV || 'development';\n}\n\n/**\n * Validate that production configuration is secure\n *\n * Checks if CORS options are appropriate for production use.\n * Logs warnings if insecure configurations are detected.\n *\n * @param options - CORS options to validate\n * @returns True if configuration appears secure\n */\nexport function validateProductionConfig(options: CorsOptions): boolean {\n const warnings: string[] = [];\n\n // Check for wildcard origin in production\n if (options.origin === true || options.origin === '*') {\n warnings.push('SECURITY WARNING: Wildcard origin (*) should not be used in production');\n }\n\n // Check for credentials with permissive origin\n if (options.credentials === true && (options.origin === true || options.origin === '*')) {\n warnings.push('SECURITY ERROR: Cannot use credentials with wildcard origin');\n // Log warnings before returning false\n if (!isDevelopmentEnvironment() && warnings.length > 0) {\n warnings.forEach(warning => console.warn(`[CORS] ${warning}`));\n }\n return false; // This is a hard error\n }\n\n // Check for overly permissive methods\n const methods = options.methods || [];\n const methodsList = typeof methods === 'string' ? methods.split(',').map(m => m.trim()) : methods;\n\n if (\n methodsList.includes('DELETE') ||\n methodsList.includes('CONNECT') ||\n methodsList.includes('TRACE')\n ) {\n warnings.push('SECURITY WARNING: Dangerous HTTP methods (DELETE, CONNECT, TRACE) are allowed');\n }\n\n // Log warnings if in production\n if (!isDevelopmentEnvironment() && warnings.length > 0) {\n warnings.forEach(warning => console.warn(`[CORS] ${warning}`));\n }\n\n return warnings.length === 0;\n}\n","/**\n * Origin Validation Module for CORS\n *\n * Provides origin validation with LRU caching for performance optimization.\n * Supports string matching, regex patterns, and async function evaluation\n * with timeout protection.\n */\n\nimport type { Context } from '@blaize-types/context';\nimport type { CacheConfig, CacheEntry, CorsOrigin } from '@blaize-types/cors';\n\n/**\n * Create an LRU cache for origin validation\n *\n * Using a functional approach with closure for state management\n */\nfunction createOriginCache(ttl: number = 60000, maxSize: number = 1000) {\n const cache = new Map<string, CacheEntry>();\n const config: CacheConfig = { ttl, maxSize };\n\n /**\n * Generate cache key from origin, configured origin identifier, and optional user ID\n * We need to include a representation of the configured origin to prevent incorrect cache hits\n */\n const getCacheKey = (origin: string, configOriginId: string, userId?: string): string => {\n return `${origin}:${configOriginId}:${userId || 'anonymous'}`;\n };\n\n /**\n * Evict least recently used entry when at capacity\n */\n const evictLRU = (): void => {\n if (cache.size === 0) return;\n\n let lruKey: string | null = null;\n let lruTime = Infinity; // Start with Infinity, not Date.now()\n\n // Find least recently used entry (oldest lastAccessed time)\n for (const [key, entry] of cache.entries()) {\n if (entry.lastAccessed < lruTime) {\n lruTime = entry.lastAccessed;\n lruKey = key;\n }\n }\n\n if (lruKey) {\n cache.delete(lruKey);\n }\n };\n\n /**\n * Get cached validation result if not expired\n */\n const get = (origin: string, configOriginId: string, userId?: string): boolean | null => {\n const key = getCacheKey(origin, configOriginId, userId);\n const entry = cache.get(key);\n\n if (!entry) {\n return null;\n }\n\n // Check if expired\n const now = Date.now();\n if (now > entry.expiresAt) {\n cache.delete(key);\n return null;\n }\n\n // Update last accessed time for LRU\n entry.lastAccessed = now;\n return entry.allowed;\n };\n\n /**\n * Set validation result in cache\n */\n const set = (origin: string, allowed: boolean, configOriginId: string, userId?: string): void => {\n const key = getCacheKey(origin, configOriginId, userId);\n const now = Date.now();\n\n // If key already exists, just update it\n if (cache.has(key)) {\n cache.set(key, {\n allowed,\n expiresAt: now + config.ttl,\n lastAccessed: now,\n });\n return;\n }\n\n // Adding new key - check if we need to evict\n if (cache.size >= config.maxSize) {\n evictLRU();\n }\n\n cache.set(key, {\n allowed,\n expiresAt: now + config.ttl,\n lastAccessed: now,\n });\n };\n\n /**\n * Clear all cache entries\n */\n const clear = (): void => {\n cache.clear();\n };\n\n /**\n * Clean up expired entries\n */\n const cleanExpired = (): number => {\n const now = Date.now();\n let cleaned = 0;\n\n for (const [key, entry] of cache.entries()) {\n if (now > entry.expiresAt) {\n cache.delete(key);\n cleaned++;\n }\n }\n\n return cleaned;\n };\n\n /**\n * Get cache statistics\n */\n const getStats = () => ({\n size: cache.size,\n maxSize: config.maxSize,\n ttl: config.ttl,\n });\n\n return {\n get,\n set,\n clear,\n cleanExpired,\n getStats,\n };\n}\n\n/**\n * Default cache instance (module-level singleton)\n */\nlet defaultCache = createOriginCache();\n\n/**\n * Replace the default cache (useful for testing)\n */\nexport function setOriginCache(ttl: number = 60000, maxSize: number = 1000): void {\n defaultCache = createOriginCache(ttl, maxSize);\n}\n\n/**\n * Reset to default cache configuration\n */\nexport function resetOriginCache(): void {\n defaultCache = createOriginCache();\n}\n\n/**\n * Get cache statistics\n */\nexport function getCacheStats() {\n return defaultCache.getStats();\n}\n\n/**\n * Clean expired cache entries\n */\nexport function cleanExpiredCacheEntries(): number {\n return defaultCache.cleanExpired();\n}\n\n/**\n * Determine if a configured origin is cacheable\n * Only string and RegExp origins are cacheable\n */\nfunction isCacheable(configuredOrigin: CorsOrigin | boolean): boolean {\n // Booleans are instant - no need to cache\n if (typeof configuredOrigin === 'boolean') {\n return false;\n }\n\n // Functions are unpredictable - shouldn't cache\n if (typeof configuredOrigin === 'function') {\n return false;\n }\n\n // Arrays may contain functions - check all elements\n if (Array.isArray(configuredOrigin)) {\n return configuredOrigin.every(origin => typeof origin === 'string' || origin instanceof RegExp);\n }\n\n // String and RegExp are cacheable\n return typeof configuredOrigin === 'string' || configuredOrigin instanceof RegExp;\n}\n\n/**\n * Generate a stable identifier for a configured origin\n * This is used as part of the cache key\n * Only called for cacheable origins\n */\nfunction getConfigOriginId(configuredOrigin: CorsOrigin | boolean): string {\n if (typeof configuredOrigin === 'string') {\n return `str:${configuredOrigin}`;\n }\n if (configuredOrigin instanceof RegExp) {\n return `regex:${configuredOrigin.source}:${configuredOrigin.flags}`;\n }\n if (Array.isArray(configuredOrigin)) {\n // For arrays, create a composite ID from the elements\n return `array:[${configuredOrigin\n .map(o => {\n if (typeof o === 'string') return `str:${o}`;\n if (o instanceof RegExp) return `regex:${o.source}:${o.flags}`;\n return 'unknown';\n })\n .join(',')}]`;\n }\n // This shouldn't be reached for cacheable origins\n return 'unknown';\n}\n\n/**\n * Validate origin string against configured origin\n */\nasync function validateStringOrigin(\n requestOrigin: string,\n configuredOrigin: string\n): Promise<boolean> {\n // Handle wildcard\n if (configuredOrigin === '*') {\n return true;\n }\n\n // Exact match (case-sensitive as per spec)\n return requestOrigin === configuredOrigin;\n}\n\n/**\n * Validate origin against regex pattern\n */\nasync function validateRegExpOrigin(\n requestOrigin: string,\n configuredOrigin: RegExp\n): Promise<boolean> {\n return configuredOrigin.test(requestOrigin);\n}\n\n/**\n * Validate origin using async function with timeout\n */\nasync function validateFunctionOrigin(\n requestOrigin: string,\n configuredOrigin: (origin: string, ctx?: Context<any, any>) => boolean | Promise<boolean>,\n ctx?: Context<any, any>,\n timeoutMs: number = 100\n): Promise<boolean> {\n let timeoutId: NodeJS.Timeout | undefined;\n\n try {\n // Create a timeout promise that resolves (not rejects) with a timeout flag\n const timeoutPromise = new Promise<{ timedOut: true }>(resolve => {\n timeoutId = setTimeout(() => {\n resolve({ timedOut: true });\n }, timeoutMs);\n });\n\n // Race between the validation function and timeout\n const result = await Promise.race([\n Promise.resolve(configuredOrigin(requestOrigin, ctx)).then(r => ({ result: r })),\n timeoutPromise,\n ]);\n\n // Clear timeout if validation completed\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n\n // Check if we timed out\n if ('timedOut' in result) {\n console.warn(\n `CORS origin validation function timed out after ${timeoutMs}ms for origin: ${requestOrigin}`\n );\n return false;\n }\n\n return result.result;\n } catch (error) {\n // Clear timeout on error\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n console.error('CORS origin validation function error:', error);\n return false; // Deny on error\n }\n}\n\n/**\n * Validate origin against an array of validators\n */\nasync function validateArrayOrigin(\n requestOrigin: string,\n configuredOrigins: Array<\n string | RegExp | ((origin: string, ctx?: Context<any, any>) => boolean | Promise<boolean>)\n >,\n ctx?: Context<any, any>\n): Promise<boolean> {\n // Check each origin in parallel for performance\n const validations = configuredOrigins.map(origin =>\n validateSingleOrigin(requestOrigin, origin, ctx)\n );\n\n const results = await Promise.all(validations);\n return results.some(result => result === true);\n}\n\n/**\n * Validate a single origin (handles all non-array types)\n */\nasync function validateSingleOrigin(\n requestOrigin: string,\n configuredOrigin:\n | string\n | RegExp\n | ((origin: string, ctx?: Context<any, any>) => boolean | Promise<boolean>),\n ctx?: Context<any, any>\n): Promise<boolean> {\n if (typeof configuredOrigin === 'string') {\n return validateStringOrigin(requestOrigin, configuredOrigin);\n }\n\n if (configuredOrigin instanceof RegExp) {\n return validateRegExpOrigin(requestOrigin, configuredOrigin);\n }\n\n if (typeof configuredOrigin === 'function') {\n return validateFunctionOrigin(requestOrigin, configuredOrigin, ctx);\n }\n\n // Unknown type, deny for safety\n console.warn('Unknown CORS origin type:', typeof configuredOrigin);\n return false;\n}\n\n/**\n * Main origin validation function with caching\n *\n * @param requestOrigin - The Origin header from the request\n * @param configuredOrigin - The configured CORS origin setting\n * @param ctx - Optional context for user-based caching\n * @returns Promise resolving to whether origin is allowed\n */\nexport async function validateOrigin(\n requestOrigin: string,\n configuredOrigin: CorsOrigin | boolean,\n ctx?: Context<any, any>\n): Promise<boolean> {\n // Handle boolean shortcuts\n if (configuredOrigin === true) {\n return true; // Allow all origins\n }\n if (configuredOrigin === false) {\n return false; // Deny all origins\n }\n\n // Determine if this origin configuration is cacheable\n const cacheable = isCacheable(configuredOrigin);\n\n // Only use cache for cacheable origins (string, RegExp, or arrays of them)\n if (cacheable) {\n // Get user ID for cache key (if available)\n const userId = ctx?.state?.user?.id || ctx?.state?.userId;\n\n // Generate a stable identifier for the configured origin\n const configOriginId = getConfigOriginId(configuredOrigin);\n\n // Check cache first\n const cached = defaultCache.get(requestOrigin, configOriginId, userId);\n if (cached !== null) {\n return cached;\n }\n\n // Perform validation\n let allowed: boolean;\n\n if (Array.isArray(configuredOrigin)) {\n // Type assertion to ensure array elements are the right type\n allowed = await validateArrayOrigin(\n requestOrigin,\n configuredOrigin as Array<\n | string\n | RegExp\n | ((origin: string, ctx?: Context<any, any>) => boolean | Promise<boolean>)\n >,\n ctx\n );\n } else {\n allowed = await validateSingleOrigin(requestOrigin, configuredOrigin, ctx);\n }\n\n // Cache the result\n defaultCache.set(requestOrigin, allowed, configOriginId, userId);\n\n return allowed;\n } else {\n // Non-cacheable origin (function, boolean, or array with functions)\n // Perform validation without caching\n if (Array.isArray(configuredOrigin)) {\n return validateArrayOrigin(\n requestOrigin,\n configuredOrigin as Array<\n | string\n | RegExp\n | ((origin: string, ctx?: Context<any, any>) => boolean | Promise<boolean>)\n >,\n ctx\n );\n } else {\n return validateSingleOrigin(requestOrigin, configuredOrigin, ctx);\n }\n }\n}\n\n/**\n * Validate that credentials aren't used with wildcard origin\n * This should be called during configuration validation\n */\nexport function validateCredentialsWithOrigin(\n configuredOrigin: CorsOrigin | boolean,\n credentials: boolean\n): void {\n if (!credentials) {\n return; // No restriction when credentials are false\n }\n\n // Check for wildcard with credentials\n if (configuredOrigin === true || configuredOrigin === '*') {\n throw new Error(\n 'CORS security violation: Cannot use wildcard origin with credentials=true. ' +\n 'Specify explicit origins when credentials are enabled.'\n );\n }\n\n // Check for wildcard in array\n if (Array.isArray(configuredOrigin)) {\n const hasWildcard = configuredOrigin.some(origin => origin === '*');\n if (hasWildcard) {\n throw new Error(\n 'CORS security violation: Cannot include wildcard (*) in origin array with credentials=true.'\n );\n }\n }\n}\n\n/**\n * Performance optimization: Pre-validate common origins\n * Can be called during server startup\n */\nexport async function prevalidateOrigins(\n origins: string[],\n configuredOrigin: CorsOrigin | boolean,\n ctx?: Context<any, any>\n): Promise<void> {\n const validations = origins.map(origin => validateOrigin(origin, configuredOrigin, ctx));\n\n await Promise.all(validations);\n}\n\n/**\n * Periodically clean expired cache entries (optional)\n * Returns a cleanup function to stop the interval\n */\nexport function startCacheCleanup(intervalMs: number = 60000): () => void {\n const interval = setInterval(() => {\n const cleaned = defaultCache.cleanExpired();\n if (cleaned > 0) {\n console.debug(`Cleaned ${cleaned} expired CORS cache entries`);\n }\n }, intervalMs);\n\n return () => clearInterval(interval);\n}\n","/**\n * CORS Preflight Request Handler\n *\n * Handles OPTIONS requests for CORS preflight checks according to W3C spec.\n * Validates requested methods and headers, sets appropriate response headers,\n * and returns 403 Forbidden on validation failures.\n */\n\nimport { validateOrigin } from './origin-validator';\nimport { ValidationError } from '../../errors/validation-error';\n\nimport type { Context } from '@blaize-types/context';\nimport type { CorsOptions } from '@blaize-types/cors';\n\n/**\n * Extract Access-Control-Request-* headers from OPTIONS request\n */\ninterface PreflightRequest {\n origin: string | undefined;\n requestedMethod: string | undefined;\n requestedHeaders: string[] | undefined;\n}\n\n/**\n * Parse preflight request headers\n */\nfunction parsePreflightRequest(ctx: Context): PreflightRequest {\n // Extract origin using the context's header method\n const origin = ctx.request.header('origin') || ctx.request.header('Origin');\n\n // Extract requested method (case-insensitive header name)\n const requestedMethod =\n ctx.request.header('access-control-request-method') ||\n ctx.request.header('Access-Control-Request-Method');\n\n // Extract requested headers (comma-delimited string)\n const requestedHeadersRaw =\n ctx.request.header('access-control-request-headers') ||\n ctx.request.header('Access-Control-Request-Headers');\n\n const requestedHeaders = requestedHeadersRaw\n ? requestedHeadersRaw.split(',').map(h => h.trim().toLowerCase())\n : undefined;\n\n return {\n origin,\n requestedMethod,\n requestedHeaders,\n };\n}\n\n/**\n * Normalize method names for comparison\n * HTTP methods are case-sensitive per spec\n */\nfunction normalizeMethod(method: string): string {\n return method.toUpperCase();\n}\n\n/**\n * Check if a method is allowed\n */\nfunction isMethodAllowed(\n requestedMethod: string,\n allowedMethods: string[] | string | undefined\n): boolean {\n if (!allowedMethods) {\n // Default allowed methods per W3C spec\n const defaults = ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'];\n return defaults.includes(normalizeMethod(requestedMethod));\n }\n\n // Convert to array if string\n const methodsArray =\n typeof allowedMethods === 'string'\n ? allowedMethods.split(',').map(m => m.trim())\n : allowedMethods;\n\n return methodsArray.map(m => normalizeMethod(m)).includes(normalizeMethod(requestedMethod));\n}\n\n/**\n * Check if headers are allowed\n * Headers are case-insensitive per HTTP spec\n */\nfunction areHeadersAllowed(\n requestedHeaders: string[] | undefined,\n allowedHeaders: string[] | string | undefined\n): boolean {\n // If no headers requested, always allowed\n if (!requestedHeaders || requestedHeaders.length === 0) {\n return true;\n }\n\n // If allowedHeaders is undefined, mirror the requested headers (permissive)\n if (allowedHeaders === undefined) {\n return true;\n }\n\n // Convert to array if string\n const allowedArray =\n typeof allowedHeaders === 'string'\n ? allowedHeaders.split(',').map(h => h.trim().toLowerCase())\n : allowedHeaders.map(h => h.toLowerCase());\n\n // Check if all requested headers are in allowed list\n return requestedHeaders.every(header => allowedArray.includes(header.toLowerCase()));\n}\n\n/**\n * Set CORS response headers for preflight\n */\nfunction setPreflightHeaders(\n ctx: Context,\n options: CorsOptions,\n origin: string,\n originAllowed: boolean\n): void {\n // Set origin header based on validation result\n if (originAllowed) {\n if (options.origin === true && !options.credentials) {\n // Wildcard allowed when credentials not enabled\n ctx.response.header('Access-Control-Allow-Origin', '*');\n } else {\n // Reflect the specific origin\n ctx.response.header('Access-Control-Allow-Origin', origin);\n // Add Vary header when origin is dynamic\n ctx.response.header('Vary', 'Origin');\n }\n }\n\n // Set credentials header if enabled\n if (options.credentials && originAllowed) {\n ctx.response.header('Access-Control-Allow-Credentials', 'true');\n }\n\n // Set allowed methods\n const methods = options.methods || ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'];\n const methodsString = typeof methods === 'string' ? methods : methods.join(', ');\n ctx.response.header('Access-Control-Allow-Methods', methodsString);\n\n // Set allowed headers\n if (options.allowedHeaders) {\n const headers =\n typeof options.allowedHeaders === 'string'\n ? options.allowedHeaders\n : options.allowedHeaders.join(', ');\n ctx.response.header('Access-Control-Allow-Headers', headers);\n } else {\n // Mirror requested headers if not specified\n const requestedHeaders =\n ctx.request.header('access-control-request-headers') ||\n ctx.request.header('Access-Control-Request-Headers');\n if (requestedHeaders) {\n ctx.response.header('Access-Control-Allow-Headers', requestedHeaders);\n }\n }\n\n // Set max age if specified\n if (options.maxAge !== undefined && options.maxAge >= 0) {\n ctx.response.header('Access-Control-Max-Age', String(options.maxAge));\n }\n}\n\n/**\n * Handle CORS preflight request\n *\n * @param ctx - The request context\n * @param options - CORS configuration options\n * @returns Promise that resolves when preflight is handled\n * @throws ValidationError with 400 status on validation failure (403 behavior via response.status)\n */\nexport async function handlePreflight(ctx: Context, options: CorsOptions): Promise<void> {\n const preflight = parsePreflightRequest(ctx);\n\n // Preflight requires both origin and method headers\n if (!preflight.origin || !preflight.requestedMethod) {\n // Set 403 status directly\n ctx.response.status(403);\n\n throw new ValidationError('Invalid preflight request: missing required headers', {\n fields: [\n {\n field: preflight.origin ? 'Access-Control-Request-Method' : 'Origin',\n messages: ['Required header is missing'],\n },\n ],\n errorCount: 1,\n section: 'body', // Using valid section type\n });\n }\n\n // Validate origin\n const originAllowed = await validateOrigin(preflight.origin, options.origin || false, ctx);\n\n if (!originAllowed) {\n // Set 403 status directly\n ctx.response.status(403);\n\n throw new ValidationError('CORS origin not allowed', {\n fields: [\n {\n field: 'Origin',\n messages: [`Origin '${preflight.origin}' is not allowed`],\n rejectedValue: preflight.origin,\n },\n ],\n errorCount: 1,\n section: 'body',\n });\n }\n\n // Validate requested method\n if (!isMethodAllowed(preflight.requestedMethod, options.methods)) {\n // Set 403 status directly\n ctx.response.status(403);\n\n throw new ValidationError('CORS method not allowed', {\n fields: [\n {\n field: 'Access-Control-Request-Method',\n messages: [`Method '${preflight.requestedMethod}' is not allowed`],\n rejectedValue: preflight.requestedMethod,\n expectedType:\n typeof options.methods === 'string' ? options.methods : options.methods?.join(', '),\n },\n ],\n errorCount: 1,\n section: 'body',\n });\n }\n\n // Validate requested headers\n if (!areHeadersAllowed(preflight.requestedHeaders, options.allowedHeaders)) {\n const rejectedHeaders = preflight.requestedHeaders?.filter(h => {\n const allowed = options.allowedHeaders;\n if (!allowed) return false;\n const allowedArray =\n typeof allowed === 'string'\n ? allowed.split(',').map(h => h.trim().toLowerCase())\n : allowed.map(h => h.toLowerCase());\n return !allowedArray.includes(h.toLowerCase());\n });\n\n // Set 403 status directly\n ctx.response.status(403);\n\n throw new ValidationError('CORS headers not allowed', {\n fields: [\n {\n field: 'Access-Control-Request-Headers',\n messages: [`Headers not allowed: ${rejectedHeaders?.join(', ')}`],\n rejectedValue: rejectedHeaders,\n },\n ],\n errorCount: 1,\n section: 'body',\n });\n }\n\n // All validations passed - set response headers\n setPreflightHeaders(ctx, options, preflight.origin, originAllowed);\n\n // Set response status\n const successStatus = options.optionsSuccessStatus || 204;\n ctx.response.status(successStatus);\n\n // If preflightContinue is false (default), end the response here\n if (!options.preflightContinue) {\n // Send empty response body\n ctx.response.text('');\n }\n}\n\n/**\n * Check if a request is a preflight request\n *\n * @param ctx - The request context\n * @returns True if this is a CORS preflight request\n */\nexport function isPreflightRequest(ctx: Context): boolean {\n return (\n ctx.request.method === 'OPTIONS' &&\n !!(\n ctx.request.header('access-control-request-method') ||\n ctx.request.header('Access-Control-Request-Method')\n )\n );\n}\n\n/**\n * Create a standalone preflight handler for router mounting\n *\n * @param options - CORS configuration options\n * @returns Async handler function for preflight requests\n */\nexport function createPreflightHandler(options: CorsOptions) {\n return async (ctx: Context) => {\n await handlePreflight(ctx, options);\n };\n}\n","/**\n * CORS Validation Schemas\n *\n * Zod schemas for validating CORS configuration options\n * following BlaizeJS validation patterns.\n */\n\nimport { z } from 'zod';\n\nimport type { Context } from '@blaize-types/context';\nimport type { CorsOptions, CorsOrigin, CorsHttpMethod } from '@blaize-types/cors';\n\n/**\n * Validation for CORS HTTP methods\n * Includes all standard HTTP methods plus CONNECT and TRACE\n */\nconst corsHttpMethodSchema = z.enum([\n 'GET',\n 'POST',\n 'PUT',\n 'DELETE',\n 'PATCH',\n 'HEAD',\n 'OPTIONS',\n 'CONNECT',\n 'TRACE',\n]) as z.ZodType<CorsHttpMethod>;\n\n/**\n * Validation for methods field - can be array or comma-delimited string\n */\nconst corsMethodsSchema = z\n .union([\n z.array(corsHttpMethodSchema),\n z.string().transform(val => {\n // Transform comma-delimited string to array\n return val.split(',').map(m => m.trim()) as CorsHttpMethod[];\n }),\n ])\n .optional();\n\n/**\n * Validation for headers - can be array or comma-delimited string\n * Note: Headers are case-insensitive per HTTP spec. Node.js handles\n * normalization automatically (lowercase for HTTP/2, case-preserving for HTTP/1.1)\n */\nconst corsHeadersSchema = z\n .union([\n z.array(z.string()),\n z.string().transform(val => {\n // Transform comma-delimited string to array\n return val.split(',').map(h => h.trim());\n }),\n ])\n .optional();\n\n/**\n * Custom validation for origin functions\n * Zod doesn't have built-in function validation with specific signatures\n */\nconst corsOriginFunctionSchema = z.custom<\n (origin: string, ctx?: Context<any, any>) => boolean | Promise<boolean>\n>(\n data => {\n return typeof data === 'function' && data.length <= 2;\n },\n {\n message: 'Origin validator must be a function accepting (origin, ctx?) parameters',\n }\n);\n\n/**\n * Validation for single origin value\n * Can be string, RegExp, or validation function\n */\nconst singleOriginSchema = z.union([z.string(), z.instanceof(RegExp), corsOriginFunctionSchema]);\n\n/**\n * Full origin validation schema\n * Supports boolean, single origin, or array of origins\n */\nconst corsOriginSchema: z.ZodType<boolean | CorsOrigin> = z.union([\n z.boolean(),\n singleOriginSchema,\n z.array(singleOriginSchema),\n]);\n\n/**\n * Main CORS options validation schema\n */\nexport const corsOptionsSchema = z\n .object({\n /**\n * Origin configuration\n * - true: allow all origins\n * - false: disable CORS\n * - string/RegExp/function: specific origin validation\n * - array: multiple origin validators\n */\n origin: corsOriginSchema.optional(),\n\n /**\n * Allowed HTTP methods\n * Default: ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE']\n */\n methods: corsMethodsSchema,\n\n /**\n * Allowed request headers\n * Default: mirror Access-Control-Request-Headers\n */\n allowedHeaders: corsHeadersSchema,\n\n /**\n * Headers exposed to the client\n * Default: []\n */\n exposedHeaders: corsHeadersSchema,\n\n /**\n * Allow credentials (cookies, auth headers)\n * Default: false\n */\n credentials: z.boolean().optional(),\n\n /**\n * Preflight cache duration in seconds\n * -1 disables caching\n */\n maxAge: z.number().int().optional(),\n\n /**\n * Pass preflight to next handler\n * Default: false\n */\n preflightContinue: z.boolean().optional(),\n\n /**\n * Success status for OPTIONS requests\n * Default: 204\n */\n optionsSuccessStatus: z.number().int().min(200).max(299).optional(),\n })\n .strict() as z.ZodType<CorsOptions>;\n\n/**\n * Schema for server options CORS field\n * Can be boolean or CorsOptions\n */\nexport const serverCorsSchema = z.union([z.boolean(), corsOptionsSchema]).optional();\n\n/**\n * Validate CORS options with detailed error messages\n */\nexport function validateCorsOptions(options: unknown): CorsOptions {\n try {\n // Handle boolean shortcuts\n if (typeof options === 'boolean') {\n if (options === false) {\n // CORS disabled\n return { origin: false };\n }\n // true means allow all origins (dev mode)\n return { origin: true };\n }\n\n // Validate as CorsOptions\n return corsOptionsSchema.parse(options);\n } catch (error) {\n if (error instanceof z.ZodError) {\n const formattedErrors = formatCorsValidationErrors(error);\n throw new Error(`Invalid CORS options:\\n${formattedErrors}`);\n }\n throw new Error(`Invalid CORS options: ${String(error)}`);\n }\n}\n\n/**\n * Format Zod validation errors for CORS options\n */\nfunction formatCorsValidationErrors(error: z.ZodError): string {\n const errors = error.errors.map(err => {\n const path = err.path.join('.');\n return ` - ${path || 'root'}: ${err.message}`;\n });\n return errors.join('\\n');\n}\n\n/**\n * Type guards for origin types\n * Note: These guards work with the union type, not recursive arrays\n */\nexport function isOriginString(origin: unknown): origin is string {\n return typeof origin === 'string';\n}\n\nexport function isOriginRegExp(origin: unknown): origin is RegExp {\n return origin instanceof RegExp;\n}\n\nexport function isOriginFunction(\n origin: unknown\n): origin is (origin: string, ctx?: Context<any, any>) => boolean | Promise<boolean> {\n return typeof origin === 'function';\n}\n\nexport function isOriginArray(\n origin: unknown\n): origin is Array<\n string | RegExp | ((origin: string, ctx?: Context<any, any>) => boolean | Promise<boolean>)\n> {\n return Array.isArray(origin);\n}\n\n/**\n * Validate that wildcard (*) is not used with credentials\n * This is a security requirement per W3C CORS specification\n */\nexport function validateOriginSecurity(options: CorsOptions): void {\n if (options.credentials === true && options.origin !== undefined) {\n if (options.origin === true || options.origin === '*') {\n throw new Error(\n 'CORS security violation: Cannot use wildcard origin (*) with credentials. ' +\n 'When credentials are enabled, you must specify explicit origins.'\n );\n }\n\n // Check for wildcard in array\n if (isOriginArray(options.origin)) {\n const hasWildcard = options.origin.some(o => o === '*');\n if (hasWildcard) {\n throw new Error(\n 'CORS security violation: Cannot include wildcard origin (*) in array when credentials are enabled.'\n );\n }\n }\n }\n}\n\n/**\n * Merge user options with defaults\n */\nexport function mergeCorsOptions(\n userOptions: CorsOptions | boolean | undefined,\n defaults: CorsOptions\n): CorsOptions {\n // Handle boolean shortcuts\n if (userOptions === true) {\n return { ...defaults, origin: true };\n }\n if (userOptions === false) {\n return { origin: false };\n }\n if (!userOptions) {\n return defaults;\n }\n\n // Merge with defaults\n return {\n ...defaults,\n ...userOptions,\n // Special handling for methods and headers to avoid overwriting with undefined\n methods: userOptions.methods ?? defaults.methods,\n allowedHeaders: userOptions.allowedHeaders ?? defaults.allowedHeaders,\n exposedHeaders: userOptions.exposedHeaders ?? defaults.exposedHeaders,\n };\n}\n","/**\n * CORS Middleware for BlaizeJS\n *\n * W3C-compliant CORS implementation with origin validation, preflight handling,\n * and proper error responses. Must run early in middleware chain before SSE.\n */\nimport { ForbiddenError } from '../../errors/forbidden-error';\nimport { create as createMiddleware } from '../create';\nimport { getDefaultCorsOptions } from './defaults';\nimport { validateOrigin } from './origin-validator';\nimport { handlePreflight, isPreflightRequest } from './preflight';\nimport { validateCorsOptions, mergeCorsOptions, validateOriginSecurity } from './validation';\n\nimport type { Context } from '@blaize-types/context';\nimport type { CorsOptions } from '@blaize-types/cors';\nimport type { BlaizeLogger } from '@blaize-types/logger';\nimport type { Middleware, NextFunction } from '@blaize-types/middleware';\n\n/**\n * Set CORS headers for simple (non-preflight) requests\n */\nfunction setCorsHeaders(\n ctx: Context,\n options: CorsOptions,\n origin: string | undefined,\n originAllowed: boolean\n): void {\n // Only set headers if origin is allowed\n if (!originAllowed || !origin) {\n return;\n }\n\n // Set origin header\n if (options.origin === true && !options.credentials) {\n // Wildcard allowed when credentials not enabled\n ctx.response.header('Access-Control-Allow-Origin', '*');\n } else {\n // Reflect the specific origin\n ctx.response.header('Access-Control-Allow-Origin', origin);\n // Add Vary header when origin is dynamic\n ctx.response.header('Vary', 'Origin');\n }\n\n // Set credentials header if enabled\n if (options.credentials) {\n ctx.response.header('Access-Control-Allow-Credentials', 'true');\n }\n\n // Set exposed headers if specified\n if (options.exposedHeaders) {\n const headers =\n typeof options.exposedHeaders === 'string'\n ? options.exposedHeaders\n : options.exposedHeaders.join(', ');\n ctx.response.header('Access-Control-Expose-Headers', headers);\n }\n}\n\n/**\n * Create CORS middleware with the specified options\n *\n * @param userOptions - CORS configuration options or boolean\n * @returns Middleware function that handles CORS\n *\n * @example\n * ```typescript\n * import { cors } from '@blaize-core/middleware/cors';\n *\n * // Development mode - allow all origins\n * server.use(cors(true));\n *\n * // Production - specific origin\n * server.use(cors({\n * origin: 'https://app.example.com',\n * credentials: true,\n * maxAge: 86400\n * }));\n *\n * // Multiple origins with regex\n * server.use(cors({\n * origin: [\n * 'https://app.example.com',\n * /^https:\\/\\/.*\\.example\\.com$/\n * ]\n * }));\n *\n * // Dynamic origin validation\n * server.use(cors({\n * origin: async (origin, ctx) => {\n * return await checkOriginAllowed(origin, ctx.state.user);\n * }\n * }));\n * ```\n */\nexport function cors(userOptions?: CorsOptions | boolean): Middleware {\n // Determine environment\n const isDevelopment = process.env.NODE_ENV === 'development';\n\n // Get defaults based on environment\n const defaults = getDefaultCorsOptions(isDevelopment);\n\n // Merge and validate options\n const options = mergeCorsOptions(userOptions, defaults);\n const validatedOptions = validateCorsOptions(options);\n\n // Security validation\n validateOriginSecurity(validatedOptions);\n\n // Create the middleware using createMiddleware\n return createMiddleware({\n name: 'cors',\n handler: async (ctx: Context, next: NextFunction) => {\n // Extract origin from request\n const origin = ctx.request.header('origin') || ctx.request.header('Origin');\n\n // Check if this is a preflight request\n if (isPreflightRequest(ctx)) {\n // Handle preflight - this may throw ValidationError\n await handlePreflight(ctx, validatedOptions);\n\n // If preflightContinue is false, we're done\n if (!validatedOptions.preflightContinue) {\n return; // Don't call next()\n }\n } else {\n // Simple request - validate origin and set headers\n\n // Skip CORS for same-origin requests (no Origin header)\n if (!origin) {\n // No origin header means same-origin request or non-browser client\n // Continue without CORS headers\n await next();\n return;\n }\n\n // Validate the origin\n const originAllowed = await validateOrigin(origin, validatedOptions.origin || false, ctx);\n\n // If origin is not allowed, return 403 Forbidden\n if (!originAllowed) {\n // Set 403 status\n ctx.response.status(403);\n\n throw new ForbiddenError('CORS validation failed', {\n reason: 'origin_not_allowed',\n origin,\n allowedOrigins: validatedOptions.origin,\n });\n }\n\n // Origin is allowed - set CORS headers\n setCorsHeaders(ctx, validatedOptions, origin, originAllowed);\n }\n\n // Continue to next middleware\n await next();\n },\n debug: process.env.DEBUG?.includes('cors'),\n });\n}\n\n/**\n * Create a strict CORS middleware that denies all cross-origin requests\n * Useful for internal APIs that should never be accessed cross-origin\n */\nexport function corsStrict(): Middleware {\n return cors({ origin: false });\n}\n\n/**\n * Create a permissive CORS middleware for development\n * Allows all origins but logs warnings\n */\nexport function corsDevelopment(): Middleware {\n const baseMiddleware = cors({\n origin: true,\n credentials: false, // Don't allow credentials with wildcard\n methods: ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'],\n maxAge: 3600,\n });\n\n // Create a wrapper middleware that adds the warning\n return createMiddleware({\n name: 'cors-development',\n handler: async (ctx: Context, next: NextFunction, logger: BlaizeLogger) => {\n logger.warn('[CORS] Running in development mode - all origins allowed');\n // Execute the base CORS middleware\n await baseMiddleware.execute(ctx, next, logger);\n },\n debug: baseMiddleware.debug,\n });\n}\n\n/**\n * Create CORS middleware for specific allowed origins\n * Convenience function for common production use case\n */\nexport function corsForOrigins(\n origins: string[],\n options?: Omit<CorsOptions, 'origin'>\n): Middleware {\n return cors({\n ...options,\n origin: origins,\n });\n}\n\n// Re-export types and utilities for convenience\nexport { validateOrigin } from './origin-validator';\nexport { isPreflightRequest } from './preflight';\n","/**\n * Request Logger Middleware\n *\n * Creates a child logger with request context and optionally logs request lifecycle events.\n * This middleware ALWAYS runs FIRST in the middleware chain to ensure all logs have request context.\n *\n * @packageDocumentation\n */\n\nimport { BlaizeError } from '@blaize-types/errors';\n\nimport { create as createMiddleware } from '../../middleware/create';\n\nimport type { RequestLoggerOptions, LogMetadata, BlaizeLogger } from '@blaize-types/logger';\nimport type { Middleware } from '@blaize-types/middleware';\n/**\n * Default safe headers to include when includeHeaders is true\n *\n * These headers are considered safe and do not contain sensitive information.\n * Sensitive headers (authorization, cookie, etc.) are NEVER included, even if\n * they appear in a custom whitelist.\n */\nconst DEFAULT_SAFE_HEADERS = ['accept', 'content-type', 'user-agent', 'x-correlation-id'];\n\n/**\n * Headers that are ALWAYS redacted, regardless of whitelist\n *\n * These headers may contain sensitive authentication or session information\n * and must never be logged for security reasons.\n */\nconst ALWAYS_REDACT_HEADERS = ['authorization', 'cookie', 'x-api-key', 'proxy-authorization'];\n\n/**\n * Filter headers based on whitelist and redaction rules\n *\n * @param headers - Request headers\n * @param whitelist - Allowed header names (case-insensitive)\n * @returns Filtered headers with sensitive values redacted\n */\nfunction filterHeaders(\n headers: Record<string, string | undefined>,\n whitelist: string[]\n): LogMetadata {\n const filtered: LogMetadata = {};\n\n // Create case-insensitive sets for efficient lookup\n const whitelistLower = new Set(whitelist.map(h => h.toLowerCase()));\n const redactSetLower = new Set(ALWAYS_REDACT_HEADERS.map(h => h.toLowerCase()));\n\n for (const [name, value] of Object.entries(headers)) {\n const nameLower = name.toLowerCase();\n\n // Check if header is in whitelist\n if (whitelistLower.has(nameLower)) {\n // Check if header should be redacted (security override)\n if (redactSetLower.has(nameLower)) {\n filtered[name] = '[REDACTED]';\n } else {\n filtered[name] = value;\n }\n }\n }\n\n return filtered;\n}\n\n/**\n * Request logger middleware factory\n *\n * Creates middleware that:\n * 1. ALWAYS creates a child logger with request context (correlationId, method, path, ip)\n * 2. Replaces ctx.services.log with the child logger\n * 3. Optionally logs request lifecycle events if requestLogging is true\n *\n * The child logger ensures that all logs during the request lifecycle automatically\n * include request context, even if requestLogging is false.\n *\n * @param options - Request logger options (headers, query, etc.)\n * @returns Middleware function\n *\n * @example Basic Usage (with lifecycle logging)\n * ```typescript\n * import { createServer } from 'blaizejs';\n * import { requestLoggerMiddleware } from './logger/middleware';\n *\n * const server = createServer({\n * port: 3000,\n * logging: {\n * level: 'info',\n * requestLogging: true, // Enable lifecycle logs\n * requestLoggerOptions: {\n * includeHeaders: true,\n * includeQuery: true\n * }\n * }\n * });\n * ```\n *\n * @example Without Lifecycle Logging\n * ```typescript\n * const server = createServer({\n * logging: {\n * level: 'info',\n * requestLogging: false // No automatic logs, but ctx.services.log still has request context\n * }\n * });\n *\n * // In route handler:\n * export const GET = appRoute.get({\n * handler: async (ctx) => {\n * // ctx.services.log still includes correlationId, method, path automatically\n * ctx.services.log.info('Custom log message');\n * return { data: 'response' };\n * }\n * });\n * ```\n *\n * @example With Header Filtering\n * ```typescript\n * const middleware = requestLoggerMiddleware({\n * includeHeaders: true,\n * headerWhitelist: ['content-type', 'user-agent', 'accept']\n * }, true);\n *\n * // Logs will include only whitelisted headers\n * // Sensitive headers (authorization, cookie) are ALWAYS redacted\n * ```\n */\nexport function requestLoggerMiddleware(options?: RequestLoggerOptions): Middleware {\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n return createMiddleware<{}, {}>({\n name: 'requestLogger',\n handler: async (ctx, next, logger: BlaizeLogger) => {\n // Start timer for duration calculation\n const startTime = Date.now();\n\n // Extract IP address from socket if available\n let ip: string | undefined;\n if ('socket' in ctx.request.raw) {\n ip = ctx.request.raw.socket?.remoteAddress;\n }\n\n // Build metadata for request start log\n const startMeta: LogMetadata = {\n timestamp: new Date().toISOString(),\n };\n\n // Add IP if available\n if (ip) {\n startMeta.ip = ip;\n }\n\n // Add headers if requested\n if (options?.includeHeaders) {\n const whitelist = options.headerWhitelist || DEFAULT_SAFE_HEADERS;\n const allHeaders = ctx.request.headers();\n const safeHeaders = filterHeaders(allHeaders, whitelist);\n\n if (Object.keys(safeHeaders).length > 0) {\n startMeta.headers = safeHeaders;\n }\n }\n\n // Add query parameters if requested\n if (options?.includeQuery) {\n const query = ctx.request.query;\n if (query && Object.keys(query).length > 0) {\n startMeta.query = query;\n }\n }\n\n // Log request started (if lifecycle logging enabled)\n logger.info('Request started', startMeta);\n\n // Execute middleware chain and capture result/error\n let error: unknown;\n try {\n await next();\n } catch (err) {\n error = err;\n } finally {\n // Log request completed/failed (if lifecycle logging enabled)\n const duration = Date.now() - startTime;\n\n if (error) {\n // Request failed - log error details\n const errorMeta: LogMetadata = {\n duration,\n timestamp: new Date().toISOString(),\n };\n\n // Extract error details based on error type\n if (error instanceof BlaizeError) {\n // BlaizeError has structured error information\n errorMeta.error = {\n type: error.type,\n title: error.title,\n status: error.status,\n message: error.message,\n details: error.details,\n // Include stack trace for server errors (5xx)\n ...(error.status >= 500 && error.stack ? { stack: error.stack } : {}),\n };\n } else if (error instanceof Error) {\n // Standard Error object\n errorMeta.error = {\n message: error.message,\n name: error.name,\n stack: error.stack,\n };\n } else {\n // Non-Error value thrown\n errorMeta.error = String(error);\n }\n\n logger.error('Request failed', errorMeta);\n } else {\n // Request completed successfully\n const statusCode = ctx.response.statusCode || 200;\n\n logger.info('Request completed', {\n statusCode,\n duration,\n timestamp: new Date().toISOString(),\n });\n }\n\n // Re-throw error if one occurred\n if (error) {\n // eslint-disable-next-line no-unsafe-finally\n throw error;\n }\n }\n },\n });\n}\n","/* eslint-disable @typescript-eslint/no-empty-object-type */\nimport { createLogger } from '../logger';\n\nimport type { Plugin, PluginFactory, CreatePluginOptions, BlaizeLogger } from '@blaize-types/index';\n\n/**\n * Create a type-safe plugin with full IntelliSense support\n *\n * This is the primary way to create plugins in BlaizeJS. It provides:\n * - IntelliSense for all lifecycle hooks\n * - Automatic config merging with defaults\n * - Full type safety for state and services\n * - Consistent DX with createMiddleware\n *\n * @template TConfig - Plugin configuration shape\n * @template TState - State added to context (default: {})\n * @template TServices - Services added to context (default: {})\n *\n * @param options - Plugin creation options\n * @returns Plugin factory function\n *\n * @example Basic plugin with config\n * ```typescript\n * const createDbPlugin = createPlugin<\n * { host: string; port: number },\n * {},\n * { db: Database }\n * >({\n * name: '@my-app/database',\n * version: '1.0.0',\n * defaultConfig: {\n * host: 'localhost',\n * port: 5432,\n * },\n * setup: (config) => {\n * let db: Database;\n *\n * return {\n * register: async (server) => {\n * // Add typed middleware\n * server.use(createMiddleware<{}, { db: Database }>({\n * handler: async (ctx, next) => {\n * ctx.services.db = db;\n * await next();\n * },\n * }));\n * },\n *\n * initialize: async () => {\n * db = await Database.connect(config);\n * },\n *\n * terminate: async () => {\n * await db?.close();\n * },\n * };\n * },\n * });\n *\n * // Usage\n * const plugin = createDbPlugin({ host: 'prod.db.com' });\n * ```\n *\n * @example Simple plugin without config\n * ```typescript\n * const loggerPlugin = createPlugin<{}, {}, { logger: Logger }>({\n * name: '@my-app/logger',\n * version: '1.0.0',\n * setup: () => ({\n * initialize: async () => {\n * console.log('Logger initialized');\n * },\n * }),\n * });\n *\n * // Usage (no config needed)\n * const plugin = loggerPlugin();\n * ```\n */\nexport function createPlugin<TConfig = {}, TState = {}, TServices = {}>(\n options: CreatePluginOptions<TConfig, TState, TServices>\n): PluginFactory<TConfig, TState, TServices> {\n // Validate inputs\n if (!options.name || typeof options.name !== 'string') {\n throw new Error('Plugin name must be a non-empty string');\n }\n\n if (!options.version || typeof options.version !== 'string') {\n throw new Error('Plugin version must be a non-empty string');\n }\n\n if (typeof options.setup !== 'function') {\n throw new Error('Plugin setup must be a function');\n }\n\n // Return factory function\n return function pluginFactory(userConfig?: Partial<TConfig>): Plugin<TState, TServices> {\n // Merge config (defaultConfig + userConfig)\n const config = {\n ...(options.defaultConfig || ({} as TConfig)),\n ...(userConfig || {}),\n } as TConfig;\n\n // Create plugin-specific child logger with context\n const pluginLogger: BlaizeLogger = createLogger().child({\n plugin: options.name,\n version: options.version,\n });\n\n // Call setup to get hooks\n const hooks = options.setup(config, pluginLogger);\n\n // Validate hooks (must return object)\n if (hooks === null || typeof hooks !== 'object') {\n throw new Error(\n `Plugin \"${options.name}\" setup() must return an object with lifecycle hooks`\n );\n }\n\n // Build plugin with all hooks\n const plugin: Plugin<TState, TServices> = {\n name: options.name,\n version: options.version,\n\n // Required hook (always present, even if empty)\n register:\n hooks.register ||\n (async () => {\n pluginLogger.debug('Plugin registered (no-op)');\n }),\n\n // Optional hooks (undefined if not provided)\n initialize: hooks.initialize,\n onServerStart: hooks.onServerStart,\n onServerStop: hooks.onServerStop,\n terminate: hooks.terminate,\n };\n\n return plugin;\n };\n}\n\n// Re-export for backward compatibility (deprecate later)\nexport { createPlugin as create };\n","import { fileURLToPath } from 'node:url';\n\nimport { getRoutesDir } from '../config';\nimport { parseRoutePath } from './discovery/parser';\nimport { createSSERoute } from '../sse/create';\n\nimport type {\n CreateGetRoute,\n CreatePostRoute,\n CreatePutRoute,\n CreateDeleteRoute,\n CreatePatchRoute,\n CreateHeadRoute,\n CreateOptionsRoute,\n State,\n Services,\n} from '@blaize-types/index';\n\n/**\n * Get the file path of the function that called createXRoute\n */\nfunction getCallerFilePath(): string {\n const originalPrepareStackTrace = Error.prepareStackTrace;\n\n try {\n Error.prepareStackTrace = (_, stack) => stack;\n const stack = new Error().stack as unknown as NodeJS.CallSite[];\n\n // Stack: getCallerFilePath -> createXRoute -> route file\n const callerFrame = stack[3];\n if (!callerFrame || typeof callerFrame.getFileName !== 'function') {\n throw new Error('Unable to determine caller file frame');\n }\n const fileName = callerFrame.getFileName();\n\n if (!fileName) {\n throw new Error('Unable to determine caller file name');\n }\n\n if (fileName.startsWith('file://')) {\n return fileURLToPath(fileName);\n }\n\n return fileName;\n } finally {\n Error.prepareStackTrace = originalPrepareStackTrace;\n }\n}\n\n/**\n * Convert caller file path to route path using existing parsing logic\n */\nexport function getRoutePath(): string {\n const callerPath = getCallerFilePath();\n const routesDir = getRoutesDir();\n\n const parsedRoute = parseRoutePath(callerPath, routesDir);\n console.log(`🔎 Parsed route path: ${parsedRoute.routePath} from file: ${callerPath}`);\n\n return parsedRoute.routePath;\n}\n\n/**\n * Create a GET route\n * SIMPLER FIX: Just pass the config through, TypeScript will handle the types\n */\nexport const createGetRoute: CreateGetRoute = <\n _TState extends State = State,\n _TServices extends Services = Services,\n>() => {\n return (config: any) => {\n validateMethodConfig('GET', config);\n const path = getRoutePath();\n\n return {\n GET: config,\n path,\n };\n };\n};\n\n/**\n * Create a POST route\n */\nexport const createPostRoute: CreatePostRoute = <\n _TState extends State = State,\n _TServices extends Services = Services,\n>() => {\n return (config: any) => {\n validateMethodConfig('POST', config);\n const path = getRoutePath();\n\n return {\n POST: config,\n path,\n };\n };\n};\n\n/**\n * Create a PUT route\n */\nexport const createPutRoute: CreatePutRoute = <\n _TState extends State = State,\n _TServices extends Services = Services,\n>() => {\n return (config: any) => {\n validateMethodConfig('PUT', config);\n const path = getRoutePath();\n\n return {\n PUT: config,\n path,\n };\n };\n};\n\n/**\n * Create a DELETE route\n */\nexport const createDeleteRoute: CreateDeleteRoute = <\n _TState extends State = State,\n _TServices extends Services = Services,\n>() => {\n return (config: any) => {\n validateMethodConfig('DELETE', config);\n const path = getRoutePath();\n\n return {\n DELETE: config,\n path,\n };\n };\n};\n\n/**\n * Create a PATCH route\n */\nexport const createPatchRoute: CreatePatchRoute = <\n _TState extends State = State,\n _TServices extends Services = Services,\n>() => {\n return (config: any) => {\n validateMethodConfig('PATCH', config);\n const path = getRoutePath();\n\n return {\n PATCH: config,\n path,\n };\n };\n};\n\n/**\n * Create a HEAD route (same signature as GET - no body)\n */\nexport const createHeadRoute: CreateHeadRoute = <\n _TState extends State = State,\n _TServices extends Services = Services,\n>() => {\n return (config: any) => {\n validateMethodConfig('HEAD', config);\n const path = getRoutePath();\n\n return {\n HEAD: config,\n path,\n };\n };\n};\n\n/**\n * Create an OPTIONS route (same signature as GET - no body)\n */\nexport const createOptionsRoute: CreateOptionsRoute = <\n _TState extends State = State,\n _TServices extends Services = Services,\n>() => {\n return (config: any) => {\n validateMethodConfig('OPTIONS', config);\n const path = getRoutePath();\n\n return {\n OPTIONS: config,\n path,\n };\n };\n};\n\n/**\n * Validate a method configuration\n */\nfunction validateMethodConfig(method: string, config: any): void {\n if (!config.handler || typeof config.handler !== 'function') {\n throw new Error(`Handler for method ${method} must be a function`);\n }\n\n if (config.middleware && !Array.isArray(config.middleware)) {\n throw new Error(`Middleware for method ${method} must be an array`);\n }\n\n // Validate schema if provided\n if (config.schema) {\n validateSchema(method, config.schema);\n }\n\n // Method-specific warnings\n switch (method) {\n case 'GET':\n case 'HEAD':\n case 'DELETE':\n if (config.schema?.body) {\n console.warn(`Warning: ${method} requests typically don't have request bodies`);\n }\n break;\n }\n}\n\n/**\n * Validate schema structure\n */\nfunction validateSchema(method: string, schema: any): void {\n const { params, query, body, response } = schema;\n\n // Basic validation - ensure they look like Zod schemas if provided\n if (params && (!params._def || typeof params.parse !== 'function')) {\n throw new Error(`Params schema for ${method} must be a valid Zod schema`);\n }\n\n if (query && (!query._def || typeof query.parse !== 'function')) {\n throw new Error(`Query schema for ${method} must be a valid Zod schema`);\n }\n\n if (body && (!body._def || typeof body.parse !== 'function')) {\n throw new Error(`Body schema for ${method} must be a valid Zod schema`);\n }\n\n if (response && (!response._def || typeof response.parse !== 'function')) {\n throw new Error(`Response schema for ${method} must be a valid Zod schema`);\n }\n}\n\n/**\n * Factory that creates all route methods with consistent types\n * This is the RECOMMENDED approach for most applications\n *\n * Usage in server.ts:\n * ```typescript\n * export const route = createRouteFactory<AppState, AppServices>();\n * ```\n *\n * Usage in route files:\n * ```typescript\n * import { route } from '../server';\n *\n * export const GET = route.get({\n * handler: async (ctx) => {\n * // ctx.state and ctx.services are fully typed!\n * }\n * });\n * ```\n */\nexport function createRouteFactory<\n TState extends State = State,\n TServices extends Services = Services,\n>() {\n return {\n get: createGetRoute<TState, TServices>(),\n post: createPostRoute<TState, TServices>(),\n put: createPutRoute<TState, TServices>(),\n delete: createDeleteRoute<TState, TServices>(),\n patch: createPatchRoute<TState, TServices>(),\n head: createHeadRoute<TState, TServices>(),\n options: createOptionsRoute<TState, TServices>(),\n sse: createSSERoute<TState, TServices>(),\n } as const;\n}\n\n/**\n * Type guard to check if a value is a route factory\n */\nexport function isRouteFactory(value: any): value is ReturnType<typeof createRouteFactory> {\n return (\n value &&\n typeof value === 'object' &&\n 'get' in value &&\n 'post' in value &&\n 'put' in value &&\n 'delete' in value &&\n 'patch' in value &&\n 'head' in value &&\n 'options' in value\n );\n}\n","// config/runtime-config.ts\ninterface RuntimeConfig {\n routesDir?: string;\n basePath?: string;\n // Add other runtime configuration as needed\n}\n\n// Internal state - not exported\nlet config: RuntimeConfig = {};\n\n/**\n * Set runtime configuration\n */\nexport function setRuntimeConfig(newConfig: Partial<RuntimeConfig>): void {\n config = { ...config, ...newConfig };\n}\n\n/**\n * Get full runtime configuration\n */\nexport function getRuntimeConfig(): RuntimeConfig {\n return { ...config };\n}\n\n/**\n * Get the configured routes directory\n */\nexport function getRoutesDir(): string {\n if (!config.routesDir) {\n throw new Error('Routes directory not configured. Make sure server is properly initialized.');\n }\n return config.routesDir;\n}\n\n/**\n * Get the configured base path\n */\nexport function getBasePath(): string {\n return config.basePath || '';\n}\n\n/**\n * Clear configuration (useful for testing)\n */\nexport function clearRuntimeConfig(): void {\n config = {};\n}\n","import * as path from 'node:path';\n\nimport type { ParsedRoute } from '@blaize-types/router';\n\n/**\n * Parse a file path into a route path\n * Works consistently across Windows and Unix-like file systems\n */\nexport function parseRoutePath(filePath: string, basePath: string): ParsedRoute {\n // Clean file:// URLs if present\n if (filePath.startsWith('file://')) {\n filePath = filePath.replace('file://', '');\n }\n if (basePath.startsWith('file://')) {\n basePath = basePath.replace('file://', '');\n }\n\n // Convert all backslashes to forward slashes for consistent handling\n const forwardSlashFilePath = filePath.replace(/\\\\/g, '/');\n const forwardSlashBasePath = basePath.replace(/\\\\/g, '/');\n\n // Ensure the base path ends with a slash for proper prefix removal\n const normalizedBasePath = forwardSlashBasePath.endsWith('/')\n ? forwardSlashBasePath\n : `${forwardSlashBasePath}/`;\n\n // Remove the base path to get the relative path\n let relativePath = forwardSlashFilePath;\n if (forwardSlashFilePath.startsWith(normalizedBasePath)) {\n relativePath = forwardSlashFilePath.substring(normalizedBasePath.length);\n } else if (forwardSlashFilePath.startsWith(forwardSlashBasePath)) {\n relativePath = forwardSlashFilePath.substring(forwardSlashBasePath.length);\n // If base path didn't end with a slash but we still matched, ensure relative path doesn't start with a slash\n if (relativePath.startsWith('/')) {\n relativePath = relativePath.substring(1);\n }\n } else {\n // If base path isn't a prefix of file path, use path.relative as a fallback\n // But convert to forward slashes for consistency\n relativePath = path.relative(forwardSlashBasePath, forwardSlashFilePath).replace(/\\\\/g, '/');\n }\n\n // Remove file extension (anything after the last dot)\n relativePath = relativePath.replace(/\\.[^.]+$/, '');\n\n // Split the path into segments\n const segments = relativePath.split('/').filter(Boolean);\n const params: string[] = [];\n\n // Transform file path segments to route path segments\n const routeSegments = segments.map(segment => {\n // Handle dynamic parameters ([param])\n if (segment.startsWith('[') && segment.endsWith(']')) {\n const paramName = segment.slice(1, -1);\n params.push(paramName);\n return `:${paramName}`;\n }\n return segment;\n });\n\n // Create the final route path\n let routePath = routeSegments.length > 0 ? `/${routeSegments.join('/')}` : '/';\n\n // Handle index routes\n if (routePath.endsWith('/index')) {\n routePath = routePath.slice(0, -6) || '/';\n }\n\n return {\n filePath,\n routePath,\n params,\n };\n}\n","/**\n * @module sse/stream\n * @description SSE Stream implementation with backpressure management\n *\n * Provides a functional SSE stream implementation with:\n * - Automatic connection registry integration\n * - Configurable buffer management strategies\n * - Memory-efficient event handling\n * - Automatic cleanup on disconnect\n */\n\nimport { EventEmitter } from 'node:events';\n\nimport { BackpressureConfigSchema, type BackpressureConfig } from './back-pressure';\nimport { getConnectionRegistry } from './connection-registry';\nimport { SSEBufferOverflowError } from '../errors/sse-buffer-overflow-error';\nimport { SSEStreamClosedError } from '../errors/sse-stream-closed-error';\nimport { getCorrelationId } from '../tracing/correlation';\n\nimport type { Context } from '@blaize-types/context';\nimport type {\n SSEStreamExtended,\n SSEConnectionState,\n SSEOptions,\n SSEBufferStrategy,\n BufferedEvent,\n StreamMetrics,\n} from '@blaize-types/sse';\n\n/**\n * Default SSE options with production-ready defaults\n */\nconst DEFAULT_OPTIONS: Required<SSEOptions> = {\n heartbeatInterval: 30000, // 30 seconds - prevents proxy/firewall timeouts\n maxEventSize: 1024 * 1024, // 1MB - generous but prevents memory attacks\n autoClose: true, // Clean up resources on disconnect\n maxBufferSize: 1000, // 1000 events - reasonable for most use cases\n bufferStrategy: 'drop-oldest' as SSEBufferStrategy, // Prefer fresh data\n};\n\n/**\n * Format SSE event for wire protocol\n * @internal\n */\nfunction formatSSEEvent(event: string, data: unknown, id?: string, retry?: number): string {\n const lines: string[] = [];\n\n if (id) {\n lines.push(`id: ${id}`);\n }\n\n if (retry !== undefined) {\n lines.push(`retry: ${retry}`);\n }\n\n lines.push(`event: ${event}`);\n\n // Handle multi-line data - handle null/undefined gracefully\n const dataStr =\n data === null\n ? 'null'\n : data === undefined\n ? 'undefined'\n : typeof data === 'string'\n ? data\n : JSON.stringify(data);\n const dataLines = dataStr.split('\\n');\n for (const line of dataLines) {\n lines.push(`data: ${line}`);\n }\n\n lines.push(''); // Empty line to terminate event\n return lines.join('\\n') + '\\n';\n}\n\n/**\n * Create event ID\n * @internal\n */\nfunction createEventId(): string {\n const timestamp = Date.now().toString(36);\n const random = Math.random().toString(36).substr(2, 9);\n return `${timestamp}-${random}`;\n}\n\n/**\n * Estimate event size in bytes\n * @internal\n */\nfunction estimateEventSize(event: string, data: unknown): number {\n const dataStr =\n data === null\n ? 'null'\n : data === undefined\n ? 'undefined'\n : typeof data === 'string'\n ? data\n : JSON.stringify(data);\n // Rough estimate: event name + data + SSE formatting overhead\n return event.length + dataStr.length + 50; // 50 bytes for SSE protocol overhead\n}\n\n/**\n * Apply buffer strategy when buffer is full\n * @internal\n */\nfunction applyBufferStrategy(\n buffer: BufferedEvent[],\n strategy: SSEBufferStrategy,\n newEvent: BufferedEvent,\n maxSize: number\n): { buffer: BufferedEvent[]; dropped: number } {\n let dropped = 0;\n\n switch (strategy) {\n case 'drop-oldest': {\n // Remove oldest events to make room\n while (buffer.length >= maxSize && buffer.length > 0) {\n buffer.shift();\n dropped++;\n }\n buffer.push(newEvent);\n break;\n }\n\n case 'drop-newest': {\n // Reject the new event if buffer is full\n if (buffer.length >= maxSize) {\n dropped = 1;\n // Don't add the new event\n } else {\n buffer.push(newEvent);\n }\n break;\n }\n\n case 'close': {\n // This strategy will be handled by the caller\n // by throwing an error\n break;\n }\n\n default:\n // Default to drop-oldest\n while (buffer.length >= maxSize && buffer.length > 0) {\n buffer.shift();\n dropped++;\n }\n buffer.push(newEvent);\n }\n\n return { buffer, dropped };\n}\n\n/**\n * SSE Stream implementation using functional patterns\n */\nclass SSEStreamImpl implements SSEStreamExtended {\n readonly id: string;\n private _state: SSEConnectionState = 'connecting';\n private _buffer: BufferedEvent[] = [];\n private _closeCallbacks: Array<() => void | Promise<void>> = [];\n private _errorCallbacks: Array<(error: Error) => void> = [];\n private _emitter = new EventEmitter();\n private _metrics: StreamMetrics;\n private _options: Required<SSEOptions>;\n private _response: Context['response'];\n private _request: Context['request'];\n private _writable: boolean = true;\n private _cleanupExecuted = false;\n private _eventCounter = 0;\n private _lastEventId: string | null = null;\n private _heartbeatTimer?: NodeJS.Timeout;\n private _backpressureConfig?: BackpressureConfig;\n private _disconnectHandlers: {\n req: { close: () => void; error: () => void };\n res: { close: () => void; error: () => void };\n } | null = null;\n\n constructor(ctx: Context, options: SSEOptions = {}) {\n this.id = `sse-${createEventId()}`;\n this._options = { ...DEFAULT_OPTIONS, ...options };\n this._response = ctx.response;\n this._request = ctx.request;\n\n // Parse and validate backpressure config if provided\n if ((options as any).backpressure) {\n const result = BackpressureConfigSchema.safeParse((options as any).backpressure);\n if (result.success) {\n this._backpressureConfig = result.data;\n // Override simple options with backpressure config values\n this._options.maxBufferSize = result.data.limits.maxMessages;\n this._options.bufferStrategy = result.data.strategy;\n }\n }\n\n // Handle Last-Event-ID header for reconnection\n const lastEventId = ctx.request.header('last-event-id');\n if (lastEventId) {\n this._eventCounter = parseInt(lastEventId) || 0;\n this._lastEventId = lastEventId;\n }\n\n // Initialize metrics\n this._metrics = {\n eventsSent: 0,\n eventsDropped: 0,\n bytesWritten: 0,\n bufferHighWatermark: 0,\n lastEventTime: Date.now(),\n };\n\n // CRITICAL: Do all operations that might throw BEFORE setting headers\n\n // 1. Try to register with connection registry FIRST\n // This can throw if connection limits are exceeded\n try {\n const registry = getConnectionRegistry();\n const metadata = {\n clientIp:\n this._request.header('x-forwarded-for') ||\n this._request.header('x-real-ip') ||\n (this._request.raw as any).socket?.remoteAddress,\n userAgent: this._request.header('user-agent'),\n };\n\n registry.add(this.id, this, metadata);\n } catch (error) {\n // If registration fails (e.g., connection limit), fail immediately\n // BEFORE setting any headers\n this._state = 'closed';\n this._writable = false;\n console.error('[SSE] Failed to register connection:', error);\n throw error;\n }\n\n // 2. Set up disconnect handling (shouldn't throw, but do it before headers)\n this._setupDisconnectHandling();\n\n // 3. NOW we can safely set SSE headers\n // If anything above threw, we haven't sent headers yet\n this._response\n .status(200)\n .header('Content-Type', 'text/event-stream')\n .header('Cache-Control', 'no-cache')\n .header('X-Accel-Buffering', 'no'); // Disable Nginx buffering\n\n // Only set Connection header for HTTP/1.x\n if (!this._request.raw.httpVersionMajor || this._request.raw.httpVersionMajor < 2) {\n this._response.header('Connection', 'keep-alive');\n }\n\n // 4. Set up heartbeat if configured (after headers are sent)\n if (this._options.heartbeatInterval && this._options.heartbeatInterval > 0) {\n this._setupHeartbeat(this._options.heartbeatInterval);\n }\n\n // 5. Transition to connected state\n this._state = 'connected';\n\n // 6. Send initial comment to establish connection\n this._writeRaw(`: SSE connection established\\n\\n`);\n }\n\n /**\n * Register connection with the internal registry\n * @internal\n */\n private _registerConnection(): void {\n try {\n const registry = getConnectionRegistry();\n const metadata = {\n clientIp:\n this._request.header('x-forwarded-for') ||\n this._request.header('x-real-ip') ||\n (this._request.raw as any).socket?.remoteAddress,\n userAgent: this._request.header('user-agent'),\n };\n\n registry.add(this.id, this, metadata);\n } catch (error) {\n // If registration fails (e.g., connection limit), close immediately\n this._state = 'closed';\n this._writable = false;\n throw error;\n }\n }\n\n /**\n * Set up heartbeat timer\n * @internal\n */\n private _setupHeartbeat(interval: number): void {\n this._heartbeatTimer = global.setInterval(() => {\n if (this.isWritable) {\n const idleTime = Date.now() - this._metrics.lastEventTime;\n // Only send heartbeat if no recent activity\n if (idleTime > interval * 0.9) {\n this.ping(`heartbeat ${new Date().toISOString()}`);\n }\n }\n }, interval);\n\n // Ensure timer doesn't prevent process exit\n if (this._heartbeatTimer.unref) {\n this._heartbeatTimer.unref();\n }\n }\n\n /**\n * Set up automatic disconnect detection\n * @internal\n */\n private _setupDisconnectHandling(): void {\n const req = this._request.raw;\n const res = this._response.raw;\n\n // Handle client disconnect\n const handleDisconnect = () => {\n if (this._options.autoClose && this._state !== 'closed') {\n this.close();\n }\n };\n\n // Store handlers for cleanup\n this._disconnectHandlers = {\n req: { close: handleDisconnect, error: handleDisconnect },\n res: { close: handleDisconnect, error: handleDisconnect },\n };\n\n // Listen for various disconnect signals\n req.on('close', this._disconnectHandlers.req.close);\n req.on('error', this._disconnectHandlers.req.error);\n res.on('close', this._disconnectHandlers.res.close);\n res.on('error', this._disconnectHandlers.res.error);\n }\n\n /**\n * Write raw data to the response stream\n * @internal\n */\n private _writeRaw(data: string): boolean {\n if (!this._writable || this._state === 'closed') {\n return false;\n }\n\n try {\n const res = this._response.raw;\n // Handle the write method with proper typing for both HTTP/1.1 and HTTP/2\n let written: boolean;\n\n if ('write' in res && typeof res.write === 'function') {\n // Call write with just the data parameter to avoid signature conflicts\n written = (res as any).write(data);\n } else {\n throw new Error('Response stream does not support write operation');\n }\n\n if (written) {\n this._metrics.bytesWritten += Buffer.byteLength(data);\n }\n\n return written;\n } catch (error) {\n this._writable = false;\n this._handleError(error as Error);\n return false;\n }\n }\n\n /**\n * Process and send buffered events\n * @internal\n */\n private async _flushBuffer(): Promise<void> {\n while (this._buffer.length > 0 && this._writable) {\n const event = this._buffer.shift();\n if (!event) break;\n\n const formatted = formatSSEEvent(event.event, event.data, event.id);\n\n if (!this._writeRaw(formatted)) {\n // If write failed, put event back and wait for drain\n this._buffer.unshift(event);\n await this._waitForDrain();\n } else {\n this._metrics.eventsSent++;\n this._metrics.lastEventTime = Date.now();\n }\n }\n }\n\n /**\n * Wait for the response stream to drain\n * @internal\n */\n private _waitForDrain(): Promise<void> {\n return new Promise(resolve => {\n const res = this._response.raw;\n res.once('drain', resolve);\n });\n }\n\n /**\n * Handle internal errors\n * @internal\n */\n private _handleError(error: Error): void {\n this._errorCallbacks.forEach(cb => {\n try {\n cb(error);\n } catch (err) {\n console.error('Error in error callback:', err);\n }\n });\n\n // Send error event if still writable\n if (this._writable) {\n this.sendError(error);\n }\n }\n\n /**\n * Execute cleanup operations\n * @internal\n */\n private _executeCleanup(): void {\n if (this._cleanupExecuted) return;\n this._cleanupExecuted = true;\n\n // Clear heartbeat timer\n if (this._heartbeatTimer) {\n global.clearInterval(this._heartbeatTimer);\n this._heartbeatTimer = undefined;\n }\n\n // Remove event listeners\n if (this._disconnectHandlers) {\n const req = this._request.raw;\n const res = this._response.raw;\n\n req.removeListener('close', this._disconnectHandlers.req.close);\n req.removeListener('error', this._disconnectHandlers.req.error);\n res.removeListener('close', this._disconnectHandlers.res.close);\n res.removeListener('error', this._disconnectHandlers.res.error);\n\n this._disconnectHandlers = null;\n }\n\n // Deregister from connection registry\n try {\n const registry = getConnectionRegistry();\n registry.remove(this.id);\n } catch (error) {\n // Ignore registry errors during cleanup\n console.error('Registry cleanup error:', error);\n }\n\n // Execute close callbacks synchronously\n // Make a copy to avoid modification during iteration\n const callbacks = [...this._closeCallbacks];\n for (const cb of callbacks) {\n try {\n const result = cb();\n // If it's a promise, catch any errors but don't await\n if (result && typeof result.then === 'function') {\n result.catch((error: Error) => {\n console.error('Error in async close callback:', error);\n });\n }\n } catch (error) {\n console.error('Error in close callback:', error);\n }\n }\n\n // Clear callbacks and buffer\n this._closeCallbacks = [];\n this._errorCallbacks = [];\n this._buffer = [];\n this._emitter.removeAllListeners();\n }\n\n // Public API Implementation\n\n get state(): SSEConnectionState {\n return this._state;\n }\n\n get bufferSize(): number {\n return this._buffer.length;\n }\n\n get isWritable(): boolean {\n return this._writable && this._state === 'connected';\n }\n\n send<T>(event: string, data: T): void {\n if (!this.isWritable) {\n throw new SSEStreamClosedError('Cannot send event to closed stream', {\n clientId: this.id,\n closedAt: new Date().toISOString(),\n closeReason: 'server-close',\n canReconnect: false,\n });\n }\n\n // Use sequential event IDs for proper reconnection support\n const eventId = String(++this._eventCounter);\n this._lastEventId = eventId;\n const correlationId = getCorrelationId();\n const size = estimateEventSize(event, data);\n\n // Validate event size to prevent memory attacks\n const maxEventSize = this._options.maxEventSize;\n if (size > maxEventSize) {\n throw new SSEBufferOverflowError('Event size exceeds maximum allowed', {\n currentSize: size,\n maxSize: maxEventSize,\n strategy: 'close',\n clientId: this.id,\n eventsDropped: 0,\n triggeringEvent: event,\n });\n }\n\n // Create buffered event\n const bufferedEvent: BufferedEvent = {\n id: eventId,\n event,\n data,\n size,\n timestamp: Date.now(),\n correlationId,\n };\n\n // Check buffer limit (use backpressure config if available)\n const maxBuffer = this._backpressureConfig\n ? this._backpressureConfig.watermarks.high\n : this._options.maxBufferSize;\n\n if (this._buffer.length >= maxBuffer) {\n if (this._options.bufferStrategy === 'close') {\n const currentSize = this._buffer.length;\n\n // Close the stream on buffer overflow\n this.close();\n throw new SSEBufferOverflowError('Buffer overflow - stream closed', {\n currentSize,\n maxSize: maxBuffer,\n strategy: 'close',\n clientId: this.id,\n });\n }\n\n // Apply buffer strategy\n const result = applyBufferStrategy(\n this._buffer,\n this._options.bufferStrategy,\n bufferedEvent,\n maxBuffer\n );\n\n this._buffer = result.buffer;\n this._metrics.eventsDropped += result.dropped;\n\n if (result.dropped > 0) {\n console.warn(\n `SSE stream ${this.id}: Dropped ${result.dropped} events due to buffer overflow`\n );\n }\n } else {\n this._buffer.push(bufferedEvent);\n }\n\n // Update high watermark\n this._metrics.bufferHighWatermark = Math.max(\n this._metrics.bufferHighWatermark,\n this._buffer.length\n );\n\n // Emit event for async iterator\n this._emitter.emit('event');\n\n // Try to flush immediately\n this._flushBuffer().catch(error => {\n this._handleError(error as Error);\n });\n }\n\n sendError(error: Error): void {\n if (!this.isWritable) return;\n\n const errorData = {\n message: error.message,\n name: error.name,\n correlationId: getCorrelationId(),\n timestamp: new Date().toISOString(),\n stack: process.env.NODE_ENV === 'development' ? error.stack : undefined,\n };\n\n try {\n this.send('error', errorData);\n } catch (sendError) {\n // If we can't send the error event, just log it\n console.error('Failed to send error event:', sendError);\n }\n }\n\n close(): void {\n if (this._state === 'closed') return;\n\n this._state = 'closed';\n this._writable = false;\n\n // Emit close event for async iterator\n this._emitter.emit('close');\n\n // Send close event if possible\n try {\n const closeEvent = formatSSEEvent('close', {\n reason: 'stream-closed',\n reconnect: false,\n });\n const res = this._response.raw;\n // Use type assertion to handle union type\n if ('write' in res && typeof res.write === 'function') {\n (res as any).write(closeEvent);\n }\n } catch {\n // Ignore errors when sending close event\n }\n\n // End the response\n try {\n const res = this._response.raw;\n if (!res.writableEnded && typeof res.end === 'function') {\n res.end();\n }\n } catch (error) {\n console.error('Error ending response:', error);\n }\n\n // Execute cleanup synchronously\n this._executeCleanup();\n }\n\n onClose(cb: () => void | Promise<void>): void {\n if (this._state === 'closed') {\n // If already closed, execute immediately\n try {\n const result = cb();\n if (result && typeof result.then === 'function') {\n result.catch((error: Error) => {\n console.error('Error in close callback:', error);\n });\n }\n } catch (error) {\n console.error('Error in close callback:', error);\n }\n } else {\n this._closeCallbacks.push(cb);\n }\n }\n\n ping(comment?: string): void {\n if (!this.isWritable) return;\n\n const message = comment ? `: ${comment}\\n\\n` : `: ping\\n\\n`;\n this._writeRaw(message);\n }\n\n setRetry(milliseconds: number): void {\n if (!this.isWritable) return;\n\n if (milliseconds < 0 || !Number.isFinite(milliseconds)) {\n throw new Error('Retry interval must be a positive number');\n }\n\n this._writeRaw(`retry: ${Math.floor(milliseconds)}\\n\\n`);\n }\n\n flush(): void {\n if (!this.isWritable) return;\n\n // Force flush all buffered events\n this._flushBuffer().catch(error => {\n this._handleError(error as Error);\n });\n }\n\n /**\n * Get stream metrics for monitoring\n */\n getMetrics(): StreamMetrics {\n return { ...this._metrics };\n }\n\n /**\n * Create async iterator for generator-based streaming\n * Enables using the stream with for-await-of loops\n */\n async *[Symbol.asyncIterator](): AsyncGenerator<BufferedEvent, void, unknown> {\n while (this.isWritable) {\n // Yield buffered events\n while (this._buffer.length > 0) {\n const event = this._buffer.shift();\n if (event) {\n yield event;\n }\n }\n\n // Wait for next event or close\n await new Promise<void>(resolve => {\n const checkBuffer = () => {\n if (this._buffer.length > 0 || !this.isWritable) {\n this._emitter.off('event', checkBuffer);\n this._emitter.off('close', checkBuffer);\n resolve();\n }\n };\n\n this._emitter.on('event', checkBuffer);\n this._emitter.on('close', checkBuffer);\n });\n }\n }\n}\n\n/**\n * Create an SSE stream with backpressure management\n *\n * This factory function creates a fully-featured SSE stream that:\n * - Automatically registers with the connection registry\n * - Manages buffer overflow with configurable strategies\n * - Handles client disconnections gracefully\n * - Provides async iteration support\n * - Supports reconnection with event ID sequencing\n * - Optional heartbeat for connection health monitoring\n * - Prevents memory attacks via event size validation\n *\n * @param ctx - The request context\n * @param options - Stream configuration options\n * @returns A new SSE stream instance\n *\n * @example Basic usage:\n * ```typescript\n * const stream = createSSEStream(ctx);\n * stream.send('message', { text: 'Hello SSE!' });\n * stream.close();\n * ```\n *\n * @example With custom configuration:\n * ```typescript\n * const stream = createSSEStream(ctx, {\n * heartbeatInterval: 30000, // 30s heartbeat\n * maxEventSize: 512 * 1024, // 512KB max event size\n * maxBufferSize: 100,\n * bufferStrategy: 'drop-oldest',\n * autoClose: true\n * });\n *\n * // Send events with automatic size validation\n * try {\n * stream.send('data', largePayload); // Throws if > maxEventSize\n * } catch (error) {\n * console.error('Event too large:', error);\n * }\n * ```\n *\n * @example Using async iteration:\n * ```typescript\n * const stream = createSSEStream(ctx);\n *\n * // Process events using async generator\n * for await (const event of stream) {\n * console.log('Processing event:', event);\n * }\n * ```\n *\n * @example Handling reconnection:\n * ```typescript\n * // Client sends Last-Event-ID header on reconnection\n * // Stream automatically resumes from that ID\n * const stream = createSSEStream(ctx);\n * // If Last-Event-ID: \"42\" was sent, next event will be \"43\"\n * stream.send('message', { text: 'Continuing from where we left off' });\n * ```\n */\nexport function createSSEStream(ctx: Context, options?: SSEOptions): SSEStreamExtended {\n return new SSEStreamImpl(ctx, options);\n}\n","/**\n * Backpressure strategy types and validation schemas for SSE streaming.\n * Provides runtime type checking and sensible defaults for buffer management.\n */\n\nimport { z } from 'zod';\n\n/**\n * Buffer overflow strategies when high watermark is reached.\n * Aligned with SSEBufferStrategy from @blaize-types/sse\n */\nexport const BufferStrategySchema = z.enum([\n 'drop-oldest', // Drop oldest messages from buffer (FIFO)\n 'drop-newest', // Drop newest messages (reject new)\n 'close', // Close the stream when buffer limit is reached\n]);\n\nexport type BufferStrategy = z.infer<typeof BufferStrategySchema>;\n\n/**\n * Watermark configuration for buffer management.\n * Low watermark resumes flow, high watermark triggers strategy.\n */\nexport const WatermarkConfigSchema = z\n .object({\n low: z.number().int().positive().describe('Resume threshold in messages'),\n high: z.number().int().positive().describe('Trigger threshold in messages'),\n })\n .refine(data => data.low < data.high, {\n message: 'Low watermark must be less than high watermark',\n path: ['low'],\n });\n\nexport type WatermarkConfig = z.infer<typeof WatermarkConfigSchema>;\n\n/**\n * Size limits for buffer management.\n */\nexport const SizeLimitsSchema = z.object({\n maxMessages: z\n .number()\n .int()\n .positive()\n .max(100000)\n .describe('Maximum number of messages in buffer'),\n maxBytes: z\n .number()\n .int()\n .positive()\n .max(100 * 1024 * 1024) // 100MB max\n .optional()\n .describe('Maximum buffer size in bytes'),\n messageTimeout: z\n .number()\n .int()\n .nonnegative()\n .max(300000) // 5 minutes max\n .optional()\n .describe('Message TTL in milliseconds'),\n});\n\nexport type SizeLimits = z.infer<typeof SizeLimitsSchema>;\n\n/**\n * Complete backpressure configuration.\n */\nexport const BackpressureConfigSchema = z\n .object({\n enabled: z.boolean().default(true).describe('Enable backpressure management'),\n\n strategy: BufferStrategySchema.default('drop-oldest').describe(\n 'Strategy when buffer reaches high watermark'\n ),\n\n watermarks: WatermarkConfigSchema.default({\n low: 100,\n high: 1000,\n }).describe('Buffer watermark thresholds'),\n\n limits: SizeLimitsSchema.default({\n maxMessages: 10000,\n }).describe('Buffer size constraints'),\n\n metrics: z\n .object({\n enabled: z.boolean().default(false),\n interval: z.number().int().positive().default(5000),\n })\n .optional()\n .describe('Metrics collection configuration'),\n })\n .refine(\n data => {\n // Ensure watermarks are within limits\n return data.watermarks.high <= data.limits.maxMessages;\n },\n {\n message: 'High watermark cannot exceed maxMessages limit',\n path: ['watermarks', 'high'],\n }\n );\n\nexport type BackpressureConfig = z.infer<typeof BackpressureConfigSchema>;\n\n/**\n * Factory for creating default configurations.\n */\nexport const createDefaultConfig = (\n overrides?: Partial<BackpressureConfig>\n): BackpressureConfig => {\n return BackpressureConfigSchema.parse(overrides || {});\n};\n\n/**\n * Validation helper with detailed error messages.\n */\nexport const validateConfig = (\n config: unknown\n): { success: true; data: BackpressureConfig } | { success: false; errors: string[] } => {\n const result = BackpressureConfigSchema.safeParse(config);\n\n if (result.success) {\n return { success: true, data: result.data };\n }\n\n const errors = result.error.issues.map(issue => {\n const path = issue.path.join('.');\n return path ? `${path}: ${issue.message}` : issue.message;\n });\n\n return { success: false, errors };\n};\n\n/**\n * Type guards for runtime checks.\n */\nexport const isValidStrategy = (value: unknown): value is BufferStrategy => {\n return BufferStrategySchema.safeParse(value).success;\n};\n\nexport const isValidWatermarks = (value: unknown): value is WatermarkConfig => {\n return WatermarkConfigSchema.safeParse(value).success;\n};\n\nexport const isValidConfig = (value: unknown): value is BackpressureConfig => {\n return BackpressureConfigSchema.safeParse(value).success;\n};\n","/**\n * Internal SSE Connection Registry\n *\n * This module is INTERNAL ONLY and not exposed in the public API.\n * It manages active SSE connections, enforces limits, and handles cleanup.\n * The registry is created lazily on first SSE route initialization.\n *\n */\n\nimport type { ConnectionEntry, ConnectionRegistry, RegistryConfig } from '@blaize-types/sse';\n\n/**\n *\n * Default configuration values\n *\n */\nconst DEFAULT_CONFIG: Required<RegistryConfig> = {\n maxConnections: 10000,\n maxConnectionsPerClient: 100,\n inactiveTimeout: 30 * 60 * 1000, // 30 minutes\n cleanupInterval: 60 * 1000, // 1 minute\n};\n\n/**\n * Creates a connection registry using functional patterns with closure-based state\n * @internal\n */\nfunction createConnectionRegistry(config?: RegistryConfig): ConnectionRegistry {\n // Merge with defaults\n const settings = { ...DEFAULT_CONFIG, ...config };\n\n // Private state using closure\n const connections = new Map<string, ConnectionEntry>();\n const clientConnectionCounts = new Map<string, number>();\n let cleanupTimer: NodeJS.Timeout | null = null;\n\n // Create the registry object first so we can reference its methods\n const registry: ConnectionRegistry = {} as ConnectionRegistry;\n\n /**\n * Start periodic cleanup if not already running\n */\n const startCleanupTimer = (cleanupFn: () => void): void => {\n if (!cleanupTimer && settings.cleanupInterval > 0) {\n cleanupTimer = setInterval(() => {\n cleanupFn();\n }, settings.cleanupInterval);\n\n // Ensure cleanup timer doesn't prevent process exit\n if (cleanupTimer.unref) {\n cleanupTimer.unref();\n }\n }\n };\n\n /**\n * Stop the cleanup timer\n */\n const stopCleanupTimer = (): void => {\n if (cleanupTimer) {\n clearInterval(cleanupTimer);\n cleanupTimer = null;\n }\n };\n\n /**\n * Update client connection count\n */\n const updateClientCount = (clientIp: string | undefined, delta: number): void => {\n if (!clientIp) return;\n\n const current = clientConnectionCounts.get(clientIp) || 0;\n const newCount = current + delta;\n\n if (newCount <= 0) {\n clientConnectionCounts.delete(clientIp);\n } else {\n clientConnectionCounts.set(clientIp, newCount);\n }\n };\n\n /**\n * Add a connection to the registry\n * @throws {Error} If connection ID already exists or limits exceeded\n */\n const add: ConnectionRegistry['add'] = (id, stream, metadata) => {\n // Check if ID already exists\n if (connections.has(id)) {\n throw new Error(`Connection with ID ${id} already exists`);\n }\n\n // Check total connection limit\n if (connections.size >= settings.maxConnections) {\n throw new Error(`Maximum connection limit reached (${settings.maxConnections})`);\n }\n\n // Check per-client limit\n if (metadata?.clientIp) {\n const clientCount = clientConnectionCounts.get(metadata.clientIp) || 0;\n if (clientCount >= settings.maxConnectionsPerClient) {\n throw new Error(\n `Maximum connections per client reached (${settings.maxConnectionsPerClient})`\n );\n }\n }\n\n // Add the connection\n const now = Date.now();\n connections.set(id, {\n stream,\n connectedAt: now,\n lastActivity: now,\n clientIp: metadata?.clientIp,\n userAgent: metadata?.userAgent,\n });\n\n // Update client count\n updateClientCount(metadata?.clientIp, 1);\n\n // Start cleanup timer on first connection\n if (connections.size === 1) {\n startCleanupTimer(registry.cleanup);\n }\n\n // Register cleanup callback on stream close\n stream.onClose(() => {\n remove(id);\n });\n };\n\n /**\n * Remove a connection from the registry\n */\n const remove: ConnectionRegistry['remove'] = id => {\n const entry = connections.get(id);\n if (!entry) return;\n\n // Remove from registry\n connections.delete(id);\n\n // Update client count\n updateClientCount(entry.clientIp, -1);\n\n // Stop cleanup timer if no connections\n if (connections.size === 0) {\n stopCleanupTimer();\n }\n };\n\n /**\n * Get current connection count\n */\n const count: ConnectionRegistry['count'] = () => {\n return connections.size;\n };\n\n /**\n * Clean up inactive or closed connections\n */\n const cleanup: ConnectionRegistry['cleanup'] = () => {\n const now = Date.now();\n const idsToRemove: string[] = [];\n\n connections.forEach((entry, id) => {\n // Check if connection is inactive\n const isInactive = now - entry.lastActivity > settings.inactiveTimeout;\n\n // Check if stream is closed (assuming SSEStream has an isWritable property)\n // Since we don't have the actual implementation yet, we'll check if the stream\n // has been explicitly closed by checking a hypothetical state\n const isClosed =\n !entry.stream ||\n (entry.stream as any).state === 'closed' ||\n !(entry.stream as any).isWritable;\n\n if (isInactive || isClosed) {\n idsToRemove.push(id);\n\n // Close the stream if it's still open\n if (entry.stream && typeof entry.stream.close === 'function') {\n try {\n entry.stream.close();\n } catch {\n // Ignore errors during cleanup\n }\n }\n }\n });\n\n // Remove marked connections\n idsToRemove.forEach(id => remove(id));\n };\n\n /**\n * Get a connection by ID\n */\n const get: ConnectionRegistry['get'] = id => {\n const entry = connections.get(id);\n return entry?.stream;\n };\n\n /**\n * Check if a connection exists\n */\n const has: ConnectionRegistry['has'] = id => {\n return connections.has(id);\n };\n\n /**\n * Get all connection IDs\n */\n const getIds: ConnectionRegistry['getIds'] = () => {\n return Array.from(connections.keys());\n };\n\n /**\n * Shutdown the registry and close all connections\n */\n const shutdown: ConnectionRegistry['shutdown'] = () => {\n // Stop cleanup timer\n stopCleanupTimer();\n\n // Close all connections\n connections.forEach(entry => {\n if (entry.stream && typeof entry.stream.close === 'function') {\n try {\n entry.stream.close();\n } catch {\n // Ignore errors during shutdown\n }\n }\n });\n\n // Clear all state\n connections.clear();\n clientConnectionCounts.clear();\n };\n\n // Assign methods to the registry object\n registry.add = add;\n registry.remove = remove;\n registry.count = count;\n registry.cleanup = cleanup;\n registry.get = get;\n registry.has = has;\n registry.getIds = getIds;\n registry.shutdown = shutdown;\n\n // Return the registry interface\n return registry;\n}\n\n/**\n *\n * Singleton instance holder using closure\n *\n */\nlet registryInstance: ConnectionRegistry | null = null;\n\n/**\n * Get or create the singleton registry instance (lazy initialization)\n * This is the only function that should be used by other SSE modules\n *\n * @param config - Optional configuration (only used on first initialization)\n * @returns The singleton connection registry\n */\nexport function getConnectionRegistry(config?: RegistryConfig): ConnectionRegistry {\n if (!registryInstance) {\n registryInstance = createConnectionRegistry(config);\n }\n return registryInstance;\n}\n\n/**\n *\n * Reset the singleton instance (for testing purposes only)\n *\n */\nexport function resetRegistry(): void {\n if (registryInstance) {\n registryInstance.shutdown();\n registryInstance = null;\n }\n}\n","/**\n * SSEBufferOverflowError class for SSE buffer overflow conditions\n *\n * This error is thrown when an SSE stream buffer exceeds its configured limits.\n * It provides context about the overflow and the strategy applied.\n */\n\nimport { BlaizeError, ErrorType } from '@blaize-types/errors';\n\nimport { getCorrelationId } from '../tracing/correlation';\n\nimport type { SSEBufferOverflowErrorDetails } from '@blaize-types/errors';\n\n/**\n * Error thrown when SSE buffer overflows\n *\n * Automatically sets HTTP status to 503 (Service Unavailable) indicating\n * the server cannot handle the request due to overload.\n *\n * @example Basic usage with required details:\n * ```typescript\n * throw new SSEBufferOverflowError('SSE buffer limit exceeded', {\n * currentSize: 1000,\n * maxSize: 1000,\n * strategy: 'drop-oldest'\n * });\n * ```\n *\n * @example With full context:\n * ```typescript\n * throw new SSEBufferOverflowError('Buffer overflow on high-frequency stream', {\n * clientId: 'client-123',\n * currentSize: 5000,\n * maxSize: 5000,\n * eventsDropped: 25,\n * strategy: 'drop-oldest',\n * triggeringEvent: 'market-data-update'\n * });\n * ```\n *\n * @example Stream closed due to overflow:\n * ```typescript\n * throw new SSEBufferOverflowError('Stream closed due to buffer overflow', {\n * clientId: 'client-456',\n * currentSize: 1000,\n * maxSize: 1000,\n * strategy: 'close',\n * eventsDropped: 0\n * });\n * ```\n */\nexport class SSEBufferOverflowError extends BlaizeError<SSEBufferOverflowErrorDetails> {\n /**\n * Creates a new SSEBufferOverflowError instance\n *\n * @param title - Human-readable error message\n * @param details - Required context about the buffer overflow\n * @param correlationId - Optional correlation ID (uses current context if not provided)\n */\n constructor(\n title: string,\n details: SSEBufferOverflowErrorDetails,\n correlationId: string | undefined = undefined\n ) {\n super(\n ErrorType.SSE_BUFFER_OVERFLOW,\n title,\n 503, // HTTP 503 Service Unavailable - server cannot handle the request\n correlationId ?? getCorrelationId(),\n details\n );\n }\n}\n","/**\n * SSEStreamClosedError class for operations on closed SSE streams\n *\n * This error is thrown when attempting to perform operations on a closed SSE stream.\n * It provides context about when and why the stream was closed.\n */\n\nimport { BlaizeError, ErrorType } from '@blaize-types/errors';\n\nimport { getCorrelationId } from '../tracing/correlation';\n\nimport type { SSEStreamClosedErrorDetails } from '@blaize-types/errors';\n\n/**\n * Error thrown when attempting operations on a closed SSE stream\n *\n * Automatically sets HTTP status to 410 (Gone) indicating\n * the resource is no longer available.\n *\n * @example Basic usage:\n * ```typescript\n * throw new SSEStreamClosedError('Cannot send event to closed stream');\n * ```\n *\n * @example With closure context:\n * ```typescript\n * throw new SSEStreamClosedError('Stream closed by client', {\n * clientId: 'client-123',\n * closedAt: new Date().toISOString(),\n * closeReason: 'client-disconnect',\n * canReconnect: true,\n * retryAfter: 5000\n * });\n * ```\n *\n * @example Timeout closure:\n * ```typescript\n * throw new SSEStreamClosedError('Stream closed due to inactivity', {\n * clientId: 'client-456',\n * closedAt: new Date().toISOString(),\n * closeReason: 'timeout',\n * canReconnect: true,\n * retryAfter: 1000\n * });\n * ```\n *\n * @example Permanent closure:\n * ```typescript\n * throw new SSEStreamClosedError('Stream permanently closed', {\n * clientId: 'client-789',\n * closedAt: new Date().toISOString(),\n * closeReason: 'error',\n * canReconnect: false\n * });\n * ```\n */\nexport class SSEStreamClosedError extends BlaizeError<SSEStreamClosedErrorDetails> {\n /**\n * Creates a new SSEStreamClosedError instance\n *\n * @param title - Human-readable error message\n * @param details - Optional context about the stream closure\n * @param correlationId - Optional correlation ID (uses current context if not provided)\n */\n constructor(\n title: string,\n details: SSEStreamClosedErrorDetails | undefined = undefined,\n correlationId: string | undefined = undefined\n ) {\n super(\n ErrorType.SSE_STREAM_CLOSED,\n title,\n 410, // HTTP 410 Gone - resource no longer available\n correlationId ?? getCorrelationId(),\n details\n );\n }\n}\n","import { BlaizeError, ErrorType } from '@blaize-types/errors';\nimport { getCorrelationId } from 'src/tracing/correlation';\n\nexport class SSENotAcceptableError extends BlaizeError<{\n acceptHeader: string;\n requiredHeader: string;\n endpoint: string;\n}> {\n constructor(message: string, details: any, correlationId?: string) {\n super(\n ErrorType.SSE_NOT_ACCEPTABLE,\n message,\n 406, // Not Acceptable status\n correlationId || getCorrelationId(),\n details\n );\n }\n}\n","/**\n * @module sse/route-creator\n * @description SSE route creator following BlaizeJS v0.4.x patterns\n */\n\nimport { z } from 'zod';\n\nimport { createSSEStream } from './stream';\nimport { SSENotAcceptableError } from '../errors/sse-not-acceptable-error';\nimport { getRoutePath } from '../router/create';\n\nimport type { State, Services, Context } from '@blaize-types/context';\nimport type { CreateSSERoute, SSEStreamExtended, TypedSSEStream } from '@blaize-types/sse';\n\n/**\n * Validate an SSE configuration\n */\nfunction validateSSEConfig(config: any): void {\n if (!config.handler || typeof config.handler !== 'function') {\n throw new Error('SSE route handler must be a function');\n }\n\n if (config.middleware && !Array.isArray(config.middleware)) {\n throw new Error('Middleware for SSE route must be an array');\n }\n\n // Validate schema if provided\n if (config.schema) {\n const { params, query, events } = config.schema;\n\n if (params && (!params._def || typeof params.parse !== 'function')) {\n throw new Error('Params schema for SSE must be a valid Zod schema');\n }\n\n if (query && (!query._def || typeof query.parse !== 'function')) {\n throw new Error('Query schema for SSE must be a valid Zod schema');\n }\n\n // Events can be either a Zod schema or an object of Zod schemas\n if (events) {\n if (typeof events === 'object' && !events._def) {\n // It's an event map, validate each event schema\n for (const [eventName, eventSchema] of Object.entries(events)) {\n if (\n !eventSchema ||\n typeof eventSchema !== 'object' ||\n !(eventSchema as any)._def ||\n typeof (eventSchema as any).parse !== 'function'\n ) {\n throw new Error(`Event schema for '${eventName}' must be a valid Zod schema`);\n }\n }\n } else if (events._def && typeof events.parse === 'function') {\n // Single schema - that's fine too\n } else {\n throw new Error('Events schema for SSE must be a valid Zod schema or event map');\n }\n }\n }\n}\n\n/**\n * Create a typed SSE stream wrapper if event schemas are provided\n */\nfunction createTypedStream<TEvents extends Record<string, z.ZodType>>(\n stream: SSEStreamExtended,\n eventSchemas: TEvents\n): TypedSSEStream<TEvents> {\n const typedStream = Object.create(stream) as TypedSSEStream<TEvents>;\n\n // Override send method with validation\n const originalSend = stream.send.bind(stream);\n typedStream.send = function <K extends keyof TEvents>(\n event: K & string,\n data: z.infer<TEvents[K]>\n ): void {\n // Validate the data against the schema if it exists\n const schema = eventSchemas[event];\n if (schema) {\n try {\n const validated = schema.parse(data);\n originalSend(event, validated);\n } catch (error) {\n stream.sendError(\n new Error(\n `Event '${event}' validation failed: ${error instanceof Error ? error.message : String(error)}`\n )\n );\n }\n } else {\n // No schema for this event, send as-is\n originalSend(event, data);\n }\n };\n\n return typedStream;\n}\n\n/**\n * Create an SSE route following BlaizeJS patterns\n *\n * SSE routes use a stream-first handler signature: (stream, ctx, params)\n * This makes sense because SSE is fundamentally about streaming events.\n *\n * @example Basic usage:\n * ```typescript\n * export default createSSERoute<AppState, AppServices>()({\n * handler: async (stream, ctx, params) => {\n * stream.send('message', { text: 'Hello SSE!' });\n *\n * // Access state and services as usual\n * const user = ctx.state.user;\n * const db = ctx.services.database;\n * }\n * });\n * ```\n *\n * @example With typed events (automatic type inference!):\n * ```typescript\n * export default createSSERoute<AppState, AppServices>()({\n * schema: {\n * params: z.object({ roomId: z.string() }),\n * events: {\n * message: z.object({ content: z.string(), author: z.string() }),\n * typing: z.object({ userId: z.string(), isTyping: z.boolean() }),\n * presence: z.object({ users: z.array(z.string()) })\n * }\n * },\n * handler: async (stream, ctx, params) => {\n * // stream is automatically typed as TypedSSEStream!\n * stream.send('message', { content: 'Hi', author: 'bot' }); // ✅ Type-safe!\n * stream.send('typing', { userId: params.roomId, isTyping: true }); // ✅ Type-safe!\n * // stream.send('unknown', {}); // ❌ TypeScript error!\n * }\n * });\n * ```\n */\nexport const createSSERoute: CreateSSERoute = <\n _TState extends State = State,\n _TServices extends Services = Services,\n>() => {\n return (config: any) => {\n // Validate the configuration\n validateSSEConfig(config);\n\n // Get the route path\n const path = getRoutePath();\n\n // Create a wrapped handler that manages the SSE stream lifecycle\n const wrappedHandler = async (ctx: Context, params: any) => {\n // Validate SSE accept header\n const accept = ctx.request.header('accept');\n if (accept && !accept.includes('text/event-stream') && !accept.includes('*/*')) {\n throw new SSENotAcceptableError('This endpoint requires Server-Sent Events support', {\n acceptHeader: accept,\n requiredHeader: 'text/event-stream',\n endpoint: ctx.request.path,\n });\n }\n\n if (config.schema) {\n try {\n if (config.schema.params) {\n params = config.schema.params.parse(params);\n }\n if (config.schema.query) {\n ctx.request.query = config.schema.query.parse(ctx.request.query);\n }\n } catch (validationError) {\n // Validation failed BEFORE SSE started - safe to throw\n console.error('[SSE] Validation error:', validationError);\n throw validationError;\n }\n }\n\n // Create the SSE stream\n // CRITICAL FIX: Mark the response as sent immediately\n // This prevents the framework from trying to send any additional response\n const baseStream = createSSEStream(ctx, config.options);\n\n // Create typed stream if event schemas provided\n const stream =\n config.schema?.events &&\n typeof config.schema.events === 'object' &&\n !config.schema.events._def\n ? createTypedStream(baseStream, config.schema.events)\n : baseStream;\n\n // Handle client disconnect\n ctx.request.raw.on('close', () => stream.close());\n\n try {\n // Execute the original handler with (stream, ctx, params) signature\n await config.handler(stream, ctx, params);\n } catch (error) {\n console.error('[SSE] Handler error - THIS IS THE REAL ERROR:', error);\n console.error('[SSE] Stack trace:', error instanceof Error ? error.stack : 'No stack');\n // Send error to stream if still writable\n if (stream.isWritable) {\n stream.sendError(error instanceof Error ? error : new Error(String(error)));\n }\n stream.close();\n\n throw error;\n }\n };\n\n // Return the route definition with GET method (SSE uses GET)\n return {\n GET: {\n handler: wrappedHandler,\n schema:\n config.schema?.params || config.schema?.query\n ? {\n params: config.schema?.params,\n query: config.schema?.query,\n }\n : undefined,\n middleware: config.middleware,\n options: config.options,\n },\n path,\n };\n };\n};\n","/**\n * Extract parameter values from a URL path\n */\nexport function extractParams(\n path: string,\n pattern: RegExp,\n paramNames: string[]\n): Record<string, string> {\n const match = pattern.exec(path);\n if (!match) {\n return {};\n }\n\n const params: Record<string, string> = {};\n\n // Extract parameter values from regex match groups\n for (let i = 0; i < paramNames.length; i++) {\n // Add 1 to index since the first capture group is at index 1\n params[paramNames[i]!] = match[i + 1] || '';\n }\n\n return params;\n}\n\n/**\n * Compile a path pattern with parameters\n */\nexport function compilePathPattern(path: string): { pattern: RegExp; paramNames: string[] } {\n const paramNames: string[] = [];\n\n // Special case for root path\n if (path === '/') {\n return {\n pattern: /^\\/$/,\n paramNames: [],\n };\n }\n\n // First escape special regex characters (except for : and [ ] which we process specially)\n let patternString = path.replace(/([.+*?^$(){}|\\\\])/g, '\\\\$1');\n\n // Replace route parameters with regex capture groups\n patternString = patternString\n // Replace :param syntax with capture groups\n .replace(/\\/:([^/]+)/g, (_, paramName) => {\n paramNames.push(paramName);\n return '/([^/]+)';\n })\n // Replace [param] syntax (for file-based routing)\n .replace(/\\/\\[([^\\]]+)\\]/g, (_, paramName) => {\n paramNames.push(paramName);\n return '/([^/]+)';\n });\n\n // Make the trailing slash optional (if not already the root path)\n // This adds an optional trailing slash to the end of the pattern\n patternString = `${patternString}(?:/)?`;\n\n // Create the regex pattern\n // This is safe because we've escaped special RegExp characters and\n // we're using developer-defined routes, not user input\n const pattern = new RegExp(`^${patternString}$`);\n\n return {\n pattern,\n paramNames,\n };\n}\n\n/**\n * Convert parameters object to URL query string\n */\nexport function paramsToQuery(params: Record<string, string | number | boolean>): string {\n const parts: string[] = [];\n\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n const encodedKey = encodeURIComponent(key);\n const encodedValue = encodeURIComponent(String(value));\n parts.push(`${encodedKey}=${encodedValue}`);\n }\n }\n\n return parts.length > 0 ? `?${parts.join('&')}` : '';\n}\n\n/**\n * Build a URL with path parameters\n */\nexport function buildUrl(\n pathPattern: string,\n params: Record<string, string | number | boolean> = {},\n query: Record<string, string | number | boolean> = {}\n): string {\n // Extract path parameters and query parameters\n const pathParams: Record<string, string | number | boolean> = {};\n const queryParams: Record<string, string | number | boolean> = { ...query };\n\n // Find all parameter names in the path\n const paramNames: string[] = [];\n pathPattern.replace(/\\/:([^/]+)/g, (_, paramName) => {\n paramNames.push(paramName);\n return '/';\n });\n\n // Separate params into path params and additional query params\n for (const [key, value] of Object.entries(params)) {\n if (paramNames.includes(key)) {\n pathParams[key] = value;\n } else {\n queryParams[key] = value;\n }\n }\n\n // Replace path parameters\n let url = pathPattern;\n for (const [key, value] of Object.entries(pathParams)) {\n url = url.replace(`:${key}`, encodeURIComponent(String(value)));\n }\n\n // Add query string if needed\n const queryString = paramsToQuery(queryParams);\n\n return url + queryString;\n}\n","import { compilePathPattern, extractParams } from './params';\n\nimport type {\n HttpMethod,\n RouteMethodOptions,\n RouteMatch,\n Matcher,\n RouteEntry,\n Route,\n} from '../../index';\n\n/**\n * Create a route matcher\n */\nexport function createMatcher(): Matcher {\n // Private state\n const routes: RouteEntry[] = [];\n\n return {\n /**\n * Add a route to the matcher\n */\n add(path: string, method: HttpMethod, routeOptions: RouteMethodOptions) {\n const { pattern, paramNames } = compilePathPattern(path);\n\n const newRoute: RouteEntry = {\n path,\n method,\n pattern,\n paramNames,\n routeOptions,\n };\n\n // Find the insertion point using findIndex\n const insertIndex = routes.findIndex(route => paramNames.length < route.paramNames.length);\n\n // If no insertion point found, append to end\n if (insertIndex === -1) {\n routes.push(newRoute);\n } else {\n routes.splice(insertIndex, 0, newRoute);\n }\n },\n\n /**\n * Remove a route from the matcher by path\n */\n remove(path: string) {\n // Remove all routes that match the given path\n for (let i = routes.length - 1; i >= 0; i--) {\n if ((routes[i] as Route).path === path) {\n routes.splice(i, 1);\n }\n }\n },\n\n /**\n * Clear all routes from the matcher\n */\n clear() {\n routes.length = 0;\n },\n\n /**\n * Match a URL path to a route\n */\n match(path: string, method: HttpMethod): RouteMatch | null {\n // First, try to find an exact match for the method\n const pathname = path.split('?')[0];\n if (!pathname) return null;\n\n for (const route of routes) {\n // Skip routes that don't match the method\n if (route.method !== method) continue;\n\n // Try to match the path\n const match = route.pattern.exec(pathname);\n if (match) {\n // Extract parameters from the match\n const params = extractParams(path, route.pattern, route.paramNames);\n\n return {\n route: route.routeOptions,\n params,\n };\n }\n }\n\n // If no exact method match, check if path exists but method is different\n // This allows returning 405 Method Not Allowed instead of 404 Not Found\n const matchingPath = routes.find(\n route => route.method !== method && route.pattern.test(path)\n );\n\n if (matchingPath) {\n // Return null but with allowedMethods to indicate method not allowed\n return {\n route: null,\n params: {},\n methodNotAllowed: true,\n allowedMethods: routes\n .filter(route => route.pattern.test(path))\n .map(route => route.method),\n } as unknown as RouteMatch; // Type assertion for the extended return type\n }\n\n return null; // No match found\n },\n\n /**\n * Get all registered routes\n */\n getRoutes(): { path: string; method: HttpMethod }[] {\n return routes.map(route => ({\n path: route.path,\n method: route.method,\n }));\n },\n\n /**\n * Find routes matching a specific path\n */\n findRoutes(\n path: string\n ): { path: string; method: HttpMethod; params: Record<string, string> }[] {\n return routes\n .filter(route => route.pattern.test(path))\n .map(route => ({\n path: route.path,\n method: route.method,\n params: extractParams(path, route.pattern, route.paramNames),\n }));\n },\n };\n}\n","/* eslint-disable @typescript-eslint/no-empty-object-type */\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport EventEmitter from 'node:events';\n\nimport { setRuntimeConfig } from '../config';\nimport { startServer } from './start';\nimport { registerSignalHandlers, stopServer } from './stop';\nimport { validateServerOptions } from './validation';\nimport { configureGlobalLogger, createLogger } from '../logger';\nimport { createPluginLifecycleManager } from '../plugins/lifecycle';\nimport { validatePlugin } from '../plugins/validation';\nimport { createRouter } from '../router/router';\nimport { _setCorrelationConfig } from '../tracing/correlation';\n\nimport type {\n ComposeMiddlewareStates,\n ComposeMiddlewareServices,\n ComposePluginStates,\n ComposePluginServices,\n} from '@blaize-types/composition';\nimport type { Context } from '@blaize-types/context';\nimport type { Middleware } from '@blaize-types/middleware';\nimport type { Plugin } from '@blaize-types/plugins';\nimport type {\n Server,\n ServerOptions,\n ServerOptionsInput,\n StopOptions,\n UnknownServer,\n} from '@blaize-types/server';\n\nexport const DEFAULT_OPTIONS: ServerOptions = {\n port: 3000,\n host: 'localhost',\n routesDir: './routes',\n http2: {\n enabled: true,\n },\n middleware: [],\n plugins: [],\n bodyLimits: {\n // 🆕 NEW\n json: 512 * 1024,\n form: 1024 * 1024,\n text: 5 * 1024 * 1024,\n raw: 10 * 1024 * 1024,\n multipart: {\n maxFileSize: 50 * 1024 * 1024,\n maxTotalSize: 100 * 1024 * 1024,\n maxFiles: 10,\n maxFieldSize: 1024 * 1024,\n },\n },\n};\n\n/**\n * Creates the configuration options by merging defaults with user-provided options\n */\nfunction createServerOptions(options: ServerOptionsInput = {}): ServerOptions {\n const mergedOptions: ServerOptions = {\n port: options.port ?? DEFAULT_OPTIONS.port,\n host: options.host ?? DEFAULT_OPTIONS.host,\n routesDir: options.routesDir ?? DEFAULT_OPTIONS.routesDir,\n http2: {\n enabled: options.http2?.enabled ?? DEFAULT_OPTIONS.http2!.enabled,\n keyFile: options.http2?.keyFile,\n certFile: options.http2?.certFile,\n },\n middleware: options.middleware ?? DEFAULT_OPTIONS.middleware,\n plugins: options.plugins ?? DEFAULT_OPTIONS.plugins,\n correlation: options.correlation,\n cors: options.cors,\n bodyLimits: options.bodyLimits\n ? {\n json: options.bodyLimits.json ?? DEFAULT_OPTIONS.bodyLimits.json,\n form: options.bodyLimits.form ?? DEFAULT_OPTIONS.bodyLimits.form,\n text: options.bodyLimits.text ?? DEFAULT_OPTIONS.bodyLimits.text,\n raw: options.bodyLimits.raw ?? DEFAULT_OPTIONS.bodyLimits.raw,\n multipart: {\n maxFileSize:\n options.bodyLimits.multipart?.maxFileSize ??\n DEFAULT_OPTIONS.bodyLimits.multipart.maxFileSize,\n maxTotalSize:\n options.bodyLimits.multipart?.maxTotalSize ??\n DEFAULT_OPTIONS.bodyLimits.multipart.maxTotalSize,\n maxFiles:\n options.bodyLimits.multipart?.maxFiles ??\n DEFAULT_OPTIONS.bodyLimits.multipart.maxFiles,\n maxFieldSize:\n options.bodyLimits.multipart?.maxFieldSize ??\n DEFAULT_OPTIONS.bodyLimits.multipart.maxFieldSize,\n },\n }\n : DEFAULT_OPTIONS.bodyLimits,\n logging: options.logging || DEFAULT_OPTIONS.logging,\n };\n try {\n const validated = validateServerOptions(mergedOptions);\n\n // Set runtime config after successful validation\n setRuntimeConfig({ routesDir: validated.routesDir });\n return validated;\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Failed to create server: ${error.message}`);\n }\n throw new Error(`Failed to create server: ${String(error)}`);\n }\n}\n\n/**\n * Configures the correlation ID system based on server options\n *\n * @param options - The validated server options\n */\nfunction configureCorrelation(options: ServerOptions): void {\n if (options.correlation) {\n // Apply correlation configuration if provided\n _setCorrelationConfig(options.correlation.headerName, options.correlation.generator);\n }\n // If no correlation options provided, the system uses defaults\n}\n\n/**\n * Creates the server listen method\n */\nfunction createListenMethod(\n serverInstance: UnknownServer,\n validatedOptions: ServerOptions\n): UnknownServer['listen'] {\n return async () => {\n // Configure correlation before starting the server\n configureCorrelation(validatedOptions);\n // Initialize middleware and plugins\n await initializePlugins(serverInstance);\n\n // Use the functional manager\n await serverInstance.pluginManager.initializePlugins(serverInstance);\n\n // Start the server\n await startServer(serverInstance, validatedOptions);\n\n await serverInstance.pluginManager.onServerStart(serverInstance, serverInstance.server);\n\n // Setup signal handlers and emit events\n setupServerLifecycle(serverInstance);\n\n return serverInstance;\n };\n}\n\n/**\n * Initializes plugins\n */\nasync function initializePlugins(serverInstance: UnknownServer): Promise<void> {\n // Register plugins from options\n for (const p of serverInstance.plugins) {\n await p.register(serverInstance);\n }\n}\n\n/**\n * Sets up server lifecycle (signal handlers, events)\n */\nfunction setupServerLifecycle(serverInstance: UnknownServer): void {\n // Register signal handlers for graceful shutdown\n const signalHandlers = registerSignalHandlers(() => serverInstance.close());\n\n // Store handlers to unregister when server closes\n serverInstance._signalHandlers = signalHandlers;\n\n // Emit started event\n serverInstance.events.emit('started');\n}\n\n/**\n * Creates the server close method\n */\nfunction createCloseMethod(serverInstance: UnknownServer): UnknownServer['close'] {\n return async (stopOptions?: StopOptions) => {\n if (!serverInstance.server) {\n return;\n }\n\n // Prepare options\n const options: StopOptions = { ...stopOptions };\n\n // Unregister signal handlers if they exist\n if (serverInstance._signalHandlers) {\n serverInstance._signalHandlers.unregister();\n delete serverInstance._signalHandlers;\n }\n\n // Call stopServer with the server instance\n await stopServer(serverInstance, options);\n };\n}\n\n/**\n * Creates the server use method for adding middleware\n * This version properly handles type accumulation for both single and array middleware\n */\nfunction createUseMethod<TState, TServices>(\n serverInstance: Server<TState, TServices>\n): Server<TState, TServices>['use'] {\n return ((middleware: Middleware | Middleware[]) => {\n const middlewareArray = Array.isArray(middleware) ? middleware : [middleware];\n serverInstance.middleware.push(...middlewareArray);\n // Return the server instance with accumulated types\n // TypeScript will infer the correct return type based on the overload\n return serverInstance;\n }) as Server<TState, TServices>['use'];\n}\n\n/**\n * Creates the server register method for plugins\n * This version properly handles type accumulation for both single and array plugins\n */\nfunction createRegisterMethod<TState, TServices>(\n serverInstance: Server<TState, TServices>\n): Server<TState, TServices>['register'] {\n return (async (plugin: Plugin | Plugin[]) => {\n if (Array.isArray(plugin)) {\n // Handle array of plugins\n for (const p of plugin) {\n validatePlugin(p);\n serverInstance.plugins.push(p);\n await p.register(serverInstance);\n }\n } else {\n // Handle single plugin\n validatePlugin(plugin);\n serverInstance.plugins.push(plugin);\n await plugin.register(serverInstance);\n }\n // Return the server instance with accumulated types\n return serverInstance;\n }) as Server<TState, TServices>['register'];\n}\n\n/**\n * Creates a BlaizeJS server instance\n */\nexport function create<\n const TMw extends readonly Middleware<any, any>[] = [],\n const TP extends readonly Plugin<any, any>[] = [],\n>(\n options: ServerOptionsInput & {\n middleware?: TMw;\n plugins?: TP;\n } = {}\n): Server<\n ComposeMiddlewareStates<TMw> & ComposePluginStates<TP>,\n ComposeMiddlewareServices<TMw> & ComposePluginServices<TP>\n> {\n // Create and validate options\n const validatedOptions = createServerOptions(options);\n\n // Extract options and prepare initial components\n const { port, host, middleware, plugins, cors, bodyLimits } = validatedOptions;\n\n // Create server logger (internal only, not middleware)\n const serverLogger = createLogger(validatedOptions.logging || {});\n configureGlobalLogger(validatedOptions.logging || {});\n\n // TODO: create registries to manage middleware and plugins\n const initialMiddleware = Array.isArray(middleware) ? [...middleware] : [];\n const initialPlugins = Array.isArray(plugins) ? [...plugins] : [];\n\n // Initialize core server components\n const contextStorage = new AsyncLocalStorage<Context>();\n const router = createRouter({\n routesDir: validatedOptions.routesDir,\n watchMode: process.env.NODE_ENV === 'development',\n });\n // Create plugin lifecycle manager\n const pluginManager = createPluginLifecycleManager({\n continueOnError: true,\n });\n const events = new EventEmitter();\n\n // Type alias for the accumulated types\n type AccumulatedState = ComposeMiddlewareStates<TMw> & ComposePluginStates<TP>;\n type AccumulatedServices = ComposeMiddlewareServices<TMw> & ComposePluginServices<TP>;\n\n // Create server instance with minimal properties\n const serverInstance: Server<AccumulatedState, AccumulatedServices> = {\n server: null as any,\n port,\n host,\n context: contextStorage,\n events,\n plugins: [...initialPlugins],\n middleware: [...initialMiddleware],\n corsOptions: cors,\n bodyLimits,\n _signalHandlers: { unregister: () => {} },\n _logger: serverLogger,\n use: () => serverInstance,\n register: async () => serverInstance,\n listen: async () => serverInstance,\n close: async () => {},\n router,\n pluginManager,\n };\n\n // Add methods to the server instance\n serverInstance.listen = createListenMethod(serverInstance, validatedOptions);\n serverInstance.close = createCloseMethod(serverInstance);\n serverInstance.use = createUseMethod(serverInstance);\n serverInstance.register = createRegisterMethod(serverInstance);\n\n return serverInstance;\n}\n","import * as fs from 'node:fs';\nimport * as http from 'node:http';\nimport * as http2 from 'node:http2';\n\nimport { generateDevCertificates } from './dev-certificate';\nimport { createRequestHandler } from './request-handler';\nimport { logger } from '../logger';\n\nimport type { Http2Options, ServerOptions, UnknownServer } from '@blaize-types/server';\n\n// Extract certificate handling to a separate function\nasync function prepareCertificates(\n http2Options: Http2Options\n): Promise<{ keyFile?: string; certFile?: string }> {\n // Not using HTTP/2? No certificates needed\n if (!http2Options.enabled) {\n return {};\n }\n\n const { keyFile, certFile } = http2Options;\n\n // If certificates are missing and in development, generate them\n const isDevMode = process.env.NODE_ENV === 'development';\n const certificatesMissing = !keyFile || !certFile;\n\n if (certificatesMissing && isDevMode) {\n const devCerts = await generateDevCertificates();\n return devCerts;\n }\n\n // If certificates are still missing, throw error\n if (certificatesMissing) {\n throw new Error(\n 'HTTP/2 requires SSL certificates. Provide keyFile and certFile in http2 options. ' +\n 'In development, set NODE_ENV=development to generate them automatically.'\n );\n }\n\n return { keyFile, certFile };\n}\n\n// Create server based on protocol\nfunction createServerInstance(\n isHttp2: boolean,\n certOptions: { keyFile?: string; certFile?: string }\n): http.Server | http2.Http2SecureServer {\n if (!isHttp2) {\n return http.createServer();\n }\n\n // Create HTTP/2 server options\n const http2ServerOptions: http2.SecureServerOptions = {\n allowHTTP1: true, // Allow fallback to HTTP/1.1\n };\n\n // Read certificate files\n try {\n if (certOptions.keyFile) {\n http2ServerOptions.key = fs.readFileSync(certOptions.keyFile);\n }\n if (certOptions.certFile) {\n http2ServerOptions.cert = fs.readFileSync(certOptions.certFile);\n }\n } catch (err) {\n throw new Error(\n `Failed to read certificate files: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n\n return http2.createSecureServer(http2ServerOptions);\n}\n\n// Start listening on the specified port and host\nfunction listenOnPort(\n server: http.Server | http2.Http2SecureServer,\n port: number,\n host: string,\n isHttp2: boolean\n): Promise<void> {\n return new Promise((resolve, reject) => {\n server.listen(port, host, () => {\n const protocol = isHttp2 ? 'https' : 'http';\n const url = `${protocol}://${host}:${port}`;\n logger.info(`\n🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥\n\n ⚡ BlaizeJS DEVELOPMENT SERVER HOT AND READY ⚡\n \n 🚀 Server: ${url}\n 🔥 Hot Reload: Enabled\n 🛠️ Mode: Development\n \n Time to build something amazing! 🚀\n\n🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥\n`);\n resolve();\n });\n\n server.on('error', err => {\n logger.error('Server error:', { error: err, host, port });\n reject(err);\n });\n });\n}\n\nasync function initializePlugins(serverInstance: UnknownServer): Promise<void> {\n for (const plugin of serverInstance.plugins) {\n if (typeof plugin.initialize === 'function') {\n await plugin.initialize(serverInstance);\n }\n }\n}\n\n// Main server start function - now with much lower complexity\nexport async function startServer(\n serverInstance: UnknownServer,\n serverOptions: ServerOptions\n): Promise<void> {\n // Server already running? Do nothing.\n if (serverInstance.server) {\n return;\n }\n\n try {\n // Get effective port and host\n const port = serverOptions.port;\n const host = serverOptions.host;\n\n // Initialize all registered plugins\n await initializePlugins(serverInstance);\n\n // Determine if using HTTP/2\n const http2Options = serverOptions.http2 || { enabled: true };\n const isHttp2 = !!http2Options.enabled;\n\n // Prepare certificates if needed\n const certOptions = await prepareCertificates(http2Options);\n\n // Update the server options if we generated certificates\n if (serverOptions.http2 && certOptions.keyFile && certOptions.certFile) {\n serverOptions.http2.keyFile = certOptions.keyFile;\n serverOptions.http2.certFile = certOptions.certFile;\n }\n\n // Create the server instance\n const server = createServerInstance(isHttp2, certOptions);\n\n // Store the server in the instance\n serverInstance.server = server;\n\n // Update server instance properties\n serverInstance.port = port;\n serverInstance.host = host;\n\n // Configure request handling\n const requestHandler = createRequestHandler(serverInstance);\n server.on('request', requestHandler);\n\n // Start listening\n await listenOnPort(server, port, host, isHttp2);\n } catch (error) {\n logger.error('Failed to start server:', { error });\n throw error;\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport * as selfsigned from 'selfsigned';\n\nexport interface DevCertificates {\n keyFile: string;\n certFile: string;\n}\n\nexport async function generateDevCertificates(): Promise<DevCertificates> {\n const certDir = path.join(process.cwd(), '.blaizejs', 'certs');\n const keyPath = path.join(certDir, 'dev.key');\n const certPath = path.join(certDir, 'dev.cert');\n \n // Check if certificates already exist\n if (fs.existsSync(keyPath) && fs.existsSync(certPath)) {\n return {\n keyFile: keyPath,\n certFile: certPath\n };\n }\n \n // Create directory if it doesn't exist\n if (!fs.existsSync(certDir)) {\n fs.mkdirSync(certDir, { recursive: true });\n }\n \n // Generate self-signed certificate\n const attrs = [{ name: 'commonName', value: 'localhost' }];\n const options = {\n days: 365,\n algorithm: 'sha256',\n keySize: 2048,\n extensions: [\n { name: 'basicConstraints', cA: true },\n {\n name: 'keyUsage',\n keyCertSign: true,\n digitalSignature: true,\n nonRepudiation: true,\n keyEncipherment: true,\n dataEncipherment: true\n },\n {\n name: 'extKeyUsage',\n serverAuth: true,\n clientAuth: true\n },\n {\n name: 'subjectAltName',\n altNames: [\n { type: 2, value: 'localhost' },\n { type: 7, ip: '127.0.0.1' }\n ]\n }\n ]\n };\n \n // Generate the certificates\n const pems = selfsigned.generate(attrs, options);\n \n // Write the key and certificate to files\n fs.writeFileSync(keyPath, Buffer.from(pems.private, 'utf-8'));\n fs.writeFileSync(certPath, Buffer.from(pems.cert, 'utf-8'));\n \n console.log(`\\n🔒 Generated self-signed certificates for development at ${certDir}\\n`);\n \n return {\n keyFile: keyPath,\n certFile: certPath\n };\n}","export class ResponseSentError extends Error {\n constructor(message: string = '❌ Response has already been sent') {\n super(message);\n this.name = 'ResponseSentError';\n }\n}\n\nexport class ResponseSentHeaderError extends ResponseSentError {\n constructor(message: string = 'Cannot set header after response has been sent') {\n super(message);\n }\n}\n\nexport class ResponseSentContentError extends ResponseSentError {\n constructor(message: string = 'Cannot set content type after response has been sent') {\n super(message);\n }\n}\n\nexport class ParseUrlError extends ResponseSentError {\n constructor(message: string = 'Invalide URL') {\n super(message);\n }\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\n\nimport type { Context, QueryParams, Services, State, UnknownFunction } from '@blaize-types/context';\n\n/**\n * AsyncLocalStorage instance for storing request context\n */\nexport const contextStorage = new AsyncLocalStorage<Context>();\n\n/**\n * Returns the current context from AsyncLocalStorage\n */\nexport function getContext<\n S extends State = State,\n Svc extends Services = Services,\n TBody = unknown,\n TQuery = QueryParams,\n>(): Context<S, Svc, TBody, TQuery> | undefined {\n return contextStorage.getStore() as Context<S, Svc, TBody, TQuery> | undefined;\n}\n\n/**\n * Wraps a callback function with a context\n */\nexport function runWithContext<T>(\n context: Context,\n callback: () => T | Promise<T>\n): T | Promise<T> {\n return contextStorage.run(context, callback);\n}\n\n/**\n * Middleware function that ensures a context is available in AsyncLocalStorage\n */\nexport async function contextMiddleware(\n context: Context,\n next: () => Promise<void>\n): Promise<void> {\n return runWithContext(context, next);\n}\n\n/**\n * Utility to check if code is running within a context\n */\nexport function hasContext(): boolean {\n return contextStorage.getStore() !== undefined;\n}\n\n/**\n * Creates a function that will run with the current context\n *\n * @param fn The function to bind to the current context\n * @returns A function that will execute with the bound context\n */\nexport function bindContext<TFunction extends UnknownFunction>(fn: TFunction): TFunction {\n const context = getContext();\n if (!context) {\n return fn;\n }\n\n // Using function instead of arrow function to preserve 'this'\n return function (this: unknown, ...args: Parameters<TFunction>): ReturnType<TFunction> {\n return runWithContext(context, () => fn.apply(this, args)) as ReturnType<TFunction>;\n } as TFunction;\n}\n","import * as crypto from 'node:crypto';\nimport { createWriteStream, type WriteStream } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { Readable } from 'node:stream';\n\nimport { extractBoundary, parseContentDisposition, parseContentType } from './utils';\n\nimport type { UnifiedRequest } from '@blaize-types/context';\nimport type { UploadedFile, MultipartData, ParseOptions, ParserState } from '@blaize-types/upload';\n\n// Default options with sensible defaults\nconst DEFAULT_OPTIONS: Required<ParseOptions> = {\n maxFileSize: 10 * 1024 * 1024, // 10MB\n maxFiles: 10,\n maxFieldSize: 1 * 1024 * 1024, // 1MB\n allowedMimeTypes: [],\n allowedExtensions: [],\n strategy: 'stream',\n tempDir: tmpdir(),\n computeHash: false,\n};\n\n/**\n * Create initial parser state\n */\nfunction createParserState(boundary: string, options: Partial<ParseOptions> = {}): ParserState {\n return {\n boundary: Buffer.from(`--${boundary}`),\n options: { ...DEFAULT_OPTIONS, ...options },\n fields: new Map(),\n files: new Map(),\n buffer: Buffer.alloc(0),\n stage: 'boundary',\n currentHeaders: '',\n currentField: null,\n currentFilename: undefined,\n currentMimetype: 'application/octet-stream',\n currentContentLength: 0,\n fileCount: 0,\n fieldCount: 0,\n currentBufferChunks: [],\n currentStream: null,\n currentTempPath: null,\n currentWriteStream: null,\n streamController: null,\n cleanupTasks: [],\n // Track validation state\n hasFoundValidBoundary: false,\n hasProcessedAnyPart: false,\n isFinished: false,\n };\n}\n\n/**\n * Process a chunk of data through the parser state machine\n */\nasync function processChunk(state: ParserState, chunk: Buffer): Promise<ParserState> {\n const newBuffer = Buffer.concat([state.buffer, chunk]);\n let currentState = { ...state, buffer: newBuffer };\n\n // Process buffer until no more progress can be made\n while (currentState.buffer.length > 0 && !currentState.isFinished) {\n const nextState = await processCurrentStage(currentState);\n if (nextState === currentState) break; // No progress made, need more data\n currentState = nextState;\n }\n\n return currentState;\n}\n\n/**\n * Process current stage of parsing\n */\nasync function processCurrentStage(state: ParserState): Promise<ParserState> {\n switch (state.stage) {\n case 'boundary':\n return processBoundary(state);\n case 'headers':\n return processHeaders(state);\n case 'content':\n return processContent(state);\n default: {\n const { InternalServerError } = await import('../errors/internal-server-error');\n throw new InternalServerError(`Invalid parser stage`, {\n operation: state.stage,\n });\n }\n }\n}\n\n/**\n * Process boundary detection\n */\nfunction processBoundary(state: ParserState): ParserState {\n const boundaryIndex = state.buffer.indexOf(state.boundary);\n if (boundaryIndex === -1) return state;\n\n // Mark that we found at least one boundary\n const hasFoundValidBoundary = true;\n\n // Consume boundary and check for end\n let buffer = state.buffer.subarray(boundaryIndex + state.boundary.length);\n\n // Check for end boundary (-- after boundary)\n if (buffer.length >= 2 && buffer.subarray(0, 2).equals(Buffer.from('--'))) {\n return {\n ...state,\n buffer,\n hasFoundValidBoundary,\n isFinished: true,\n stage: 'boundary',\n };\n }\n\n // Skip CRLF after boundary\n if (buffer.length >= 2 && buffer.subarray(0, 2).equals(Buffer.from('\\r\\n'))) {\n buffer = buffer.subarray(2);\n }\n\n return {\n ...state,\n buffer,\n hasFoundValidBoundary,\n stage: 'headers',\n currentHeaders: '',\n };\n}\n\n/**\n * Process headers section\n */\nasync function processHeaders(state: ParserState): Promise<ParserState> {\n const headerEnd = state.buffer.indexOf('\\r\\n\\r\\n');\n if (headerEnd === -1) return state;\n\n const headers = state.buffer.subarray(0, headerEnd).toString('utf8');\n const buffer = state.buffer.subarray(headerEnd + 4);\n\n const disposition = parseContentDisposition(headers);\n if (!disposition) {\n // ✅ HTTP 400 - Bad Request for malformed headers\n const { ValidationError } = await import('../errors/validation-error');\n throw new ValidationError('Missing or invalid Content-Disposition header');\n }\n\n const mimetype = parseContentType(headers);\n const isFile = disposition.filename !== undefined;\n\n // Validation\n if (isFile && state.fileCount >= state.options.maxFiles) {\n const { PayloadTooLargeError } = await import('../errors/payload-too-large-error');\n throw new PayloadTooLargeError('Too many files in upload', {\n fileCount: state.fileCount + 1,\n maxFiles: state.options.maxFiles,\n filename: disposition.filename,\n });\n }\n\n if (\n isFile &&\n state.options.allowedMimeTypes.length > 0 &&\n !state.options.allowedMimeTypes.includes(mimetype)\n ) {\n const { UnsupportedMediaTypeError } = await import('../errors/unsupported-media-type-error');\n throw new UnsupportedMediaTypeError('File type not allowed', {\n receivedMimeType: mimetype,\n allowedMimeTypes: state.options.allowedMimeTypes,\n filename: disposition.filename,\n });\n }\n\n return {\n ...state,\n buffer,\n stage: 'content',\n currentHeaders: headers,\n currentField: disposition.name,\n currentFilename: disposition.filename,\n currentMimetype: mimetype,\n currentContentLength: 0,\n fileCount: isFile ? state.fileCount + 1 : state.fileCount,\n fieldCount: isFile ? state.fieldCount : state.fieldCount + 1,\n currentBufferChunks: [],\n };\n}\n\n/**\n * Process content section\n */\nasync function processContent(state: ParserState): Promise<ParserState> {\n const nextBoundaryIndex = state.buffer.indexOf(state.boundary);\n\n let contentChunk: Buffer;\n let isComplete = false;\n let buffer = state.buffer;\n\n if (nextBoundaryIndex === -1) {\n // No boundary found, process safely\n const safeLength = Math.max(0, state.buffer.length - state.boundary.length);\n if (safeLength === 0) return state; // Need more data\n\n contentChunk = state.buffer.subarray(0, safeLength);\n buffer = state.buffer.subarray(safeLength);\n } else {\n // Found boundary, process content before it (minus CRLF)\n const contentEnd = Math.max(0, nextBoundaryIndex - 2);\n contentChunk = state.buffer.subarray(0, contentEnd);\n buffer = state.buffer.subarray(nextBoundaryIndex);\n isComplete = true;\n }\n\n let updatedState = { ...state, buffer };\n\n if (contentChunk.length > 0) {\n updatedState = await processContentChunk(updatedState, contentChunk);\n }\n\n if (isComplete) {\n updatedState = await finalizeCurrentPart(updatedState);\n updatedState = {\n ...updatedState,\n stage: 'boundary' as const,\n hasProcessedAnyPart: true, // Mark that we've processed at least one part\n };\n }\n\n return updatedState;\n}\n\n/**\n * Process a chunk of content data\n */\nasync function processContentChunk(state: ParserState, chunk: Buffer): Promise<ParserState> {\n const newContentLength = state.currentContentLength + chunk.length;\n\n // Size validation\n const maxSize =\n state.currentFilename !== undefined ? state.options.maxFileSize : state.options.maxFieldSize;\n\n if (newContentLength > maxSize) {\n const isFile = state.currentFilename !== undefined;\n const { PayloadTooLargeError } = await import('../errors/payload-too-large-error');\n const payloadErrorDetals = state.currentField\n ? {\n contentType: isFile ? 'file' : 'field',\n currentSize: newContentLength,\n maxSize,\n field: state.currentField,\n filename: state.currentFilename,\n }\n : {\n contentType: isFile ? 'file' : 'field',\n currentSize: newContentLength,\n maxSize,\n filename: state.currentFilename,\n };\n throw new PayloadTooLargeError(\n `${isFile ? 'File' : 'Field'} size exceeds limit`,\n payloadErrorDetals\n );\n }\n\n if (state.currentFilename !== undefined) {\n return processFileChunk(state, chunk, newContentLength);\n } else {\n return {\n ...state,\n currentContentLength: newContentLength,\n currentBufferChunks: [...state.currentBufferChunks, chunk],\n };\n }\n}\n\n/**\n * Process file chunk based on strategy\n */\nasync function processFileChunk(\n state: ParserState,\n chunk: Buffer,\n newContentLength: number\n): Promise<ParserState> {\n switch (state.options.strategy) {\n case 'memory':\n return {\n ...state,\n currentContentLength: newContentLength,\n currentBufferChunks: [...state.currentBufferChunks, chunk],\n };\n\n case 'stream':\n if (state.streamController) {\n state.streamController.enqueue(chunk);\n }\n return { ...state, currentContentLength: newContentLength };\n\n case 'temp':\n if (state.currentWriteStream) {\n await writeToStream(state.currentWriteStream, chunk);\n }\n return { ...state, currentContentLength: newContentLength };\n\n default: {\n const { ValidationError } = await import('../errors/validation-error');\n throw new ValidationError(`Invalid parsing strategy`);\n // TODO: create new error type to support \"strategy\" + \"supportedStrategies\"\n // throw new ValidationError(`Invalid parsing strategy`, {\n // strategy: state.options.strategy,\n // supportedStrategies: ['memory', 'stream', 'temp'],\n // });\n }\n }\n}\n\n/**\n * Initialize file processing for current part\n */\nasync function initializeFileProcessing(state: ParserState): Promise<ParserState> {\n if (state.currentFilename === undefined) return state;\n\n switch (state.options.strategy) {\n case 'memory':\n return { ...state, currentBufferChunks: [] };\n\n case 'stream': {\n let streamController: ReadableStreamDefaultController<Uint8Array> | null = null;\n const stream = new ReadableStream<Uint8Array>({\n start: controller => {\n streamController = controller;\n },\n });\n\n return {\n ...state,\n currentStream: stream as any, // Type cast for Node.js compatibility\n streamController,\n };\n }\n\n case 'temp': {\n const tempPath = join(state.options.tempDir, `upload-${crypto.randomUUID()}`);\n const writeStream = createWriteStream(tempPath);\n const cleanupTask = async () => {\n try {\n const { unlink } = await import('node:fs/promises');\n await unlink(tempPath);\n } catch (error) {\n console.warn(`Failed to cleanup temp file: ${tempPath}`, error);\n }\n };\n\n return {\n ...state,\n currentTempPath: tempPath,\n currentWriteStream: writeStream,\n cleanupTasks: [...state.cleanupTasks, cleanupTask],\n };\n }\n\n default: {\n const { ValidationError } = await import('../errors/validation-error');\n throw new ValidationError(`Invalid file processing strategy`);\n // throw new ValidationError(`Invalid file processing strategy`, {\n // strategy: state.options.strategy,\n // });\n }\n }\n}\n\n/**\n * Finalize current part and add to collections\n */\nasync function finalizeCurrentPart(state: ParserState): Promise<ParserState> {\n if (!state.currentField) return resetCurrentPart(state);\n\n if (state.currentFilename !== undefined) {\n return finalizeFile(state);\n } else {\n return finalizeField(state);\n }\n}\n\n/**\n * Finalize file processing\n */\nasync function finalizeFile(state: ParserState): Promise<ParserState> {\n if (!state.currentField || state.currentFilename === undefined) {\n return resetCurrentPart(state);\n }\n\n let stream: Readable;\n let buffer: Buffer | undefined;\n let tempPath: string | undefined;\n\n switch (state.options.strategy) {\n case 'memory':\n buffer = Buffer.concat(state.currentBufferChunks);\n stream = Readable.from(buffer);\n break;\n\n case 'stream':\n if (state.streamController) {\n state.streamController.close();\n }\n stream = state.currentStream!;\n break;\n\n case 'temp':\n if (state.currentWriteStream) {\n await closeStream(state.currentWriteStream);\n }\n tempPath = state.currentTempPath!;\n stream = Readable.from(Buffer.alloc(0)); // Placeholder\n break;\n\n default: {\n // ✅ HTTP 400 - Bad Request for invalid strategy\n const { ValidationError } = await import('../errors/validation-error');\n throw new ValidationError(`Invalid file finalization strategy`);\n // throw new ValidationError(`Invalid file finalization strategy`, {\n // strategy: state.options.strategy,\n // });\n }\n }\n\n const file: UploadedFile = {\n filename: state.currentFilename,\n fieldname: state.currentField,\n mimetype: state.currentMimetype,\n size: state.currentContentLength,\n stream,\n buffer,\n tempPath,\n };\n\n const updatedFiles = addToCollection(state.files, state.currentField, file);\n\n return {\n ...resetCurrentPart(state),\n files: updatedFiles,\n };\n}\n\n/**\n * Finalize field processing\n */\nfunction finalizeField(state: ParserState): ParserState {\n if (!state.currentField) return resetCurrentPart(state);\n\n const value = Buffer.concat(state.currentBufferChunks).toString('utf8');\n const updatedFields = addToCollection(state.fields, state.currentField, value);\n\n return {\n ...resetCurrentPart(state),\n fields: updatedFields,\n };\n}\n\n/**\n * Reset current part state\n */\nfunction resetCurrentPart(state: ParserState): ParserState {\n return {\n ...state,\n currentField: null,\n currentFilename: undefined,\n currentContentLength: 0,\n currentBufferChunks: [],\n currentStream: null,\n streamController: null,\n currentTempPath: null,\n currentWriteStream: null,\n };\n}\n\n/**\n * Add item to collection immutably\n */\nfunction addToCollection<T>(collection: Map<string, T[]>, key: string, value: T): Map<string, T[]> {\n const newCollection = new Map(collection);\n const existing = newCollection.get(key) || [];\n newCollection.set(key, [...existing, value]);\n return newCollection;\n}\n\n/**\n * Finalize parsing and return results\n */\nasync function finalize(state: ParserState): Promise<MultipartData> {\n // Validate that we found valid multipart data\n if (!state.hasFoundValidBoundary) {\n const { ValidationError } = await import('../errors/validation-error');\n throw new ValidationError('No valid multipart boundary found');\n // throw new ValidationError('No valid multipart boundary found', {\n // errorType: 'invalid_multipart',\n // reason: 'Missing or malformed boundary markers',\n // });`\n }\n\n // If we found boundaries but didn't process any parts, it's empty/invalid\n if (state.hasFoundValidBoundary && !state.hasProcessedAnyPart) {\n const { ValidationError } = await import('../errors/validation-error');\n throw new ValidationError('Empty multipart request');\n // throw new ValidationError('Empty multipart request', {\n // errorType: 'empty_multipart',\n // reason: 'Valid boundaries found but no data parts processed',\n // });\n }\n\n const fields: Record<string, string | string[]> = {};\n for (const [key, values] of state.fields.entries()) {\n fields[key] = values.length === 1 ? values[0]! : values;\n }\n\n const files: Record<string, UploadedFile | UploadedFile[]> = {};\n for (const [key, fileList] of state.files.entries()) {\n files[key] = fileList.length === 1 ? fileList[0]! : fileList;\n }\n\n return { fields, files };\n}\n\n/**\n * Cleanup resources\n */\nasync function cleanup(state: ParserState): Promise<void> {\n // Execute all cleanup tasks\n await Promise.allSettled(state.cleanupTasks.map(task => task()));\n\n // Close any open streams\n if (state.streamController) {\n state.streamController.close();\n }\n\n if (state.currentWriteStream) {\n await closeStream(state.currentWriteStream);\n }\n}\n\n// Helper functions\nasync function writeToStream(stream: WriteStream, chunk: Buffer): Promise<void> {\n return new Promise((resolve, reject) => {\n stream.write(chunk, error => {\n if (error) reject(error);\n else resolve();\n });\n });\n}\n\nasync function closeStream(stream: WriteStream): Promise<void> {\n return new Promise(resolve => {\n stream.end(() => resolve());\n });\n}\n\n/**\n * Main parsing function (functional interface)\n */\nexport async function parseMultipartRequest(\n request: UnifiedRequest,\n options: Partial<ParseOptions> = {}\n): Promise<MultipartData> {\n const contentType = (request.headers['content-type'] as string) || '';\n const boundary = extractBoundary(contentType);\n\n if (!boundary) {\n const { UnsupportedMediaTypeError } = await import('../errors/unsupported-media-type-error');\n throw new UnsupportedMediaTypeError('Missing boundary in multipart content-type', {\n receivedContentType: contentType,\n expectedFormat: 'multipart/form-data; boundary=...',\n });\n }\n\n let state = createParserState(boundary, options);\n\n // Initialize file processing if needed\n if (state.currentFilename !== undefined) {\n state = await initializeFileProcessing(state);\n }\n\n try {\n // Process request stream\n for await (const chunk of request) {\n state = await processChunk(state, chunk as Buffer);\n }\n\n return finalize(state);\n } finally {\n await cleanup(state);\n }\n}\n","// Hoisted regex patterns\nconst BOUNDARY_REGEX = /boundary=([^;]+)/i;\nconst CONTENT_DISPOSITION_REGEX =\n /Content-Disposition:\\s*form-data;\\s*name=\"([^\"]+)\"(?:;[\\s\\r\\n]*filename=\"([^\"]*)\")?/i;\nconst CONTENT_TYPE_REGEX = /Content-Type:\\s*([^\\r\\n]+)/i;\nconst MULTIPART_REGEX = /multipart\\/form-data/i;\n\n/**\n * Extract boundary from Content-Type header\n */\nexport function extractBoundary(contentType: string): string | null {\n const match = contentType.match(BOUNDARY_REGEX);\n if (!match || !match[1]) return null;\n\n let boundary = match[1].trim();\n if (boundary.startsWith('\"') && boundary.endsWith('\"')) {\n boundary = boundary.slice(1, -1);\n }\n\n return boundary || null;\n}\n\n/**\n * Parse Content-Disposition header\n */\nexport function parseContentDisposition(\n headers: string\n): { name: string; filename?: string } | null {\n const match = headers.match(CONTENT_DISPOSITION_REGEX);\n if (!match || !match[1]) return null;\n\n return {\n name: match[1],\n filename: match[2] !== undefined ? match[2] : undefined,\n };\n}\n\n/**\n * Parse Content-Type header\n */\nexport function parseContentType(headers: string): string {\n const match = headers.match(CONTENT_TYPE_REGEX);\n return match && match[1]?.trim() ? match[1].trim() : 'application/octet-stream';\n}\n\n/**\n * Check if content type is multipart\n */\nexport function isMultipartContent(contentType: string): boolean {\n return MULTIPART_REGEX.test(contentType);\n}\n","import {\n ParseUrlError,\n ResponseSentContentError,\n ResponseSentError,\n ResponseSentHeaderError,\n} from './errors';\nimport { hasContext, getContext } from './store';\nimport { PayloadTooLargeError } from '../errors/payload-too-large-error';\nimport { UnsupportedMediaTypeError } from '../errors/unsupported-media-type-error';\nimport { ValidationError } from '../errors/validation-error';\nimport { getCorrelationHeaderName, getCorrelationId } from '../tracing/correlation';\nimport { parseMultipartRequest } from '../upload/multipart-parser';\nimport { isMultipartContent } from '../upload/utils';\n\nimport type {\n Context,\n ContextOptions,\n MultipartLimits,\n QueryParams,\n RequestParams,\n State,\n StreamOptions,\n UnifiedRequest,\n UnifiedResponse,\n Services,\n} from '@blaize-types/context';\n\nconst CONTENT_TYPE_HEADER = 'Content-Type';\n\n/**\n * Parse URL and extract path and query parameters using modern URL API\n */\nfunction parseRequestUrl(req: UnifiedRequest): {\n path: string;\n url: URL | null;\n query: QueryParams;\n} {\n const originalUrl = (req as any).url || '/';\n\n // Construct full URL for parsing\n const host = req.headers.host || 'localhost';\n const protocol = req.socket && (req.socket as any).encrypted ? 'https' : 'http';\n const fullUrl = `${protocol}://${host}${originalUrl.startsWith('/') ? '' : '/'}${originalUrl}`;\n try {\n const url = new URL(fullUrl);\n\n // Extract path\n const path = url.pathname;\n\n // Parse query parameters using URLSearchParams\n const query: QueryParams = {};\n url.searchParams.forEach((value, key) => {\n // Handle array parameters (key=value1&key=value2)\n if (query[key] !== undefined) {\n if (Array.isArray(query[key])) {\n (query[key] as string[]).push(value);\n } else {\n query[key] = [query[key] as string, value];\n }\n } else {\n query[key] = value;\n }\n });\n\n return { path, url, query };\n } catch (error) {\n // Fallback for invalid URLs\n console.warn(`Invalid URL: ${fullUrl}`, error);\n throw new ParseUrlError(`Invalid URL: ${fullUrl}`);\n }\n}\n\n/**\n * Determine if the request is using HTTP/2\n */\nfunction isHttp2Request(req: UnifiedRequest): boolean {\n // Check for HTTP/2 specific properties\n return 'stream' in req || ('httpVersionMajor' in req && (req as any).httpVersionMajor === 2);\n}\n\n/**\n * Get the HTTP protocol (http or https)\n */\nfunction getProtocol(req: UnifiedRequest): string {\n // Check for encrypted socket\n const encrypted = req.socket && (req.socket as any).encrypted;\n // Check for X-Forwarded-Proto header (common in proxy environments)\n const forwardedProto = req.headers['x-forwarded-proto'];\n\n if (forwardedProto) {\n if (Array.isArray(forwardedProto)) {\n // Handle array of header values (uncommon but possible)\n return forwardedProto[0]?.split(',')[0]?.trim() || 'http';\n } else {\n // Handle string header value (typical case)\n return forwardedProto.split(',')[0]?.trim() || 'http';\n }\n }\n\n // Default protocol based on socket encryption\n return encrypted ? 'https' : 'http';\n}\n\n/**\n * Create a new context object for a request/response cycle\n */\nexport async function createContext<\n S extends State = State,\n Svc extends Services = Services,\n TBody = unknown,\n TQuery = QueryParams,\n>(\n req: UnifiedRequest,\n res: UnifiedResponse,\n options: ContextOptions\n): Promise<Context<S, Svc, TBody, TQuery>> {\n // Extract basic request information\n const { path, url, query } = parseRequestUrl(req);\n const method = req.method || 'GET';\n const isHttp2 = isHttp2Request(req);\n const protocol = getProtocol(req);\n\n // Initialize state\n const params: RequestParams = {};\n const state = { ...(options.initialState || {}) } as S;\n const services = { ...(options.initialServices || {}) } as Svc;\n\n // Track response status\n const responseState = { sent: false };\n\n // Create the context object with its components\n const ctx: Context<S, Svc, TBody, TQuery> = {\n request: createRequestObject<TBody, TQuery>(req, {\n path,\n url,\n query: query as TQuery,\n params,\n method,\n isHttp2,\n protocol,\n }),\n response: {} as Context<S, Svc, TBody, TQuery>['response'],\n state,\n services,\n };\n\n ctx.response = createResponseObject(res, responseState, ctx);\n\n // Parse body if requested\n if (options.parseBody) {\n await parseBodyIfNeeded(req, ctx, options);\n }\n\n return ctx;\n}\n\n/**\n * Create the request object portion of the context\n */\nfunction createRequestObject<TBody = unknown, TQuery = QueryParams>(\n req: UnifiedRequest,\n info: {\n path: string;\n url: URL | null;\n query: TQuery;\n params: RequestParams;\n method: string;\n isHttp2: boolean;\n protocol: string;\n }\n): Context<State, Services, TBody, TQuery>['request'] {\n return {\n raw: req,\n ...info,\n header: createRequestHeaderGetter(req),\n headers: createRequestHeadersGetter(req),\n body: undefined as unknown as TBody,\n };\n}\n\n/**\n * Create a function to get a single request header\n */\nfunction createRequestHeaderGetter(req: UnifiedRequest) {\n return (name: string): string | undefined => {\n const value = req.headers[name.toLowerCase()];\n if (Array.isArray(value)) {\n return value.join(', ');\n }\n return value || undefined;\n };\n}\n\n/**\n * Create a function to get multiple request headers\n */\nfunction createRequestHeadersGetter(req: UnifiedRequest) {\n const headerGetter = createRequestHeaderGetter(req);\n\n return (names?: string[]): Record<string, string | undefined> => {\n if (names && Array.isArray(names) && names.length > 0) {\n return names.reduce<Record<string, string | undefined>>((acc, name) => {\n acc[name] = headerGetter(name);\n return acc;\n }, {});\n } else {\n return Object.entries(req.headers).reduce<Record<string, string | undefined>>(\n (acc, [key, value]) => {\n acc[key] = Array.isArray(value) ? value.join(', ') : value || undefined;\n return acc;\n },\n {}\n );\n }\n };\n}\n\n/**\n * Helper to add correlation header if available in state\n * Works for both HTTP/1.1 and HTTP/2 by using the context's setHeader abstraction\n */\nfunction addCorrelationHeader(res: UnifiedResponse, state: State): void {\n // Only add if correlation ID exists in state\n if (state.correlationId) {\n const headerName = getCorrelationHeaderName();\n const correlationValue = String(state.correlationId);\n res.setHeader(headerName, correlationValue);\n }\n}\n\n/**\n * Create the response object portion of the context\n */\nfunction createResponseObject<\n S extends State = State,\n Svc extends Services = Services,\n TBody = unknown,\n TQuery = QueryParams,\n>(\n res: UnifiedResponse,\n responseState: { sent: boolean },\n ctx: Context<S, Svc, TBody, TQuery>\n): Context<S, Svc, TBody, TQuery>['response'] {\n return {\n raw: res,\n\n // TODO: this does not work well and should be enhanced\n get statusCode() {\n return res.statusCode || 200;\n },\n\n get sent() {\n return responseState.sent;\n },\n\n status: createStatusSetter(res, responseState, ctx),\n header: createHeaderSetter(res, responseState, ctx),\n headers: createHeadersSetter(res, responseState, ctx),\n type: createContentTypeSetter(res, responseState, ctx),\n\n json: createJsonResponder(res, responseState, ctx.state),\n text: createTextResponder(res, responseState, ctx.state),\n html: createHtmlResponder(res, responseState, ctx.state),\n redirect: createRedirectResponder(res, responseState, ctx.state),\n stream: createStreamResponder(res, responseState, ctx.state),\n };\n}\n\n/**\n * Create a function to set response status\n */\nfunction createStatusSetter<\n S extends State = State,\n Svc extends Services = Services,\n TBody = unknown,\n TQuery = QueryParams,\n>(res: UnifiedResponse, responseState: { sent: boolean }, ctx: Context<S, Svc, TBody, TQuery>) {\n return function statusSetter(code: number): Context['response'] {\n if (responseState.sent) {\n throw new ResponseSentError();\n }\n res.statusCode = code;\n return ctx.response;\n };\n}\n\n/**\n * Create a function to set a response header\n */\nfunction createHeaderSetter<\n S extends State = State,\n Svc extends Services = Services,\n TBody = unknown,\n TQuery = QueryParams,\n>(res: UnifiedResponse, responseState: { sent: boolean }, ctx: Context<S, Svc, TBody, TQuery>) {\n return function headerSetter(name: string, value: string) {\n if (responseState.sent) {\n throw new ResponseSentHeaderError();\n }\n res.setHeader(name, value);\n return ctx.response;\n };\n}\n\n/**\n * Create a function to set multiple response headers\n */\nfunction createHeadersSetter<\n S extends State = State,\n Svc extends Services = Services,\n TBody = unknown,\n TQuery = QueryParams,\n>(res: UnifiedResponse, responseState: { sent: boolean }, ctx: Context<S, Svc, TBody, TQuery>) {\n return function headersSetter(headers: Record<string, string>) {\n if (responseState.sent) {\n throw new ResponseSentHeaderError();\n }\n for (const [name, value] of Object.entries(headers)) {\n res.setHeader(name, value);\n }\n return ctx.response;\n };\n}\n\n/**\n * Create a function to set content type header\n */\nfunction createContentTypeSetter<\n S extends State = State,\n Svc extends Services = Services,\n TBody = unknown,\n TQuery = QueryParams,\n>(res: UnifiedResponse, responseState: { sent: boolean }, ctx: Context<S, Svc, TBody, TQuery>) {\n return function typeSetter(type: string) {\n if (responseState.sent) {\n throw new ResponseSentContentError();\n }\n res.setHeader(CONTENT_TYPE_HEADER, type);\n return ctx.response;\n };\n}\n\n/**\n * Create a function to send JSON response\n */\nfunction createJsonResponder(res: UnifiedResponse, responseState: { sent: boolean }, state: State) {\n return function jsonResponder(body: unknown, status?: number) {\n if (responseState.sent) {\n throw new ResponseSentError();\n }\n\n if (status !== undefined) {\n res.statusCode = status;\n }\n\n addCorrelationHeader(res, state);\n res.setHeader(CONTENT_TYPE_HEADER, 'application/json');\n res.end(JSON.stringify(body));\n responseState.sent = true;\n };\n}\n\n/**\n * Create a function to send text response\n */\nfunction createTextResponder(res: UnifiedResponse, responseState: { sent: boolean }, state: State) {\n return function textResponder(body: string, status?: number) {\n if (responseState.sent) {\n throw new ResponseSentError();\n }\n\n if (status !== undefined) {\n res.statusCode = status;\n }\n\n addCorrelationHeader(res, state);\n res.setHeader(CONTENT_TYPE_HEADER, 'text/plain');\n res.end(body);\n responseState.sent = true;\n };\n}\n\n/**\n * Create a function to send HTML response\n */\nfunction createHtmlResponder(res: UnifiedResponse, responseState: { sent: boolean }, state: State) {\n return function htmlResponder(body: string, status?: number) {\n if (responseState.sent) {\n throw new ResponseSentError();\n }\n\n if (status !== undefined) {\n res.statusCode = status;\n }\n\n addCorrelationHeader(res, state);\n res.setHeader(CONTENT_TYPE_HEADER, 'text/html');\n res.end(body);\n responseState.sent = true;\n };\n}\n\n/**\n * Create a function to send redirect response\n */\nfunction createRedirectResponder(\n res: UnifiedResponse,\n responseState: { sent: boolean },\n state: State\n) {\n return function redirectResponder(url: string, status = 302) {\n if (responseState.sent) {\n throw new ResponseSentError();\n }\n\n addCorrelationHeader(res, state);\n res.statusCode = status;\n res.setHeader('Location', url);\n res.end();\n responseState.sent = true;\n };\n}\n\n/**\n * Create a function to stream response\n */\nfunction createStreamResponder(\n res: UnifiedResponse,\n responseState: { sent: boolean },\n state: State\n) {\n return function streamResponder(readable: NodeJS.ReadableStream, options: StreamOptions = {}) {\n if (responseState.sent) {\n throw new ResponseSentError();\n }\n\n if (options.status !== undefined) {\n res.statusCode = options.status;\n }\n\n addCorrelationHeader(res, state);\n if (options.contentType) {\n res.setHeader(CONTENT_TYPE_HEADER, options.contentType);\n }\n\n if (options.headers) {\n for (const [name, value] of Object.entries(options.headers)) {\n res.setHeader(name, value);\n }\n }\n\n // Handle streaming\n readable.pipe(res);\n\n // Mark as sent when the stream ends\n readable.on('end', () => {\n responseState.sent = true;\n });\n\n // Handle errors\n readable.on('error', err => {\n console.error('Stream error:', err);\n if (!responseState.sent) {\n res.statusCode = 500;\n res.end('Stream error');\n responseState.sent = true;\n }\n });\n };\n}\n\n/**\n * Parse request body if enabled in options\n *\n * Throws appropriate errors on parsing failures:\n * - ValidationError (400) for malformed data\n * - PayloadTooLargeError (413) for size limit violations\n * - UnsupportedMediaTypeError (415) for unsupported content types\n */\nasync function parseBodyIfNeeded<TBody = unknown, TQuery = QueryParams>(\n req: UnifiedRequest,\n ctx: Context<State, Services, TBody, TQuery>,\n options: ContextOptions\n): Promise<void> {\n // Skip parsing for methods that typically don't have bodies\n if (shouldSkipParsing(req.method)) {\n return;\n }\n\n const contentType = req.headers['content-type'] || '';\n const contentLength = parseInt(req.headers['content-length'] || '0', 10);\n\n // Skip if no content\n if (contentLength === 0) {\n return;\n }\n\n const limits = options.bodyLimits;\n\n // ✅ Check size limits BEFORE parsing and throw immediately\n if (contentType.includes('application/json')) {\n if (contentLength > limits.json) {\n throw new PayloadTooLargeError(\n 'JSON body exceeds size limit',\n {\n currentSize: contentLength,\n maxSize: limits.json,\n contentType: 'application/json',\n },\n getCorrelationId()\n );\n }\n await parseJsonBody(req, ctx); // Throws ValidationError on malformed JSON\n } else if (contentType.includes('application/x-www-form-urlencoded')) {\n if (contentLength > limits.form) {\n throw new PayloadTooLargeError(\n 'Form body exceeds size limit',\n {\n currentSize: contentLength,\n maxSize: limits.form,\n contentType: 'application/x-www-form-urlencoded',\n },\n getCorrelationId()\n );\n }\n await parseFormUrlEncodedBody(req, ctx); // Throws ValidationError on malformed form\n } else if (contentType.includes('text/')) {\n if (contentLength > limits.text) {\n throw new PayloadTooLargeError(\n 'Text body exceeds size limit',\n {\n currentSize: contentLength,\n maxSize: limits.text,\n contentType,\n },\n getCorrelationId()\n );\n }\n await parseTextBody(req, ctx);\n } else if (isMultipartContent(contentType)) {\n // Multipart has its own size validation in parseMultipartRequest\n // Throws PayloadTooLargeError or UnsupportedMediaTypeError\n await parseMultipartBody(req, ctx, limits.multipart);\n } else {\n // Unknown content type - apply raw limit\n if (contentLength > limits.raw) {\n throw new PayloadTooLargeError(\n 'Request body exceeds size limit',\n {\n currentSize: contentLength,\n maxSize: limits.raw,\n contentType: contentType || 'unknown',\n },\n getCorrelationId()\n );\n }\n // Don't parse unknown content types, but allow them through\n return;\n }\n\n // ✅ No try/catch - let errors bubble up to error boundary\n}\n\n/**\n * Determine if body parsing should be skipped based on HTTP method\n */\nfunction shouldSkipParsing(method?: string): boolean {\n const skipMethods = ['GET', 'HEAD', 'OPTIONS'];\n return skipMethods.includes(method || 'GET');\n}\n\n/**\n * Parse JSON request body\n */\nasync function parseJsonBody<TBody = unknown, TQuery = QueryParams>(\n req: UnifiedRequest,\n ctx: Context<State, Services, TBody, TQuery>\n): Promise<void> {\n const body = await readRequestBody(req);\n\n if (!body) {\n console.warn('Empty body, skipping JSON parsing');\n return;\n }\n\n // Check if the body is actually \"null\" string\n if (body.trim() === 'null') {\n console.warn('Body is the string \"null\"');\n ctx.request.body = null as TBody;\n return;\n }\n\n try {\n const json = JSON.parse(body);\n ctx.request.body = json as TBody;\n } catch (error) {\n throw new ValidationError(\n 'Invalid JSON in request body',\n {\n fields: [\n {\n field: 'body',\n messages: [\n 'Request body contains malformed JSON',\n error instanceof Error ? error.message : 'JSON parse failed',\n ],\n },\n ],\n errorCount: 1,\n section: 'body',\n },\n getCorrelationId()\n );\n }\n}\n\n/**\n * Parse URL-encoded form data\n */\nasync function parseFormUrlEncodedBody<TBody = unknown, TQuery = QueryParams>(\n req: UnifiedRequest,\n ctx: Context<State, Services, TBody, TQuery>\n): Promise<void> {\n const body = await readRequestBody(req);\n if (!body) return;\n\n try {\n ctx.request.body = parseUrlEncodedData(body) as TBody;\n } catch (error) {\n throw new ValidationError(\n 'Request body contains malformed form data',\n {\n fields: [\n {\n field: 'body',\n messages: [\n 'Invalid URL-encoded form data',\n error instanceof Error ? error.message : 'Form parse failed',\n ],\n },\n ],\n errorCount: 1,\n section: 'body',\n },\n getCorrelationId()\n );\n }\n}\n\n/**\n * Parse URL-encoded data into an object\n */\nfunction parseUrlEncodedData(body: string): Record<string, string | string[]> {\n const params = new URLSearchParams(body);\n const formData: Record<string, string | string[]> = {};\n\n params.forEach((value, key) => {\n if (formData[key] !== undefined) {\n if (Array.isArray(formData[key])) {\n (formData[key] as string[]).push(value);\n } else {\n formData[key] = [formData[key] as string, value];\n }\n } else {\n formData[key] = value;\n }\n });\n\n return formData;\n}\n\n/**\n * Parse plain text body\n */\nasync function parseTextBody<TBody = null, TQuery = QueryParams>(\n req: UnifiedRequest,\n ctx: Context<State, Services, TBody, TQuery>\n): Promise<void> {\n const body = await readRequestBody(req);\n if (body) {\n ctx.request.body = body as TBody;\n }\n}\n\n/**\n * Parse multipart/form-data request body with improved error handling\n */\nasync function parseMultipartBody<TBody = unknown, TQuery = QueryParams>(\n req: UnifiedRequest,\n ctx: Context<State, Services, TBody, TQuery>,\n multipartLimits: MultipartLimits\n): Promise<void> {\n try {\n const limits = multipartLimits;\n const multipartData = await parseMultipartRequest(req, {\n strategy: 'stream',\n maxFileSize: limits.maxFileSize,\n maxFiles: limits.maxFiles,\n maxFieldSize: limits.maxFieldSize,\n // Could add total size validation here\n });\n\n // Extend context with multipart data (type-safe assignments)\n (ctx.request as any).multipart = multipartData;\n (ctx.request as any).files = multipartData.files;\n\n // Set body to fields for backward compatibility with existing form handling\n ctx.request.body = multipartData.fields as TBody;\n } catch (error) {\n if (error instanceof PayloadTooLargeError) {\n throw error; // Already correct type\n }\n if (error instanceof UnsupportedMediaTypeError) {\n throw error; // Already correct type\n }\n // Generic multipart errors\n throw new UnsupportedMediaTypeError(\n 'Failed to parse multipart/form-data',\n {\n receivedContentType: req.headers['content-type'],\n expectedFormat: 'multipart/form-data; boundary=...',\n },\n getCorrelationId()\n );\n }\n}\n\n/**\n * Read the entire request body as a string\n */\nasync function readRequestBody(req: UnifiedRequest): Promise<string> {\n return new Promise<string>((resolve, reject) => {\n const chunks: Buffer[] = [];\n\n req.on('data', (chunk: Buffer | string) => {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n });\n\n req.on('end', () => {\n resolve(Buffer.concat(chunks).toString('utf8'));\n });\n\n req.on('error', err => {\n reject(err);\n });\n });\n}\n\n/**\n * Get the current context or throw an error if none exists\n */\nexport function getCurrentContext<\n S extends State = State,\n Svc extends Services = Services,\n TBody = unknown,\n TQuery = QueryParams,\n>(): Context<S, Svc, TBody, TQuery> {\n const ctx = getContext<S, Svc, TBody, TQuery>();\n if (!ctx) {\n throw new Error(\n 'No context found. Ensure this function is called within a request handler, ' +\n 'middleware, or function wrapped with runWithContext().'\n );\n }\n return ctx;\n}\n\n/**\n * Check if we're currently in a request context\n */\nexport function isInRequestContext(): boolean {\n return hasContext();\n}\n","/**\n * NotFoundError class for resource not found errors\n *\n * This error is thrown when a requested resource cannot be found.\n * It provides context about what resource was being looked for and how.\n */\n\nimport { BlaizeError, ErrorType } from '@blaize-types/errors';\n\nimport { getCorrelationId } from '../tracing/correlation';\n\nimport type { NotFoundErrorDetails } from '@blaize-types/errors';\n/**\n * Error thrown when a requested resource cannot be found\n *\n * Automatically sets HTTP status to 404 and provides context\n * about the missing resource for better debugging and user experience.\n *\n * @example Basic usage:\n * ```typescript\n * throw new NotFoundError('User not found');\n * ```\n *\n * @example With resource context:\n * ```typescript\n * throw new NotFoundError('User not found', {\n * resourceType: 'User',\n * resourceId: 'user-123',\n * suggestion: 'Check if the user ID is correct'\n * });\n * ```\n *\n * @example API endpoint not found:\n * ```typescript\n * throw new NotFoundError('Endpoint not found', {\n * path: '/api/v1/unknown',\n * method: 'GET',\n * suggestion: 'Check the API documentation'\n * });\n * ```\n */\nexport class NotFoundError extends BlaizeError<NotFoundErrorDetails> {\n /**\n * Creates a new NotFoundError instance\n *\n * @param title - Human-readable error message\n * @param details - Optional context about the missing resource\n * @param correlationId - Optional correlation ID (uses current context if not provided)\n */\n constructor(\n title: string,\n details: NotFoundErrorDetails | undefined = undefined,\n correlationId: string | undefined = undefined\n ) {\n super(\n ErrorType.NOT_FOUND,\n title,\n 404, // HTTP 404 Not Found\n correlationId ?? getCorrelationId(),\n details\n );\n }\n}\n","import { BlaizeError } from '@blaize-types/errors';\n\nimport { InternalServerError } from './internal-server-error';\nimport {\n getCorrelationId,\n createCorrelationIdFromHeaders,\n getCorrelationHeaderName,\n} from '../tracing/correlation';\n\nimport type { BlaizeErrorResponse } from '@blaize-types/errors';\n\n/**\n * Checks if an error is a handled BlaizeError instance\n */\nexport function isHandledError(error: unknown): error is BlaizeError {\n return error instanceof BlaizeError;\n}\n\n/**\n * Formats any error into a standardized BlaizeErrorResponse\n */\nexport function formatErrorResponse(error: unknown): BlaizeErrorResponse {\n // Handle BlaizeError instances - they're already properly formatted\n if (isHandledError(error)) {\n return {\n type: error.type,\n title: error.title,\n status: error.status,\n correlationId: error.correlationId,\n timestamp: error.timestamp.toISOString(),\n details: error.details,\n };\n }\n\n // Handle unexpected errors by wrapping them in InternalServerError\n const correlationId = getCorrelationId();\n let originalMessage: string;\n\n if (error instanceof Error) {\n originalMessage = error.message;\n } else if (error === null || error === undefined) {\n originalMessage = 'Unknown error occurred';\n } else {\n originalMessage = String(error);\n }\n\n // Create InternalServerError for unexpected errors\n const wrappedError = new InternalServerError(\n 'Internal Server Error',\n { originalMessage },\n correlationId\n );\n\n return {\n type: wrappedError.type,\n title: wrappedError.title,\n status: wrappedError.status,\n correlationId: wrappedError.correlationId,\n timestamp: wrappedError.timestamp.toISOString(),\n details: wrappedError.details,\n };\n}\n\n/**\n * Extracts correlation ID from request headers or generates a new one\n *\n * Uses the configured header name (default: 'x-correlation-id') to extract\n * the correlation ID from request headers. If not found, generates a new one.\n *\n * @param headerGetter - Function to retrieve header values by name\n * @returns Correlation ID (extracted or generated)\n */\nexport function extractOrGenerateCorrelationId(\n headerGetter: (name: string) => string | undefined\n): string {\n // Get the configured header name\n const headerName = getCorrelationHeaderName();\n\n // Build a headers object that the correlation module expects\n const headers: Record<string, string | undefined> = {\n [headerName]: headerGetter(headerName),\n };\n\n // Use the correlation module's function which handles the configured header\n return createCorrelationIdFromHeaders(headers);\n}\n\n/**\n * Sets response headers for error responses\n *\n * Sets the correlation ID header using the configured header name\n * (default: 'x-correlation-id'). This ensures error responses always\n * include the correlation ID for tracing.\n *\n * @param headerSetter - Function to set response headers\n * @param correlationId - The correlation ID to include in the response\n */\nexport function setErrorResponseHeaders(\n headerSetter: (name: string, value: string) => void,\n correlationId: string\n): void {\n // Get the configured header name\n const headerName = getCorrelationHeaderName();\n\n // Set the correlation header with the configured name\n headerSetter(headerName, correlationId);\n\n // Add any other standard error headers here if needed\n // For example: headerSetter('content-type', 'application/json');\n}\n","import {\n formatErrorResponse,\n extractOrGenerateCorrelationId,\n setErrorResponseHeaders,\n} from '../../errors/boundary';\nimport { create as createMiddleware } from '../create';\n\nimport type { Context } from '@blaize-types/context';\nimport type { BlaizeLogger } from '@blaize-types/logger';\nimport type { Middleware, NextFunction } from '@blaize-types/middleware';\n\n/**\n * Options for configuring the error boundary middleware\n */\nexport interface ErrorBoundaryOptions {\n /** Enable debug logging of caught errors */\n debug?: boolean;\n}\n\n/**\n * Creates an error boundary middleware that catches all errors and converts them to proper HTTP responses\n *\n * This middleware should be placed early in the middleware chain to catch all downstream errors.\n * It ensures that:\n * - All BlaizeError instances are properly formatted as HTTP responses\n * - Unexpected errors are wrapped in InternalServerError and logged\n * - Correlation IDs are preserved and added to response headers\n * - No unhandled errors escape the middleware chain\n */\nexport function createErrorBoundary(options: ErrorBoundaryOptions = {}): Middleware {\n const { debug = false } = options;\n\n return createMiddleware({\n name: 'ErrorBoundary',\n debug,\n handler: async (ctx: Context, next: NextFunction, logger: BlaizeLogger) => {\n try {\n await next();\n } catch (error) {\n // Don't handle errors if response was already sent\n if (ctx.response.sent) {\n if (debug) {\n logger.error('Error occurred after response was sent:', { error });\n }\n return;\n }\n\n // Log error in debug mode\n if (debug) {\n logger.error('Error boundary caught error:', { error });\n }\n\n // Extract or generate correlation ID from request\n const correlationId = extractOrGenerateCorrelationId(ctx.request.header);\n\n // Format the error as a proper response\n const errorResponse = formatErrorResponse(error);\n\n // Ensure correlation ID is consistent\n errorResponse.correlationId = correlationId;\n\n // Set appropriate response headers\n setErrorResponseHeaders(ctx.response.header, correlationId);\n\n // Send the formatted error response\n ctx.response.status(errorResponse.status).json(errorResponse);\n }\n },\n });\n}\n","import { createContext } from '../context/create';\nimport { runWithContext } from '../context/store';\nimport { NotFoundError } from '../errors/not-found-error';\nimport { compose } from '../middleware/compose';\nimport { cors } from '../middleware/cors';\nimport { createErrorBoundary } from '../middleware/error-boundary/create';\nimport {\n createCorrelationIdFromHeaders,\n getCorrelationHeaderName,\n withCorrelationId,\n} from '../tracing/correlation';\n\nimport type { Middleware } from '@blaize-types/middleware';\nimport type { RequestHandler, UnknownServer } from '@blaize-types/server';\n\nexport function createRequestHandler(serverInstance: UnknownServer): RequestHandler {\n return async (req, res) => {\n const correlationId = createCorrelationIdFromHeaders(\n req.headers as Record<string, string | string[] | undefined>\n );\n\n try {\n await withCorrelationId(correlationId, async () => {\n // Create context for this request\n const context = await createContext(req, res, {\n parseBody: true, // Enable automatic body parsing\n initialState: {\n correlationId,\n },\n bodyLimits: serverInstance.bodyLimits,\n });\n\n // Create request logger\n const requestLogger = serverInstance._logger.child({\n correlationId,\n method: context.request.method,\n path: context.request.path,\n });\n\n // Create error boundary middleware that catches all thrown error classes\n const errorBoundary = createErrorBoundary();\n const middlewareChain: Middleware[] = [errorBoundary];\n\n if ('corsOptions' in serverInstance && serverInstance.corsOptions !== false) {\n middlewareChain.push(cors(serverInstance.corsOptions));\n }\n\n // Compose all middleware with error boundary first (to catch all errors)\n middlewareChain.push(...serverInstance.middleware);\n\n // Compose all middleware into a single function\n const handler = compose(middlewareChain);\n\n // Run the request with context in AsyncLocalStorage\n await runWithContext(context, async () => {\n await handler(\n context,\n async () => {\n if (!context.response.sent) {\n // Let the router handle the request\n await serverInstance.router.handleRequest(context, requestLogger);\n // If router didn't handle it either, send a 404\n if (!res.headersSent && !context.response.sent) {\n throw new NotFoundError(\n `Route not found: ${context.request.method} ${context.request.path}`\n );\n }\n }\n },\n requestLogger\n );\n });\n });\n } catch (error) {\n // Fixed to handle HTTP/2 and check if headers already sent (SSE case)\n serverInstance._logger.error('Unhandled request error', { error, correlationId });\n const headerName = getCorrelationHeaderName();\n\n // Check if headers have already been sent (happens with SSE after stream starts)\n if (res.headersSent || (res as any).stream?.headersSent) {\n // Can't send HTTP error response after headers are sent\n // For SSE, the stream's error handling will take care of it\n serverInstance._logger.error('Headers already sent, cannot send error response');\n return;\n }\n\n if ('stream' in res && typeof (res as any).stream?.respond === 'function') {\n // HTTP/2\n (res as any).stream.respond({\n ':status': 500,\n 'content-type': 'application/json',\n [headerName.toLowerCase()]: correlationId,\n });\n (res as any).stream.end(\n JSON.stringify({\n error: 'Internal Server Error',\n message: 'An unexpected error occurred while processing the request',\n correlationId,\n })\n );\n } else {\n // HTTP/1.1\n res.setHeader(headerName, correlationId);\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n error: 'Internal Server Error',\n message: 'An unexpected error occurred while processing the request',\n correlationId,\n })\n );\n }\n }\n };\n}\n","import type { StopOptions, UnknownServer } from '@blaize-types/server';\n\n// Add a global flag to prevent multiple shutdowns\nlet isShuttingDown = false;\n\n// Replace the stopServer function in stop.ts with this version:\n\nexport async function stopServer(\n serverInstance: UnknownServer,\n options: StopOptions = {}\n): Promise<void> {\n const server = serverInstance.server;\n const events = serverInstance.events;\n\n if (isShuttingDown) {\n console.log('⚠️ Shutdown already in progress, ignoring duplicate shutdown request');\n return;\n }\n\n if (!server) {\n return;\n }\n\n isShuttingDown = true;\n const timeout = options.timeout || 5000; // Reduced to 5 seconds for faster restarts\n\n try {\n if (options.onStopping) {\n await options.onStopping();\n }\n\n events.emit('stopping');\n\n // Close router watchers with timeout\n if (serverInstance.router && typeof serverInstance.router.close === 'function') {\n console.log('🔌 Closing router watchers...');\n try {\n // Add timeout to router close\n await Promise.race([\n serverInstance.router.close(),\n new Promise((_, reject) =>\n setTimeout(() => reject(new Error('Router close timeout')), 2000)\n ),\n ]);\n console.log('✅ Router watchers closed');\n } catch (error) {\n console.error('❌ Error closing router watchers:', error);\n // Continue with shutdown\n }\n }\n\n // Notify plugins with timeout\n try {\n await Promise.race([\n serverInstance.pluginManager.onServerStop(serverInstance, server),\n new Promise((_, reject) =>\n setTimeout(() => reject(new Error('Plugin stop timeout')), 2000)\n ),\n ]);\n } catch (error) {\n console.error('❌ Plugin stop timeout:', error);\n // Continue with shutdown\n }\n\n // Create server close promise with shorter timeout\n const closePromise = new Promise<void>((resolve, reject) => {\n server.close((err?: Error) => {\n if (err) return reject(err);\n resolve();\n });\n });\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => {\n reject(new Error('Server shutdown timeout'));\n }, timeout);\n });\n\n await Promise.race([closePromise, timeoutPromise]);\n\n // Terminate plugins with timeout\n try {\n await Promise.race([\n serverInstance.pluginManager.terminatePlugins(serverInstance),\n new Promise((_, reject) =>\n setTimeout(() => reject(new Error('Plugin terminate timeout')), 1000)\n ),\n ]);\n } catch (error) {\n console.error('❌ Plugin terminate timeout:', error);\n // Continue with shutdown\n }\n\n if (options.onStopped) {\n await options.onStopped();\n }\n\n events.emit('stopped');\n serverInstance.server = null as any;\n\n console.log('✅ Graceful shutdown completed');\n isShuttingDown = false;\n } catch (error) {\n isShuttingDown = false;\n console.error('⚠️ Shutdown error (forcing exit):', error);\n\n // Force close the server if graceful shutdown fails\n if (server && typeof server.close === 'function') {\n server.close();\n }\n\n // In development, force exit to allow tsx to restart\n if (process.env.NODE_ENV === 'development') {\n console.log('🔄 Forcing exit for development restart...');\n process.exit(0);\n }\n\n events.emit('error', error);\n throw error;\n }\n}\n\n/**\n * Register signal handlers for graceful shutdown\n */\nexport function registerSignalHandlers(stopFn: () => Promise<void>): { unregister: () => void } {\n const isDevelopment = process.env.NODE_ENV === 'development';\n\n if (isDevelopment) {\n // Development: Force exit for fast restarts\n const sigintHandler = () => {\n console.log('📤 SIGINT received, forcing exit for development restart...');\n process.exit(0);\n };\n\n const sigtermHandler = () => {\n console.log('📤 SIGTERM received, forcing exit for development restart...');\n process.exit(0);\n };\n\n process.on('SIGINT', sigintHandler);\n process.on('SIGTERM', sigtermHandler);\n\n return {\n unregister: () => {\n process.removeListener('SIGINT', sigintHandler);\n process.removeListener('SIGTERM', sigtermHandler);\n },\n };\n } else {\n // Production: Graceful shutdown\n const sigintHandler = () => {\n console.log('📤 SIGINT received, starting graceful shutdown...');\n stopFn().catch(console.error);\n };\n\n const sigtermHandler = () => {\n console.log('📤 SIGTERM received, starting graceful shutdown...');\n stopFn().catch(console.error);\n };\n\n process.on('SIGINT', sigintHandler);\n process.on('SIGTERM', sigtermHandler);\n\n return {\n unregister: () => {\n process.removeListener('SIGINT', sigintHandler);\n process.removeListener('SIGTERM', sigtermHandler);\n },\n };\n }\n}\n","import { z } from 'zod';\n\nimport { serverCorsSchema } from '../middleware/cors/validation';\n\nimport type { Middleware } from '@blaize-types/middleware';\nimport type { Plugin } from '@blaize-types/plugins';\nimport type { ServerOptions } from '@blaize-types/server';\n\n// Create a more flexible validation for the middleware function type\nconst middlewareSchema = z.custom<Middleware>(\n data =>\n data !== null &&\n typeof data === 'object' &&\n 'execute' in data &&\n typeof data.execute === 'function',\n {\n message: 'Expected middleware to have an execute function',\n }\n);\n\n// Create a schema for plugins\nconst pluginSchema = z.custom<Plugin>(\n data =>\n data !== null &&\n typeof data === 'object' &&\n 'register' in data &&\n typeof data.register === 'function',\n {\n message: 'Expected a valid plugin object with a register method',\n }\n);\n\n// Create a schema for HTTP/2 options with conditional validation\nconst http2Schema = z\n .object({\n enabled: z.boolean().optional().default(true),\n keyFile: z.string().optional(),\n certFile: z.string().optional(),\n })\n .refine(\n data => {\n // If HTTP/2 is enabled and not in development mode,\n // both keyFile and certFile must be provided\n if (data.enabled && process.env.NODE_ENV === 'production') {\n return data.keyFile && data.certFile;\n }\n return true;\n },\n {\n message:\n 'When HTTP/2 is enabled (outside of development mode), both keyFile and certFile must be provided',\n }\n );\n\n// Create a schema for correlation options\nconst correlationSchema = z\n .object({\n /**\n * HTTP header name for correlation IDs\n * Must be a valid HTTP header name (lowercase, alphanumeric with hyphens)\n */\n headerName: z\n .string()\n .regex(/^[a-z][a-z0-9-]*$/, {\n message:\n 'Header name must start with a letter and contain only lowercase letters, numbers, and hyphens',\n })\n .optional(),\n\n /**\n * Custom generator function for correlation IDs\n * Must be a function that returns a string\n */\n generator: z.function().args().returns(z.string()).optional(),\n })\n .optional();\n\nconst multipartLimitsSchema = z.object({\n maxFileSize: z\n .number()\n .positive()\n .default(50 * 1024 * 1024),\n maxTotalSize: z\n .number()\n .positive()\n .default(100 * 1024 * 1024),\n maxFiles: z.number().positive().int().default(10),\n maxFieldSize: z\n .number()\n .positive()\n .default(1024 * 1024),\n});\n\nconst bodyLimitsSchema = z.object({\n json: z\n .number()\n .positive()\n .default(512 * 1024),\n form: z\n .number()\n .positive()\n .default(1024 * 1024),\n text: z\n .number()\n .positive()\n .default(5 * 1024 * 1024),\n raw: z\n .number()\n .positive()\n .default(10 * 1024 * 1024),\n multipart: multipartLimitsSchema,\n});\n\n/**\n * Request logger options validation schema\n */\nconst requestLoggerOptionsSchema = z\n .object({\n includeHeaders: z.boolean().optional(),\n headerWhitelist: z.array(z.string().min(1)).optional(),\n includeQuery: z.boolean().optional(),\n })\n .optional();\n\n/**\n * Logger configuration validation schema\n *\n * NOTE: Defaults are NOT set here - they're handled by:\n * - Core logger config: logger.ts:createLogger()\n * - Request config: server/create.ts:initializeLogger()\n */\nconst loggerConfigSchema = z\n .object({\n level: z.enum(['debug', 'info', 'warn', 'error']).optional(),\n transport: z.any().optional(),\n redactKeys: z.array(z.string().min(1)).optional(),\n includeTimestamp: z.boolean().optional(),\n requestLogging: z.boolean().optional(),\n requestLoggerOptions: requestLoggerOptionsSchema,\n })\n .optional();\n\n// Validation schema for server options\nexport const serverOptionsSchema = z.object({\n port: z.number().int().positive().optional().default(3000),\n host: z.string().optional().default('localhost'),\n routesDir: z.string().optional().default('./routes'),\n http2: http2Schema.optional().default({\n enabled: true,\n }),\n middleware: z.array(middlewareSchema).optional().default([]),\n plugins: z.array(pluginSchema).optional().default([]),\n correlation: correlationSchema,\n cors: serverCorsSchema,\n bodyLimits: bodyLimitsSchema,\n logging: loggerConfigSchema,\n});\n\nexport function validateServerOptions(options: ServerOptions): ServerOptions {\n try {\n return serverOptionsSchema.parse(options);\n } catch (error) {\n // Properly type the error as Zod validation error\n if (error instanceof z.ZodError) {\n // Format the Zod error for better readability\n const formattedError = error.format();\n throw new Error(`Invalid server options: ${JSON.stringify(formattedError, null, 2)}`);\n }\n // For other types of errors\n throw new Error(`Invalid server options: ${String(error)}`);\n }\n}\n","import { logger } from '../logger';\n\nimport type { Plugin, PluginLifecycleManager, PluginLifecycleOptions } from '@blaize-types/plugins';\nimport type { UnknownServer } from '@blaize-types/server';\n\n/**\n * Create a plugin lifecycle manager\n */\nexport function createPluginLifecycleManager(\n options: PluginLifecycleOptions = {}\n): PluginLifecycleManager {\n const { continueOnError = true, onError } = options;\n\n /**\n * Handle plugin errors\n */\n function handleError(plugin: Plugin, phase: string, error: Error) {\n const errorMessage = `Plugin ${plugin.name} failed during ${phase}: ${error.message}`;\n\n if (onError) {\n onError(plugin, phase, error);\n } else {\n logger.error(`[PluginLifecycle] ${errorMessage}`, {\n plugin: plugin.name,\n phase,\n error: {\n message: error.message,\n stack: error.stack,\n name: error.name,\n },\n });\n }\n\n if (!continueOnError) {\n throw new Error(errorMessage);\n }\n }\n\n return {\n /**\n * Initialize all plugins\n */\n async initializePlugins(server: UnknownServer): Promise<void> {\n logger.debug('[PluginLifecycle] Initializing plugins', { count: server.plugins.length });\n\n for (const plugin of server.plugins) {\n if (plugin.initialize) {\n try {\n logger.debug(`[PluginLifecycle] Initializing plugin`, {\n plugin: plugin.name,\n });\n await plugin.initialize(server);\n } catch (error) {\n handleError(plugin, 'initialize', error as Error);\n }\n }\n }\n\n logger.info('[PluginLifecycle] Plugins initialized', {\n count: server.plugins.length,\n plugins: server.plugins.map(p => p.name),\n });\n },\n\n /**\n * Terminate all plugins in reverse order\n */\n async terminatePlugins(server: UnknownServer): Promise<void> {\n logger.debug('[PluginLifecycle] Terminating plugins', { count: server.plugins.length });\n\n const pluginsToTerminate = [...server.plugins].reverse();\n\n for (const plugin of pluginsToTerminate) {\n if (plugin.terminate) {\n try {\n logger.debug(`[PluginLifecycle] Terminating plugin`, {\n plugin: plugin.name,\n });\n await plugin.terminate(server);\n } catch (error) {\n handleError(plugin, 'terminate', error as Error);\n }\n }\n }\n logger.info('[PluginLifecycle] Plugins terminated', { count: pluginsToTerminate.length });\n },\n\n /**\n * Notify plugins that the server has started\n */\n async onServerStart(server: UnknownServer, httpServer: any): Promise<void> {\n logger.debug('[PluginLifecycle] Notifying plugins of server start');\n\n for (const plugin of server.plugins) {\n if (plugin.onServerStart) {\n try {\n logger.debug(`[PluginLifecycle] Notifying plugin of server start`, {\n plugin: plugin.name,\n });\n await plugin.onServerStart(httpServer);\n } catch (error) {\n handleError(plugin, 'onServerStart', error as Error);\n }\n }\n }\n },\n\n /**\n * Notify plugins that the server is stopping\n */\n async onServerStop(server: UnknownServer, httpServer: any): Promise<void> {\n logger.debug('[PluginLifecycle] Notifying plugins of server stop...');\n\n const pluginsToNotify = [...server.plugins].reverse();\n\n for (const plugin of pluginsToNotify) {\n if (plugin.onServerStop) {\n try {\n logger.debug(`[PluginLifecycle] Notifying plugin of server stop: ${plugin.name}`);\n await plugin.onServerStop(httpServer);\n } catch (error) {\n handleError(plugin, 'onServerStop', error as Error);\n }\n }\n }\n },\n };\n}\n","/**\n * Base error class for plugin-related errors\n */\nexport class PluginError extends Error {\n constructor(\n public pluginName: string,\n message: string,\n public cause?: Error\n ) {\n super(`Plugin \"${pluginName}\": ${message}`);\n this.name = 'PluginError';\n }\n}\n\n/**\n * Error thrown when a plugin fails during a lifecycle phase\n */\nexport class PluginLifecycleError extends PluginError {\n constructor(\n pluginName: string,\n public phase: 'register' | 'initialize' | 'terminate' | 'start' | 'stop',\n cause: Error\n ) {\n super(pluginName, `Failed during ${phase} phase: ${cause.message}`, cause);\n this.name = 'PluginLifecycleError';\n }\n}\n\n/**\n * Error thrown when a plugin has missing dependencies\n */\nexport class PluginDependencyError extends PluginError {\n constructor(\n pluginName: string,\n public missingDependency: string\n ) {\n super(pluginName, `Missing dependency: ${missingDependency}`);\n this.name = 'PluginDependencyError';\n }\n}\n\n/**\n * Error thrown when plugin validation fails\n */\nexport class PluginValidationError extends Error {\n constructor(\n public pluginName: string,\n message: string\n ) {\n super(`Plugin validation error${pluginName ? ` for \"${pluginName}\"` : ''}: ${message}`);\n this.name = 'PluginValidationError';\n }\n}\n\n/**\n * Error thrown when plugin registration fails\n */\nexport class PluginRegistrationError extends Error {\n constructor(\n public pluginName: string,\n message: string\n ) {\n super(`Plugin registration error for \"${pluginName}\": ${message}`);\n this.name = 'PluginRegistrationError';\n }\n}\n","import { PluginValidationError } from './errors';\n\nimport type { Plugin } from '@blaize-types/plugins';\n\nexport interface PluginValidationOptions {\n /** Require specific plugin properties */\n requireVersion?: boolean;\n /** Validate plugin name format */\n validateNameFormat?: boolean;\n /** Check for reserved plugin names */\n checkReservedNames?: boolean;\n}\n\n/**\n * Reserved plugin names that cannot be used\n */\nconst RESERVED_NAMES = new Set([\n 'core',\n 'server',\n 'router',\n 'middleware',\n 'context',\n 'blaize',\n 'blaizejs',\n]);\n\n/**\n * Valid plugin name pattern (lowercase, letters, numbers, hyphens)\n */\nconst VALID_NAME_PATTERN = /^[a-z]([a-z0-9-]*[a-z0-9])?$/;\n\n/**\n * Valid semantic version pattern\n */\nconst VALID_VERSION_PATTERN = /^\\d+\\.\\d+\\.\\d+(?:-[a-zA-Z0-9-.]+)?(?:\\+[a-zA-Z0-9-.]+)?$/;\n\n/**\n * Validate a plugin object\n */\nexport function validatePlugin(\n plugin: unknown,\n options: PluginValidationOptions = {}\n): asserts plugin is Plugin {\n const { requireVersion = true, validateNameFormat = true, checkReservedNames = true } = options;\n\n // Basic type validation\n if (!plugin || typeof plugin !== 'object') {\n throw new PluginValidationError('', 'Plugin must be an object');\n }\n\n const p = plugin as any;\n\n // Validate name\n if (!p.name || typeof p.name !== 'string') {\n throw new PluginValidationError('', 'Plugin must have a name (string)');\n }\n\n // Validate name format\n if (validateNameFormat && !VALID_NAME_PATTERN.test(p.name)) {\n throw new PluginValidationError(\n p.name,\n 'Plugin name must be lowercase letters, numbers, and hyphens only'\n );\n }\n\n // Check reserved names\n if (checkReservedNames && RESERVED_NAMES.has(p.name.toLowerCase())) {\n throw new PluginValidationError(p.name, `Plugin name \"${p.name}\" is reserved`);\n }\n\n // Validate version\n if (requireVersion) {\n if (!p.version || typeof p.version !== 'string') {\n throw new PluginValidationError(p.name, 'Plugin must have a version (string)');\n }\n\n if (!VALID_VERSION_PATTERN.test(p.version)) {\n throw new PluginValidationError(\n p.name,\n 'Plugin version must follow semantic versioning (e.g., \"1.0.0\")'\n );\n }\n }\n\n // Validate register method\n if (!p.register || typeof p.register !== 'function') {\n throw new PluginValidationError(p.name, 'Plugin must have a register method (function)');\n }\n\n // Validate optional lifecycle methods\n const lifecycleMethods = ['initialize', 'terminate', 'onServerStart', 'onServerStop'];\n\n for (const method of lifecycleMethods) {\n if (p[method] && typeof p[method] !== 'function') {\n throw new PluginValidationError(p.name, `Plugin ${method} must be a function if provided`);\n }\n }\n\n // Validate dependencies if present\n // if (p.dependencies) {\n // if (!Array.isArray(p.dependencies) && typeof p.dependencies !== 'string') {\n // throw new PluginValidationError(\n // p.name,\n // 'Plugin dependencies must be a string or array of strings'\n // );\n // }\n\n // const deps = Array.isArray(p.dependencies) ? p.dependencies : [p.dependencies];\n // for (const dep of deps) {\n // if (typeof dep !== 'string') {\n // throw new PluginValidationError(p.name, 'Plugin dependencies must be strings');\n // }\n // }\n // }\n}\n\n/**\n * Validate plugin options object\n */\nexport function validatePluginOptions(pluginName: string, options: unknown, schema?: any): void {\n // Basic validation\n if (options !== undefined && typeof options !== 'object') {\n throw new PluginValidationError(pluginName, 'Plugin options must be an object');\n }\n\n // If a schema is provided, validate against it\n if (schema && options) {\n try {\n schema.parse(options);\n } catch (error) {\n throw new PluginValidationError(\n pluginName,\n `Plugin options validation failed: ${(error as Error).message}`\n );\n }\n }\n}\n\n/**\n * Validate plugin factory function\n */\nexport function validatePluginFactory(\n factory: unknown\n): asserts factory is (...args: any[]) => any {\n if (typeof factory !== 'function') {\n throw new PluginValidationError('', 'Plugin factory must be a function');\n }\n}\n\n/**\n * Check if a plugin name is valid\n */\nexport function isValidPluginName(name: string): boolean {\n return (\n typeof name === 'string' &&\n name.length > 0 &&\n VALID_NAME_PATTERN.test(name) &&\n !RESERVED_NAMES.has(name.toLowerCase())\n );\n}\n\n/**\n * Check if a version string is valid\n */\nexport function isValidVersion(version: string): boolean {\n return typeof version === 'string' && VALID_VERSION_PATTERN.test(version);\n}\n\n/**\n * Sanitize plugin name (remove invalid characters)\n */\nexport function sanitizePluginName(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9-]/g, '-')\n .replace(/^-+|-+$/g, '')\n .replace(/-+/g, '-');\n}\n","// packages/blaize-core/src/router/discovery/cache.ts\nimport * as crypto from 'node:crypto';\nimport * as fs from 'node:fs/promises';\n\nimport { loadRouteModule } from './loader';\n\nimport type { FileCache, Route } from '@blaize-types/router';\n\nconst fileRouteCache = new Map<string, FileCache>();\n\nexport async function processChangedFile(\n filePath: string,\n routesDir: string,\n updateCache: boolean = true\n): Promise<Route[]> {\n const stat = await fs.stat(filePath);\n const lastModified = stat.mtime.getTime();\n const cachedEntry = fileRouteCache.get(filePath);\n\n // Skip if file hasn't changed by timestamp (only when updating cache)\n if (updateCache && cachedEntry && cachedEntry.timestamp === lastModified) {\n return cachedEntry.routes;\n }\n\n // Load only this file\n const routes = await loadRouteModule(filePath, routesDir);\n\n // Only update cache if requested\n if (updateCache) {\n // Calculate content hash for change detection\n const hash = hashRoutes(routes);\n\n // Update cache\n fileRouteCache.set(filePath, {\n routes,\n timestamp: lastModified,\n hash,\n });\n }\n\n return routes;\n}\n\nexport function hasRouteContentChanged(filePath: string, newRoutes: Route[]): boolean {\n const cachedEntry = fileRouteCache.get(filePath);\n if (!cachedEntry) {\n return true;\n }\n\n const newHash = hashRoutes(newRoutes);\n\n return cachedEntry.hash !== newHash;\n}\n\nexport function clearFileCache(filePath?: string): void {\n if (filePath) {\n fileRouteCache.delete(filePath);\n } else {\n fileRouteCache.clear();\n }\n}\n\nfunction hashRoutes(routes: Route[]): string {\n const routeData = routes.map(route => ({\n path: route.path,\n methods: Object.keys(route)\n .filter(key => key !== 'path')\n .sort()\n .map(method => {\n const methodDef = route[method as keyof Route] as any;\n const handlerString = methodDef?.handler ? methodDef.handler.toString() : null;\n return {\n method,\n // Include handler function string for change detection\n handler: handlerString,\n // Include middleware if present\n middleware: methodDef?.middleware ? methodDef.middleware.length : 0,\n // Include schema structure (but not full serialization which can be unstable)\n hasSchema: !!methodDef?.schema,\n schemaKeys: methodDef?.schema ? Object.keys(methodDef.schema).sort() : [],\n };\n }),\n }));\n\n const dataString = JSON.stringify(routeData);\n const hash = crypto.createHash('md5').update(dataString).digest('hex');\n\n return hash;\n}\n","import { parseRoutePath } from './parser';\n\nimport type { Route, RouteDefinition } from '@blaize-types/router';\n\nexport async function dynamicImport(filePath: string) {\n // Add a cache-busting query parameter for ESM\n const cacheBuster = `?t=${Date.now()}`;\n const importPath = filePath + cacheBuster;\n\n try {\n const module = await import(importPath);\n console.log(`✅ Successfully imported module`);\n return module;\n } catch (error) {\n // Type guard to ensure resolveError is an Error object\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.log(`⚠️ Error importing with cache buster, trying original path:`, errorMessage);\n // Fallback to original path\n return import(filePath);\n }\n}\n\n/**\n * Load route modules from a file - supports both default export and named exports\n */\nexport async function loadRouteModule(filePath: string, basePath: string): Promise<Route[]> {\n try {\n // Parse the route path from the file path\n const parsedRoute = parseRoutePath(filePath, basePath);\n // Dynamically import the module\n const module = await dynamicImport(filePath);\n console.log('📦 Module exports:', Object.keys(module));\n\n const routes: Route[] = [];\n\n // Method 1: Check for default export (existing pattern)\n if (module.default && typeof module.default === 'object') {\n const route: Route = {\n ...(module.default as RouteDefinition),\n path: parsedRoute.routePath,\n };\n\n routes.push(route);\n }\n\n // Method 2: Check for named exports that look like routes\n Object.entries(module).forEach(([exportName, exportValue]) => {\n // Skip default export (already handled) and non-objects\n if (exportName === 'default' || !exportValue || typeof exportValue !== 'object') {\n return;\n }\n\n // Check if this export looks like a route (has path property and HTTP methods)\n const potentialRoute = exportValue as any;\n\n if (isValidRoute(potentialRoute)) {\n // For named exports, we might want to use the export name or the route's path\n const route: Route = {\n ...potentialRoute,\n // Use the route's own path if it has one, otherwise derive from file\n path: parsedRoute.routePath,\n };\n\n routes.push(route);\n }\n });\n\n if (routes.length === 0) {\n console.warn(`Route file ${filePath} does not export any valid route definitions`);\n return [];\n }\n\n console.log(`✅ Successfully Loaded ${routes.length} route(s)`);\n return routes;\n } catch (error) {\n console.error(`Failed to load route module ${filePath}:`, error);\n return [];\n }\n}\n\n/**\n * Check if an object looks like a valid route\n */\nfunction isValidRoute(obj: any): boolean {\n if (!obj || typeof obj !== 'object') {\n return false;\n }\n\n // Check if it has at least one HTTP method\n const httpMethods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'];\n const hasHttpMethod = httpMethods.some(\n method => obj[method] && typeof obj[method] === 'object' && obj[method].handler\n );\n\n return hasHttpMethod;\n}\n","import * as os from 'node:os';\n\nimport { processChangedFile } from './cache';\nimport { findRouteFiles } from './finder';\n\nimport type { Route } from '@blaize-types/router';\n\nexport async function processFilesInParallel(\n filePaths: string[],\n processor: (filePath: string) => Promise<Route[]>,\n concurrency: number = Math.max(1, Math.floor(os.cpus().length / 2))\n): Promise<Route[][]> {\n const chunks = chunkArray(filePaths, concurrency);\n const results: Route[][] = [];\n\n for (const chunk of chunks) {\n const chunkResults = await Promise.allSettled(chunk.map(filePath => processor(filePath)));\n\n const successfulResults = chunkResults\n .filter(result => result.status === 'fulfilled')\n .map(result => (result as PromiseFulfilledResult<Route[]>).value);\n\n results.push(...successfulResults);\n }\n\n return results;\n}\n\nexport async function loadInitialRoutesParallel(routesDir: string): Promise<Route[]> {\n const files = await findRouteFiles(routesDir);\n const routeArrays = await processFilesInParallel(files, filePath =>\n processChangedFile(filePath, routesDir)\n );\n\n return routeArrays.flat();\n}\n\nfunction chunkArray<T>(array: T[], chunkSize: number): T[][] {\n const chunks: T[][] = [];\n for (let i = 0; i < array.length; i += chunkSize) {\n chunks.push(array.slice(i, i + chunkSize));\n }\n return chunks;\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\nimport type { FindRouteFilesOptions } from '@blaize-types/router';\n\n/**\n * Find all route files in the specified directory\n */\nexport async function findRouteFiles(\n routesDir: string,\n options: FindRouteFilesOptions = {}\n): Promise<string[]> {\n // Convert to absolute path if it's relative\n const absoluteDir = path.isAbsolute(routesDir)\n ? routesDir\n : path.resolve(process.cwd(), routesDir);\n\n console.log('Creating router with routes directory:', absoluteDir);\n\n // Check if directory exists\n try {\n const stats = await fs.stat(absoluteDir);\n if (!stats.isDirectory()) {\n throw new Error(`Route directory is not a directory: ${absoluteDir}`);\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new Error(`Route directory not found: ${absoluteDir}`);\n }\n throw error;\n }\n\n const routeFiles: string[] = [];\n const ignore = options.ignore || ['node_modules', '.git'];\n\n async function scanDirectory(dir: string) {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n\n // Skip ignored directories\n if (entry.isDirectory() && ignore.includes(entry.name)) {\n continue;\n }\n\n if (entry.isDirectory()) {\n await scanDirectory(fullPath);\n } else if (isRouteFile(entry.name)) {\n routeFiles.push(fullPath);\n }\n }\n }\n\n await scanDirectory(absoluteDir);\n return routeFiles;\n}\n\n/**\n * Check if a file is a valid route file\n */\nfunction isRouteFile(filename: string): boolean {\n // Route files are TypeScript/JavaScript files that don't start with underscore\n return !filename.startsWith('_') && (filename.endsWith('.ts') || filename.endsWith('.js'));\n}\n","import type { ReloadMetrics } from '@blaize-types/router';\n\nconst profilerState: ReloadMetrics = {\n fileChanges: 0,\n totalReloadTime: 0,\n averageReloadTime: 0,\n slowReloads: [],\n};\n\nexport function trackReloadPerformance(filePath: string, startTime: number): void {\n const duration = Date.now() - startTime;\n\n profilerState.fileChanges++;\n profilerState.totalReloadTime += duration;\n profilerState.averageReloadTime = profilerState.totalReloadTime / profilerState.fileChanges;\n\n if (duration > 100) {\n profilerState.slowReloads.push({ file: filePath, time: duration });\n if (profilerState.slowReloads.length > 10) {\n profilerState.slowReloads.shift();\n }\n }\n\n if (process.env.NODE_ENV === 'development') {\n const emoji = duration < 50 ? '⚡' : duration < 100 ? '🔄' : '🐌';\n console.log(`${emoji} Route reload: ${filePath} (${duration}ms)`);\n }\n}\n\nexport function getReloadMetrics(): Readonly<ReloadMetrics> {\n return { ...profilerState };\n}\n\nexport function resetReloadMetrics(): void {\n profilerState.fileChanges = 0;\n profilerState.totalReloadTime = 0;\n profilerState.averageReloadTime = 0;\n profilerState.slowReloads = [];\n}\n\nexport function withPerformanceTracking<T extends (...args: any[]) => Promise<any>>(\n fn: T,\n filePath: string\n): T {\n console.log(`Tracking performance for: ${filePath}`);\n return (async (...args: Parameters<T>) => {\n const startTime = Date.now();\n try {\n const result = await fn(...args);\n trackReloadPerformance(filePath, startTime);\n return result;\n } catch (error) {\n trackReloadPerformance(filePath, startTime);\n throw error;\n }\n }) as T;\n}\n","import * as path from 'node:path';\n\nimport { watch } from 'chokidar';\n\nimport { hasRouteContentChanged, processChangedFile } from './cache';\n\nimport type { Route, WatchOptions } from '@blaize-types/router';\n\n/**\n * Watch for route file changes\n */\nexport function watchRoutes(routesDir: string, options: WatchOptions = {}) {\n // Debounce rapid file changes\n const debounceMs = options.debounceMs || 16;\n const debouncedCallbacks = new Map<string, NodeJS.Timeout>();\n\n function createDebouncedCallback<T extends (...args: any[]) => void>(\n fn: T,\n filePath: string\n ): (...args: Parameters<T>) => void {\n return (...args: Parameters<T>) => {\n // Clear existing timeout for this file\n const existingTimeout = debouncedCallbacks.get(filePath);\n if (existingTimeout) {\n clearTimeout(existingTimeout);\n }\n\n // Set new timeout\n const timeoutId = setTimeout(() => {\n fn(...args);\n debouncedCallbacks.delete(filePath);\n }, debounceMs);\n\n debouncedCallbacks.set(filePath, timeoutId);\n };\n }\n // Track loaded routes by file path - now stores arrays of routes\n const routesByPath = new Map<string, Route[]>();\n\n // Optimized load and notify function\n async function loadAndNotify(filePath: string) {\n try {\n const existingRoutes = routesByPath.get(filePath);\n\n // Step 1: Load new routes WITHOUT updating cache\n const newRoutes = await processChangedFile(filePath, routesDir, false);\n\n if (!newRoutes || newRoutes.length === 0) {\n return;\n }\n\n // Step 2: Check if content has actually changed (cache still has old data)\n if (existingRoutes && !hasRouteContentChanged(filePath, newRoutes)) {\n return;\n }\n\n // Step 3: Content changed! Now update the cache\n await processChangedFile(filePath, routesDir, true);\n\n const normalizedPath = path.normalize(filePath);\n\n if (existingRoutes) {\n routesByPath.set(filePath, newRoutes);\n if (options.onRouteChanged) {\n options.onRouteChanged(normalizedPath, newRoutes);\n }\n } else {\n routesByPath.set(filePath, newRoutes);\n if (options.onRouteAdded) {\n options.onRouteAdded(normalizedPath, newRoutes);\n }\n }\n } catch (error) {\n console.log(`⚠️ Error processing file ${filePath}:`, error);\n handleError(error);\n }\n }\n\n // Handle route file removal\n function handleRemoved(filePath: string) {\n const normalizedPath = path.normalize(filePath);\n const routes = routesByPath.get(normalizedPath);\n\n if (routes && routes.length > 0 && options.onRouteRemoved) {\n options.onRouteRemoved(normalizedPath, routes);\n }\n\n routesByPath.delete(normalizedPath);\n }\n\n // Handle errors\n function handleError(error: unknown) {\n if (options.onError && error instanceof Error) {\n options.onError(error);\n } else {\n console.error('⚠️ Route watcher error:', error);\n }\n }\n\n // Start file watcher\n // Create optimized watcher\n const watcher = watch(routesDir, {\n ignoreInitial: true,\n // Much faster response times\n awaitWriteFinish: {\n stabilityThreshold: 50, // Reduced from 300ms\n pollInterval: 10, // Reduced from 100ms\n },\n\n // Performance optimizations\n usePolling: false,\n atomic: true,\n followSymlinks: false,\n depth: 10,\n\n // More aggressive ignoring\n ignored: [\n /(^|[/\\\\])\\../,\n /node_modules/,\n /\\.git/,\n /\\.DS_Store/,\n /Thumbs\\.db/,\n /\\.(test|spec)\\.(ts|js)$/,\n /\\.d\\.ts$/,\n /\\.map$/,\n /~$/,\n ...(options.ignore || []),\n ],\n });\n\n // Set up event handlers\n watcher\n .on('add', filePath => {\n const debouncedLoad = createDebouncedCallback(loadAndNotify, filePath);\n debouncedLoad(filePath);\n })\n .on('change', filePath => {\n const debouncedLoad = createDebouncedCallback(loadAndNotify, filePath);\n\n // Call debounced load for changed file\n debouncedLoad(filePath);\n })\n .on('unlink', filePath => {\n const debouncedRemove = createDebouncedCallback(handleRemoved, filePath);\n debouncedRemove(filePath);\n })\n .on('error', handleError);\n\n // Return control methods\n return {\n close: () => {\n // Clear any pending debounced callbacks\n debouncedCallbacks.forEach(timeout => clearTimeout(timeout));\n debouncedCallbacks.clear();\n\n return watcher.close();\n },\n getRoutes: () => {\n const allRoutes: Route[] = [];\n for (const routes of routesByPath.values()) {\n allRoutes.push(...routes);\n }\n return allRoutes;\n },\n getRoutesByFile: () => new Map(routesByPath),\n };\n}\n","import { z } from 'zod';\n\nimport { validateBody } from './body';\nimport { validateParams } from './params';\nimport { validateQuery } from './query';\nimport { validateResponse } from './response';\nimport { InternalServerError } from '../../errors/internal-server-error';\nimport { ValidationError } from '../../errors/validation-error';\nimport { create as createMiddleware } from '../../middleware/create';\n\nimport type { Context } from '@blaize-types/context';\nimport type { BlaizeLogger } from '@blaize-types/logger';\nimport type { Middleware, NextFunction } from '@blaize-types/middleware';\nimport type { RouteSchema } from '@blaize-types/router';\n\n/**\n * Create a validation middleware for request data\n */\nexport function createRequestValidator(schema: RouteSchema, debug: boolean = false): Middleware {\n return createMiddleware({\n name: 'RequestValidator',\n debug,\n handler: async (ctx: Context, next: NextFunction, _logger: BlaizeLogger) => {\n if (schema.params && ctx.request.params) {\n try {\n ctx.request.params = validateParams(ctx.request.params, schema.params);\n } catch (error) {\n const fieldErrors = extractZodFieldErrors(error);\n const errorCount = fieldErrors.reduce((sum, fe) => sum + fe.messages.length, 0);\n\n throw new ValidationError('Request validation failed', {\n fields: fieldErrors,\n errorCount,\n section: 'params',\n });\n }\n }\n\n // Validate query if schema exists - throw immediately on failure\n if (schema.query && ctx.request.query) {\n try {\n ctx.request.query = validateQuery(ctx.request.query, schema.query);\n } catch (error) {\n const fieldErrors = extractZodFieldErrors(error);\n const errorCount = fieldErrors.reduce((sum, fe) => sum + fe.messages.length, 0);\n\n throw new ValidationError('Request validation failed', {\n fields: fieldErrors,\n errorCount,\n section: 'query',\n });\n }\n }\n\n // Validate body if schema exists - throw immediately on failure\n if (schema.body) {\n try {\n ctx.request.body = validateBody(ctx.request.body, schema.body);\n } catch (error) {\n const fieldErrors = extractZodFieldErrors(error);\n const errorCount = fieldErrors.reduce((sum, fe) => sum + fe.messages.length, 0);\n\n throw new ValidationError('Request validation failed', {\n fields: fieldErrors,\n errorCount,\n section: 'body',\n });\n }\n }\n // Continue if validation passed\n await next();\n },\n });\n}\n\n/**\n * Type guard to detect error responses\n * Error responses have: type, status, correlationId, timestamp\n */\nfunction isErrorResponse(body: unknown): boolean {\n return (\n body !== null &&\n typeof body === 'object' &&\n 'type' in body &&\n 'status' in body &&\n 'correlationId' in body &&\n 'timestamp' in body\n );\n}\n\n/**\n * Create a validation middleware for response data\n */\nexport function createResponseValidator<T>(\n responseSchema: z.ZodType<T, z.ZodTypeDef, unknown>\n): Middleware {\n return createMiddleware({\n name: 'ResponseValidator',\n handler: async (ctx: Context, next: NextFunction) => {\n const originalJson = ctx.response.json;\n let validatorActive = true; // Track if validator should run\n\n // Override json method to validate responses\n ctx.response.json = (body: unknown, status?: number) => {\n // If validator was deactivated (error occurred), skip validation\n if (!validatorActive) {\n return originalJson.call(ctx.response, body, status);\n }\n\n // Don't validate error responses - they have their own schema\n // This allows NotFoundError, ValidationError, etc. to pass through\n if (isErrorResponse(body)) {\n return originalJson.call(ctx.response, body, status);\n }\n\n // Validate success responses\n try {\n const validatedBody = validateResponse(body, responseSchema);\n return originalJson.call(ctx.response, validatedBody, status);\n } catch (error) {\n // Deactivate validator to prevent recursion when error is thrown\n validatorActive = false;\n\n // Throw validation error for error boundary to catch\n throw new InternalServerError('Response validation failed', {\n validationError: extractZodFieldErrors(error),\n hint: 'The handler returned data that does not match the response schema',\n });\n }\n };\n\n try {\n // Execute the handler and downstream middleware\n await next();\n } catch (error) {\n // On any error, deactivate validator and restore original method\n validatorActive = false;\n ctx.response.json = originalJson;\n // Re-throw for error boundary to handle\n throw error;\n } finally {\n // Always restore original json method when middleware completes\n ctx.response.json = originalJson;\n }\n },\n });\n}\n\n/**\n * Extract structured field errors from Zod validation errors\n *\n * Converts Zod errors into a clean array of error messages per field.\n *\n * @param error - The validation error (typically a ZodError)\n * @returns Array of error messages for the field\n *\n * @example\n * ```typescript\n * const zodError = new z.ZodError([\n * { path: ['email'], message: 'Invalid email' },\n * { path: ['email'], message: 'Email is required' }\n * ]);\n *\n * const fieldErrors = extractZodFieldErrors(zodError);\n * // Returns: ['Invalid email', 'Email is required']\n * ```\n */\nfunction extractZodFieldErrors(error: unknown): { field: string; messages: string[] }[] {\n if (error instanceof z.ZodError) {\n // Group errors by field path\n const fieldErrorMap = new Map<string, string[]>();\n\n for (const issue of error.issues) {\n // Get the field path (e.g., ['user', 'email'] becomes 'user.email')\n const fieldPath = issue.path.length > 0 ? issue.path.join('.') : 'root';\n\n if (!fieldErrorMap.has(fieldPath)) {\n fieldErrorMap.set(fieldPath, []);\n }\n fieldErrorMap.get(fieldPath)!.push(issue.message);\n }\n\n // Convert map to array of field errors\n return Array.from(fieldErrorMap.entries()).map(([field, messages]) => ({\n field,\n messages,\n }));\n }\n\n if (error instanceof Error) {\n return [{ field: 'unknown', messages: [error.message] }];\n }\n\n return [{ field: 'unknown', messages: [String(error)] }];\n}\n","import { z } from 'zod';\n\n/**\n * Validate request body\n */\nexport function validateBody<T>(body: unknown, schema: z.ZodType<T>): T {\n if (schema instanceof z.ZodObject) {\n return schema.strict().parse(body) as T;\n }\n // Parse and validate with the provided schema\n return schema.parse(body);\n}\n","import { z } from 'zod';\n\n/**\n * Validate request parameters\n */\nexport function validateParams<T>(\n params: Record<string, string>,\n schema: z.ZodType<T, z.ZodTypeDef, unknown>\n): T {\n if (schema instanceof z.ZodObject) {\n // If schema is an object, ensure strict parsing\n return schema.strict().parse(params) as T;\n }\n // Parse and validate with the provided schema\n return schema.parse(params);\n}\n","import { z } from 'zod';\n\n/**\n * Validate query parameters\n */\nexport function validateQuery<T>(\n query: Record<string, string | string[] | undefined>,\n schema: z.ZodType<T, z.ZodTypeDef, unknown>\n): T {\n if (schema instanceof z.ZodObject) {\n // If schema is an object, ensure strict parsing\n return schema.strict().parse(query) as T;\n }\n // Parse and validate with the provided schema\n return schema.parse(query);\n}\n","import { z } from 'zod';\n\n/**\n * Validate response body\n */\nexport function validateResponse<T>(\n response: unknown,\n schema: z.ZodType<T, z.ZodTypeDef, unknown>\n): T {\n if (schema instanceof z.ZodObject) {\n return schema.strict().parse(response) as T;\n }\n // Parse and validate with the provided schema\n return schema.parse(response);\n}\n","import { compose } from '../../middleware/compose';\nimport { createRequestValidator, createResponseValidator } from '../validation';\n\nimport type { Context } from '@blaize-types/context';\nimport type { BlaizeLogger } from '@blaize-types/logger';\nimport type { RouteMethodOptions } from '@blaize-types/router';\n\n/**\n * Execute a route handler with its middleware\n */\nexport async function executeHandler(\n ctx: Context,\n routeOptions: RouteMethodOptions,\n params: Record<string, string>,\n baseLogger: BlaizeLogger\n): Promise<void> {\n // Set up middleware chain\n const middleware = [...(routeOptions.middleware || [])];\n\n // Add validation middleware if schemas are defined\n if (routeOptions.schema) {\n if (routeOptions.schema.params || routeOptions.schema.query || routeOptions.schema.body) {\n middleware.unshift(createRequestValidator(routeOptions.schema));\n }\n\n if (routeOptions.schema.response) {\n middleware.push(createResponseValidator(routeOptions.schema.response));\n }\n }\n\n // Compose middleware with the final handler\n const handler = compose([...middleware]);\n\n // Execute the middleware chain\n await handler(\n ctx,\n async () => {\n const routeLogger = baseLogger.child({\n route: ctx.request.path,\n method: ctx.request.method,\n });\n // Execute the handler with the new argument style\n const result = await routeOptions.handler(ctx, params, routeLogger);\n\n // Handle the result if it wasn't already handled by the handler\n if (!ctx.response.sent && result !== undefined) {\n ctx.response.json(result);\n }\n },\n baseLogger\n );\n}\n","import type { Route, RouteRegistry } from '@blaize-types/router';\n\nexport function createRouteRegistry(): RouteRegistry {\n return {\n routesByPath: new Map(),\n routesByFile: new Map(),\n pathToFile: new Map(),\n };\n}\n\nexport function updateRoutesFromFile(\n registry: RouteRegistry,\n filePath: string,\n newRoutes: Route[]\n): { added: Route[]; removed: string[]; changed: Route[] } {\n console.log(`Updating routes from file: ${filePath}`);\n const oldPaths = registry.routesByFile.get(filePath) || new Set();\n const newPaths = new Set(newRoutes.map(r => r.path));\n\n // Fast diff calculation\n const added = newRoutes.filter(r => !oldPaths.has(r.path));\n const removed = Array.from(oldPaths).filter(p => !newPaths.has(p));\n const potentiallyChanged = newRoutes.filter(r => oldPaths.has(r.path));\n\n // Check for actual content changes\n const changed = potentiallyChanged.filter(route => {\n const existingRoute = registry.routesByPath.get(route.path);\n return !existingRoute || !routesEqual(existingRoute, route);\n });\n\n // Apply updates\n applyRouteUpdates(registry, filePath, { added, removed, changed });\n\n return { added, removed, changed };\n}\n\nexport function getRouteFromRegistry(registry: RouteRegistry, path: string): Route | undefined {\n return registry.routesByPath.get(path);\n}\n\nexport function getAllRoutesFromRegistry(registry: RouteRegistry): Route[] {\n return Array.from(registry.routesByPath.values());\n}\n\nexport function getFileRoutes(registry: RouteRegistry, filePath: string): Route[] {\n const paths = registry.routesByFile.get(filePath) || new Set();\n return Array.from(paths)\n .map(path => registry.routesByPath.get(path)!)\n .filter(Boolean);\n}\n\nfunction applyRouteUpdates(\n registry: RouteRegistry,\n filePath: string,\n updates: { added: Route[]; removed: string[]; changed: Route[] }\n): void {\n const { added, removed, changed } = updates;\n\n // Remove old routes\n removed.forEach(path => {\n registry.routesByPath.delete(path);\n registry.pathToFile.delete(path);\n });\n\n // Add/update routes\n [...added, ...changed].forEach(route => {\n registry.routesByPath.set(route.path, route);\n registry.pathToFile.set(route.path, filePath);\n });\n\n // Update file -> paths mapping\n const allPathsForFile = new Set([\n ...added.map(r => r.path),\n ...changed.map(r => r.path),\n ...Array.from(registry.routesByFile.get(filePath) || []).filter(p => !removed.includes(p)),\n ]);\n\n if (allPathsForFile.size > 0) {\n registry.routesByFile.set(filePath, allPathsForFile);\n } else {\n registry.routesByFile.delete(filePath);\n }\n}\n\nfunction routesEqual(route1: Route, route2: Route): boolean {\n if (route1.path !== route2.path) return false;\n\n const methods1 = Object.keys(route1)\n .filter(k => k !== 'path')\n .sort();\n const methods2 = Object.keys(route2)\n .filter(k => k !== 'path')\n .sort();\n\n if (methods1.length !== methods2.length) return false;\n\n return methods1.every(method => {\n const handler1 = route1[method as keyof Route];\n const handler2 = route2[method as keyof Route];\n\n // Compare handler signatures/structure rather than function references\n return typeof handler1 === typeof handler2;\n });\n}\n","import type { Route, HttpMethod, RouteMethodOptions, Matcher } from '@blaize-types/router';\n\nexport function addRouteToMatcher(route: Route, matcher: Matcher): void {\n Object.entries(route).forEach(([method, methodOptions]) => {\n if (method === 'path' || !methodOptions) return;\n matcher.add(route.path, method as HttpMethod, methodOptions as RouteMethodOptions);\n });\n}\n\nexport function removeRouteFromMatcher(path: string, matcher: Matcher): void {\n // Use matcher's remove method if available, otherwise fallback to clear/rebuild\n if ('remove' in matcher && typeof matcher.remove === 'function') {\n matcher.remove(path);\n } else {\n // This requires rebuilding the matcher - could be optimized\n console.warn('Matcher does not support selective removal, consider adding remove() method');\n }\n}\n\nexport function updateRouteInMatcher(route: Route, matcher: Matcher): void {\n removeRouteFromMatcher(route.path, matcher);\n addRouteToMatcher(route, matcher);\n}\n\nexport function rebuildMatcherWithRoutes(routes: Route[], matcher: Matcher): void {\n if ('clear' in matcher && typeof matcher.clear === 'function') {\n matcher.clear();\n }\n\n routes.forEach(route => addRouteToMatcher(route, matcher));\n}\n","import { NotFoundError } from '../errors/not-found-error';\nimport { clearFileCache } from './discovery/cache';\nimport { loadInitialRoutesParallel } from './discovery/parallel';\nimport { withPerformanceTracking } from './discovery/profiler';\nimport { watchRoutes } from './discovery/watchers';\nimport { executeHandler } from './handlers';\nimport { createMatcher } from './matching';\nimport {\n createRouteRegistry,\n updateRoutesFromFile,\n getAllRoutesFromRegistry,\n} from './registry/fast-registry';\nimport {\n addRouteToMatcher,\n removeRouteFromMatcher,\n updateRouteInMatcher,\n} from './utils/matching-helpers';\n\nimport type { Context } from '@blaize-types/context';\nimport type { BlaizeLogger } from '@blaize-types/logger';\nimport type { HttpMethod, Route, RouterOptions, Router } from '@blaize-types/router';\n\nconst DEFAULT_ROUTER_OPTIONS = {\n routesDir: './routes',\n basePath: '/',\n watchMode: process.env.NODE_ENV === 'development',\n};\n\n/**\n * Create an optimized router instance with fast hot reload\n */\nexport function createRouter(options: RouterOptions): Router {\n // Merge with default options\n const routerOptions = {\n ...DEFAULT_ROUTER_OPTIONS,\n ...options,\n };\n\n if (options.basePath && !options.basePath.startsWith('/')) {\n console.warn('Base path does nothing');\n }\n\n // Use optimized registry instead of simple array\n const registry = createRouteRegistry();\n const matcher = createMatcher();\n\n // Initialize routes\n let initialized = false;\n let initializationPromise: Promise<void> | null = null;\n let _watchers: Map<string, ReturnType<typeof watchRoutes>> | null = null;\n\n const routeDirectories = new Set<string>([routerOptions.routesDir]);\n\n /**\n * Apply registry changes to matcher efficiently\n */\n function applyMatcherChanges(changes: { added: Route[]; removed: string[]; changed: Route[] }) {\n console.log('\\n🔧 APPLYING MATCHER CHANGES:');\n console.log(` Adding ${changes.added.length} routes`);\n console.log(` Removing ${changes.removed.length} routes`);\n console.log(` Updating ${changes.changed.length} routes`);\n\n // Remove routes first\n changes.removed.forEach(routePath => {\n console.log(` ➖ Removing: ${routePath}`);\n removeRouteFromMatcher(routePath, matcher);\n });\n\n // Add new routes\n changes.added.forEach(route => {\n const methods = Object.keys(route).filter(key => key !== 'path');\n console.log(` ➕ Adding: ${route.path} [${methods.join(', ')}]`);\n addRouteToMatcher(route, matcher);\n });\n\n // Update changed routes\n changes.changed.forEach(route => {\n const methods = Object.keys(route).filter(key => key !== 'path');\n console.log(` 🔄 Updating: ${route.path} [${methods.join(', ')}]`);\n updateRouteInMatcher(route, matcher);\n });\n\n console.log('✅ Matcher changes applied\\n');\n }\n\n /**\n * Add multiple routes with batch processing\n */\n function addRoutesWithSource(routes: Route[], source: string) {\n try {\n // Use registry for batch conflict detection and management\n const changes = updateRoutesFromFile(registry, source, routes);\n\n // Apply all changes to matcher in one operation\n applyMatcherChanges(changes);\n\n return changes;\n } catch (error) {\n console.error(`⚠️ Route conflicts from ${source}:`, error);\n throw error;\n }\n }\n\n /**\n * Optimized route loading with parallel processing\n */\n async function loadRoutesFromDirectory(directory: string, source: string, prefix?: string) {\n try {\n // Use parallel loading for better performance\n const discoveredRoutes = await loadInitialRoutesParallel(directory);\n\n // Apply prefix if provided\n const finalRoutes = discoveredRoutes.map(route =>\n prefix ? { ...route, path: `${prefix}${route.path}` } : route\n );\n\n // Batch add all routes from this directory\n const changes = addRoutesWithSource(finalRoutes, source);\n\n console.log(\n `Loaded ${discoveredRoutes.length} routes from ${source}${prefix ? ` with prefix ${prefix}` : ''} ` +\n `(${changes.added.length} added, ${changes.changed.length} changed, ${changes.removed.length} removed)`\n );\n } catch (error) {\n console.error(`⚠️ Failed to load routes from ${source}:`, error);\n throw error;\n }\n }\n\n /**\n * Initialize the router with parallel route loading\n */\n async function initialize() {\n if (initialized || initializationPromise) {\n return initializationPromise;\n }\n\n initializationPromise = (async () => {\n try {\n // Load routes from all directories in parallel\n await Promise.all(\n Array.from(routeDirectories).map(directory =>\n loadRoutesFromDirectory(directory, directory)\n )\n );\n\n // Set up optimized watching\n if (routerOptions.watchMode) {\n setupOptimizedWatching();\n }\n\n initialized = true;\n } catch (error) {\n console.error('⚠️ Failed to initialize router:', error);\n throw error;\n }\n })();\n\n return initializationPromise;\n }\n\n /**\n * Setup optimized file watching with fast updates\n */\n function setupOptimizedWatching() {\n if (!_watchers) {\n _watchers = new Map();\n }\n\n for (const directory of routeDirectories) {\n if (!_watchers.has(directory)) {\n const watcher = watchRoutes(directory, {\n debounceMs: 16, // ~60fps debouncing\n ignore: ['node_modules', '.git'],\n\n onRouteAdded: (filepath: string, addedRoutes: Route[]) => {\n // Batch process all added routes\n try {\n const changes = updateRoutesFromFile(registry, filepath, addedRoutes);\n applyMatcherChanges(changes);\n } catch (error) {\n console.error(`Error adding routes from ${directory}:`, error);\n }\n },\n\n onRouteChanged: withPerformanceTracking(\n async (filepath: string, changedRoutes: Route[]) => {\n // console.log(`${changedRoutes.length} route(s) changed in ${directory}`);\n\n try {\n console.log(`Processing changes for ${filepath}`);\n // Process all changed routes in one batch operation\n const changes = updateRoutesFromFile(registry, filepath, changedRoutes);\n\n console.log(\n `Changes detected: ${changes.added.length} added, ` +\n `${changes.changed.length} changed, ${changes.removed.length} removed`\n );\n\n // Apply matcher updates efficiently\n applyMatcherChanges(changes);\n\n console.log(\n `Route changes applied: ${changes.added.length} added, ` +\n `${changes.changed.length} changed, ${changes.removed.length} removed`\n );\n } catch (error) {\n console.error(`⚠️ Error updating routes from ${directory}:`, error);\n }\n },\n directory\n ),\n\n onRouteRemoved: (filePath: string, removedRoutes: Route[]) => {\n console.log(`File removed: ${filePath} with ${removedRoutes.length} routes`);\n\n try {\n // Remove all routes from this file\n removedRoutes.forEach(route => {\n removeRouteFromMatcher(route.path, matcher);\n });\n\n // Clear cache for removed file\n clearFileCache(filePath);\n } catch (error) {\n console.error(`⚠️ Error removing routes from ${filePath}:`, error);\n }\n },\n\n onError: (error: Error) => {\n console.error(`⚠️ Route watcher error for ${directory}:`, error);\n },\n });\n\n _watchers.set(directory, watcher);\n }\n }\n }\n\n /**\n * Setup watcher for newly added directory\n */\n function setupWatcherForNewDirectory(directory: string, prefix?: string) {\n if (!_watchers) {\n _watchers = new Map();\n }\n\n const watcher = watchRoutes(directory, {\n debounceMs: 16,\n ignore: ['node_modules', '.git'],\n\n onRouteAdded: (filePath: string, addedRoutes: Route[]) => {\n try {\n // Apply prefix to all routes\n const finalRoutes = addedRoutes.map(route =>\n prefix ? { ...route, path: `${prefix}${route.path}` } : route\n );\n\n // Batch process all added routes\n const changes = updateRoutesFromFile(registry, filePath, finalRoutes);\n applyMatcherChanges(changes);\n } catch (error) {\n console.error(`⚠️ Error adding routes from ${directory}:`, error);\n }\n },\n\n onRouteChanged: withPerformanceTracking(async (filePath: string, changedRoutes: Route[]) => {\n try {\n // Apply prefix to all routes\n const finalRoutes = changedRoutes.map(route =>\n prefix ? { ...route, path: `${prefix}${route.path}` } : route\n );\n\n // Process all changed routes in one batch operation\n const changes = updateRoutesFromFile(registry, filePath, finalRoutes);\n applyMatcherChanges(changes);\n } catch (error) {\n console.error(`⚠️ Error updating routes from ${directory}:`, error);\n }\n }, directory),\n\n onRouteRemoved: (filePath: string, removedRoutes: Route[]) => {\n try {\n removedRoutes.forEach(route => {\n const finalPath = prefix ? `${prefix}${route.path}` : route.path;\n removeRouteFromMatcher(finalPath, matcher);\n });\n clearFileCache(filePath);\n } catch (error) {\n console.error(`Error removing routes from ${filePath}:`, error);\n }\n },\n\n onError: (error: Error) => {\n console.error(`⚠️ Route watcher error for ${directory}:`, error);\n },\n });\n\n _watchers.set(directory, watcher);\n return watcher;\n }\n\n // Initialize router on creation\n initialize().catch(error => {\n console.error('⚠️ Failed to initialize router on creation:', error);\n });\n\n // Public API\n return {\n /**\n * Handle an incoming request\n */\n async handleRequest(ctx: Context, logger: BlaizeLogger) {\n // Ensure router is initialized\n if (!initialized) {\n console.log('🔄 Router not initialized, initializing...');\n await initialize();\n }\n\n const { method, path } = ctx.request;\n console.log(`\\n📥 Handling request: ${method} ${path}`);\n\n // Find matching route\n const match = matcher.match(path, method as HttpMethod);\n\n if (!match) {\n console.log(`❌ No match found for: ${method} ${path}`);\n // Handle 404 Not Found\n throw new NotFoundError('Not found');\n }\n\n console.log(`✅ Route matched: ${method} ${path}`);\n console.log(` Params: ${JSON.stringify(match.params)}`);\n\n // Check for method not allowed\n if (match.methodNotAllowed) {\n // Handle 405 Method Not Allowed\n // TODO: Add support for Method Not Allowed Error\n ctx.response.status(405).json({\n error: '❌ Method Not Allowed',\n allowed: match.allowedMethods,\n });\n\n // Set Allow header with allowed methods\n if (match.allowedMethods && match.allowedMethods.length > 0) {\n ctx.response.header('Allow', match.allowedMethods.join(', '));\n }\n\n return;\n }\n\n // Extract route parameters\n ctx.request.params = match.params;\n\n // Execute the route handler with middleware\n await executeHandler(ctx, match.route!, match.params, logger);\n },\n\n /**\n * Get all registered routes (using optimized registry)\n */\n getRoutes() {\n return getAllRoutesFromRegistry(registry);\n },\n\n /**\n * Add a route programmatically\n */\n addRoute(route: Route) {\n const changes = updateRoutesFromFile(registry, 'programmatic', [route]);\n applyMatcherChanges(changes);\n },\n\n /**\n * Add multiple routes programmatically with batch processing\n */\n addRoutes(routes: Route[]) {\n const changes = updateRoutesFromFile(registry, 'programmatic', routes);\n applyMatcherChanges(changes);\n return changes;\n },\n\n /**\n * Add a route directory (for plugins) with optimized loading\n */\n async addRouteDirectory(directory: string, options: { prefix?: string } = {}) {\n if (routeDirectories.has(directory)) {\n console.warn(`Route directory ${directory} already registered`);\n return;\n }\n\n routeDirectories.add(directory);\n\n // If already initialized, load routes immediately\n if (initialized) {\n await loadRoutesFromDirectory(directory, directory, options.prefix);\n\n // Set up watching for this directory if in watch mode\n if (routerOptions.watchMode) {\n setupWatcherForNewDirectory(directory, options.prefix);\n }\n }\n },\n\n /**\n * Get route conflicts (using registry)\n */\n getRouteConflicts() {\n // Registry handles conflict detection internally\n // This could be enhanced to expose more detailed conflict info\n const conflicts: Array<{ path: string; sources: string[] }> = [];\n // Implementation would depend on registry's conflict tracking\n return conflicts;\n },\n\n /**\n * Close watchers and cleanup (useful for testing)\n */\n async close() {\n if (_watchers) {\n for (const watcher of _watchers.values()) {\n await watcher.close();\n }\n _watchers.clear();\n }\n },\n };\n}\n","/**\n * Type inference utilities for BlaizeJS\n * Minimal set of utilities needed for type-safe routing\n */\n\nimport type { Server, Context, State, Services } from '@blaize-types/index';\n\n/**\n * Infers the context type from a server instance\n *\n * @example\n * ```typescript\n * const server = createServer().use(authMiddleware);\n * type AppContext = InferContext<typeof server>;\n * ```\n */\nexport type InferContext<T> =\n T extends Server<infer TState, infer TServices>\n ? TState extends State\n ? TServices extends Services\n ? Context<TState, TServices, any, any>\n : Context<State, Services, any, any>\n : Context<State, Services, any, any>\n : Context<State, Services, any, any>;\n\n/**\n * Extracts just the state type from a server\n */\nexport type InferServerState<T> =\n T extends Server<infer TState, any> ? (TState extends State ? TState : State) : State;\n\n/**\n * Extracts just the services type from a server\n */\nexport type InferServerServices<T> =\n T extends Server<any, infer TServices>\n ? TServices extends Services\n ? TServices\n : Services\n : Services;\n\n/**\n * Runtime helper that provides type hints for development\n * Returns an empty object but gives TypeScript the correct context type\n *\n * @param _server - The server instance (not used at runtime)\n * @returns An empty object typed as the server's context\n */\nexport function inferContext<TState extends State, TServices extends Services>(\n _server: Server<TState, TServices>\n): InferContext<Server<TState, TServices>> {\n return {} as InferContext<Server<TState, TServices>>;\n}\n","/* eslint-disable @typescript-eslint/no-empty-object-type */\n/**\n * Type composition utilities for extracting and composing middleware type contributions\n * @module composition\n * @since v0.4.0\n */\n\nimport type { Middleware } from './middleware';\nimport type { Plugin } from './plugins';\n\n/**\n * Extracts the State type contribution from a middleware\n * @template T - The middleware type to extract from\n * @returns The state type if present, empty object otherwise\n */\nexport type ExtractMiddlewareState<T> = T extends Middleware<infer S, any> ? S : {};\n\n/**\n * Extracts the State type contribution from a plugin\n * @template T - The plugin type to extract from\n * @returns The state type if present, empty object otherwise\n */\nexport type ExtractPluginState<T> = T extends Plugin<infer S, any> ? S : {};\n\n/**\n * Extracts the Services type contribution from a middleware\n * @template T - The middleware type to extract from\n * @returns The services type if present, empty object otherwise\n */\nexport type ExtractMiddlewareServices<T> = T extends Middleware<any, infer S> ? S : {};\n\n/**\n * Extracts the Services type contribution from a plugin\n * @template T - The plugin type to extract from\n * @returns The services type if present, empty object otherwise\n */\nexport type ExtractPluginServices<T> = T extends Plugin<any, infer S> ? S : {};\n\n/**\n * Utility type to convert a union type to an intersection type\n * This is the magic that allows us to compose multiple middleware contributions\n *\n * @example\n * type U = { a: string } | { b: number }\n * type I = UnionToIntersection<U> // { a: string } & { b: number }\n *\n */\nexport type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (\n k: infer I\n) => void\n ? I\n : never;\n\n/**\n * Composes state contributions from an array of middleware\n * Merges all state types into a single intersection type\n *\n * @template T - ReadonlyArray of Middleware\n * @returns Intersection of all state contributions\n *\n * @example\n * const middlewares = [authMiddleware, loggerMiddleware] as const;\n * type ComposedState = ComposeStates<typeof middlewares>;\n * // Result: { user: User } & { requestId: string }\n */\nexport type ComposeMiddlewareStates<T extends ReadonlyArray<Middleware>> = T extends readonly []\n ? {}\n : UnionToIntersection<ExtractMiddlewareState<T[number]>>;\n\n/**\n * Composes state contributions from an array of plugins\n * Merges all state types into a single intersection type\n *\n * @template T - ReadonlyArray of Plugin\n * @returns Intersection of all state contributions\n *\n * @example\n * const plugins = [authPlugin, dbPlugin] as const;\n * type ComposedState = ComposePluginStates<typeof plugins>;\n * // Result: { config: AuthConfig } & { dbConnected: boolean }\n */\nexport type ComposePluginStates<T extends ReadonlyArray<Plugin<any, any>>> = T extends readonly []\n ? {}\n : UnionToIntersection<ExtractPluginState<T[number]>>;\n\n/**\n * Composes service contributions from an array of middleware\n * Merges all service types into a single intersection type\n *\n * @template T - ReadonlyArray of Middleware\n * @returns Intersection of all service contributions\n *\n * @example\n * const middlewares = [dbMiddleware, cacheMiddleware] as const;\n * type ComposedServices = ComposeServices<typeof middlewares>;\n * // Result: { db: Database } & { cache: Cache }\n */\nexport type ComposeMiddlewareServices<T extends ReadonlyArray<Middleware>> = T extends readonly []\n ? {}\n : UnionToIntersection<ExtractMiddlewareServices<T[number]>>;\n\n/**\n * Composes service contributions from an array of plugins\n * Merges all service types into a single intersection type\n *\n * @template T - ReadonlyArray of Plugin\n * @returns Intersection of all service contributions\n *\n * @example\n * const plugins = [dbPlugin, cachePlugin] as const;\n * type ComposedServices = ComposePluginServices<typeof plugins>;\n * // Result: { db: Database } & { cache: Cache }\n */\nexport type ComposePluginServices<T extends ReadonlyArray<Plugin<any, any>>> = T extends readonly []\n ? {}\n : UnionToIntersection<ExtractPluginServices<T[number]>>;\n\n/**\n * Helper type to check if a type is never\n * @internal\n */\ntype IsNever<T> = [T] extends [never] ? true : false;\n\n/**\n * Helper type to check if a type is any\n * @internal\n */\ntype IsAny<T> = 0 extends 1 & T ? true : false;\n\n/**\n * Safe version of ExtractState that handles edge cases\n * @template T - The middleware type to extract from\n * @returns The state type, handling never/any/unknown gracefully\n */\nexport type SafeExtractMiddlewareState<T> =\n IsNever<T> extends true\n ? {}\n : IsAny<T> extends true\n ? {}\n : T extends Middleware<infer S, any>\n ? unknown extends S\n ? {}\n : S\n : {};\n\n/**\n * Safe version of ExtractPluginState that handles edge cases\n * @template T - The plugin type to extract from\n * @returns The state type, handling never/any/unknown gracefully\n */\nexport type SafeExtractPluginState<T> =\n IsNever<T> extends true\n ? {}\n : IsAny<T> extends true\n ? {}\n : T extends Plugin<infer S, any>\n ? unknown extends S\n ? {}\n : S\n : {};\n\n/**\n * Safe version of ExtractServices that handles edge cases\n * @template T - The middleware type to extract from\n * @returns The services type, handling never/any/unknown gracefully\n */\nexport type SafeExtractMiddlewareServices<T> =\n IsNever<T> extends true\n ? {}\n : IsAny<T> extends true\n ? {}\n : T extends Middleware<any, infer S>\n ? unknown extends S\n ? {}\n : S\n : {};\n\n/**\n * Safe version of ExtractPluginServices that handles edge cases\n * @template T - The plugin type to extract from\n * @returns The services type, handling never/any/unknown gracefully\n */\nexport type SafeExtractPluginServices<T> =\n IsNever<T> extends true\n ? {}\n : IsAny<T> extends true\n ? {}\n : T extends Plugin<any, infer S>\n ? unknown extends S\n ? {}\n : S\n : {};\n\n/**\n * Composes state with better edge case handling\n * @template T - ReadonlyArray of Middleware\n * @returns Safely composed state types\n */\nexport type SafeComposeMiddlewareStates<T extends ReadonlyArray<Middleware>> = T extends readonly []\n ? {}\n : T extends readonly [infer First, ...infer Rest]\n ? First extends Middleware\n ? Rest extends ReadonlyArray<Middleware>\n ? SafeExtractMiddlewareState<First> & SafeComposeMiddlewareStates<Rest>\n : SafeExtractMiddlewareState<First>\n : {}\n : UnionToIntersection<SafeExtractMiddlewareState<T[number]>>;\n\n/**\n * Composes plugin state with better edge case handling\n * @template T - ReadonlyArray of Plugin\n * @returns Safely composed state types\n */\nexport type SafeComposePluginStates<T extends ReadonlyArray<Plugin<any, any>>> =\n T extends readonly []\n ? {}\n : T extends readonly [infer First, ...infer Rest]\n ? First extends Plugin<any, any>\n ? Rest extends ReadonlyArray<Plugin<any, any>>\n ? SafeExtractPluginState<First> & SafeComposePluginStates<Rest>\n : SafeExtractPluginState<First>\n : {}\n : UnionToIntersection<SafeExtractPluginState<T[number]>>;\n\n/**\n * Composes services with better edge case handling\n * @template T - ReadonlyArray of Middleware\n * @returns Safely composed service types\n */\nexport type SafeComposeMiddlewareServices<T extends ReadonlyArray<Middleware>> =\n T extends readonly []\n ? {}\n : T extends readonly [infer First, ...infer Rest]\n ? First extends Middleware\n ? Rest extends ReadonlyArray<Middleware>\n ? SafeExtractMiddlewareServices<First> & SafeComposeMiddlewareServices<Rest>\n : SafeExtractMiddlewareServices<First>\n : {}\n : UnionToIntersection<SafeExtractMiddlewareServices<T[number]>>;\n\n/**\n * Composes plugin services with better edge case handling\n * @template T - ReadonlyArray of Plugin\n * @returns Safely composed service types\n */\nexport type SafeComposePluginServices<T extends ReadonlyArray<Plugin<any, any>>> =\n T extends readonly []\n ? {}\n : T extends readonly [infer First, ...infer Rest]\n ? First extends Plugin<any, any>\n ? Rest extends ReadonlyArray<Plugin<any, any>>\n ? SafeExtractPluginServices<First> & SafeComposePluginServices<Rest>\n : SafeExtractPluginServices<First>\n : {}\n : UnionToIntersection<SafeExtractPluginServices<T[number]>>;\n\n/**\n * Utility to merge two state types\n * Handles conflicts by using the rightmost (latest) type\n *\n * @template A - First state type\n * @template B - Second state type\n * @returns Merged state with B taking precedence\n */\nexport type MergeStates<A, B> = Omit<A, keyof B> & B;\n\n/**\n * Utility to merge two service types\n * Handles conflicts by using the rightmost (latest) type\n *\n * @template A - First services type\n * @template B - Second services type\n * @returns Merged services with B taking precedence\n */\nexport type MergeServices<A, B> = Omit<A, keyof B> & B;\n\n/**\n * Extract both state and services from a middleware at once\n * @template T - The middleware type\n * @returns Object with state and services types\n */\nexport type ExtractMiddlewareTypes<T> = {\n state: ExtractMiddlewareState<T>;\n services: ExtractMiddlewareServices<T>;\n};\n\n/**\n * Extract both state and services from a plugin at once\n * @template T - The plugin type\n * @returns Object with state and services types\n */\nexport type ExtractPluginTypes<T> = {\n state: ExtractPluginState<T>;\n services: ExtractPluginServices<T>;\n};\n\n/**\n * Compose both state and services from middleware array at once\n * @template T - ReadonlyArray of Middleware\n * @returns Object with composed state and services\n */\nexport type ComposeMiddlewareTypes<T extends ReadonlyArray<Middleware>> = {\n state: ComposeMiddlewareStates<T>;\n services: ComposeMiddlewareServices<T>;\n};\n\n/**\n * Compose both state and services from plugin array at once\n * @template T - ReadonlyArray of Plugin\n * @returns Object with composed state and services\n */\nexport type ComposePluginTypes<T extends ReadonlyArray<Plugin<any, any>>> = {\n state: ComposePluginStates<T>;\n services: ComposePluginServices<T>;\n};\n\n/**\n * Type guard to check if a value is a Middleware\n * @param value - Value to check\n * @returns True if value is a Middleware\n */\nexport function isMiddleware(value: unknown): value is Middleware {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'name' in value &&\n 'execute' in value &&\n typeof (value as any).name === 'string' &&\n typeof (value as any).execute === 'function'\n );\n}\n\n/**\n * Type guard to check if a value is a Plugin\n * @param value - Value to check\n * @returns True if value is a Plugin\n */\nexport function isPlugin(value: unknown): value is Plugin {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'name' in value &&\n 'version' in value &&\n 'register' in value &&\n typeof (value as any).name === 'string' &&\n typeof (value as any).version === 'string' &&\n typeof (value as any).register === 'function'\n );\n}\n\n/**\n * Type helper for middleware arrays\n * Ensures proper readonly array typing for composition\n *\n * @example\n * const middlewares = asMiddlewareArray([auth, logger, cache]);\n * type State = ComposeStates<typeof middlewares>;\n */\nexport function asMiddlewareArray<T extends ReadonlyArray<Middleware>>(middlewares: T): T {\n return middlewares;\n}\n\n/**\n * Type helper for plugin arrays\n * Ensures proper readonly array typing for composition\n *\n * @example\n * const plugins = asPluginArray([dbPlugin, cachePlugin]);\n * type Services = ComposePluginServices<typeof plugins>;\n */\nexport function asPluginArray<T extends ReadonlyArray<Plugin<any, any>>>(plugins: T): T {\n return plugins;\n}\n\n/**\n * Create a typed middleware array with inferred types\n * Useful for getting proper const assertions\n *\n * @example\n * const middlewares = createMiddlewareArray(auth, logger, cache);\n * type State = ComposeStates<typeof middlewares>;\n */\nexport function createMiddlewareArray<T extends ReadonlyArray<Middleware>>(...middlewares: T): T {\n return middlewares;\n}\n\n/**\n * Create a typed plugin array with inferred types\n * Useful for getting proper const assertions\n *\n * @example\n * const plugins = createPluginArray(dbPlugin, cachePlugin);\n * type Services = ComposePluginServices<typeof plugins>;\n */\nexport function createPluginArray<T extends ReadonlyArray<Plugin<any, any>>>(...plugins: T): T {\n return plugins;\n}\n","/**\n * UnauthorizedError class for authentication failures\n *\n * This error is thrown when authentication is required or has failed.\n * It provides context about authentication requirements and failure reasons.\n */\n\nimport { ErrorType, BlaizeError } from '@blaize-types/errors';\n\nimport { getCorrelationId } from '../tracing/correlation';\n\nimport type { UnauthorizedErrorDetails } from '@blaize-types/errors';\n\n/**\n * Error thrown when authentication is required or has failed\n *\n * Automatically sets HTTP status to 401 and provides authentication context.\n *\n * @example Basic usage:\n * ```typescript\n * throw new UnauthorizedError('Authentication required');\n * ```\n *\n * @example With authentication details:\n * ```typescript\n * throw new UnauthorizedError('Token expired', {\n * reason: 'expired_token',\n * authScheme: 'Bearer',\n * loginUrl: '/auth/login'\n * });\n * ```\n */\nexport class UnauthorizedError extends BlaizeError<UnauthorizedErrorDetails> {\n /**\n * Creates a new UnauthorizedError instance\n *\n * @param title - Human-readable error message\n * @param details - Optional authentication context\n * @param correlationId - Optional correlation ID (uses current context if not provided)\n */\n constructor(\n title: string,\n details: UnauthorizedErrorDetails | undefined = undefined,\n correlationId: string | undefined = undefined\n ) {\n super(\n ErrorType.UNAUTHORIZED,\n title,\n 401, // HTTP 401 Unauthorized\n correlationId ?? getCorrelationId(),\n details\n );\n }\n}\n","/**\n * ConflictError class for resource conflicts\n *\n * This error is thrown when a resource conflict occurs, such as duplicate keys,\n * version mismatches, or concurrent modifications.\n */\n\nimport { BlaizeError, ErrorType } from '@blaize-types/errors';\n\nimport { getCorrelationId } from '../tracing/correlation';\n\nimport type { ConflictErrorDetails } from '@blaize-types/errors';\n\n/**\n * Error thrown when a resource conflict occurs\n *\n * Automatically sets HTTP status to 409 and provides conflict context.\n *\n * @example Basic usage:\n * ```typescript\n * throw new ConflictError('Email already exists');\n * ```\n *\n * @example With conflict details:\n * ```typescript\n * throw new ConflictError('Version conflict', {\n * conflictType: 'version_mismatch',\n * currentVersion: '2',\n * expectedVersion: '1',\n * resolution: 'Fetch the latest version and retry'\n * });\n * ```\n */\nexport class ConflictError extends BlaizeError<ConflictErrorDetails> {\n /**\n * Creates a new ConflictError instance\n *\n * @param title - Human-readable error message\n * @param details - Optional conflict context\n * @param correlationId - Optional correlation ID (uses current context if not provided)\n */\n constructor(\n title: string,\n details: ConflictErrorDetails | undefined = undefined,\n correlationId: string | undefined = undefined\n ) {\n super(\n ErrorType.CONFLICT,\n title,\n 409, // HTTP 409 Conflict\n correlationId ?? getCorrelationId(),\n details\n );\n }\n}\n","/**\n * RateLimitError class for rate limiting violations\n *\n * This error is thrown when rate limits are exceeded.\n * It provides context about the rate limit and when requests can resume.\n */\n\nimport { BlaizeError, ErrorType } from '@blaize-types/errors';\n\nimport { getCorrelationId } from '../tracing/correlation';\n\nimport type { RateLimitErrorDetails } from '@blaize-types/errors';\n\n/**\n * Error thrown when rate limits are exceeded\n *\n * Automatically sets HTTP status to 429 and provides rate limit context.\n *\n * @example Basic usage:\n * ```typescript\n * throw new RateLimitError('Too many requests');\n * ```\n *\n * @example With rate limit details:\n * ```typescript\n * throw new RateLimitError('Rate limit exceeded', {\n * limit: 100,\n * remaining: 0,\n * retryAfter: 3600,\n * window: 'hour',\n * identifier: 'user-123'\n * });\n * ```\n */\nexport class RateLimitError extends BlaizeError<RateLimitErrorDetails> {\n /**\n * Creates a new RateLimitError instance\n *\n * @param title - Human-readable error message\n * @param details - Optional rate limit context\n * @param correlationId - Optional correlation ID (uses current context if not provided)\n */\n constructor(\n title: string,\n details: RateLimitErrorDetails | undefined = undefined,\n correlationId: string | undefined = undefined\n ) {\n super(\n ErrorType.RATE_LIMITED,\n title,\n 429, // HTTP 429 Too Many Requests\n correlationId ?? getCorrelationId(),\n details\n );\n }\n}\n","import { BlaizeError, ErrorType } from '../../../blaize-types/src/errors';\nimport { getCorrelationId } from '../tracing/correlation';\n\nexport class RequestTimeoutError extends BlaizeError {\n constructor(title: string, details?: unknown, correlationId?: string) {\n super(\n ErrorType.UPLOAD_TIMEOUT,\n title,\n 408,\n correlationId ?? getCorrelationId(),\n details\n );\n }\n}\n","import { BlaizeError, ErrorType } from '../../../blaize-types/src/errors';\nimport { getCorrelationId } from '../tracing/correlation';\n\nexport class UnprocessableEntityError extends BlaizeError {\n constructor(title: string, details?: unknown, correlationId?: string) {\n super(\n ErrorType.UNPROCESSABLE_ENTITY,\n title,\n 422,\n correlationId ?? getCorrelationId(),\n details\n );\n }\n}\n","// ============================================\n// packages/blaize-core/src/errors/service-unavailable-error.ts\n// ============================================\n\nimport { BlaizeError, ErrorType } from '@blaize-types/errors';\n\nimport { getCorrelationId } from '../tracing/correlation';\n\nimport type { ServiceNotAvailableDetails } from '@blaize-types/errors';\n\n/**\n * Error thrown when a service is temporarily unavailable\n *\n * Automatically sets HTTP status to 503 and optionally includes Retry-After.\n *\n * @example Basic usage:\n * ```typescript\n * throw new ServiceNotAvailableError('Database unavailable');\n * ```\n *\n * @example With retry guidance:\n * ```typescript\n * throw new ServiceNotAvailableError('Payment service down', {\n * service: 'stripe',\n * retryAfter: 30,\n * reason: 'circuit_breaker'\n * });\n * ```\n */\nexport class ServiceNotAvailableError extends BlaizeError<ServiceNotAvailableDetails> {\n constructor(\n title: string,\n details: ServiceNotAvailableDetails | undefined = undefined,\n correlationId: string | undefined = undefined\n ) {\n super(ErrorType.SERVICE_UNAVAILABLE, title, 503, correlationId ?? getCorrelationId(), details);\n }\n}\n","/**\n * BlaizeJS Core\n *\n * A blazing-fast, type-safe Node.js framework with file-based routing,\n * powerful middleware, and end-to-end type safety.\n *\n * @package blaizejs\n */\n// Logging\nimport {\n logger,\n createLogger,\n NullTransport,\n JSONTransport,\n ConsoleTransport,\n configureGlobalLogger,\n Logger,\n} from './logger';\n// Middleware System\nimport { compose } from './middleware/compose';\nimport { cors } from './middleware/cors';\nimport {\n create as createMiddleware,\n serviceMiddleware as createServiceMiddleware,\n stateMiddleware as createStateMiddleware,\n} from './middleware/create';\nimport { requestLoggerMiddleware } from './middleware/logger/request-logger';\n// Plugin System\nimport { create as createPlugin } from './plugins/create';\n// Router System\nimport {\n createDeleteRoute,\n createGetRoute,\n createHeadRoute,\n createOptionsRoute,\n createPatchRoute,\n createPostRoute,\n createPutRoute,\n createRouteFactory,\n} from './router/create';\nimport { createMatcher } from './router/matching/matcher';\nimport {\n extractParams,\n compilePathPattern,\n paramsToQuery,\n buildUrl,\n} from './router/matching/params';\n// Server\nimport { create as createServer } from './server/create';\nimport { inferContext, type InferContext } from './server/types';\n// Tracing\nimport { getCorrelationId } from './tracing/correlation';\n\n// TODO: ideally this could be import as an npm package, but for now we use a relative path\n// Explicit imports to avoid using values without importing\nexport * from '../../blaize-types/src/index';\n\n// Re-export everything\n\nexport {\n // Server module exports\n createServer,\n inferContext,\n type InferContext,\n\n // Router module exports\n createDeleteRoute,\n createGetRoute,\n createHeadRoute,\n createOptionsRoute,\n createPatchRoute,\n createPostRoute,\n createPutRoute,\n createRouteFactory,\n createMatcher,\n extractParams,\n compilePathPattern,\n paramsToQuery,\n buildUrl,\n\n // Middleware module exports\n createMiddleware,\n createServiceMiddleware,\n createStateMiddleware,\n compose,\n cors,\n requestLoggerMiddleware,\n\n // Plugins module exports\n createPlugin,\n\n // Tracing module exports\n getCorrelationId,\n\n // Logger exports\n logger,\n createLogger,\n configureGlobalLogger,\n Logger,\n ConsoleTransport,\n JSONTransport,\n NullTransport,\n};\n\n// Version information\nexport const VERSION = '0.1.0';\n\n// Namespaced exports with different names to avoid conflicts\nexport const ServerAPI = { createServer, inferContext };\nexport const RouterAPI = {\n createDeleteRoute,\n createGetRoute,\n createHeadRoute,\n createOptionsRoute,\n createPatchRoute,\n createPostRoute,\n createPutRoute,\n createRouteFactory,\n createMatcher,\n extractParams,\n compilePathPattern,\n paramsToQuery,\n buildUrl,\n};\nexport const MiddlewareAPI = {\n createMiddleware,\n createServiceMiddleware,\n createStateMiddleware,\n compose,\n cors,\n requestLoggerMiddleware,\n};\nexport const PluginsAPI = { createPlugin };\n\n// Server-side error classes\nexport { ValidationError } from './errors/validation-error';\nexport { NotFoundError } from './errors/not-found-error';\nexport { UnauthorizedError } from './errors/unauthorized-error';\nexport { ForbiddenError } from './errors/forbidden-error';\nexport { ConflictError } from './errors/conflict-error';\nexport { RateLimitError } from './errors/rate-limit-error';\nexport { InternalServerError } from './errors/internal-server-error';\nexport { PayloadTooLargeError } from './errors/payload-too-large-error';\nexport { RequestTimeoutError } from './errors/request-timeout-error';\nexport { UnprocessableEntityError } from './errors/unprocessable-entity-error';\nexport { UnsupportedMediaTypeError } from './errors/unsupported-media-type-error';\nexport { ServiceNotAvailableError } from './errors/service-not-available-error';\n\n// Default export\nconst Blaize = {\n // Core functions\n createServer,\n createMiddleware,\n createServiceMiddleware,\n createStateMiddleware,\n createPlugin,\n getCorrelationId,\n configureGlobalLogger,\n createLogger,\n logger,\n\n // Namespaces (using the non-conflicting names)\n Server: ServerAPI,\n Router: RouterAPI,\n Middleware: MiddlewareAPI,\n Plugins: PluginsAPI,\n\n // Constants\n VERSION,\n};\n\nexport { Blaize };\n"],"mappings":"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","names":["inspect","isError","value","serializeError","error","serializeMetadata","meta","serialized","key","item","nested","nestedKey","nestedValue","createCircularReplacer","seen","_key","LEVEL_COLORS","RESET","BOLD","ConsoleTransport","level","message","meta","serializedMeta","serializeMetadata","formattedMessage","metadataText","inspect","JSONTransport","level","message","meta","serializedMeta","serializeMetadata","logEntry","json","createCircularReplacer","LOG_LEVEL_PRIORITY","Logger","_Logger","config","inheritedMeta","message","meta","mergedMeta","level","finalMeta","redactedMeta","redactKeysLower","key","redacted","value","getDefaultTransport","ConsoleTransport","JSONTransport","createLogger","isDevelopment","resolvedConfig","NullTransport","_level","_message","_meta","logger","createLogger","ConsoleTransport","_globalLoggerInstance","configureGlobalLogger","config","newLogger","execute","middleware","ctx","next","logger","result","error","compose","middlewareStack","_","next","__","ctx","finalHandler","baseLogger","called","dispatch","i","middleware","nextDispatch","middlewareLogger","execute","ForbiddenError","BlaizeError","title","details","correlationId","getCorrelationId","create","handlerOrOptions","name","handler","skip","debug","stateMiddleware","serviceMiddleware","DEVELOPMENT_DEFAULTS","PRODUCTION_DEFAULTS","getDefaultCorsOptions","isDevelopment","createOriginCache","ttl","maxSize","cache","config","getCacheKey","origin","configOriginId","userId","evictLRU","lruKey","lruTime","key","entry","now","allowed","cleaned","defaultCache","isCacheable","configuredOrigin","origin","getConfigOriginId","o","validateStringOrigin","requestOrigin","validateRegExpOrigin","validateFunctionOrigin","ctx","timeoutMs","timeoutId","timeoutPromise","resolve","result","r","error","validateArrayOrigin","configuredOrigins","validations","validateSingleOrigin","validateOrigin","userId","configOriginId","cached","defaultCache","allowed","parsePreflightRequest","ctx","origin","requestedMethod","requestedHeadersRaw","requestedHeaders","h","normalizeMethod","method","isMethodAllowed","allowedMethods","m","areHeadersAllowed","allowedHeaders","allowedArray","header","setPreflightHeaders","options","originAllowed","methods","methodsString","headers","handlePreflight","preflight","ValidationError","validateOrigin","rejectedHeaders","allowed","successStatus","isPreflightRequest","z","corsHttpMethodSchema","corsMethodsSchema","val","m","corsHeadersSchema","h","corsOriginFunctionSchema","data","singleOriginSchema","corsOriginSchema","corsOptionsSchema","serverCorsSchema","validateCorsOptions","options","error","formattedErrors","formatCorsValidationErrors","err","isOriginArray","origin","validateOriginSecurity","options","o","mergeCorsOptions","userOptions","defaults","setCorsHeaders","ctx","options","origin","originAllowed","headers","cors","userOptions","isDevelopment","defaults","getDefaultCorsOptions","mergeCorsOptions","validatedOptions","validateCorsOptions","validateOriginSecurity","create","next","isPreflightRequest","handlePreflight","validateOrigin","ForbiddenError","DEFAULT_SAFE_HEADERS","ALWAYS_REDACT_HEADERS","filterHeaders","headers","whitelist","filtered","whitelistLower","h","redactSetLower","name","value","nameLower","requestLoggerMiddleware","options","create","ctx","next","logger","startTime","ip","startMeta","allHeaders","safeHeaders","query","error","err","duration","errorMeta","BlaizeError","statusCode","createPlugin","options","userConfig","config","pluginLogger","createLogger","hooks","fileURLToPath","config","setRuntimeConfig","newConfig","getRoutesDir","config","path","parseRoutePath","filePath","basePath","forwardSlashFilePath","forwardSlashBasePath","normalizedBasePath","relativePath","segments","params","routeSegments","segment","paramName","routePath","EventEmitter","BufferStrategySchema","WatermarkConfigSchema","data","SizeLimitsSchema","BackpressureConfigSchema","DEFAULT_CONFIG","createConnectionRegistry","config","settings","connections","clientConnectionCounts","cleanupTimer","registry","startCleanupTimer","cleanupFn","stopCleanupTimer","updateClientCount","clientIp","delta","newCount","add","id","stream","metadata","now","remove","entry","count","cleanup","idsToRemove","isInactive","isClosed","get","has","getIds","shutdown","registryInstance","getConnectionRegistry","SSEBufferOverflowError","BlaizeError","title","details","correlationId","getCorrelationId","SSEStreamClosedError","BlaizeError","title","details","correlationId","getCorrelationId","DEFAULT_OPTIONS","formatSSEEvent","event","data","id","retry","lines","dataLines","line","createEventId","timestamp","random","estimateEventSize","dataStr","applyBufferStrategy","buffer","strategy","newEvent","maxSize","dropped","SSEStreamImpl","EventEmitter","ctx","options","result","BackpressureConfigSchema","lastEventId","registry","getConnectionRegistry","metadata","error","interval","req","res","handleDisconnect","written","formatted","resolve","cb","err","callbacks","SSEStreamClosedError","eventId","correlationId","getCorrelationId","size","maxEventSize","SSEBufferOverflowError","bufferedEvent","maxBuffer","currentSize","errorData","sendError","closeEvent","comment","message","milliseconds","checkBuffer","createSSEStream","SSENotAcceptableError","BlaizeError","message","details","correlationId","getCorrelationId","validateSSEConfig","config","params","query","events","eventName","eventSchema","createTypedStream","stream","eventSchemas","typedStream","originalSend","event","data","schema","validated","error","createSSERoute","path","getRoutePath","ctx","accept","SSENotAcceptableError","validationError","baseStream","createSSEStream","getCallerFilePath","originalPrepareStackTrace","_","stack","callerFrame","fileName","fileURLToPath","getRoutePath","callerPath","routesDir","getRoutesDir","parsedRoute","parseRoutePath","createGetRoute","config","validateMethodConfig","path","createPostRoute","createPutRoute","createDeleteRoute","createPatchRoute","createHeadRoute","createOptionsRoute","method","validateSchema","schema","params","query","body","response","createRouteFactory","createSSERoute","extractParams","path","pattern","paramNames","match","params","compilePathPattern","patternString","_","paramName","paramsToQuery","parts","key","value","encodedKey","encodedValue","buildUrl","pathPattern","query","pathParams","queryParams","url","queryString","createMatcher","routes","path","method","routeOptions","pattern","paramNames","compilePathPattern","newRoute","insertIndex","route","i","pathname","params","extractParams","AsyncLocalStorage","EventEmitter","fs","http","http2","fs","path","selfsigned","generateDevCertificates","certDir","keyPath","certPath","pems","ResponseSentError","message","ResponseSentHeaderError","ResponseSentContentError","ParseUrlError","AsyncLocalStorage","contextStorage","runWithContext","context","callback","contextStorage","crypto","createWriteStream","tmpdir","join","Readable","BOUNDARY_REGEX","CONTENT_DISPOSITION_REGEX","CONTENT_TYPE_REGEX","MULTIPART_REGEX","extractBoundary","contentType","match","boundary","parseContentDisposition","headers","parseContentType","isMultipartContent","DEFAULT_OPTIONS","tmpdir","createParserState","boundary","options","processChunk","state","chunk","newBuffer","currentState","nextState","processCurrentStage","processBoundary","processHeaders","processContent","InternalServerError","boundaryIndex","hasFoundValidBoundary","buffer","headerEnd","headers","disposition","parseContentDisposition","ValidationError","mimetype","parseContentType","isFile","PayloadTooLargeError","UnsupportedMediaTypeError","nextBoundaryIndex","contentChunk","isComplete","safeLength","contentEnd","updatedState","processContentChunk","finalizeCurrentPart","newContentLength","maxSize","payloadErrorDetals","processFileChunk","writeToStream","initializeFileProcessing","streamController","stream","controller","tempPath","join","writeStream","createWriteStream","cleanupTask","unlink","error","finalizeFile","finalizeField","resetCurrentPart","Readable","closeStream","file","updatedFiles","addToCollection","value","updatedFields","collection","key","newCollection","existing","finalize","fields","values","files","fileList","cleanup","task","resolve","reject","parseMultipartRequest","request","contentType","extractBoundary","CONTENT_TYPE_HEADER","parseRequestUrl","req","originalUrl","host","fullUrl","url","path","query","value","key","error","ParseUrlError","isHttp2Request","getProtocol","encrypted","forwardedProto","createContext","res","options","method","isHttp2","protocol","params","state","services","responseState","ctx","createRequestObject","createResponseObject","parseBodyIfNeeded","info","createRequestHeaderGetter","createRequestHeadersGetter","name","headerGetter","names","acc","addCorrelationHeader","headerName","getCorrelationHeaderName","correlationValue","createStatusSetter","createHeaderSetter","createHeadersSetter","createContentTypeSetter","createJsonResponder","createTextResponder","createHtmlResponder","createRedirectResponder","createStreamResponder","code","ResponseSentError","ResponseSentHeaderError","headers","type","ResponseSentContentError","body","status","readable","err","shouldSkipParsing","contentType","contentLength","limits","PayloadTooLargeError","getCorrelationId","parseJsonBody","parseFormUrlEncodedBody","parseTextBody","isMultipartContent","parseMultipartBody","readRequestBody","json","ValidationError","parseUrlEncodedData","formData","multipartLimits","multipartData","parseMultipartRequest","UnsupportedMediaTypeError","resolve","reject","chunks","chunk","NotFoundError","BlaizeError","title","details","correlationId","getCorrelationId","isHandledError","error","BlaizeError","formatErrorResponse","correlationId","getCorrelationId","originalMessage","wrappedError","InternalServerError","extractOrGenerateCorrelationId","headerGetter","headerName","getCorrelationHeaderName","headers","createCorrelationIdFromHeaders","setErrorResponseHeaders","headerSetter","createErrorBoundary","options","debug","create","ctx","next","logger","error","correlationId","extractOrGenerateCorrelationId","errorResponse","formatErrorResponse","setErrorResponseHeaders","createRequestHandler","serverInstance","req","res","correlationId","createCorrelationIdFromHeaders","withCorrelationId","context","createContext","requestLogger","middlewareChain","createErrorBoundary","cors","handler","compose","runWithContext","NotFoundError","error","headerName","getCorrelationHeaderName","prepareCertificates","http2Options","keyFile","certFile","isDevMode","certificatesMissing","generateDevCertificates","createServerInstance","isHttp2","certOptions","http2ServerOptions","err","listenOnPort","server","port","host","resolve","reject","url","logger","initializePlugins","serverInstance","plugin","startServer","serverOptions","requestHandler","createRequestHandler","error","isShuttingDown","stopServer","serverInstance","options","server","events","timeout","_","reject","error","closePromise","resolve","err","timeoutPromise","registerSignalHandlers","stopFn","sigintHandler","sigtermHandler","z","middlewareSchema","z","data","pluginSchema","http2Schema","correlationSchema","multipartLimitsSchema","bodyLimitsSchema","requestLoggerOptionsSchema","loggerConfigSchema","serverOptionsSchema","serverCorsSchema","validateServerOptions","options","error","formattedError","createPluginLifecycleManager","options","continueOnError","onError","handleError","plugin","phase","error","errorMessage","logger","server","p","pluginsToTerminate","httpServer","pluginsToNotify","PluginValidationError","pluginName","message","RESERVED_NAMES","VALID_NAME_PATTERN","VALID_VERSION_PATTERN","validatePlugin","plugin","options","requireVersion","validateNameFormat","checkReservedNames","PluginValidationError","p","lifecycleMethods","method","crypto","fs","dynamicImport","filePath","cacheBuster","importPath","module","error","errorMessage","loadRouteModule","basePath","parsedRoute","parseRoutePath","routes","route","exportName","exportValue","potentialRoute","isValidRoute","obj","method","fileRouteCache","processChangedFile","filePath","routesDir","updateCache","lastModified","cachedEntry","routes","loadRouteModule","hash","hashRoutes","hasRouteContentChanged","newRoutes","newHash","clearFileCache","routeData","route","key","method","methodDef","handlerString","dataString","os","fs","path","findRouteFiles","routesDir","options","absoluteDir","error","routeFiles","ignore","scanDirectory","dir","entries","entry","fullPath","isRouteFile","filename","processFilesInParallel","filePaths","processor","concurrency","chunks","chunkArray","results","chunk","successfulResults","filePath","result","loadInitialRoutesParallel","routesDir","files","findRouteFiles","processChangedFile","array","chunkSize","i","profilerState","trackReloadPerformance","filePath","startTime","duration","emoji","withPerformanceTracking","fn","filePath","args","startTime","result","trackReloadPerformance","error","path","watch","watchRoutes","routesDir","options","debounceMs","debouncedCallbacks","createDebouncedCallback","fn","filePath","args","existingTimeout","timeoutId","routesByPath","loadAndNotify","existingRoutes","newRoutes","processChangedFile","hasRouteContentChanged","normalizedPath","error","handleError","handleRemoved","routes","watcher","watch","timeout","allRoutes","z","z","validateBody","body","schema","z","validateParams","params","schema","z","validateQuery","query","schema","z","validateResponse","response","schema","createRequestValidator","schema","debug","create","ctx","next","_logger","validateParams","error","fieldErrors","extractZodFieldErrors","errorCount","sum","fe","ValidationError","validateQuery","validateBody","isErrorResponse","body","createResponseValidator","responseSchema","originalJson","validatorActive","status","validatedBody","validateResponse","InternalServerError","z","fieldErrorMap","issue","fieldPath","field","messages","executeHandler","ctx","routeOptions","params","baseLogger","middleware","createRequestValidator","createResponseValidator","compose","routeLogger","result","createRouteRegistry","updateRoutesFromFile","registry","filePath","newRoutes","oldPaths","newPaths","r","added","removed","p","changed","route","existingRoute","routesEqual","applyRouteUpdates","getAllRoutesFromRegistry","registry","applyRouteUpdates","registry","filePath","updates","added","removed","changed","path","route","allPathsForFile","r","p","routesEqual","route1","route2","methods1","k","methods2","method","handler1","handler2","addRouteToMatcher","route","matcher","method","methodOptions","removeRouteFromMatcher","path","updateRouteInMatcher","DEFAULT_ROUTER_OPTIONS","createRouter","options","routerOptions","registry","createRouteRegistry","matcher","createMatcher","initialized","initializationPromise","_watchers","routeDirectories","applyMatcherChanges","changes","routePath","removeRouteFromMatcher","route","methods","key","addRouteToMatcher","updateRouteInMatcher","addRoutesWithSource","routes","source","updateRoutesFromFile","error","loadRoutesFromDirectory","directory","prefix","discoveredRoutes","loadInitialRoutesParallel","finalRoutes","initialize","setupOptimizedWatching","watcher","watchRoutes","filepath","addedRoutes","withPerformanceTracking","changedRoutes","filePath","removedRoutes","clearFileCache","setupWatcherForNewDirectory","finalPath","ctx","logger","method","path","match","NotFoundError","executeHandler","getAllRoutesFromRegistry","DEFAULT_OPTIONS","createServerOptions","options","mergedOptions","validated","validateServerOptions","setRuntimeConfig","error","configureCorrelation","_setCorrelationConfig","createListenMethod","serverInstance","validatedOptions","initializePlugins","startServer","setupServerLifecycle","p","signalHandlers","registerSignalHandlers","createCloseMethod","stopOptions","stopServer","createUseMethod","middleware","middlewareArray","createRegisterMethod","plugin","validatePlugin","create","port","host","plugins","cors","bodyLimits","serverLogger","createLogger","configureGlobalLogger","initialMiddleware","initialPlugins","contextStorage","AsyncLocalStorage","router","createRouter","pluginManager","createPluginLifecycleManager","events","EventEmitter","inferContext","_server","isMiddleware","value","isPlugin","asMiddlewareArray","middlewares","asPluginArray","plugins","createMiddlewareArray","createPluginArray","UnauthorizedError","BlaizeError","title","details","correlationId","getCorrelationId","ConflictError","BlaizeError","title","details","correlationId","getCorrelationId","RateLimitError","BlaizeError","title","details","correlationId","getCorrelationId","RequestTimeoutError","BlaizeError","title","details","correlationId","getCorrelationId","UnprocessableEntityError","BlaizeError","title","details","correlationId","getCorrelationId","ServiceNotAvailableError","BlaizeError","title","details","correlationId","getCorrelationId","VERSION","ServerAPI","create","inferContext","RouterAPI","createDeleteRoute","createGetRoute","createHeadRoute","createOptionsRoute","createPatchRoute","createPostRoute","createPutRoute","createRouteFactory","createMatcher","extractParams","compilePathPattern","paramsToQuery","buildUrl","MiddlewareAPI","serviceMiddleware","stateMiddleware","compose","cors","requestLoggerMiddleware","PluginsAPI","createPlugin","Blaize","getCorrelationId","configureGlobalLogger","createLogger","logger"]}