@morojs/moro 1.8.4 → 1.8.6

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.
@@ -27,6 +27,7 @@ export interface JobExecutorOptions {
27
27
  circuitBreakerThreshold?: number;
28
28
  circuitBreakerResetTimeout?: number;
29
29
  enableMemoryMonitoring?: boolean;
30
+ /** Heap ceiling in MB. Defaults to 90% of the process's V8 heap limit. */
30
31
  memoryThreshold?: number;
31
32
  }
32
33
  export interface JobFunction {
@@ -1,7 +1,29 @@
1
1
  // Production-grade Job Executor
2
2
  // Handles job execution with retry logic, timeout, circuit breaker, and memory monitoring
3
3
  import { EventEmitter } from 'events';
4
+ import { getHeapStatistics } from 'v8';
4
5
  import { CircuitBreaker } from '../utilities/circuit-breaker.js';
6
+ /**
7
+ * Default memory ceiling for job execution, in MB.
8
+ *
9
+ * Derived from the process's actual V8 heap limit rather than a fixed number.
10
+ * A hardcoded default (previously 512MB) is meaningless in isolation: 64-bit
11
+ * Node defaults to a ~4GB heap, so 512MB is only ~12% of what the process may
12
+ * legitimately use. Every job would refuse to run once the process crossed
13
+ * that line — and because heap usage rarely falls back, the failure was
14
+ * permanent rather than transient.
15
+ *
16
+ * 90% of the heap limit is the point where allocation pressure is real and
17
+ * refusing new work is the right call. An explicit `memoryThreshold` option
18
+ * still wins, so existing configuration is unaffected.
19
+ */
20
+ function defaultMemoryThresholdMB() {
21
+ const limitMB = getHeapStatistics().heap_size_limit / 1024 / 1024;
22
+ // No floor: V8's own minimum heap is ~256MB, so any absolute floor would
23
+ // meet or exceed the limit in a memory-constrained container and disable
24
+ // the guard entirely. A percentage of the real limit is correct at any size.
25
+ return Math.round(limitMB * 0.9);
26
+ }
5
27
  // Reference to global AbortController
6
28
  const AbortControllerClass = globalThis.AbortController;
7
29
  /**
@@ -34,7 +56,7 @@ export class JobExecutor extends EventEmitter {
34
56
  circuitBreakerThreshold: options.circuitBreakerThreshold ?? 5,
35
57
  circuitBreakerResetTimeout: options.circuitBreakerResetTimeout ?? 60000,
36
58
  enableMemoryMonitoring: options.enableMemoryMonitoring ?? true,
37
- memoryThreshold: options.memoryThreshold ?? 512, // 512MB default
59
+ memoryThreshold: options.memoryThreshold ?? defaultMemoryThresholdMB(),
38
60
  };
39
61
  this.logger.debug('JobExecutor initialized', 'JobExecutor', { options: this.options });
40
62
  }
@@ -1 +1 @@
1
- {"version":3,"file":"job-executor.js","sourceRoot":"","sources":["../../../src/core/jobs/job-executor.ts"],"names":[],"mappings":"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","sourcesContent":["// Production-grade Job Executor\n// Handles job execution with retry logic, timeout, circuit breaker, and memory monitoring\n\nimport { EventEmitter } from 'events';\nimport { Logger } from '../../types/logger.js';\nimport { CircuitBreaker } from '../utilities/circuit-breaker.js';\n\n// Type definitions for native Node.js AbortController (available in Node.js 15+)\ntype AbortSignal = {\n readonly aborted: boolean;\n addEventListener(type: 'abort', listener: () => void, options?: { once: boolean }): void;\n removeEventListener(type: 'abort', listener: () => void): void;\n};\n\ntype AbortController = {\n readonly signal: AbortSignal;\n abort(): void;\n};\n\n// Access global AbortController through globalThis\ndeclare global {\n interface GlobalThis {\n AbortController: new () => AbortController;\n }\n}\n\n// Reference to global AbortController\nconst AbortControllerClass = globalThis.AbortController;\n\nexport interface JobExecutorOptions {\n maxRetries?: number;\n retryDelay?: number;\n retryBackoff?: 'linear' | 'exponential';\n retryBackoffMultiplier?: number;\n maxRetryDelay?: number;\n timeout?: number;\n enableCircuitBreaker?: boolean;\n circuitBreakerThreshold?: number;\n circuitBreakerResetTimeout?: number;\n enableMemoryMonitoring?: boolean;\n memoryThreshold?: number; // MB\n}\n\nexport interface JobFunction {\n (...args: any[]): Promise<any> | any;\n}\n\nexport interface ExecutionContext {\n jobId: string;\n executionId: string;\n attempt: number;\n startTime: Date;\n metadata?: Record<string, any>;\n}\n\nexport interface ExecutionResult {\n success: boolean;\n value?: any;\n error?: Error | undefined;\n attempts: number;\n duration: number;\n memoryUsed?: number;\n circuitBreakerTripped?: boolean;\n timedOut?: boolean;\n}\n\n/**\n * JobExecutor - Executes jobs with production-grade resilience\n * Features:\n * - Configurable retry with exponential backoff + jitter\n * - Timeout enforcement\n * - Circuit breaker integration\n * - Memory leak detection\n * - Graceful cancellation\n */\nexport class JobExecutor extends EventEmitter {\n private options: Required<JobExecutorOptions>;\n private logger: Logger;\n private circuitBreakers = new Map<string, CircuitBreaker>();\n private activeExecutions = new Map<string, AbortController>();\n private isShuttingDown = false;\n\n constructor(logger: Logger, options: JobExecutorOptions = {}) {\n super();\n this.logger = logger;\n\n // Set defaults\n this.options = {\n maxRetries: options.maxRetries ?? 3,\n retryDelay: options.retryDelay ?? 1000,\n retryBackoff: options.retryBackoff ?? 'exponential',\n retryBackoffMultiplier: options.retryBackoffMultiplier ?? 2,\n maxRetryDelay: options.maxRetryDelay ?? 60000,\n timeout: options.timeout ?? 300000, // 5 minutes default\n enableCircuitBreaker: options.enableCircuitBreaker ?? true,\n circuitBreakerThreshold: options.circuitBreakerThreshold ?? 5,\n circuitBreakerResetTimeout: options.circuitBreakerResetTimeout ?? 60000,\n enableMemoryMonitoring: options.enableMemoryMonitoring ?? true,\n memoryThreshold: options.memoryThreshold ?? 512, // 512MB default\n };\n\n this.logger.debug('JobExecutor initialized', 'JobExecutor', { options: this.options });\n }\n\n /**\n * Execute a job with full resilience features\n *\n * @param jobId - Unique job identifier\n * @param executionId - Unique execution identifier\n * @param jobFn - The job function to execute\n * @param context - Execution context\n * @param optionOverrides - Per-execution option overrides (merged on top of constructor defaults)\n */\n public async execute(\n jobId: string,\n executionId: string,\n jobFn: JobFunction,\n context?: ExecutionContext,\n optionOverrides?: Partial<JobExecutorOptions>\n ): Promise<ExecutionResult> {\n if (this.isShuttingDown) {\n throw new Error('JobExecutor is shutting down');\n }\n\n // Merge per-execution overrides with constructor defaults\n const opts = optionOverrides ? { ...this.options, ...optionOverrides } : this.options;\n\n const ctx: ExecutionContext = context || {\n jobId,\n executionId,\n attempt: 1,\n startTime: new Date(),\n };\n\n const startTime = Date.now();\n const abortController = new AbortControllerClass();\n this.activeExecutions.set(executionId, abortController);\n\n let lastError: Error | undefined;\n let attempts = 0;\n let circuitBreakerTripped = false;\n let timedOut = false;\n\n try {\n // Check memory before execution\n if (opts.enableMemoryMonitoring) {\n await this.checkMemoryUsage(jobId);\n }\n\n // Execute with retries\n while (attempts <= opts.maxRetries) {\n attempts++;\n ctx.attempt = attempts;\n\n try {\n // Check circuit breaker\n if (opts.enableCircuitBreaker) {\n const breaker = this.getCircuitBreaker(jobId);\n\n if (breaker.isOpen()) {\n circuitBreakerTripped = true;\n throw new Error(`Circuit breaker open for job ${jobId}`);\n }\n }\n\n // Execute with timeout\n const result = await this.executeWithTimeout(\n jobFn,\n ctx,\n abortController.signal,\n opts.timeout\n );\n\n // Success - record in circuit breaker\n if (opts.enableCircuitBreaker) {\n const breaker = this.getCircuitBreaker(jobId);\n breaker.recordSuccess();\n }\n\n const duration = Date.now() - startTime;\n const memoryUsed = this.getMemoryUsage();\n\n this.logger.debug(`Job executed successfully: ${jobId}`, 'JobExecutor', {\n executionId,\n attempts,\n duration,\n memoryUsed,\n });\n\n this.emit('execution:success', {\n jobId,\n executionId,\n attempts,\n duration,\n memoryUsed,\n });\n\n return {\n success: true,\n value: result,\n attempts,\n duration,\n memoryUsed,\n circuitBreakerTripped: false,\n timedOut: false,\n };\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n // Check if it's a timeout\n if (lastError.name === 'TimeoutError' || lastError.message.includes('timeout')) {\n timedOut = true;\n }\n\n // Record failure in circuit breaker\n if (opts.enableCircuitBreaker && !circuitBreakerTripped) {\n const breaker = this.getCircuitBreaker(jobId);\n breaker.recordFailure();\n }\n\n this.logger.warn(\n `Job execution failed: ${jobId} (attempt ${attempts}/${opts.maxRetries + 1})`,\n 'JobExecutor',\n {\n executionId,\n error: lastError.message,\n timedOut,\n circuitBreakerTripped,\n }\n );\n\n this.emit('execution:retry', {\n jobId,\n executionId,\n attempt: attempts,\n maxAttempts: opts.maxRetries + 1,\n error: lastError,\n timedOut,\n });\n\n // Don't retry if circuit breaker tripped or shutting down\n if (circuitBreakerTripped || this.isShuttingDown) {\n break;\n }\n\n // Calculate retry delay with backoff and jitter\n if (attempts <= opts.maxRetries) {\n const delay = this.calculateRetryDelay(attempts, opts);\n await this.sleep(delay);\n }\n }\n }\n\n // All retries exhausted\n const duration = Date.now() - startTime;\n\n this.logger.error(\n `Job execution failed after ${attempts} attempts: ${jobId}`,\n 'JobExecutor',\n {\n executionId,\n error: lastError?.message,\n timedOut,\n circuitBreakerTripped,\n }\n );\n\n this.emit('execution:failed', {\n jobId,\n executionId,\n attempts,\n duration,\n error: lastError,\n timedOut,\n circuitBreakerTripped,\n });\n\n return {\n success: false,\n error: lastError,\n attempts,\n duration,\n circuitBreakerTripped,\n timedOut,\n };\n } finally {\n this.activeExecutions.delete(executionId);\n\n // Force GC if memory threshold exceeded\n if (opts.enableMemoryMonitoring) {\n const memUsage = process.memoryUsage();\n const heapUsedMB = memUsage.heapUsed / 1024 / 1024;\n\n if (heapUsedMB > opts.memoryThreshold * 0.9 && globalThis.gc) {\n this.logger.warn('High memory usage detected, triggering GC', 'JobExecutor', {\n heapUsedMB: Math.round(heapUsedMB),\n threshold: opts.memoryThreshold,\n });\n globalThis.gc();\n }\n }\n }\n }\n\n /**\n * Execute job function with timeout\n */\n private async executeWithTimeout(\n jobFn: JobFunction,\n context: ExecutionContext,\n signal: AbortSignal,\n timeout?: number\n ): Promise<any> {\n const effectiveTimeout = timeout ?? this.options.timeout;\n return new Promise((resolve, reject) => {\n // Setup timeout\n const timeoutId = setTimeout(() => {\n const error = new Error(`Job execution timeout after ${effectiveTimeout}ms`);\n error.name = 'TimeoutError';\n reject(error);\n }, effectiveTimeout);\n\n // Don't keep process alive for job execution timeout\n timeoutId.unref();\n\n // Setup abort handler\n const abortHandler = () => {\n clearTimeout(timeoutId);\n reject(new Error('Job execution cancelled'));\n };\n\n if (signal.aborted) {\n clearTimeout(timeoutId);\n reject(new Error('Job execution cancelled'));\n return;\n }\n\n signal.addEventListener('abort', abortHandler, { once: true });\n\n // Execute job\n Promise.resolve()\n .then(() => jobFn(context))\n .then(result => {\n clearTimeout(timeoutId);\n signal.removeEventListener('abort', abortHandler);\n resolve(result);\n })\n .catch(error => {\n clearTimeout(timeoutId);\n signal.removeEventListener('abort', abortHandler);\n reject(error);\n });\n });\n }\n\n /**\n * Calculate retry delay with backoff and jitter\n */\n private calculateRetryDelay(\n attempt: number,\n opts?: Pick<\n Required<JobExecutorOptions>,\n 'retryBackoff' | 'retryDelay' | 'retryBackoffMultiplier' | 'maxRetryDelay'\n >\n ): number {\n const effectiveOpts = opts ?? this.options;\n let delay: number;\n\n if (effectiveOpts.retryBackoff === 'exponential') {\n delay =\n effectiveOpts.retryDelay * Math.pow(effectiveOpts.retryBackoffMultiplier, attempt - 1);\n } else {\n delay = effectiveOpts.retryDelay * attempt;\n }\n\n // Cap at max delay\n delay = Math.min(delay, effectiveOpts.maxRetryDelay);\n\n // Add jitter (±20%)\n const jitter = delay * 0.2 * (Math.random() * 2 - 1);\n delay = Math.max(0, delay + jitter);\n\n return Math.floor(delay);\n }\n\n /**\n * Sleep helper\n */\n private sleep(ms: number): Promise<void> {\n return new Promise(resolve => {\n const timer = setTimeout(resolve, ms);\n timer.unref(); // Don't keep process alive\n });\n }\n\n /**\n * Get or create circuit breaker for job\n */\n private getCircuitBreaker(jobId: string): CircuitBreaker {\n let breaker = this.circuitBreakers.get(jobId);\n\n if (!breaker) {\n breaker = new CircuitBreaker({\n failureThreshold: this.options.circuitBreakerThreshold,\n resetTimeout: this.options.circuitBreakerResetTimeout,\n });\n\n // Log circuit breaker state changes\n breaker.on('open', () => {\n this.logger.error(`Circuit breaker opened for job: ${jobId}`);\n this.emit('circuit-breaker:open', { jobId });\n });\n\n breaker.on('halfOpen', () => {\n this.logger.info(`Circuit breaker half-open for job: ${jobId}`);\n this.emit('circuit-breaker:half-open', { jobId });\n });\n\n breaker.on('closed', () => {\n this.logger.info(`Circuit breaker closed for job: ${jobId}`);\n this.emit('circuit-breaker:closed', { jobId });\n });\n\n this.circuitBreakers.set(jobId, breaker);\n }\n\n return breaker;\n }\n\n /**\n * Check memory usage before execution\n */\n private async checkMemoryUsage(jobId: string): Promise<void> {\n const memUsage = process.memoryUsage();\n const heapUsedMB = memUsage.heapUsed / 1024 / 1024;\n\n if (heapUsedMB > this.options.memoryThreshold) {\n const error = `Memory threshold exceeded: ${Math.round(heapUsedMB)}MB / ${this.options.memoryThreshold}MB`;\n this.logger.error(error, 'JobExecutor', { jobId });\n\n this.emit('memory:threshold-exceeded', {\n jobId,\n heapUsedMB,\n threshold: this.options.memoryThreshold,\n });\n\n // Try to force GC if available\n if (globalThis.gc) {\n this.logger.warn('Forcing garbage collection', 'JobExecutor', { jobId });\n globalThis.gc();\n\n // Check again after GC\n const newMemUsage = process.memoryUsage();\n const newHeapUsedMB = newMemUsage.heapUsed / 1024 / 1024;\n\n if (newHeapUsedMB > this.options.memoryThreshold) {\n throw new Error(error);\n }\n\n this.logger.info('Memory recovered after GC', 'JobExecutor', {\n before: Math.round(heapUsedMB),\n after: Math.round(newHeapUsedMB),\n });\n } else {\n throw new Error(error);\n }\n }\n }\n\n /**\n * Get current memory usage in MB\n */\n private getMemoryUsage(): number {\n const memUsage = process.memoryUsage();\n return Math.round(memUsage.heapUsed / 1024 / 1024);\n }\n\n /**\n * Cancel a running execution\n */\n public cancelExecution(executionId: string): boolean {\n const controller = this.activeExecutions.get(executionId);\n if (!controller) {\n return false;\n }\n\n controller.abort();\n this.logger.info(`Execution cancelled: ${executionId}`);\n this.emit('execution:cancelled', { executionId });\n\n return true;\n }\n\n /**\n * Cancel all running executions\n */\n public cancelAllExecutions(): void {\n const executionIds = Array.from(this.activeExecutions.keys());\n\n this.logger.info(`Cancelling ${executionIds.length} running executions`);\n\n for (const executionId of executionIds) {\n this.cancelExecution(executionId);\n }\n }\n\n /**\n * Get active execution count\n */\n public getActiveExecutionCount(): number {\n return this.activeExecutions.size;\n }\n\n /**\n * Get circuit breaker status for job\n */\n public getCircuitBreakerStatus(jobId: string): {\n exists: boolean;\n state?: string;\n failures?: number;\n threshold?: number;\n } {\n const breaker = this.circuitBreakers.get(jobId);\n\n if (!breaker) {\n return { exists: false };\n }\n\n return {\n exists: true,\n state: breaker.getState().toLowerCase(),\n failures: breaker.getFailures(),\n threshold: this.options.circuitBreakerThreshold,\n };\n }\n\n /**\n * Reset circuit breaker for job\n */\n public resetCircuitBreaker(jobId: string): boolean {\n const breaker = this.circuitBreakers.get(jobId);\n if (!breaker) {\n return false;\n }\n\n breaker.reset();\n this.logger.info(`Circuit breaker reset for job: ${jobId}`);\n return true;\n }\n\n /**\n * Update executor options at runtime\n */\n public updateOptions(options: Partial<JobExecutorOptions>): void {\n Object.assign(this.options, options);\n this.logger.info('JobExecutor options updated', 'JobExecutor', { options });\n }\n\n /**\n * Get current options\n */\n public getOptions(): Required<JobExecutorOptions> {\n return { ...this.options };\n }\n\n /**\n * Shutdown and cleanup\n */\n public async shutdown(gracePeriod: number = 30000): Promise<void> {\n this.logger.info('JobExecutor shutting down...', 'JobExecutor', {\n activeExecutions: this.activeExecutions.size,\n gracePeriod,\n });\n\n this.isShuttingDown = true;\n\n // Wait for active executions to complete or grace period to expire\n const startTime = Date.now();\n\n while (this.activeExecutions.size > 0 && Date.now() - startTime < gracePeriod) {\n this.logger.debug(`Waiting for ${this.activeExecutions.size} active executions to complete`);\n await this.sleep(1000);\n }\n\n // Force cancel remaining executions\n if (this.activeExecutions.size > 0) {\n this.logger.warn(`Force cancelling ${this.activeExecutions.size} remaining executions`);\n this.cancelAllExecutions();\n }\n\n // Cleanup state\n this.circuitBreakers.clear();\n this.activeExecutions.clear();\n\n this.removeAllListeners();\n this.logger.info('JobExecutor shutdown complete');\n }\n}\n"]}
1
+ {"version":3,"file":"job-executor.js","sourceRoot":"","sources":["../../../src/core/jobs/job-executor.ts"],"names":[],"mappings":"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","sourcesContent":["// Production-grade Job Executor\n// Handles job execution with retry logic, timeout, circuit breaker, and memory monitoring\n\nimport { EventEmitter } from 'events';\nimport { getHeapStatistics } from 'v8';\nimport { Logger } from '../../types/logger.js';\nimport { CircuitBreaker } from '../utilities/circuit-breaker.js';\n\n/**\n * Default memory ceiling for job execution, in MB.\n *\n * Derived from the process's actual V8 heap limit rather than a fixed number.\n * A hardcoded default (previously 512MB) is meaningless in isolation: 64-bit\n * Node defaults to a ~4GB heap, so 512MB is only ~12% of what the process may\n * legitimately use. Every job would refuse to run once the process crossed\n * that line — and because heap usage rarely falls back, the failure was\n * permanent rather than transient.\n *\n * 90% of the heap limit is the point where allocation pressure is real and\n * refusing new work is the right call. An explicit `memoryThreshold` option\n * still wins, so existing configuration is unaffected.\n */\nfunction defaultMemoryThresholdMB(): number {\n const limitMB = getHeapStatistics().heap_size_limit / 1024 / 1024;\n // No floor: V8's own minimum heap is ~256MB, so any absolute floor would\n // meet or exceed the limit in a memory-constrained container and disable\n // the guard entirely. A percentage of the real limit is correct at any size.\n return Math.round(limitMB * 0.9);\n}\n\n// Type definitions for native Node.js AbortController (available in Node.js 15+)\ntype AbortSignal = {\n readonly aborted: boolean;\n addEventListener(type: 'abort', listener: () => void, options?: { once: boolean }): void;\n removeEventListener(type: 'abort', listener: () => void): void;\n};\n\ntype AbortController = {\n readonly signal: AbortSignal;\n abort(): void;\n};\n\n// Access global AbortController through globalThis\ndeclare global {\n interface GlobalThis {\n AbortController: new () => AbortController;\n }\n}\n\n// Reference to global AbortController\nconst AbortControllerClass = globalThis.AbortController;\n\nexport interface JobExecutorOptions {\n maxRetries?: number;\n retryDelay?: number;\n retryBackoff?: 'linear' | 'exponential';\n retryBackoffMultiplier?: number;\n maxRetryDelay?: number;\n timeout?: number;\n enableCircuitBreaker?: boolean;\n circuitBreakerThreshold?: number;\n circuitBreakerResetTimeout?: number;\n enableMemoryMonitoring?: boolean;\n /** Heap ceiling in MB. Defaults to 90% of the process's V8 heap limit. */\n memoryThreshold?: number;\n}\n\nexport interface JobFunction {\n (...args: any[]): Promise<any> | any;\n}\n\nexport interface ExecutionContext {\n jobId: string;\n executionId: string;\n attempt: number;\n startTime: Date;\n metadata?: Record<string, any>;\n}\n\nexport interface ExecutionResult {\n success: boolean;\n value?: any;\n error?: Error | undefined;\n attempts: number;\n duration: number;\n memoryUsed?: number;\n circuitBreakerTripped?: boolean;\n timedOut?: boolean;\n}\n\n/**\n * JobExecutor - Executes jobs with production-grade resilience\n * Features:\n * - Configurable retry with exponential backoff + jitter\n * - Timeout enforcement\n * - Circuit breaker integration\n * - Memory leak detection\n * - Graceful cancellation\n */\nexport class JobExecutor extends EventEmitter {\n private options: Required<JobExecutorOptions>;\n private logger: Logger;\n private circuitBreakers = new Map<string, CircuitBreaker>();\n private activeExecutions = new Map<string, AbortController>();\n private isShuttingDown = false;\n\n constructor(logger: Logger, options: JobExecutorOptions = {}) {\n super();\n this.logger = logger;\n\n // Set defaults\n this.options = {\n maxRetries: options.maxRetries ?? 3,\n retryDelay: options.retryDelay ?? 1000,\n retryBackoff: options.retryBackoff ?? 'exponential',\n retryBackoffMultiplier: options.retryBackoffMultiplier ?? 2,\n maxRetryDelay: options.maxRetryDelay ?? 60000,\n timeout: options.timeout ?? 300000, // 5 minutes default\n enableCircuitBreaker: options.enableCircuitBreaker ?? true,\n circuitBreakerThreshold: options.circuitBreakerThreshold ?? 5,\n circuitBreakerResetTimeout: options.circuitBreakerResetTimeout ?? 60000,\n enableMemoryMonitoring: options.enableMemoryMonitoring ?? true,\n memoryThreshold: options.memoryThreshold ?? defaultMemoryThresholdMB(),\n };\n\n this.logger.debug('JobExecutor initialized', 'JobExecutor', { options: this.options });\n }\n\n /**\n * Execute a job with full resilience features\n *\n * @param jobId - Unique job identifier\n * @param executionId - Unique execution identifier\n * @param jobFn - The job function to execute\n * @param context - Execution context\n * @param optionOverrides - Per-execution option overrides (merged on top of constructor defaults)\n */\n public async execute(\n jobId: string,\n executionId: string,\n jobFn: JobFunction,\n context?: ExecutionContext,\n optionOverrides?: Partial<JobExecutorOptions>\n ): Promise<ExecutionResult> {\n if (this.isShuttingDown) {\n throw new Error('JobExecutor is shutting down');\n }\n\n // Merge per-execution overrides with constructor defaults\n const opts = optionOverrides ? { ...this.options, ...optionOverrides } : this.options;\n\n const ctx: ExecutionContext = context || {\n jobId,\n executionId,\n attempt: 1,\n startTime: new Date(),\n };\n\n const startTime = Date.now();\n const abortController = new AbortControllerClass();\n this.activeExecutions.set(executionId, abortController);\n\n let lastError: Error | undefined;\n let attempts = 0;\n let circuitBreakerTripped = false;\n let timedOut = false;\n\n try {\n // Check memory before execution\n if (opts.enableMemoryMonitoring) {\n await this.checkMemoryUsage(jobId);\n }\n\n // Execute with retries\n while (attempts <= opts.maxRetries) {\n attempts++;\n ctx.attempt = attempts;\n\n try {\n // Check circuit breaker\n if (opts.enableCircuitBreaker) {\n const breaker = this.getCircuitBreaker(jobId);\n\n if (breaker.isOpen()) {\n circuitBreakerTripped = true;\n throw new Error(`Circuit breaker open for job ${jobId}`);\n }\n }\n\n // Execute with timeout\n const result = await this.executeWithTimeout(\n jobFn,\n ctx,\n abortController.signal,\n opts.timeout\n );\n\n // Success - record in circuit breaker\n if (opts.enableCircuitBreaker) {\n const breaker = this.getCircuitBreaker(jobId);\n breaker.recordSuccess();\n }\n\n const duration = Date.now() - startTime;\n const memoryUsed = this.getMemoryUsage();\n\n this.logger.debug(`Job executed successfully: ${jobId}`, 'JobExecutor', {\n executionId,\n attempts,\n duration,\n memoryUsed,\n });\n\n this.emit('execution:success', {\n jobId,\n executionId,\n attempts,\n duration,\n memoryUsed,\n });\n\n return {\n success: true,\n value: result,\n attempts,\n duration,\n memoryUsed,\n circuitBreakerTripped: false,\n timedOut: false,\n };\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n // Check if it's a timeout\n if (lastError.name === 'TimeoutError' || lastError.message.includes('timeout')) {\n timedOut = true;\n }\n\n // Record failure in circuit breaker\n if (opts.enableCircuitBreaker && !circuitBreakerTripped) {\n const breaker = this.getCircuitBreaker(jobId);\n breaker.recordFailure();\n }\n\n this.logger.warn(\n `Job execution failed: ${jobId} (attempt ${attempts}/${opts.maxRetries + 1})`,\n 'JobExecutor',\n {\n executionId,\n error: lastError.message,\n timedOut,\n circuitBreakerTripped,\n }\n );\n\n this.emit('execution:retry', {\n jobId,\n executionId,\n attempt: attempts,\n maxAttempts: opts.maxRetries + 1,\n error: lastError,\n timedOut,\n });\n\n // Don't retry if circuit breaker tripped or shutting down\n if (circuitBreakerTripped || this.isShuttingDown) {\n break;\n }\n\n // Calculate retry delay with backoff and jitter\n if (attempts <= opts.maxRetries) {\n const delay = this.calculateRetryDelay(attempts, opts);\n await this.sleep(delay);\n }\n }\n }\n\n // All retries exhausted\n const duration = Date.now() - startTime;\n\n this.logger.error(\n `Job execution failed after ${attempts} attempts: ${jobId}`,\n 'JobExecutor',\n {\n executionId,\n error: lastError?.message,\n timedOut,\n circuitBreakerTripped,\n }\n );\n\n this.emit('execution:failed', {\n jobId,\n executionId,\n attempts,\n duration,\n error: lastError,\n timedOut,\n circuitBreakerTripped,\n });\n\n return {\n success: false,\n error: lastError,\n attempts,\n duration,\n circuitBreakerTripped,\n timedOut,\n };\n } finally {\n this.activeExecutions.delete(executionId);\n\n // Force GC if memory threshold exceeded\n if (opts.enableMemoryMonitoring) {\n const memUsage = process.memoryUsage();\n const heapUsedMB = memUsage.heapUsed / 1024 / 1024;\n\n if (heapUsedMB > opts.memoryThreshold * 0.9 && globalThis.gc) {\n this.logger.warn('High memory usage detected, triggering GC', 'JobExecutor', {\n heapUsedMB: Math.round(heapUsedMB),\n threshold: opts.memoryThreshold,\n });\n globalThis.gc();\n }\n }\n }\n }\n\n /**\n * Execute job function with timeout\n */\n private async executeWithTimeout(\n jobFn: JobFunction,\n context: ExecutionContext,\n signal: AbortSignal,\n timeout?: number\n ): Promise<any> {\n const effectiveTimeout = timeout ?? this.options.timeout;\n return new Promise((resolve, reject) => {\n // Setup timeout\n const timeoutId = setTimeout(() => {\n const error = new Error(`Job execution timeout after ${effectiveTimeout}ms`);\n error.name = 'TimeoutError';\n reject(error);\n }, effectiveTimeout);\n\n // Don't keep process alive for job execution timeout\n timeoutId.unref();\n\n // Setup abort handler\n const abortHandler = () => {\n clearTimeout(timeoutId);\n reject(new Error('Job execution cancelled'));\n };\n\n if (signal.aborted) {\n clearTimeout(timeoutId);\n reject(new Error('Job execution cancelled'));\n return;\n }\n\n signal.addEventListener('abort', abortHandler, { once: true });\n\n // Execute job\n Promise.resolve()\n .then(() => jobFn(context))\n .then(result => {\n clearTimeout(timeoutId);\n signal.removeEventListener('abort', abortHandler);\n resolve(result);\n })\n .catch(error => {\n clearTimeout(timeoutId);\n signal.removeEventListener('abort', abortHandler);\n reject(error);\n });\n });\n }\n\n /**\n * Calculate retry delay with backoff and jitter\n */\n private calculateRetryDelay(\n attempt: number,\n opts?: Pick<\n Required<JobExecutorOptions>,\n 'retryBackoff' | 'retryDelay' | 'retryBackoffMultiplier' | 'maxRetryDelay'\n >\n ): number {\n const effectiveOpts = opts ?? this.options;\n let delay: number;\n\n if (effectiveOpts.retryBackoff === 'exponential') {\n delay =\n effectiveOpts.retryDelay * Math.pow(effectiveOpts.retryBackoffMultiplier, attempt - 1);\n } else {\n delay = effectiveOpts.retryDelay * attempt;\n }\n\n // Cap at max delay\n delay = Math.min(delay, effectiveOpts.maxRetryDelay);\n\n // Add jitter (±20%)\n const jitter = delay * 0.2 * (Math.random() * 2 - 1);\n delay = Math.max(0, delay + jitter);\n\n return Math.floor(delay);\n }\n\n /**\n * Sleep helper\n */\n private sleep(ms: number): Promise<void> {\n return new Promise(resolve => {\n const timer = setTimeout(resolve, ms);\n timer.unref(); // Don't keep process alive\n });\n }\n\n /**\n * Get or create circuit breaker for job\n */\n private getCircuitBreaker(jobId: string): CircuitBreaker {\n let breaker = this.circuitBreakers.get(jobId);\n\n if (!breaker) {\n breaker = new CircuitBreaker({\n failureThreshold: this.options.circuitBreakerThreshold,\n resetTimeout: this.options.circuitBreakerResetTimeout,\n });\n\n // Log circuit breaker state changes\n breaker.on('open', () => {\n this.logger.error(`Circuit breaker opened for job: ${jobId}`);\n this.emit('circuit-breaker:open', { jobId });\n });\n\n breaker.on('halfOpen', () => {\n this.logger.info(`Circuit breaker half-open for job: ${jobId}`);\n this.emit('circuit-breaker:half-open', { jobId });\n });\n\n breaker.on('closed', () => {\n this.logger.info(`Circuit breaker closed for job: ${jobId}`);\n this.emit('circuit-breaker:closed', { jobId });\n });\n\n this.circuitBreakers.set(jobId, breaker);\n }\n\n return breaker;\n }\n\n /**\n * Check memory usage before execution\n */\n private async checkMemoryUsage(jobId: string): Promise<void> {\n const memUsage = process.memoryUsage();\n const heapUsedMB = memUsage.heapUsed / 1024 / 1024;\n\n if (heapUsedMB > this.options.memoryThreshold) {\n const error = `Memory threshold exceeded: ${Math.round(heapUsedMB)}MB / ${this.options.memoryThreshold}MB`;\n this.logger.error(error, 'JobExecutor', { jobId });\n\n this.emit('memory:threshold-exceeded', {\n jobId,\n heapUsedMB,\n threshold: this.options.memoryThreshold,\n });\n\n // Try to force GC if available\n if (globalThis.gc) {\n this.logger.warn('Forcing garbage collection', 'JobExecutor', { jobId });\n globalThis.gc();\n\n // Check again after GC\n const newMemUsage = process.memoryUsage();\n const newHeapUsedMB = newMemUsage.heapUsed / 1024 / 1024;\n\n if (newHeapUsedMB > this.options.memoryThreshold) {\n throw new Error(error);\n }\n\n this.logger.info('Memory recovered after GC', 'JobExecutor', {\n before: Math.round(heapUsedMB),\n after: Math.round(newHeapUsedMB),\n });\n } else {\n throw new Error(error);\n }\n }\n }\n\n /**\n * Get current memory usage in MB\n */\n private getMemoryUsage(): number {\n const memUsage = process.memoryUsage();\n return Math.round(memUsage.heapUsed / 1024 / 1024);\n }\n\n /**\n * Cancel a running execution\n */\n public cancelExecution(executionId: string): boolean {\n const controller = this.activeExecutions.get(executionId);\n if (!controller) {\n return false;\n }\n\n controller.abort();\n this.logger.info(`Execution cancelled: ${executionId}`);\n this.emit('execution:cancelled', { executionId });\n\n return true;\n }\n\n /**\n * Cancel all running executions\n */\n public cancelAllExecutions(): void {\n const executionIds = Array.from(this.activeExecutions.keys());\n\n this.logger.info(`Cancelling ${executionIds.length} running executions`);\n\n for (const executionId of executionIds) {\n this.cancelExecution(executionId);\n }\n }\n\n /**\n * Get active execution count\n */\n public getActiveExecutionCount(): number {\n return this.activeExecutions.size;\n }\n\n /**\n * Get circuit breaker status for job\n */\n public getCircuitBreakerStatus(jobId: string): {\n exists: boolean;\n state?: string;\n failures?: number;\n threshold?: number;\n } {\n const breaker = this.circuitBreakers.get(jobId);\n\n if (!breaker) {\n return { exists: false };\n }\n\n return {\n exists: true,\n state: breaker.getState().toLowerCase(),\n failures: breaker.getFailures(),\n threshold: this.options.circuitBreakerThreshold,\n };\n }\n\n /**\n * Reset circuit breaker for job\n */\n public resetCircuitBreaker(jobId: string): boolean {\n const breaker = this.circuitBreakers.get(jobId);\n if (!breaker) {\n return false;\n }\n\n breaker.reset();\n this.logger.info(`Circuit breaker reset for job: ${jobId}`);\n return true;\n }\n\n /**\n * Update executor options at runtime\n */\n public updateOptions(options: Partial<JobExecutorOptions>): void {\n Object.assign(this.options, options);\n this.logger.info('JobExecutor options updated', 'JobExecutor', { options });\n }\n\n /**\n * Get current options\n */\n public getOptions(): Required<JobExecutorOptions> {\n return { ...this.options };\n }\n\n /**\n * Shutdown and cleanup\n */\n public async shutdown(gracePeriod: number = 30000): Promise<void> {\n this.logger.info('JobExecutor shutting down...', 'JobExecutor', {\n activeExecutions: this.activeExecutions.size,\n gracePeriod,\n });\n\n this.isShuttingDown = true;\n\n // Wait for active executions to complete or grace period to expire\n const startTime = Date.now();\n\n while (this.activeExecutions.size > 0 && Date.now() - startTime < gracePeriod) {\n this.logger.debug(`Waiting for ${this.activeExecutions.size} active executions to complete`);\n await this.sleep(1000);\n }\n\n // Force cancel remaining executions\n if (this.activeExecutions.size > 0) {\n this.logger.warn(`Force cancelling ${this.activeExecutions.size} remaining executions`);\n this.cancelAllExecutions();\n }\n\n // Cleanup state\n this.circuitBreakers.clear();\n this.activeExecutions.clear();\n\n this.removeAllListeners();\n this.logger.info('JobExecutor shutdown complete');\n }\n}\n"]}
@@ -5,7 +5,17 @@ export function requireAuth(options = {}) {
5
5
  return async (req, res, next) => {
6
6
  const auth = req.auth;
7
7
  if (!auth) {
8
- throw new Error('Auth middleware must be installed before using requireAuth');
8
+ // Server misconfiguration, not a client error. Throwing here surfaced as
9
+ // a generic "Internal server error" with no hint at the cause, which is
10
+ // a miserable first-run experience for anyone who declares .auth() on a
11
+ // route but forgets to install the middleware.
12
+ return res.status(500).json({
13
+ success: false,
14
+ error: 'Auth middleware not installed',
15
+ message: 'This route requires authentication, but no auth middleware is installed. ' +
16
+ 'Add `app.use(auth({ ... }))` during setup before using .auth() on a route ' +
17
+ 'or requireAuth() directly.',
18
+ });
9
19
  }
10
20
  // Check if already authenticated and should redirect
11
21
  if (auth.isAuthenticated && options.redirectOnAuth) {
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../../../src/core/middleware/built-in/auth/helpers.ts"],"names":[],"mappings":"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","sourcesContent":["// Auth Helper Middleware and Utilities\nimport { AuthRequest } from '../../../../types/auth.js';\n\nexport interface AuthGuardOptions {\n redirectTo?: string;\n redirectOnAuth?: string; // Redirect if already authenticated\n authorize?: (user: any) => boolean | Promise<boolean>;\n roles?: string[];\n permissions?: string[];\n allowUnauthenticated?: boolean;\n onUnauthorized?: (req: any, res: any) => void;\n onForbidden?: (req: any, res: any) => void;\n}\n\nexport interface AuthRouteOptions {\n requireAuth?: boolean;\n roles?: string[];\n permissions?: string[];\n redirectTo?: string;\n}\n\n/**\n * Auth Guard Middleware - Protects routes with authentication and authorization\n */\nexport function requireAuth(options: AuthGuardOptions = {}) {\n return async (req: any, res: any, next: any) => {\n const auth: AuthRequest = req.auth;\n\n if (!auth) {\n throw new Error('Auth middleware must be installed before using requireAuth');\n }\n\n // Check if already authenticated and should redirect\n if (auth.isAuthenticated && options.redirectOnAuth) {\n return res.redirect(options.redirectOnAuth);\n }\n\n // Check authentication requirement\n if (!options.allowUnauthenticated && !auth.isAuthenticated) {\n if (options.onUnauthorized) {\n return options.onUnauthorized(req, res);\n }\n\n if (options.redirectTo) {\n return res.redirect(`${options.redirectTo}?callbackUrl=${encodeURIComponent(req.url)}`);\n }\n\n return res.status(401).json({\n error: 'Authentication required',\n message: 'You must be logged in to access this resource',\n signInUrl: '/api/auth/signin',\n });\n }\n\n // Skip further checks if not authenticated but allowed\n if (!auth.isAuthenticated && options.allowUnauthenticated) {\n return next();\n }\n\n const user = auth.user;\n\n // Check roles if specified\n if (options.roles && options.roles.length > 0) {\n const userRoles = user?.roles || [];\n const hasRole = options.roles.some(role => userRoles.includes(role));\n\n if (!hasRole) {\n if (options.onForbidden) {\n return options.onForbidden(req, res);\n }\n\n return res.status(403).json({\n error: 'Insufficient permissions',\n message: `Required roles: ${options.roles.join(', ')}`,\n userRoles,\n });\n }\n }\n\n // Check permissions if specified\n if (options.permissions && options.permissions.length > 0) {\n const userPermissions = user?.permissions || [];\n const hasPermission = options.permissions.every(permission =>\n userPermissions.includes(permission)\n );\n\n if (!hasPermission) {\n if (options.onForbidden) {\n return options.onForbidden(req, res);\n }\n\n return res.status(403).json({\n error: 'Insufficient permissions',\n message: `Required permissions: ${options.permissions.join(', ')}`,\n userPermissions,\n });\n }\n }\n\n // Custom authorization function\n if (options.authorize) {\n try {\n const authorized = await options.authorize(user);\n\n if (!authorized) {\n if (options.onForbidden) {\n return options.onForbidden(req, res);\n }\n\n return res.status(403).json({\n error: 'Access denied',\n message: 'Custom authorization check failed',\n });\n }\n } catch {\n return res.status(500).json({\n error: 'Authorization error',\n message: 'Failed to verify authorization',\n });\n }\n }\n\n // All checks passed\n next();\n };\n}\n\n/**\n * Role-based access control middleware\n */\nexport function requireRole(\n role: string | string[],\n options: Omit<AuthGuardOptions, 'roles'> = {}\n) {\n const roles = Array.isArray(role) ? role : [role];\n return requireAuth({ ...options, roles });\n}\n\n/**\n * Permission-based access control middleware\n */\nexport function requirePermission(\n permission: string | string[],\n options: Omit<AuthGuardOptions, 'permissions'> = {}\n) {\n const permissions = Array.isArray(permission) ? permission : [permission];\n return requireAuth({ ...options, permissions });\n}\n\n/**\n * Admin-only access middleware\n */\nexport function requireAdmin(options: Omit<AuthGuardOptions, 'roles'> = {}) {\n return requireRole('admin', options);\n}\n\n/**\n * Guest-only middleware (redirect if authenticated)\n */\nexport function guestOnly(redirectTo = '/dashboard') {\n return requireAuth({\n allowUnauthenticated: true,\n redirectOnAuth: redirectTo,\n });\n}\n\n/**\n * Optional auth middleware (allows both authenticated and unauthenticated)\n */\nexport function optionalAuth() {\n return requireAuth({\n allowUnauthenticated: true,\n });\n}\n\n/**\n * Route-level auth decorator\n */\nexport function withAuth(options: AuthRouteOptions = {}) {\n return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {\n const originalMethod = descriptor.value;\n\n descriptor.value = async function (req: any, res: any, next: any) {\n if (options.requireAuth !== false) {\n const authMiddleware = requireAuth({\n ...(options.roles !== undefined ? { roles: options.roles } : {}),\n ...(options.redirectTo !== undefined ? { redirectTo: options.redirectTo } : {}),\n });\n\n await new Promise<void>((resolve, reject) => {\n void authMiddleware(req, res, (error: any) => {\n if (error) reject(error);\n else resolve();\n });\n });\n }\n\n return originalMethod.call(this, req, res, next);\n };\n\n return descriptor;\n };\n}\n\n/**\n * Auth utilities for manual checks in route handlers\n */\nexport const authUtils = {\n /**\n * Check if user is authenticated\n */\n isAuthenticated(req: any): boolean {\n return req.auth?.isAuthenticated || false;\n },\n\n /**\n * Get current user\n */\n getUser(req: any) {\n return req.auth?.user || null;\n },\n\n /**\n * Check if user has role\n */\n hasRole(req: any, role: string | string[]): boolean {\n const user = this.getUser(req);\n if (!user?.roles) return false;\n\n const roles = Array.isArray(role) ? role : [role];\n return roles.some(r => user.roles.includes(r));\n },\n\n /**\n * Check if user has permission\n */\n hasPermission(req: any, permission: string | string[]): boolean {\n const user = this.getUser(req);\n if (!user?.permissions) return false;\n\n const permissions = Array.isArray(permission) ? permission : [permission];\n return permissions.every(p => user.permissions.includes(p));\n },\n\n /**\n * Check if user is admin\n */\n isAdmin(req: any): boolean {\n return this.hasRole(req, 'admin');\n },\n\n /**\n * Get user ID\n */\n getUserId(req: any): string | null {\n return this.getUser(req)?.id || null;\n },\n\n /**\n * Force authentication check and redirect if needed\n */\n ensureAuth(req: any, res: any, redirectTo = '/api/auth/signin'): boolean {\n if (!this.isAuthenticated(req)) {\n res.redirect(`${redirectTo}?callbackUrl=${encodeURIComponent(req.url)}`);\n return false;\n }\n return true;\n },\n\n /**\n * Create auth response for API endpoints\n */\n createAuthResponse(req: any) {\n const auth = req.auth;\n\n return {\n isAuthenticated: auth?.isAuthenticated || false,\n user: auth?.user || null,\n session: auth?.session || null,\n timestamp: new Date().toISOString(),\n };\n },\n};\n\n/**\n * API Response helpers for auth endpoints\n */\nexport const authResponses = {\n unauthorized: (res: any, message = 'Authentication required') => {\n return res.status(401).json({\n error: 'Unauthorized',\n message,\n code: 'AUTH_REQUIRED',\n signInUrl: '/api/auth/signin',\n });\n },\n\n forbidden: (res: any, message = 'Insufficient permissions') => {\n return res.status(403).json({\n error: 'Forbidden',\n message,\n code: 'INSUFFICIENT_PERMISSIONS',\n });\n },\n\n authSuccess: (res: any, user: any, message = 'Authentication successful') => {\n return res.json({\n success: true,\n message,\n user: {\n id: user.id,\n name: user.name,\n email: user.email,\n roles: user.roles || [],\n permissions: user.permissions || [],\n },\n });\n },\n\n authError: (res: any, error: string, message = 'Authentication failed') => {\n return res.status(400).json({\n error,\n message,\n code: 'AUTH_ERROR',\n });\n },\n};\n\n/**\n * Higher-order function to create protected route handlers\n */\nexport function protectedRoute(\n handler: (req: any, res: any, next?: any) => any,\n options: AuthGuardOptions = {}\n) {\n return async (req: any, res: any, next: any) => {\n const authMiddleware = requireAuth(options);\n\n return new Promise<void>((resolve, reject) => {\n void authMiddleware(req, res, (error: any) => {\n if (error) {\n reject(error);\n } else {\n Promise.resolve(handler(req, res, next))\n .then(() => resolve())\n .catch(reject);\n }\n });\n });\n };\n}\n\n/**\n * Session management helpers\n */\nexport const sessionHelpers = {\n /**\n * Store data in session\n */\n async setSessionData(req: any, key: string, value: any) {\n if (req.session) {\n req.session[key] = value;\n await req.session.save();\n }\n },\n\n /**\n * Get data from session\n */\n getSessionData(req: any, key: string) {\n return req.session?.[key] || null;\n },\n\n /**\n * Remove data from session\n */\n async removeSessionData(req: any, key: string) {\n if (req.session && key in req.session.data) {\n delete req.session.data[key];\n await req.session.save();\n }\n },\n\n /**\n * Clear entire session\n */\n async clearSession(req: any) {\n if (req.session) {\n await req.session.destroy();\n }\n },\n\n /**\n * Regenerate session ID\n */\n async regenerateSession(req: any) {\n if (req.session) {\n return await req.session.regenerate();\n }\n },\n};\n"]}
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../../../src/core/middleware/built-in/auth/helpers.ts"],"names":[],"mappings":"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","sourcesContent":["// Auth Helper Middleware and Utilities\nimport { AuthRequest } from '../../../../types/auth.js';\n\nexport interface AuthGuardOptions {\n redirectTo?: string;\n redirectOnAuth?: string; // Redirect if already authenticated\n authorize?: (user: any) => boolean | Promise<boolean>;\n roles?: string[];\n permissions?: string[];\n allowUnauthenticated?: boolean;\n onUnauthorized?: (req: any, res: any) => void;\n onForbidden?: (req: any, res: any) => void;\n}\n\nexport interface AuthRouteOptions {\n requireAuth?: boolean;\n roles?: string[];\n permissions?: string[];\n redirectTo?: string;\n}\n\n/**\n * Auth Guard Middleware - Protects routes with authentication and authorization\n */\nexport function requireAuth(options: AuthGuardOptions = {}) {\n return async (req: any, res: any, next: any) => {\n const auth: AuthRequest = req.auth;\n\n if (!auth) {\n // Server misconfiguration, not a client error. Throwing here surfaced as\n // a generic \"Internal server error\" with no hint at the cause, which is\n // a miserable first-run experience for anyone who declares .auth() on a\n // route but forgets to install the middleware.\n return res.status(500).json({\n success: false,\n error: 'Auth middleware not installed',\n message:\n 'This route requires authentication, but no auth middleware is installed. ' +\n 'Add `app.use(auth({ ... }))` during setup before using .auth() on a route ' +\n 'or requireAuth() directly.',\n });\n }\n\n // Check if already authenticated and should redirect\n if (auth.isAuthenticated && options.redirectOnAuth) {\n return res.redirect(options.redirectOnAuth);\n }\n\n // Check authentication requirement\n if (!options.allowUnauthenticated && !auth.isAuthenticated) {\n if (options.onUnauthorized) {\n return options.onUnauthorized(req, res);\n }\n\n if (options.redirectTo) {\n return res.redirect(`${options.redirectTo}?callbackUrl=${encodeURIComponent(req.url)}`);\n }\n\n return res.status(401).json({\n error: 'Authentication required',\n message: 'You must be logged in to access this resource',\n signInUrl: '/api/auth/signin',\n });\n }\n\n // Skip further checks if not authenticated but allowed\n if (!auth.isAuthenticated && options.allowUnauthenticated) {\n return next();\n }\n\n const user = auth.user;\n\n // Check roles if specified\n if (options.roles && options.roles.length > 0) {\n const userRoles = user?.roles || [];\n const hasRole = options.roles.some(role => userRoles.includes(role));\n\n if (!hasRole) {\n if (options.onForbidden) {\n return options.onForbidden(req, res);\n }\n\n return res.status(403).json({\n error: 'Insufficient permissions',\n message: `Required roles: ${options.roles.join(', ')}`,\n userRoles,\n });\n }\n }\n\n // Check permissions if specified\n if (options.permissions && options.permissions.length > 0) {\n const userPermissions = user?.permissions || [];\n const hasPermission = options.permissions.every(permission =>\n userPermissions.includes(permission)\n );\n\n if (!hasPermission) {\n if (options.onForbidden) {\n return options.onForbidden(req, res);\n }\n\n return res.status(403).json({\n error: 'Insufficient permissions',\n message: `Required permissions: ${options.permissions.join(', ')}`,\n userPermissions,\n });\n }\n }\n\n // Custom authorization function\n if (options.authorize) {\n try {\n const authorized = await options.authorize(user);\n\n if (!authorized) {\n if (options.onForbidden) {\n return options.onForbidden(req, res);\n }\n\n return res.status(403).json({\n error: 'Access denied',\n message: 'Custom authorization check failed',\n });\n }\n } catch {\n return res.status(500).json({\n error: 'Authorization error',\n message: 'Failed to verify authorization',\n });\n }\n }\n\n // All checks passed\n next();\n };\n}\n\n/**\n * Role-based access control middleware\n */\nexport function requireRole(\n role: string | string[],\n options: Omit<AuthGuardOptions, 'roles'> = {}\n) {\n const roles = Array.isArray(role) ? role : [role];\n return requireAuth({ ...options, roles });\n}\n\n/**\n * Permission-based access control middleware\n */\nexport function requirePermission(\n permission: string | string[],\n options: Omit<AuthGuardOptions, 'permissions'> = {}\n) {\n const permissions = Array.isArray(permission) ? permission : [permission];\n return requireAuth({ ...options, permissions });\n}\n\n/**\n * Admin-only access middleware\n */\nexport function requireAdmin(options: Omit<AuthGuardOptions, 'roles'> = {}) {\n return requireRole('admin', options);\n}\n\n/**\n * Guest-only middleware (redirect if authenticated)\n */\nexport function guestOnly(redirectTo = '/dashboard') {\n return requireAuth({\n allowUnauthenticated: true,\n redirectOnAuth: redirectTo,\n });\n}\n\n/**\n * Optional auth middleware (allows both authenticated and unauthenticated)\n */\nexport function optionalAuth() {\n return requireAuth({\n allowUnauthenticated: true,\n });\n}\n\n/**\n * Route-level auth decorator\n */\nexport function withAuth(options: AuthRouteOptions = {}) {\n return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {\n const originalMethod = descriptor.value;\n\n descriptor.value = async function (req: any, res: any, next: any) {\n if (options.requireAuth !== false) {\n const authMiddleware = requireAuth({\n ...(options.roles !== undefined ? { roles: options.roles } : {}),\n ...(options.redirectTo !== undefined ? { redirectTo: options.redirectTo } : {}),\n });\n\n await new Promise<void>((resolve, reject) => {\n void authMiddleware(req, res, (error: any) => {\n if (error) reject(error);\n else resolve();\n });\n });\n }\n\n return originalMethod.call(this, req, res, next);\n };\n\n return descriptor;\n };\n}\n\n/**\n * Auth utilities for manual checks in route handlers\n */\nexport const authUtils = {\n /**\n * Check if user is authenticated\n */\n isAuthenticated(req: any): boolean {\n return req.auth?.isAuthenticated || false;\n },\n\n /**\n * Get current user\n */\n getUser(req: any) {\n return req.auth?.user || null;\n },\n\n /**\n * Check if user has role\n */\n hasRole(req: any, role: string | string[]): boolean {\n const user = this.getUser(req);\n if (!user?.roles) return false;\n\n const roles = Array.isArray(role) ? role : [role];\n return roles.some(r => user.roles.includes(r));\n },\n\n /**\n * Check if user has permission\n */\n hasPermission(req: any, permission: string | string[]): boolean {\n const user = this.getUser(req);\n if (!user?.permissions) return false;\n\n const permissions = Array.isArray(permission) ? permission : [permission];\n return permissions.every(p => user.permissions.includes(p));\n },\n\n /**\n * Check if user is admin\n */\n isAdmin(req: any): boolean {\n return this.hasRole(req, 'admin');\n },\n\n /**\n * Get user ID\n */\n getUserId(req: any): string | null {\n return this.getUser(req)?.id || null;\n },\n\n /**\n * Force authentication check and redirect if needed\n */\n ensureAuth(req: any, res: any, redirectTo = '/api/auth/signin'): boolean {\n if (!this.isAuthenticated(req)) {\n res.redirect(`${redirectTo}?callbackUrl=${encodeURIComponent(req.url)}`);\n return false;\n }\n return true;\n },\n\n /**\n * Create auth response for API endpoints\n */\n createAuthResponse(req: any) {\n const auth = req.auth;\n\n return {\n isAuthenticated: auth?.isAuthenticated || false,\n user: auth?.user || null,\n session: auth?.session || null,\n timestamp: new Date().toISOString(),\n };\n },\n};\n\n/**\n * API Response helpers for auth endpoints\n */\nexport const authResponses = {\n unauthorized: (res: any, message = 'Authentication required') => {\n return res.status(401).json({\n error: 'Unauthorized',\n message,\n code: 'AUTH_REQUIRED',\n signInUrl: '/api/auth/signin',\n });\n },\n\n forbidden: (res: any, message = 'Insufficient permissions') => {\n return res.status(403).json({\n error: 'Forbidden',\n message,\n code: 'INSUFFICIENT_PERMISSIONS',\n });\n },\n\n authSuccess: (res: any, user: any, message = 'Authentication successful') => {\n return res.json({\n success: true,\n message,\n user: {\n id: user.id,\n name: user.name,\n email: user.email,\n roles: user.roles || [],\n permissions: user.permissions || [],\n },\n });\n },\n\n authError: (res: any, error: string, message = 'Authentication failed') => {\n return res.status(400).json({\n error,\n message,\n code: 'AUTH_ERROR',\n });\n },\n};\n\n/**\n * Higher-order function to create protected route handlers\n */\nexport function protectedRoute(\n handler: (req: any, res: any, next?: any) => any,\n options: AuthGuardOptions = {}\n) {\n return async (req: any, res: any, next: any) => {\n const authMiddleware = requireAuth(options);\n\n return new Promise<void>((resolve, reject) => {\n void authMiddleware(req, res, (error: any) => {\n if (error) {\n reject(error);\n } else {\n Promise.resolve(handler(req, res, next))\n .then(() => resolve())\n .catch(reject);\n }\n });\n });\n };\n}\n\n/**\n * Session management helpers\n */\nexport const sessionHelpers = {\n /**\n * Store data in session\n */\n async setSessionData(req: any, key: string, value: any) {\n if (req.session) {\n req.session[key] = value;\n await req.session.save();\n }\n },\n\n /**\n * Get data from session\n */\n getSessionData(req: any, key: string) {\n return req.session?.[key] || null;\n },\n\n /**\n * Remove data from session\n */\n async removeSessionData(req: any, key: string) {\n if (req.session && key in req.session.data) {\n delete req.session.data[key];\n await req.session.save();\n }\n },\n\n /**\n * Clear entire session\n */\n async clearSession(req: any) {\n if (req.session) {\n await req.session.destroy();\n }\n },\n\n /**\n * Regenerate session ID\n */\n async regenerateSession(req: any) {\n if (req.session) {\n return await req.session.regenerate();\n }\n },\n};\n"]}
@@ -22,11 +22,15 @@ export class MemoryCacheAdapter {
22
22
  }
23
23
  // Set new value
24
24
  this.cache.set(key, { value, expires });
25
- // Set expiration timer
25
+ // Set expiration timer. unref() so eviction housekeeping never holds the
26
+ // process open — a pending TTL (sessions default to ~24h) must not block
27
+ // shutdown. Entries are also expiry-checked on read, so eviction stays
28
+ // correct even if the process exits and restarts before the timer fires.
26
29
  const timer = setTimeout(() => {
27
30
  this.cache.delete(key);
28
31
  this.timers.delete(key);
29
32
  }, ttl * 1000);
33
+ timer.unref?.();
30
34
  this.timers.set(key, timer);
31
35
  logger.debug(`Cached item: ${key} (TTL: ${ttl}s)`, 'MemoryCache');
32
36
  }
@@ -1 +1 @@
1
- {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../../../../../src/core/middleware/built-in/cache/adapters/cache/memory.ts"],"names":[],"mappings":"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","sourcesContent":["// Memory Cache Adapter\nimport { CacheAdapter } from '../../../../../../types/cache.js';\nimport { createFrameworkLogger } from '../../../../../logger/index.js';\n\nconst logger = createFrameworkLogger('MemoryCacheAdapter');\n\nexport class MemoryCacheAdapter implements CacheAdapter {\n private cache = new Map<string, { value: any; expires: number }>();\n private timers = new Map<string, NodeJS.Timeout>();\n\n async get(key: string): Promise<any> {\n const item = this.cache.get(key);\n if (!item) return null;\n\n if (Date.now() > item.expires) {\n await this.del(key);\n return null;\n }\n\n return item.value;\n }\n\n async set(key: string, value: any, ttl: number = 3600): Promise<void> {\n const expires = Date.now() + ttl * 1000;\n\n // Clear existing timer\n const existingTimer = this.timers.get(key);\n if (existingTimer) {\n clearTimeout(existingTimer);\n }\n\n // Set new value\n this.cache.set(key, { value, expires });\n\n // Set expiration timer\n const timer = setTimeout(() => {\n this.cache.delete(key);\n this.timers.delete(key);\n }, ttl * 1000);\n\n this.timers.set(key, timer);\n logger.debug(`Cached item: ${key} (TTL: ${ttl}s)`, 'MemoryCache');\n }\n\n async del(key: string): Promise<void> {\n this.cache.delete(key);\n const timer = this.timers.get(key);\n if (timer) {\n clearTimeout(timer);\n this.timers.delete(key);\n }\n logger.debug(`Deleted cache item: ${key}`, 'MemoryCache');\n }\n\n async clear(): Promise<void> {\n this.cache.clear();\n this.timers.forEach(timer => clearTimeout(timer));\n this.timers.clear();\n logger.debug('Cleared all cache items', 'MemoryCache');\n }\n\n async exists(key: string): Promise<boolean> {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return this.cache.has(key) && Date.now() <= this.cache.get(key)!.expires;\n }\n\n async ttl(key: string): Promise<number> {\n const item = this.cache.get(key);\n if (!item) return -1;\n\n const remaining = Math.floor((item.expires - Date.now()) / 1000);\n return remaining > 0 ? remaining : -1;\n }\n}\n"]}
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../../../../../src/core/middleware/built-in/cache/adapters/cache/memory.ts"],"names":[],"mappings":"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","sourcesContent":["// Memory Cache Adapter\nimport { CacheAdapter } from '../../../../../../types/cache.js';\nimport { createFrameworkLogger } from '../../../../../logger/index.js';\n\nconst logger = createFrameworkLogger('MemoryCacheAdapter');\n\nexport class MemoryCacheAdapter implements CacheAdapter {\n private cache = new Map<string, { value: any; expires: number }>();\n private timers = new Map<string, NodeJS.Timeout>();\n\n async get(key: string): Promise<any> {\n const item = this.cache.get(key);\n if (!item) return null;\n\n if (Date.now() > item.expires) {\n await this.del(key);\n return null;\n }\n\n return item.value;\n }\n\n async set(key: string, value: any, ttl: number = 3600): Promise<void> {\n const expires = Date.now() + ttl * 1000;\n\n // Clear existing timer\n const existingTimer = this.timers.get(key);\n if (existingTimer) {\n clearTimeout(existingTimer);\n }\n\n // Set new value\n this.cache.set(key, { value, expires });\n\n // Set expiration timer. unref() so eviction housekeeping never holds the\n // process open — a pending TTL (sessions default to ~24h) must not block\n // shutdown. Entries are also expiry-checked on read, so eviction stays\n // correct even if the process exits and restarts before the timer fires.\n const timer = setTimeout(() => {\n this.cache.delete(key);\n this.timers.delete(key);\n }, ttl * 1000);\n timer.unref?.();\n\n this.timers.set(key, timer);\n logger.debug(`Cached item: ${key} (TTL: ${ttl}s)`, 'MemoryCache');\n }\n\n async del(key: string): Promise<void> {\n this.cache.delete(key);\n const timer = this.timers.get(key);\n if (timer) {\n clearTimeout(timer);\n this.timers.delete(key);\n }\n logger.debug(`Deleted cache item: ${key}`, 'MemoryCache');\n }\n\n async clear(): Promise<void> {\n this.cache.clear();\n this.timers.forEach(timer => clearTimeout(timer));\n this.timers.clear();\n logger.debug('Cleared all cache items', 'MemoryCache');\n }\n\n async exists(key: string): Promise<boolean> {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return this.cache.has(key) && Date.now() <= this.cache.get(key)!.expires;\n }\n\n async ttl(key: string): Promise<number> {\n const item = this.cache.get(key);\n if (!item) return -1;\n\n const remaining = Math.floor((item.expires - Date.now()) / 1000);\n return remaining > 0 ? remaining : -1;\n }\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import { EventEmitter } from 'events';
2
+ import { HookManager } from '../utilities/index.js';
2
3
  import { MiddlewareInterface, SimpleMiddlewareFunction } from '../../types/hooks.js';
3
4
  export type { MiddlewareInterface, MoroMiddleware } from '../../types/hooks.js';
4
5
  export declare class MiddlewareManager extends EventEmitter {
@@ -12,6 +13,7 @@ export declare class MiddlewareManager extends EventEmitter {
12
13
  uninstall(name: string): void;
13
14
  getInstalled(): string[];
14
15
  getConfig(name: string): any;
16
+ getHookManager(): HookManager;
15
17
  isInstalled(name: string): boolean;
16
18
  get(name: string): MiddlewareInterface | SimpleMiddlewareFunction | undefined;
17
19
  list(): MiddlewareInterface[];
@@ -84,6 +84,11 @@ export class MiddlewareManager extends EventEmitter {
84
84
  getConfig(name) {
85
85
  return this.middleware.get(name)?.metadata;
86
86
  }
87
+ // The live hook manager that MiddlewareInterface.install() receives.
88
+ // Exposed so the app can offer a public `app.hooks` accessor.
89
+ getHookManager() {
90
+ return this.hooks;
91
+ }
87
92
  // Check if middleware is installed
88
93
  isInstalled(name) {
89
94
  return this.middleware.has(name);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/middleware/index.ts"],"names":[],"mappings":"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","sourcesContent":["// Middleware System for Moro\n/*\n All middleware in Moro should follow or adopt all of the following patterns:\n Core - Core.method(req, res, config) - Direct logic, no next, used by router directly\n Middleware - (req, res, next) => { ... next() } - For middleware chains, calls next\n Hooks - MiddlewareInterface with before/after hooks\n*/\n\nimport { EventEmitter } from 'events';\nimport { HookManager } from '../utilities/index.js';\nimport { MiddlewareInterface, SimpleMiddlewareFunction } from '../../types/hooks.js';\nimport { createFrameworkLogger } from '../logger/index.js';\n\n// Export types needed by built-in middleware\nexport type { MiddlewareInterface, MoroMiddleware } from '../../types/hooks.js';\n\nexport class MiddlewareManager extends EventEmitter {\n private middleware = new Map<string, MiddlewareInterface>();\n private simpleMiddleware = new Map<string, SimpleMiddlewareFunction>();\n private hooks: HookManager;\n private logger = createFrameworkLogger('Middleware');\n\n constructor() {\n super();\n this.hooks = new HookManager();\n }\n\n // Register middleware without installing\n register(name: string, middleware: MiddlewareInterface): void {\n if (this.middleware.has(name)) {\n throw new Error(`Middleware ${name} is already registered`);\n }\n\n this.middleware.set(name, middleware);\n this.logger.debug(`Registered middleware: ${name}`, 'Registration');\n this.emit('registered', { name, middleware });\n }\n\n // Install simple function-style middleware\n install(middleware: SimpleMiddlewareFunction | MiddlewareInterface, options: any = {}): void {\n if (typeof middleware === 'function') {\n // Simple function-style middleware\n const simpleName = middleware.name || 'anonymous';\n this.logger.debug(`Installing simple middleware: ${simpleName}`, 'Installation');\n\n this.simpleMiddleware.set(simpleName, middleware);\n this.emit('installed', { name: simpleName, type: 'simple' });\n this.logger.info(`Simple middleware installed: ${simpleName}`, 'Installation');\n return;\n }\n\n // Advanced middleware with dependencies and lifecycle\n const name = middleware.metadata?.name || 'unknown';\n\n if (this.middleware.has(name)) {\n throw new Error(`Middleware ${name} is already installed`);\n }\n\n // Check dependencies\n if (middleware.metadata?.dependencies) {\n for (const dep of middleware.metadata.dependencies) {\n if (!this.middleware.has(dep)) {\n throw new Error(`Dependency ${dep} not found for middleware ${name}`);\n }\n }\n }\n\n // Store middleware\n this.middleware.set(name, middleware);\n\n this.logger.debug(`Installing middleware: ${name}`, 'Installation');\n\n // Initialize middleware\n if (middleware.install) {\n void middleware.install(this.hooks, options);\n }\n\n this.emit('installed', { name, middleware, options });\n this.logger.info(`Middleware installed: ${name}`, 'Installation');\n }\n\n // Uninstall middleware and clean up\n uninstall(name: string): void {\n if (!this.middleware.has(name)) {\n throw new Error(`Middleware ${name} is not installed`);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const middleware = this.middleware.get(name)!;\n\n this.logger.debug(`Uninstalling middleware: ${name}`, 'Uninstallation');\n\n // Call cleanup if available\n if (middleware.uninstall) {\n void middleware.uninstall(this.hooks);\n }\n\n this.middleware.delete(name);\n this.emit('uninstalled', { name, middleware });\n this.logger.info(`Middleware uninstalled: ${name}`, 'Uninstallation');\n }\n\n // Get installed middleware\n getInstalled(): string[] {\n return Array.from(this.middleware.keys());\n }\n\n // Get middleware configuration\n getConfig(name: string): any {\n return this.middleware.get(name)?.metadata;\n }\n\n // Check if middleware is installed\n isInstalled(name: string): boolean {\n return this.middleware.has(name);\n }\n\n // Get middleware by name (safe getter for module usage)\n get(name: string): MiddlewareInterface | SimpleMiddlewareFunction | undefined {\n // Check installed middleware first\n if (this.middleware.has(name)) {\n return this.middleware.get(name);\n }\n\n // Check simple middleware\n if (this.simpleMiddleware.has(name)) {\n return this.simpleMiddleware.get(name);\n }\n\n return undefined;\n }\n\n // List all registered middleware\n list(): MiddlewareInterface[] {\n return Array.from(this.middleware.values());\n }\n\n // Dependency resolution with topological sorting for optimal middleware loading\n async installWithDependencies(\n middleware: MiddlewareInterface[],\n options?: Record<string, any>\n ): Promise<void> {\n // Advanced topological sort for dependency resolution\n const resolved = this.topologicalSort(middleware);\n\n for (const middlewareItem of resolved) {\n const middlewareOptions = options?.[middlewareItem.name];\n await this.install(middlewareItem, middlewareOptions);\n }\n }\n\n // Optimized topological sort implementation for middleware dependencies\n private topologicalSort(middleware: MiddlewareInterface[]): MiddlewareInterface[] {\n const visited = new Set<string>();\n const temp = new Set<string>();\n const result: MiddlewareInterface[] = [];\n\n const visit = (middlewareItem: MiddlewareInterface) => {\n if (temp.has(middlewareItem.name)) {\n throw new Error(`Circular dependency detected: ${middlewareItem.name}`);\n }\n\n if (!visited.has(middlewareItem.name)) {\n temp.add(middlewareItem.name);\n\n // Visit dependencies first\n if (middlewareItem.dependencies) {\n for (const depName of middlewareItem.dependencies) {\n const dependency = middleware.find(m => m.name === depName);\n if (dependency) {\n visit(dependency);\n }\n }\n }\n\n temp.delete(middlewareItem.name);\n visited.add(middlewareItem.name);\n result.push(middlewareItem);\n }\n };\n\n for (const middlewareItem of middleware) {\n if (!visited.has(middlewareItem.name)) {\n visit(middlewareItem);\n }\n }\n\n return result;\n }\n}\n\n// Built-in middleware exports\nexport { middleware, builtInMiddleware } from './built-in/index.js';\nexport * from './built-in/index.js';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/middleware/index.ts"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B;;;;;EAKE;AAEF,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAK3D,MAAM,OAAO,iBAAkB,SAAQ,YAAY;IACzC,UAAU,GAAG,IAAI,GAAG,EAA+B,CAAC;IACpD,gBAAgB,GAAG,IAAI,GAAG,EAAoC,CAAC;IAC/D,KAAK,CAAc;IACnB,MAAM,GAAG,qBAAqB,CAAC,YAAY,CAAC,CAAC;IAErD;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC;IACjC,CAAC;IAED,yCAAyC;IACzC,QAAQ,CAAC,IAAY,EAAE,UAA+B;QACpD,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,cAAc,IAAI,wBAAwB,CAAC,CAAC;QAC9D,CAAC;QAED,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,0BAA0B,IAAI,EAAE,EAAE,cAAc,CAAC,CAAC;QACpE,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,2CAA2C;IAC3C,OAAO,CAAC,UAA0D,EAAE,UAAe,EAAE;QACnF,IAAI,OAAO,UAAU,KAAK,UAAU,EAAE,CAAC;YACrC,mCAAmC;YACnC,MAAM,UAAU,GAAG,UAAU,CAAC,IAAI,IAAI,WAAW,CAAC;YAClD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,iCAAiC,UAAU,EAAE,EAAE,cAAc,CAAC,CAAC;YAEjF,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;YAClD,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC7D,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,gCAAgC,UAAU,EAAE,EAAE,cAAc,CAAC,CAAC;YAC/E,OAAO;QACT,CAAC;QAED,sDAAsD;QACtD,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,EAAE,IAAI,IAAI,SAAS,CAAC;QAEpD,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,cAAc,IAAI,uBAAuB,CAAC,CAAC;QAC7D,CAAC;QAED,qBAAqB;QACrB,IAAI,UAAU,CAAC,QAAQ,EAAE,YAAY,EAAE,CAAC;YACtC,KAAK,MAAM,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC;gBACnD,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC9B,MAAM,IAAI,KAAK,CAAC,cAAc,GAAG,6BAA6B,IAAI,EAAE,CAAC,CAAC;gBACxE,CAAC;YACH,CAAC;QACH,CAAC;QAED,mBAAmB;QACnB,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAEtC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,0BAA0B,IAAI,EAAE,EAAE,cAAc,CAAC,CAAC;QAEpE,wBAAwB;QACxB,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;YACvB,KAAK,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC/C,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC;QACtD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAyB,IAAI,EAAE,EAAE,cAAc,CAAC,CAAC;IACpE,CAAC;IAED,oCAAoC;IACpC,SAAS,CAAC,IAAY;QACpB,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,cAAc,IAAI,mBAAmB,CAAC,CAAC;QACzD,CAAC;QAED,oEAAoE;QACpE,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC;QAE9C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,IAAI,EAAE,EAAE,gBAAgB,CAAC,CAAC;QAExE,4BAA4B;QAC5B,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;YACzB,KAAK,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxC,CAAC;QAED,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;QAC/C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,2BAA2B,IAAI,EAAE,EAAE,gBAAgB,CAAC,CAAC;IACxE,CAAC;IAED,2BAA2B;IAC3B,YAAY;QACV,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED,+BAA+B;IAC/B,SAAS,CAAC,IAAY;QACpB,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC;IAC7C,CAAC;IAED,qEAAqE;IACrE,8DAA8D;IAC9D,cAAc;QACZ,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,mCAAmC;IACnC,WAAW,CAAC,IAAY;QACtB,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,wDAAwD;IACxD,GAAG,CAAC,IAAY;QACd,mCAAmC;QACnC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACnC,CAAC;QAED,0BAA0B;QAC1B,IAAI,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,iCAAiC;IACjC,IAAI;QACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,gFAAgF;IAChF,KAAK,CAAC,uBAAuB,CAC3B,UAAiC,EACjC,OAA6B;QAE7B,sDAAsD;QACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;QAElD,KAAK,MAAM,cAAc,IAAI,QAAQ,EAAE,CAAC;YACtC,MAAM,iBAAiB,GAAG,OAAO,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;YACzD,MAAM,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,iBAAiB,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAED,wEAAwE;IAChE,eAAe,CAAC,UAAiC;QACvD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAClC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,MAAM,MAAM,GAA0B,EAAE,CAAC;QAEzC,MAAM,KAAK,GAAG,CAAC,cAAmC,EAAE,EAAE;YACpD,IAAI,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;gBAClC,MAAM,IAAI,KAAK,CAAC,iCAAiC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC;YAC1E,CAAC;YAED,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtC,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;gBAE9B,2BAA2B;gBAC3B,IAAI,cAAc,CAAC,YAAY,EAAE,CAAC;oBAChC,KAAK,MAAM,OAAO,IAAI,cAAc,CAAC,YAAY,EAAE,CAAC;wBAClD,MAAM,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;wBAC5D,IAAI,UAAU,EAAE,CAAC;4BACf,KAAK,CAAC,UAAU,CAAC,CAAC;wBACpB,CAAC;oBACH,CAAC;gBACH,CAAC;gBAED,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;gBACjC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;gBACjC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC,CAAC;QAEF,KAAK,MAAM,cAAc,IAAI,UAAU,EAAE,CAAC;YACxC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtC,KAAK,CAAC,cAAc,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAED,8BAA8B;AAC9B,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACpE,cAAc,qBAAqB,CAAC","sourcesContent":["// Middleware System for Moro\n/*\n All middleware in Moro should follow or adopt all of the following patterns:\n Core - Core.method(req, res, config) - Direct logic, no next, used by router directly\n Middleware - (req, res, next) => { ... next() } - For middleware chains, calls next\n Hooks - MiddlewareInterface with before/after hooks\n*/\n\nimport { EventEmitter } from 'events';\nimport { HookManager } from '../utilities/index.js';\nimport { MiddlewareInterface, SimpleMiddlewareFunction } from '../../types/hooks.js';\nimport { createFrameworkLogger } from '../logger/index.js';\n\n// Export types needed by built-in middleware\nexport type { MiddlewareInterface, MoroMiddleware } from '../../types/hooks.js';\n\nexport class MiddlewareManager extends EventEmitter {\n private middleware = new Map<string, MiddlewareInterface>();\n private simpleMiddleware = new Map<string, SimpleMiddlewareFunction>();\n private hooks: HookManager;\n private logger = createFrameworkLogger('Middleware');\n\n constructor() {\n super();\n this.hooks = new HookManager();\n }\n\n // Register middleware without installing\n register(name: string, middleware: MiddlewareInterface): void {\n if (this.middleware.has(name)) {\n throw new Error(`Middleware ${name} is already registered`);\n }\n\n this.middleware.set(name, middleware);\n this.logger.debug(`Registered middleware: ${name}`, 'Registration');\n this.emit('registered', { name, middleware });\n }\n\n // Install simple function-style middleware\n install(middleware: SimpleMiddlewareFunction | MiddlewareInterface, options: any = {}): void {\n if (typeof middleware === 'function') {\n // Simple function-style middleware\n const simpleName = middleware.name || 'anonymous';\n this.logger.debug(`Installing simple middleware: ${simpleName}`, 'Installation');\n\n this.simpleMiddleware.set(simpleName, middleware);\n this.emit('installed', { name: simpleName, type: 'simple' });\n this.logger.info(`Simple middleware installed: ${simpleName}`, 'Installation');\n return;\n }\n\n // Advanced middleware with dependencies and lifecycle\n const name = middleware.metadata?.name || 'unknown';\n\n if (this.middleware.has(name)) {\n throw new Error(`Middleware ${name} is already installed`);\n }\n\n // Check dependencies\n if (middleware.metadata?.dependencies) {\n for (const dep of middleware.metadata.dependencies) {\n if (!this.middleware.has(dep)) {\n throw new Error(`Dependency ${dep} not found for middleware ${name}`);\n }\n }\n }\n\n // Store middleware\n this.middleware.set(name, middleware);\n\n this.logger.debug(`Installing middleware: ${name}`, 'Installation');\n\n // Initialize middleware\n if (middleware.install) {\n void middleware.install(this.hooks, options);\n }\n\n this.emit('installed', { name, middleware, options });\n this.logger.info(`Middleware installed: ${name}`, 'Installation');\n }\n\n // Uninstall middleware and clean up\n uninstall(name: string): void {\n if (!this.middleware.has(name)) {\n throw new Error(`Middleware ${name} is not installed`);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const middleware = this.middleware.get(name)!;\n\n this.logger.debug(`Uninstalling middleware: ${name}`, 'Uninstallation');\n\n // Call cleanup if available\n if (middleware.uninstall) {\n void middleware.uninstall(this.hooks);\n }\n\n this.middleware.delete(name);\n this.emit('uninstalled', { name, middleware });\n this.logger.info(`Middleware uninstalled: ${name}`, 'Uninstallation');\n }\n\n // Get installed middleware\n getInstalled(): string[] {\n return Array.from(this.middleware.keys());\n }\n\n // Get middleware configuration\n getConfig(name: string): any {\n return this.middleware.get(name)?.metadata;\n }\n\n // The live hook manager that MiddlewareInterface.install() receives.\n // Exposed so the app can offer a public `app.hooks` accessor.\n getHookManager(): HookManager {\n return this.hooks;\n }\n\n // Check if middleware is installed\n isInstalled(name: string): boolean {\n return this.middleware.has(name);\n }\n\n // Get middleware by name (safe getter for module usage)\n get(name: string): MiddlewareInterface | SimpleMiddlewareFunction | undefined {\n // Check installed middleware first\n if (this.middleware.has(name)) {\n return this.middleware.get(name);\n }\n\n // Check simple middleware\n if (this.simpleMiddleware.has(name)) {\n return this.simpleMiddleware.get(name);\n }\n\n return undefined;\n }\n\n // List all registered middleware\n list(): MiddlewareInterface[] {\n return Array.from(this.middleware.values());\n }\n\n // Dependency resolution with topological sorting for optimal middleware loading\n async installWithDependencies(\n middleware: MiddlewareInterface[],\n options?: Record<string, any>\n ): Promise<void> {\n // Advanced topological sort for dependency resolution\n const resolved = this.topologicalSort(middleware);\n\n for (const middlewareItem of resolved) {\n const middlewareOptions = options?.[middlewareItem.name];\n await this.install(middlewareItem, middlewareOptions);\n }\n }\n\n // Optimized topological sort implementation for middleware dependencies\n private topologicalSort(middleware: MiddlewareInterface[]): MiddlewareInterface[] {\n const visited = new Set<string>();\n const temp = new Set<string>();\n const result: MiddlewareInterface[] = [];\n\n const visit = (middlewareItem: MiddlewareInterface) => {\n if (temp.has(middlewareItem.name)) {\n throw new Error(`Circular dependency detected: ${middlewareItem.name}`);\n }\n\n if (!visited.has(middlewareItem.name)) {\n temp.add(middlewareItem.name);\n\n // Visit dependencies first\n if (middlewareItem.dependencies) {\n for (const depName of middlewareItem.dependencies) {\n const dependency = middleware.find(m => m.name === depName);\n if (dependency) {\n visit(dependency);\n }\n }\n }\n\n temp.delete(middlewareItem.name);\n visited.add(middlewareItem.name);\n result.push(middlewareItem);\n }\n };\n\n for (const middlewareItem of middleware) {\n if (!visited.has(middlewareItem.name)) {\n visit(middlewareItem);\n }\n }\n\n return result;\n }\n}\n\n// Built-in middleware exports\nexport { middleware, builtInMiddleware } from './built-in/index.js';\nexport * from './built-in/index.js';\n"]}
@@ -60,7 +60,9 @@ export declare class UnifiedRouter {
60
60
  private stats;
61
61
  constructor();
62
62
  private errorHandler?;
63
+ private hookManager?;
63
64
  setErrorHandler(fn: (err: any, req: HttpRequest, res: HttpResponse) => any | Promise<any>): void;
65
+ setHookManager(hookManager: any): void;
64
66
  private invokeErrorHandler;
65
67
  /**
66
68
  * Get singleton instance (optional - can still create new instances)
@@ -40,6 +40,11 @@ export class RouteBuilder {
40
40
  this.schema.validation.params = config.params;
41
41
  if (config.headers !== undefined)
42
42
  this.schema.validation.headers = config.headers;
43
+ // Without this, `.body(schema).validate({ onValidationError })` silently
44
+ // dropped the handler and fell back to the default 400 response.
45
+ if (config.onValidationError !== undefined) {
46
+ this.schema.validation.onValidationError = config.onValidationError;
47
+ }
43
48
  }
44
49
  return this;
45
50
  }
@@ -183,11 +188,26 @@ export class UnifiedRouter {
183
188
  }
184
189
  // User-registered global error handler (set via Moro.setErrorHandler)
185
190
  errorHandler;
191
+ // Lifecycle hook manager (set via Moro) so 'error' hooks observe handler
192
+ // errors — the router swallows them here, so the server-level error
193
+ // boundary never sees them.
194
+ hookManager;
186
195
  setErrorHandler(fn) {
187
196
  this.errorHandler = fn;
188
197
  }
198
+ setHookManager(hookManager) {
199
+ this.hookManager = hookManager;
200
+ }
189
201
  // Invoke the registered error handler (if any). Returns true if it produced a response.
190
202
  async invokeErrorHandler(err, req, res) {
203
+ // Error hooks are observational: fire-and-forget so a slow or throwing
204
+ // observer can never delay or alter the error response.
205
+ if (this.hookManager &&
206
+ (this.hookManager.hasHooks === undefined || this.hookManager.hasHooks('error'))) {
207
+ void Promise.resolve(this.hookManager.execute('error', { request: req, response: res, error: err })).catch((hookError) => logger.error('Error hook error', 'Hooks', {
208
+ error: hookError instanceof Error ? hookError.message : String(hookError),
209
+ }));
210
+ }
191
211
  if (!this.errorHandler || res.headersSent)
192
212
  return false;
193
213
  try {