@riktajs/core 0.10.1 → 0.10.3

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 (111) hide show
  1. package/dist/index.cjs +3591 -0
  2. package/dist/index.cjs.map +1 -0
  3. package/dist/index.d.cts +770 -0
  4. package/dist/index.d.ts +770 -2
  5. package/dist/index.js +3415 -2
  6. package/dist/index.js.map +1 -0
  7. package/package.json +63 -56
  8. package/dist/core/application.d.ts +0 -6
  9. package/dist/core/application.js +0 -248
  10. package/dist/core/config/abstract-config-provider.d.ts +0 -14
  11. package/dist/core/config/abstract-config-provider.js +0 -53
  12. package/dist/core/config/env-loader.d.ts +0 -3
  13. package/dist/core/config/env-loader.js +0 -26
  14. package/dist/core/config/index.d.ts +0 -2
  15. package/dist/core/config/index.js +0 -2
  16. package/dist/core/constants.d.ts +0 -30
  17. package/dist/core/constants.js +0 -31
  18. package/dist/core/container/abstract-class.utils.d.ts +0 -10
  19. package/dist/core/container/abstract-class.utils.js +0 -44
  20. package/dist/core/container/container.d.ts +0 -32
  21. package/dist/core/container/container.js +0 -292
  22. package/dist/core/container/implements.decorator.d.ts +0 -6
  23. package/dist/core/container/implements.decorator.js +0 -39
  24. package/dist/core/container/index.d.ts +0 -5
  25. package/dist/core/container/index.js +0 -5
  26. package/dist/core/container/injection-token.d.ts +0 -29
  27. package/dist/core/container/injection-token.js +0 -11
  28. package/dist/core/container/request-scope.d.ts +0 -16
  29. package/dist/core/container/request-scope.js +0 -49
  30. package/dist/core/decorators/apply-decorators.d.ts +0 -8
  31. package/dist/core/decorators/apply-decorators.js +0 -36
  32. package/dist/core/decorators/autowired.decorator.d.ts +0 -11
  33. package/dist/core/decorators/autowired.decorator.js +0 -78
  34. package/dist/core/decorators/config-property.decorator.d.ts +0 -9
  35. package/dist/core/decorators/config-property.decorator.js +0 -59
  36. package/dist/core/decorators/controller.decorator.d.ts +0 -5
  37. package/dist/core/decorators/controller.decorator.js +0 -18
  38. package/dist/core/decorators/create-param-decorator.d.ts +0 -11
  39. package/dist/core/decorators/create-param-decorator.js +0 -21
  40. package/dist/core/decorators/index.d.ts +0 -9
  41. package/dist/core/decorators/index.js +0 -9
  42. package/dist/core/decorators/injectable.decorator.d.ts +0 -3
  43. package/dist/core/decorators/injectable.decorator.js +0 -11
  44. package/dist/core/decorators/param.decorator.d.ts +0 -59
  45. package/dist/core/decorators/param.decorator.js +0 -38
  46. package/dist/core/decorators/provider.decorator.d.ts +0 -12
  47. package/dist/core/decorators/provider.decorator.js +0 -56
  48. package/dist/core/decorators/route.decorator.d.ts +0 -9
  49. package/dist/core/decorators/route.decorator.js +0 -30
  50. package/dist/core/discovery.d.ts +0 -3
  51. package/dist/core/discovery.js +0 -111
  52. package/dist/core/exceptions/catch.decorator.d.ts +0 -8
  53. package/dist/core/exceptions/catch.decorator.js +0 -13
  54. package/dist/core/exceptions/config.exceptions.d.ts +0 -9
  55. package/dist/core/exceptions/config.exceptions.js +0 -34
  56. package/dist/core/exceptions/discovery.exception.d.ts +0 -18
  57. package/dist/core/exceptions/discovery.exception.js +0 -39
  58. package/dist/core/exceptions/exception-filter.d.ts +0 -38
  59. package/dist/core/exceptions/exception-filter.js +0 -103
  60. package/dist/core/exceptions/exceptions.d.ts +0 -55
  61. package/dist/core/exceptions/exceptions.js +0 -91
  62. package/dist/core/exceptions/http-exception.d.ts +0 -24
  63. package/dist/core/exceptions/http-exception.js +0 -62
  64. package/dist/core/exceptions/index.d.ts +0 -7
  65. package/dist/core/exceptions/index.js +0 -7
  66. package/dist/core/exceptions/validation.exception.d.ts +0 -17
  67. package/dist/core/exceptions/validation.exception.js +0 -33
  68. package/dist/core/guards/can-activate.interface.d.ts +0 -4
  69. package/dist/core/guards/can-activate.interface.js +0 -1
  70. package/dist/core/guards/execution-context.d.ts +0 -28
  71. package/dist/core/guards/execution-context.js +0 -35
  72. package/dist/core/guards/index.d.ts +0 -3
  73. package/dist/core/guards/index.js +0 -2
  74. package/dist/core/guards/use-guards.decorator.d.ts +0 -6
  75. package/dist/core/guards/use-guards.decorator.js +0 -22
  76. package/dist/core/index.d.ts +0 -19
  77. package/dist/core/index.js +0 -17
  78. package/dist/core/interceptors/index.d.ts +0 -2
  79. package/dist/core/interceptors/index.js +0 -1
  80. package/dist/core/interceptors/interceptor.interface.d.ts +0 -7
  81. package/dist/core/interceptors/interceptor.interface.js +0 -1
  82. package/dist/core/interceptors/use-interceptors.decorator.d.ts +0 -6
  83. package/dist/core/interceptors/use-interceptors.decorator.js +0 -19
  84. package/dist/core/lifecycle/event-bus.d.ts +0 -57
  85. package/dist/core/lifecycle/event-bus.js +0 -108
  86. package/dist/core/lifecycle/index.d.ts +0 -3
  87. package/dist/core/lifecycle/index.js +0 -3
  88. package/dist/core/lifecycle/interfaces.d.ts +0 -15
  89. package/dist/core/lifecycle/interfaces.js +0 -1
  90. package/dist/core/lifecycle/on.decorator.d.ts +0 -11
  91. package/dist/core/lifecycle/on.decorator.js +0 -13
  92. package/dist/core/metadata.d.ts +0 -20
  93. package/dist/core/metadata.js +0 -64
  94. package/dist/core/middleware/index.d.ts +0 -3
  95. package/dist/core/middleware/index.js +0 -2
  96. package/dist/core/middleware/middleware.decorator.d.ts +0 -2
  97. package/dist/core/middleware/middleware.decorator.js +0 -7
  98. package/dist/core/middleware/rikta-middleware.interface.d.ts +0 -5
  99. package/dist/core/middleware/rikta-middleware.interface.js +0 -1
  100. package/dist/core/middleware/use-middleware.decorator.d.ts +0 -6
  101. package/dist/core/middleware/use-middleware.decorator.js +0 -22
  102. package/dist/core/profiler/index.d.ts +0 -2
  103. package/dist/core/profiler/index.js +0 -1
  104. package/dist/core/profiler/performance-profiler.d.ts +0 -42
  105. package/dist/core/profiler/performance-profiler.js +0 -95
  106. package/dist/core/registry.d.ts +0 -41
  107. package/dist/core/registry.js +0 -109
  108. package/dist/core/router/router.d.ts +0 -32
  109. package/dist/core/router/router.js +0 -300
  110. package/dist/core/types.d.ts +0 -62
  111. package/dist/core/types.js +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/core/constants.ts","../src/core/container/container.ts","../src/core/container/injection-token.ts","../src/core/exceptions/config.exceptions.ts","../src/core/registry.ts","../src/core/container/abstract-class.utils.ts","../src/core/container/request-scope.ts","../src/core/container/implements.decorator.ts","../src/core/discovery.ts","../src/core/exceptions/discovery.exception.ts","../src/core/decorators/injectable.decorator.ts","../src/core/lifecycle/event-bus.ts","../src/core/lifecycle/on.decorator.ts","../src/core/router/router.ts","../src/core/decorators/create-param-decorator.ts","../src/core/exceptions/http-exception.ts","../src/core/exceptions/validation.exception.ts","../src/core/exceptions/exceptions.ts","../src/core/guards/execution-context.ts","../src/core/guards/use-guards.decorator.ts","../src/core/middleware/use-middleware.decorator.ts","../src/core/interceptors/use-interceptors.decorator.ts","../src/core/application.ts","../src/core/exceptions/exception-filter.ts","../src/core/exceptions/catch.decorator.ts","../src/core/config/env-loader.ts","../src/core/decorators/controller.decorator.ts","../src/core/decorators/route.decorator.ts","../src/core/decorators/param.decorator.ts","../src/core/decorators/autowired.decorator.ts","../src/core/decorators/provider.decorator.ts","../src/core/decorators/config-property.decorator.ts","../src/core/decorators/apply-decorators.ts","../src/core/middleware/middleware.decorator.ts","../src/core/config/abstract-config-provider.ts","../src/core/metadata.ts","../src/core/profiler/performance-profiler.ts","../src/core/index.ts"],"sourcesContent":["/**\r\n * Rikta Framework\r\n * \r\n * A modern TypeScript backend framework with zero-config autowiring, powered by Fastify.\r\n * \r\n * Features:\r\n * - Decorator-based routing (@Controller, @Get, @Post, etc.)\r\n * - Full Autowiring - No modules needed, everything is auto-discovered\r\n * - Single DI decorator - @Autowired() for constructor and property injection\r\n * - Hybrid Lifecycle - Interface hooks + EventBus\r\n * - Exception Handling - Built-in filters with standardized JSON responses\r\n * - Fastify under the hood for maximum performance\r\n * - Full TypeScript support\r\n * \r\n * @example\r\n * ```typescript\r\n * import { Rikta, Controller, Get, Injectable, Autowired } from '@rikta/core';\r\n * \r\n * @Injectable()\r\n * class GreetingService {\r\n * getGreeting(): string {\r\n * return 'Hello from Rikta!';\r\n * }\r\n * }\r\n * \r\n * @Controller()\r\n * class AppController {\r\n * @Autowired()\r\n * private greetingService!: GreetingService;\r\n * \r\n * @Get('/')\r\n * getHello() {\r\n * return this.greetingService.getGreeting();\r\n * }\r\n * }\r\n * \r\n * // No modules - just create and run!\r\n * const app = await Rikta.create({ port: 3000 });\r\n * await app.listen();\r\n * ```\r\n */\r\n\r\n// Re-export everything from core\r\nexport * from './core/index.js';\r\n\r\n// Default export for convenience\r\nexport { RiktaFactory as default } from './core/application.js';\r\n\r\n","/** Metadata keys for Reflect API. Using Symbol.for() for cross-package sharing. */\r\n\r\nexport const CONTROLLER_METADATA = Symbol.for('rikta:controller:metadata');\r\nexport const ROUTES_METADATA = Symbol.for('rikta:routes:metadata');\r\nexport const INJECTABLE_METADATA = Symbol.for('rikta:injectable:metadata');\r\nexport const PARAM_METADATA = Symbol.for('rikta:param:metadata');\r\nexport const GUARDS_METADATA = Symbol.for('rikta:guards:metadata');\r\nexport const INTERCEPTORS_METADATA = Symbol.for('rikta:interceptors:metadata');\r\nexport const MIDDLEWARE_METADATA = Symbol.for('rikta:middleware:metadata');\r\nexport const HTTP_CODE_METADATA = Symbol.for('rikta:http:code:metadata');\r\nexport const HEADERS_METADATA = Symbol.for('rikta:headers:metadata');\r\nexport const INJECT_METADATA = Symbol.for('rikta:inject:metadata');\r\nexport const ZOD_SCHEMA_METADATA = Symbol.for('rikta:zod:schema:metadata');\r\nexport const AUTOWIRED_METADATA = Symbol.for('rikta:autowired:metadata');\r\nexport const PROVIDER_METADATA = Symbol.for('rikta:provider:metadata');\r\n\r\n/** Stores @Provider() token for config provider auto-discovery. */\r\nexport const CONFIG_PROVIDER_METADATA = Symbol('config:provider:metadata');\r\n\r\n/** Maps @ConfigProperty() properties to env var names (explicit or auto upper_snake_case). */\r\nexport const CONFIG_PROPERTY_METADATA = Symbol('config:property:metadata');\r\n\r\nexport enum ParamType {\r\n BODY = 'body',\r\n QUERY = 'query',\r\n PARAM = 'param',\r\n HEADERS = 'headers',\r\n REQUEST = 'request',\r\n REPLY = 'reply',\r\n CONTEXT = 'context',\r\n}\r\n\r\nexport const DEFAULT_CONFIG = {\r\n port: 3000,\r\n host: '0.0.0.0',\r\n logger: true,\r\n prefix: '',\r\n} as const;\r\n","import 'reflect-metadata';\r\nimport { Constructor, ProviderScope, InjectableOptions } from '../types.js';\r\nimport { INJECT_METADATA, AUTOWIRED_METADATA } from '../constants.js';\r\nimport { Token, InjectionToken, ProviderDefinition, ValueProvider, FactoryProvider, ClassProvider, ExistingProvider } from './injection-token.js';\r\nimport { AutowiredMetadata } from '../decorators/autowired.decorator.js';\r\nimport { registry } from '../registry.js';\r\nimport { isAbstractClass } from './abstract-class.utils.js';\r\nimport { requestScopeStorage } from './request-scope.js';\r\n\r\n/**\r\n * Dependency Injection Container\r\n * \r\n * Manages the lifecycle of injectable services with support for:\r\n * - Singleton scope (default): One instance shared across the app\r\n * - Transient scope: New instance on each injection\r\n * - Request scope: New instance per HTTP request (via AsyncLocalStorage)\r\n * - Property injection (autowire)\r\n * - Token-based injection\r\n * - Value and factory providers\r\n * - Abstract class-based injection (strategy pattern)\r\n */\r\nexport class Container {\r\n private static instance: Container;\r\n \r\n /** Stores singleton instances by token */\r\n private singletons = new Map<Token, unknown>();\r\n \r\n /** Stores provider registrations */\r\n private providers = new Map<Token, { \r\n scope: ProviderScope;\r\n provider?: ProviderDefinition;\r\n }>();\r\n \r\n /** Resolution stack for circular dependency detection */\r\n private resolutionStack = new Set<Token>();\r\n\r\n private constructor() {}\r\n\r\n /**\r\n * Get the global container instance\r\n */\r\n static getInstance(): Container {\r\n if (!Container.instance) {\r\n Container.instance = new Container();\r\n }\r\n return Container.instance;\r\n }\r\n\r\n /**\r\n * Reset the container (useful for testing)\r\n */\r\n static reset(): void {\r\n Container.instance = new Container();\r\n }\r\n\r\n /**\r\n * Register a class provider in the container\r\n */\r\n register<T>(target: Constructor<T>, options: InjectableOptions = {}): void {\r\n const scope = options.scope ?? 'singleton';\r\n this.providers.set(target, { scope });\r\n }\r\n\r\n /**\r\n * Register a custom provider (value, factory, class, or existing)\r\n */\r\n registerProvider<T>(provider: ProviderDefinition<T>): void {\r\n if (typeof provider === 'function') {\r\n // Simple class provider\r\n this.register(provider);\r\n return;\r\n }\r\n\r\n const token = provider.provide;\r\n\r\n if ('useValue' in provider) {\r\n // Value provider - always singleton\r\n this.providers.set(token, { scope: 'singleton', provider });\r\n this.singletons.set(token, provider.useValue);\r\n } else if ('useFactory' in provider) {\r\n // Factory provider\r\n this.providers.set(token, { scope: 'singleton', provider });\r\n } else if ('useClass' in provider) {\r\n // Class provider\r\n this.providers.set(token, { scope: 'singleton', provider });\r\n } else if ('useExisting' in provider) {\r\n // Alias provider\r\n this.providers.set(token, { scope: 'singleton', provider });\r\n }\r\n }\r\n\r\n /**\r\n * Register a value directly\r\n */\r\n registerValue<T>(token: Token<T>, value: T): void {\r\n this.registerProvider({ provide: token, useValue: value });\r\n }\r\n\r\n /**\r\n * Register a factory function\r\n */\r\n registerFactory<T>(token: Token<T>, factory: () => T, inject?: Token[]): void {\r\n this.registerProvider({ provide: token, useFactory: factory, inject });\r\n }\r\n\r\n /**\r\n * Check if a provider is registered\r\n */\r\n has(token: Token): boolean {\r\n return this.providers.has(token);\r\n }\r\n\r\n /**\r\n * Resolve a dependency by token\r\n */\r\n resolve<T>(token: Token<T>): T {\r\n return this.resolveToken(token, false) as T;\r\n }\r\n\r\n /**\r\n * Resolve a dependency, returning undefined if not found (for optional deps)\r\n */\r\n resolveOptional<T>(token: Token<T>): T | undefined {\r\n return this.resolveToken(token, true) as T | undefined;\r\n }\r\n\r\n /**\r\n * Internal resolution logic\r\n */\r\n private resolveToken(token: Token, optional: boolean): unknown {\r\n // Check for circular dependencies\r\n if (this.resolutionStack.has(token)) {\r\n const chain = [...this.resolutionStack]\r\n .map(t => this.getTokenName(t))\r\n .join(' -> ');\r\n throw new Error(`Circular dependency detected: ${chain} -> ${this.getTokenName(token)}`);\r\n }\r\n\r\n // Check if we have a singleton cached\r\n if (this.singletons.has(token)) {\r\n return this.singletons.get(token);\r\n }\r\n\r\n // Get provider configuration\r\n const config = this.providers.get(token);\r\n \r\n if (!config) {\r\n // Token not registered - check if it's an abstract class with implementations\r\n if (typeof token === 'function') {\r\n const implementation = this.resolveAbstractClass(token as Constructor);\r\n if (implementation) {\r\n const instance = this.resolveClass(implementation);\r\n // Cache under the abstract class token\r\n this.singletons.set(token, instance);\r\n return instance;\r\n }\r\n \r\n // Not abstract, try to resolve as regular class (auto-registration)\r\n if (!isAbstractClass(token as Constructor)) {\r\n return this.resolveClass(token as Constructor);\r\n }\r\n }\r\n \r\n if (optional) {\r\n return undefined;\r\n }\r\n \r\n throw new Error(`No provider found for token: ${this.getTokenName(token)}`);\r\n }\r\n\r\n // If there's a custom provider, use it\r\n if (config.provider && typeof config.provider !== 'function') {\r\n return this.resolveProvider(config.provider, config.scope);\r\n }\r\n\r\n // Otherwise resolve as a class\r\n if (typeof token === 'function') {\r\n return this.resolveClass(token as Constructor);\r\n }\r\n\r\n throw new Error(`Cannot resolve token: ${this.getTokenName(token)}`);\r\n }\r\n\r\n /**\r\n * Try to resolve an abstract class to its concrete implementation.\r\n * \r\n * This method contains all the resolution logic for abstract classes:\r\n * 1. Check for direct provider registration (useClass)\r\n * 2. If name specified, find the named implementation\r\n * 3. If only one implementation exists, use it\r\n * 4. If multiple implementations, use the one marked @Primary\r\n * 5. If multiple without @Primary, throw an error\r\n * \r\n * @param abstractClass - The abstract class to resolve\r\n * @param name - Optional name for named implementation resolution\r\n * @returns The concrete implementation class, or undefined if not found\r\n */\r\n private resolveAbstractClass(abstractClass: Constructor, name?: string): Constructor | undefined {\r\n // First check if we have a direct provider registration\r\n const config = this.providers.get(abstractClass);\r\n if (config?.provider && 'useClass' in config.provider) {\r\n return (config.provider as ClassProvider).useClass;\r\n }\r\n\r\n // Get implementations from Registry (which only stores metadata)\r\n const implementations = registry.getImplementations(abstractClass);\r\n \r\n if (!implementations || implementations.length === 0) {\r\n return undefined;\r\n }\r\n\r\n // If a name is specified, look for that specific implementation\r\n if (name) {\r\n const named = implementations.find(i => i.name === name);\r\n if (named) {\r\n return named.implementation;\r\n }\r\n throw new Error(\r\n `No implementation named '${name}' found for abstract class ${abstractClass.name}. ` +\r\n `Available names: ${implementations.filter(i => i.name).map(i => i.name).join(', ') || 'none'}`\r\n );\r\n }\r\n\r\n // If only one implementation, return it\r\n if (implementations.length === 1) {\r\n return implementations[0].implementation;\r\n }\r\n\r\n // Look for primary implementation\r\n const primary = implementations.find(i => i.isPrimary);\r\n if (primary) {\r\n return primary.implementation;\r\n }\r\n\r\n // Multiple implementations without primary - error\r\n const implNames = implementations.map(i => i.implementation.name).join(', ');\r\n throw new Error(\r\n `Multiple implementations found for abstract class ${abstractClass.name}: ${implNames}. ` +\r\n `Use @Primary() to mark one as the default, or @Named() for qualified injection.`\r\n );\r\n }\r\n\r\n /**\r\n * Resolve a custom provider\r\n */\r\n private resolveProvider(provider: ProviderDefinition, scope: ProviderScope): unknown {\r\n if (typeof provider === 'function') {\r\n return this.resolveClass(provider);\r\n }\r\n\r\n const token = provider.provide;\r\n\r\n if ('useValue' in provider) {\r\n return (provider as ValueProvider).useValue;\r\n }\r\n\r\n if ('useFactory' in provider) {\r\n const factoryProvider = provider as FactoryProvider;\r\n \r\n // Resolve factory dependencies\r\n const deps = (factoryProvider.inject ?? []).map(dep => this.resolve(dep));\r\n const result = factoryProvider.useFactory(...deps);\r\n \r\n // Cache singleton\r\n if (scope === 'singleton') {\r\n this.singletons.set(token, result);\r\n }\r\n \r\n return result;\r\n }\r\n\r\n if ('useClass' in provider) {\r\n const classProvider = provider as ClassProvider;\r\n const instance = this.resolveClass(classProvider.useClass);\r\n \r\n // Cache under the token (not the class)\r\n if (scope === 'singleton') {\r\n this.singletons.set(token, instance);\r\n }\r\n \r\n return instance;\r\n }\r\n\r\n if ('useExisting' in provider) {\r\n return this.resolve((provider as ExistingProvider).useExisting);\r\n }\r\n\r\n throw new Error('Invalid provider configuration');\r\n }\r\n\r\n /**\r\n * Resolve a class and all its dependencies\r\n */\r\n private resolveClass<T>(target: Constructor<T>): T {\r\n // Check for circular dependencies\r\n if (this.resolutionStack.has(target)) {\r\n const chain = [...this.resolutionStack, target]\r\n .map(t => this.getTokenName(t))\r\n .join(' -> ');\r\n throw new Error(`Circular dependency detected: ${chain}`);\r\n }\r\n\r\n // Get provider configuration\r\n const providerConfig = this.providers.get(target);\r\n const scope = providerConfig?.scope ?? 'singleton';\r\n\r\n // Return singleton if exists\r\n if (scope === 'singleton' && this.singletons.has(target)) {\r\n return this.singletons.get(target) as T;\r\n }\r\n\r\n // Handle request scope\r\n if (scope === 'request') {\r\n // Check if we're in a request context\r\n if (!requestScopeStorage.isInRequestScope()) {\r\n throw new Error(\r\n `Cannot resolve request-scoped provider '${target.name}' outside of a request context. ` +\r\n `Request-scoped providers can only be resolved during HTTP request handling.`\r\n );\r\n }\r\n \r\n // Check if instance already exists in current request\r\n const existingInstance = requestScopeStorage.get(target);\r\n if (existingInstance !== undefined) {\r\n return existingInstance as T;\r\n }\r\n }\r\n\r\n // Add to resolution stack\r\n this.resolutionStack.add(target);\r\n\r\n try {\r\n // Get @Autowired() metadata for constructor parameters\r\n const injectMeta: AutowiredMetadata[] = \r\n Reflect.getMetadata(INJECT_METADATA, target) ?? [];\r\n \r\n // Get constructor parameter types via reflect-metadata\r\n const paramTypes: Constructor[] = \r\n Reflect.getMetadata('design:paramtypes', target) ?? [];\r\n\r\n // Determine the number of parameters to resolve\r\n // Use the maximum of paramTypes length and highest index in injectMeta\r\n const maxIndex = injectMeta.length > 0 \r\n ? Math.max(...injectMeta.map(m => m.index ?? -1))\r\n : -1;\r\n const paramCount = Math.max(paramTypes.length, maxIndex + 1);\r\n\r\n // Resolve all constructor dependencies\r\n const dependencies: unknown[] = [];\r\n for (let index = 0; index < paramCount; index++) {\r\n const paramType = paramTypes[index];\r\n const injectOverride = injectMeta.find(m => m.index === index);\r\n const token = injectOverride?.token ?? paramType;\r\n const isOptional = injectOverride?.optional ?? false;\r\n const name = injectOverride?.name;\r\n \r\n // If we have no token and no paramType, skip or error\r\n if (!token) {\r\n if (isOptional) {\r\n dependencies.push(undefined);\r\n continue;\r\n }\r\n throw new Error(\r\n `Cannot resolve constructor parameter ${index} of ${target.name}. ` +\r\n `Use @Autowired(token) decorator.`\r\n );\r\n }\r\n \r\n // Handle primitive types without override\r\n if (!injectOverride && this.isPrimitive(paramType)) {\r\n if (isOptional) {\r\n dependencies.push(undefined);\r\n continue;\r\n }\r\n throw new Error(\r\n `Cannot inject primitive type '${paramType?.name ?? 'unknown'}' into ${target.name}. ` +\r\n `Use @Autowired(token) decorator.`\r\n );\r\n }\r\n \r\n dependencies.push(\r\n isOptional \r\n ? this.resolveWithNameOptional(token, name)\r\n : this.resolveWithName(token, name)\r\n );\r\n }\r\n\r\n // Create instance with resolved dependencies\r\n const instance = new target(...dependencies);\r\n\r\n // Handle property injection (autowire)\r\n this.injectProperties(target, instance);\r\n\r\n // Store based on scope\r\n if (scope === 'singleton') {\r\n this.singletons.set(target, instance);\r\n } else if (scope === 'request') {\r\n // Store in request-scoped storage\r\n requestScopeStorage.set(target, instance);\r\n }\r\n // transient scope: no caching, new instance every time\r\n\r\n return instance;\r\n } finally {\r\n // Remove from resolution stack\r\n this.resolutionStack.delete(target);\r\n }\r\n }\r\n\r\n /**\r\n * Inject properties marked with @Autowired()\r\n */\r\n private injectProperties(target: Constructor, instance: unknown): void {\r\n const autowireMeta: AutowiredMetadata[] = \r\n Reflect.getMetadata(AUTOWIRED_METADATA, target) ?? [];\r\n \r\n for (const meta of autowireMeta) {\r\n if (!meta.propertyKey) continue;\r\n \r\n const isOptional = meta.optional ?? false;\r\n \r\n try {\r\n const value = isOptional \r\n ? this.resolveWithNameOptional(meta.token, meta.name)\r\n : this.resolveWithName(meta.token, meta.name);\r\n \r\n (instance as Record<string, unknown>)[meta.propertyKey] = value;\r\n } catch (error) {\r\n if (!isOptional) {\r\n throw error;\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Resolve a dependency with optional name for qualified injection\r\n */\r\n private resolveWithName<T>(token: Token<T>, name?: string): T {\r\n // If we have a name and the token is a class (potential abstract class)\r\n if (name && typeof token === 'function') {\r\n const implementation = this.resolveAbstractClass(token as Constructor, name);\r\n if (implementation) {\r\n return this.resolveClass(implementation) as T;\r\n }\r\n throw new Error(`No implementation named '${name}' found for ${this.getTokenName(token)}`);\r\n }\r\n \r\n return this.resolve(token);\r\n }\r\n\r\n /**\r\n * Resolve a dependency with optional name, returning undefined if not found\r\n */\r\n private resolveWithNameOptional<T>(token: Token<T>, name?: string): T | undefined {\r\n try {\r\n return this.resolveWithName(token, name);\r\n } catch {\r\n return undefined;\r\n }\r\n }\r\n\r\n /**\r\n * Register an existing instance as a singleton\r\n */\r\n registerInstance<T>(target: Constructor<T>, instance: T): void {\r\n this.providers.set(target, { scope: 'singleton' });\r\n this.singletons.set(target, instance);\r\n }\r\n\r\n /**\r\n * Get all registered providers\r\n */\r\n getProviders(): Token[] {\r\n return [...this.providers.keys()];\r\n }\r\n\r\n /**\r\n * Clear all singletons (useful for testing)\r\n */\r\n clearSingletons(): void {\r\n this.singletons.clear();\r\n }\r\n\r\n /**\r\n * Check if a type is a primitive (not injectable)\r\n */\r\n private isPrimitive(type: Constructor): boolean {\r\n if (!type) return true;\r\n const primitives: unknown[] = [String, Number, Boolean, Object, Array, Function];\r\n return primitives.includes(type);\r\n }\r\n\r\n /**\r\n * Get a human-readable name for a token\r\n */\r\n private getTokenName(token: Token): string {\r\n if (typeof token === 'function') {\r\n return token.name;\r\n }\r\n if (token instanceof InjectionToken) {\r\n return token.toString();\r\n }\r\n if (typeof token === 'symbol') {\r\n return token.toString();\r\n }\r\n return String(token);\r\n }\r\n}\r\n\r\n/**\r\n * Global container instance export for convenience\r\n */\r\nexport const container = Container.getInstance();\r\n","/**\r\n * Injection Token\r\n * \r\n * Used to identify dependencies that are not classes (interfaces, values, etc.)\r\n * Similar to NestJS InjectionToken and Angular's InjectionToken.\r\n * \r\n * @example\r\n * ```typescript\r\n * // Define a token for a configuration object\r\n * const CONFIG_TOKEN = new InjectionToken<AppConfig>('app.config');\r\n * \r\n * // Register with the container\r\n * container.registerValue(CONFIG_TOKEN, { apiUrl: 'https://api.example.com' });\r\n * \r\n * // Inject using the token\r\n * @Injectable()\r\n * class ApiService {\r\n * constructor(@Autowired(CONFIG_TOKEN) private config: AppConfig) {}\r\n * }\r\n * ```\r\n */\r\nexport class InjectionToken<T = unknown> {\r\n constructor(\r\n public readonly description: string,\r\n public readonly options?: {\r\n factory?: () => T;\r\n }\r\n ) {}\r\n\r\n toString(): string {\r\n return `InjectionToken(${this.description})`;\r\n }\r\n}\r\n\r\n/**\r\n * Type for any valid injection token\r\n * Can be a class constructor, InjectionToken, string, or symbol\r\n */\r\nexport type Token<T = unknown> = \r\n | (new (...args: unknown[]) => T)\r\n | InjectionToken<T>\r\n | string\r\n | symbol;\r\n\r\n/**\r\n * Provider definition for custom providers\r\n */\r\nexport interface ClassProvider<T = unknown> {\r\n provide: Token<T>;\r\n useClass: new (...args: unknown[]) => T;\r\n}\r\n\r\nexport interface ValueProvider<T = unknown> {\r\n provide: Token<T>;\r\n useValue: T;\r\n}\r\n\r\nexport interface FactoryProvider<T = unknown> {\r\n provide: Token<T>;\r\n useFactory: (...args: unknown[]) => T | Promise<T>;\r\n inject?: Token[];\r\n}\r\n\r\nexport interface ExistingProvider<T = unknown> {\r\n provide: Token<T>;\r\n useExisting: Token<T>;\r\n}\r\n\r\nexport type ProviderDefinition<T = unknown> = \r\n | ClassProvider<T> \r\n | ValueProvider<T> \r\n | FactoryProvider<T> \r\n | ExistingProvider<T>\r\n | (new (...args: unknown[]) => T); // Simple class provider\r\n\r\n","/**\r\n * Exception thrown when attempting to register a config provider with a token\r\n * that is already registered.\r\n */\r\nexport class ConfigProviderAlreadyRegisteredException extends Error {\r\n constructor(token: string, existingClass: string, newClass: string) {\r\n super(\r\n `Config provider with token \"${token}\" is already registered.\\n` +\r\n `Existing: ${existingClass}\\n` +\r\n `Attempted: ${newClass}\\n` +\r\n `Use a different token or remove the duplicate registration.`\r\n );\r\n this.name = 'ConfigProviderAlreadyRegisteredException';\r\n }\r\n}\r\n\r\n/**\r\n * Exception thrown when attempting to retrieve a config provider that\r\n * has not been registered.\r\n */\r\nexport class ConfigProviderNotFoundException extends Error {\r\n constructor(token: string, availableTokens: string[] = []) {\r\n const suggestion = availableTokens.length > 0\r\n ? `\\n\\nAvailable tokens: ${availableTokens.join(', ')}`\r\n : '';\r\n \r\n super(\r\n `Config provider with token \"${token}\" not found.${suggestion}\\n` +\r\n `Make sure the provider class is:\\n` +\r\n `1. Decorated with @Provider('${token}')\\n` +\r\n `2. Located in a file matching the autowired patterns\\n` +\r\n `3. Properly exported from its module`\r\n );\r\n this.name = 'ConfigProviderNotFoundException';\r\n }\r\n}\r\n\r\n/**\r\n * Exception thrown when a config provider fails to instantiate.\r\n */\r\nexport class ConfigProviderInstantiationException extends Error {\r\n constructor(token: string, className: string, cause: Error) {\r\n super(\r\n `Failed to instantiate config provider \"${className}\" (token: \"${token}\").\\n` +\r\n `Cause: ${cause.message}\\n\\n` +\r\n `Check that the provider:\\n` +\r\n `1. Has a valid constructor\\n` +\r\n `2. All constructor dependencies are registered\\n` +\r\n `3. The provide() method is correctly implemented`\r\n );\r\n this.name = 'ConfigProviderInstantiationException';\r\n this.cause = cause;\r\n }\r\n}\r\n","import { Constructor } from './types.js';\r\nimport { \r\n ConfigProviderAlreadyRegisteredException,\r\n} from './exceptions/config.exceptions.js';\r\n\r\n/**\r\n * Config provider registration info\r\n */\r\ninterface ConfigProviderRegistration {\r\n token: string;\r\n providerClass: Constructor;\r\n}\r\n\r\n/**\r\n * Abstract class implementation info\r\n */\r\ninterface AbstractImplementation {\r\n implementation: Constructor;\r\n isPrimary: boolean;\r\n name?: string;\r\n}\r\n\r\n/**\r\n * Global Registry\r\n * \r\n * Stores references to all decorated classes for auto-discovery.\r\n * Controllers and providers register themselves here via decorators.\r\n * \r\n * The registry acts as a collection point during the decoration phase.\r\n * Once the application initializes, the registered classes are processed\r\n * and transferred to the DI container for resolution.\r\n */\r\nclass Registry {\r\n private static instance: Registry;\r\n \r\n /** All registered controllers */\r\n private controllers = new Set<Constructor>();\r\n \r\n /** All registered providers (services via @Injectable) */\r\n private providers = new Set<Constructor>();\r\n \r\n /** All registered custom providers (via @Provider) */\r\n private customProviders = new Set<Constructor>();\r\n\r\n /** Map of config provider tokens to their class constructors */\r\n private configProviderMap = new Map<string, Constructor>();\r\n\r\n /** Map of abstract classes to their implementations */\r\n private abstractImplementations = new Map<Constructor, AbstractImplementation[]>();\r\n\r\n private constructor() {}\r\n\r\n static getInstance(): Registry {\r\n if (!Registry.instance) {\r\n Registry.instance = new Registry();\r\n }\r\n return Registry.instance;\r\n }\r\n\r\n /**\r\n * Reset the registry (useful for testing)\r\n */\r\n static reset(): void {\r\n const newInstance = new Registry();\r\n Registry.instance = newInstance;\r\n }\r\n\r\n /**\r\n * Register a controller\r\n */\r\n registerController(target: Constructor): void {\r\n this.controllers.add(target);\r\n }\r\n\r\n /**\r\n * Register a provider\r\n */\r\n registerProvider(target: Constructor): void {\r\n this.providers.add(target);\r\n }\r\n\r\n /**\r\n * Get all registered controllers\r\n */\r\n getControllers(): Constructor[] {\r\n return [...this.controllers];\r\n }\r\n\r\n /**\r\n * Get all registered providers\r\n */\r\n getProviders(): Constructor[] {\r\n return [...this.providers];\r\n }\r\n\r\n /**\r\n * Check if a controller is registered\r\n */\r\n hasController(target: Constructor): boolean {\r\n return this.controllers.has(target);\r\n }\r\n\r\n /**\r\n * Check if a provider is registered\r\n */\r\n hasProvider(target: Constructor): boolean {\r\n return this.providers.has(target);\r\n }\r\n\r\n /**\r\n * Register a custom provider (@Provider)\r\n */\r\n registerCustomProvider(target: Constructor): void {\r\n this.customProviders.add(target);\r\n }\r\n\r\n /**\r\n * Get all registered custom providers\r\n */\r\n getCustomProviders(): Constructor[] {\r\n return [...this.customProviders];\r\n }\r\n\r\n /**\r\n * Check if a custom provider is registered\r\n */\r\n hasCustomProvider(target: Constructor): boolean {\r\n return this.customProviders.has(target);\r\n }\r\n\r\n // ============================================================================\r\n // Config Provider Methods\r\n // ============================================================================\r\n\r\n /**\r\n * Register a config provider with its injection token\r\n * \r\n * @param token - The injection token (e.g., 'APP_CONFIG')\r\n * @param providerClass - The config provider class constructor\r\n * @throws {ConfigProviderAlreadyRegisteredException} If the token is already registered\r\n * \r\n * @example\r\n * ```typescript\r\n * registry.registerConfigProvider('APP_CONFIG', AppConfigProvider);\r\n * ```\r\n */\r\n registerConfigProvider(token: string, providerClass: Constructor): void {\r\n if (this.configProviderMap.has(token)) {\r\n const existingClass = this.configProviderMap.get(token)!;\r\n throw new ConfigProviderAlreadyRegisteredException(\r\n token,\r\n existingClass.name,\r\n providerClass.name\r\n );\r\n }\r\n \r\n this.configProviderMap.set(token, providerClass);\r\n }\r\n\r\n /**\r\n * Get all registered config provider classes with their tokens\r\n * \r\n * @returns Array of registration info objects\r\n * \r\n * @internal Used by auto-discovery mechanism\r\n */\r\n getConfigProviderRegistrations(): ConfigProviderRegistration[] {\r\n return Array.from(this.configProviderMap.entries()).map(([token, providerClass]) => ({\r\n token,\r\n providerClass,\r\n }));\r\n }\r\n\r\n /**\r\n * Clear all config provider registrations (useful for testing)\r\n * \r\n * This will remove all registered config providers\r\n * \r\n * @internal\r\n */\r\n clearConfigProviders(): void {\r\n this.configProviderMap.clear();\r\n }\r\n\r\n // ============================================================================\r\n // Abstract Class Implementation Methods\r\n // ============================================================================\r\n\r\n /**\r\n * Register an implementation for an abstract class\r\n * \r\n * @param abstractClass - The abstract class being implemented\r\n * @param implementation - The concrete implementation class\r\n * @param name - Optional name for named implementations\r\n * \r\n * @example\r\n * ```typescript\r\n * registry.registerAbstractImplementation(Mailer, SmtpMailer);\r\n * registry.registerAbstractImplementation(Mailer, SendGridMailer, 'sendgrid');\r\n * ```\r\n */\r\n registerAbstractImplementation(abstractClass: Constructor, implementation: Constructor, name?: string): void {\r\n const implementations = this.abstractImplementations.get(abstractClass) ?? [];\r\n \r\n // Check if already registered\r\n const existing = implementations.find(i => i.implementation === implementation);\r\n if (!existing) {\r\n implementations.push({\r\n implementation,\r\n isPrimary: false,\r\n name,\r\n });\r\n this.abstractImplementations.set(abstractClass, implementations);\r\n } else if (name && !existing.name) {\r\n // Update name if provided later\r\n existing.name = name;\r\n }\r\n }\r\n\r\n /**\r\n * Set the name for an implementation\r\n * \r\n * @param abstractClass - The abstract class\r\n * @param implementation - The implementation class\r\n * @param name - The name to assign\r\n */\r\n setImplementationName(abstractClass: Constructor, implementation: Constructor, name: string): void {\r\n const implementations = this.abstractImplementations.get(abstractClass);\r\n if (!implementations) {\r\n return;\r\n }\r\n\r\n const impl = implementations.find(i => i.implementation === implementation);\r\n if (impl) {\r\n impl.name = name;\r\n }\r\n }\r\n\r\n /**\r\n * Set an implementation as the primary for an abstract class\r\n * \r\n * @param abstractClass - The abstract class\r\n * @param implementation - The implementation to mark as primary\r\n */\r\n setPrimaryImplementation(abstractClass: Constructor, implementation: Constructor): void {\r\n const implementations = this.abstractImplementations.get(abstractClass);\r\n if (!implementations) {\r\n return;\r\n }\r\n\r\n // Reset all to non-primary, then set the specified one as primary\r\n for (const impl of implementations) {\r\n impl.isPrimary = impl.implementation === implementation;\r\n }\r\n }\r\n\r\n /**\r\n * Get all implementations for an abstract class.\r\n * \r\n * This method only returns the raw metadata - resolution logic \r\n * (deciding which implementation to use) belongs in the Container.\r\n * \r\n * @param abstractClass - The abstract class to look up\r\n * @returns Array of implementation info, or empty array if none\r\n */\r\n getImplementations(abstractClass: Constructor): AbstractImplementation[] {\r\n return this.abstractImplementations.get(abstractClass) ?? [];\r\n }\r\n\r\n /**\r\n * Check if an abstract class has registered implementations\r\n * \r\n * @param abstractClass - The abstract class to check\r\n * @returns true if at least one implementation exists\r\n */\r\n hasImplementation(abstractClass: Constructor): boolean {\r\n const implementations = this.abstractImplementations.get(abstractClass);\r\n return !!implementations && implementations.length > 0;\r\n }\r\n\r\n /**\r\n * Clear all abstract implementations (useful for testing)\r\n */\r\n clearAbstractImplementations(): void {\r\n this.abstractImplementations.clear();\r\n }\r\n}\r\n\r\n/**\r\n * Global registry instance\r\n */\r\nexport const registry = Registry.getInstance();\r\nexport { Registry };\r\n\r\n","/**\n * Abstract Class Utilities\n * \n * Provides utilities for detecting and working with abstract classes\n * in the dependency injection system.\n * \n * This enables the \"Abstract Class as Contract\" pattern where:\n * - Abstract classes serve as injection tokens (like interfaces, but exist at runtime)\n * - Concrete implementations extend abstract classes\n * - The container automatically resolves abstract → concrete mappings\n * \n * @example\n * ```typescript\n * // Define abstract contract\n * abstract class NotificationStrategy {\n * abstract send(to: string, message: string): Promise<void>;\n * }\n * \n * // Implement concrete strategy\n * @Injectable()\n * @Implements(NotificationStrategy)\n * class EmailNotificationStrategy extends NotificationStrategy {\n * async send(to: string, message: string): Promise<void> {\n * // Send email...\n * }\n * }\n * \n * // Inject abstract class (auto-resolved to concrete)\n * @Controller()\n * class UserController {\n * @Autowired()\n * private notification!: NotificationStrategy;\n * }\n * ```\n */\n\nimport { Constructor } from '../types.js';\n\n/**\n * Metadata key for storing abstract class implementations\n */\nexport const IMPLEMENTS_METADATA = Symbol('rikta:implements');\n\n/**\n * Metadata key for marking primary implementation\n */\nexport const PRIMARY_METADATA = Symbol('rikta:primary');\n\n/**\n * Check if a class is abstract\n * \n * JavaScript doesn't have true abstract classes, but TypeScript compiles\n * abstract classes as regular functions. We detect \"abstract-like\" behavior\n * by checking if the class is designed to be extended (has abstract methods marker).\n * \n * @param target - The class to check\n * @returns true if the class appears to be abstract\n */\nexport function isAbstractClass(target: unknown): target is Constructor {\n if (typeof target !== 'function') {\n return false;\n }\n \n // Check if class has the abstract marker metadata\n const isMarkedAbstract = Reflect.getMetadata(IMPLEMENTS_METADATA, target) === undefined \n && Reflect.hasMetadata('abstract:class', target);\n \n // Also check prototype for abstract method markers\n if (isMarkedAbstract) {\n return true;\n }\n \n // For classes explicitly registered as abstract via AbstractClass decorator\n return Reflect.getMetadata('abstract:class', target) === true;\n}\n\n/**\n * Check if a class extends from another class (supports inheritance chain)\n * \n * @param derived - The potential derived class\n * @param base - The potential base class\n * @returns true if derived extends base\n */\nexport function extendsFrom(derived: Constructor, base: Constructor): boolean {\n if (!derived || !base) {\n return false;\n }\n \n if (derived === base) {\n return false; // Same class doesn't count as extension\n }\n \n // Walk up the prototype chain\n let current = Object.getPrototypeOf(derived);\n \n while (current && current !== Function.prototype) {\n if (current === base) {\n return true;\n }\n current = Object.getPrototypeOf(current);\n }\n \n return false;\n}\n\n/**\n * Get the abstract class that a class implements (via @Implements decorator)\n * \n * @param target - The class to check\n * @returns The abstract class token, or undefined\n */\nexport function getImplementedAbstract(target: Constructor): Constructor | undefined {\n return Reflect.getMetadata(IMPLEMENTS_METADATA, target);\n}\n\n/**\n * Check if a class is marked as primary implementation\n * \n * @param target - The class to check\n * @returns true if marked with @Primary\n */\nexport function isPrimaryImplementation(target: Constructor): boolean {\n return Reflect.getMetadata(PRIMARY_METADATA, target) === true;\n}\n\n/**\n * Set the abstract class implementation metadata\n * \n * @param target - The implementing class\n * @param abstractClass - The abstract class being implemented\n */\nexport function setImplementsMetadata(target: Constructor, abstractClass: Constructor): void {\n Reflect.defineMetadata(IMPLEMENTS_METADATA, abstractClass, target);\n}\n\n/**\n * Set the primary implementation metadata\n * \n * @param target - The class to mark as primary\n */\nexport function setPrimaryMetadata(target: Constructor): void {\n Reflect.defineMetadata(PRIMARY_METADATA, true, target);\n}\n\n/**\n * Mark a class as abstract (for detection purposes)\n * \n * @param target - The abstract class to mark\n */\nexport function markAsAbstract(target: Constructor): void {\n Reflect.defineMetadata('abstract:class', true, target);\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\r\nimport { Token } from './injection-token.js';\r\n\r\n/**\r\n * Request-scoped storage for dependency injection\r\n * \r\n * Uses Node.js AsyncLocalStorage to maintain request-scoped instances\r\n * that are automatically cleaned up when the request ends.\r\n * \r\n * @example\r\n * ```typescript\r\n * @Injectable({ scope: 'request' })\r\n * class RequestContext {\r\n * readonly requestId = crypto.randomUUID();\r\n * readonly startTime = Date.now();\r\n * }\r\n * ```\r\n */\r\nexport class RequestScopeStorage {\r\n private static instance: RequestScopeStorage;\r\n \r\n /** AsyncLocalStorage for request-scoped data */\r\n private readonly asyncLocalStorage = new AsyncLocalStorage<Map<Token, unknown>>();\r\n\r\n private constructor() {}\r\n\r\n /**\r\n * Get the global RequestScopeStorage instance\r\n */\r\n static getInstance(): RequestScopeStorage {\r\n if (!RequestScopeStorage.instance) {\r\n RequestScopeStorage.instance = new RequestScopeStorage();\r\n }\r\n return RequestScopeStorage.instance;\r\n }\r\n\r\n /**\r\n * Reset the storage (useful for testing)\r\n */\r\n static reset(): void {\r\n RequestScopeStorage.instance = new RequestScopeStorage();\r\n }\r\n\r\n /**\r\n * Run a function within a request scope\r\n * All request-scoped dependencies resolved within this function\r\n * will be isolated to this request.\r\n * \r\n * @param fn - The function to run within the request scope\r\n * @returns The result of the function\r\n */\r\n run<T>(fn: () => T): T {\r\n const store = new Map<Token, unknown>();\r\n return this.asyncLocalStorage.run(store, fn);\r\n }\r\n\r\n /**\r\n * Run an async function within a request scope\r\n * \r\n * @param fn - The async function to run within the request scope\r\n * @returns Promise resolving to the function result\r\n */\r\n async runAsync<T>(fn: () => Promise<T>): Promise<T> {\r\n const store = new Map<Token, unknown>();\r\n return this.asyncLocalStorage.run(store, fn);\r\n }\r\n\r\n /**\r\n * Check if we're currently inside a request scope\r\n */\r\n isInRequestScope(): boolean {\r\n return this.asyncLocalStorage.getStore() !== undefined;\r\n }\r\n\r\n /**\r\n * Get a request-scoped instance by token\r\n * \r\n * @param token - The injection token\r\n * @returns The instance if found, undefined otherwise\r\n */\r\n get<T>(token: Token<T>): T | undefined {\r\n const store = this.asyncLocalStorage.getStore();\r\n if (!store) {\r\n return undefined;\r\n }\r\n return store.get(token) as T | undefined;\r\n }\r\n\r\n /**\r\n * Set a request-scoped instance\r\n * \r\n * @param token - The injection token\r\n * @param instance - The instance to store\r\n * @throws Error if not in a request scope\r\n */\r\n set<T>(token: Token<T>, instance: T): void {\r\n const store = this.asyncLocalStorage.getStore();\r\n if (!store) {\r\n throw new Error(\r\n 'Cannot set request-scoped instance outside of a request context. ' +\r\n 'Make sure RequestScopeStorage.run() or runAsync() is being used.'\r\n );\r\n }\r\n store.set(token, instance);\r\n }\r\n\r\n /**\r\n * Check if a request-scoped instance exists\r\n * \r\n * @param token - The injection token\r\n * @returns true if the instance exists in current request scope\r\n */\r\n has(token: Token): boolean {\r\n const store = this.asyncLocalStorage.getStore();\r\n return store?.has(token) ?? false;\r\n }\r\n\r\n /**\r\n * Get the current request store (for debugging/testing)\r\n * @internal\r\n */\r\n getStore(): Map<Token, unknown> | undefined {\r\n return this.asyncLocalStorage.getStore();\r\n }\r\n}\r\n\r\n/**\r\n * Global request scope storage instance\r\n */\r\nexport const requestScopeStorage = RequestScopeStorage.getInstance();\r\n","import 'reflect-metadata';\nimport { Constructor, AnyConstructor } from '../types.js';\nimport { \n setImplementsMetadata, \n setPrimaryMetadata,\n markAsAbstract,\n IMPLEMENTS_METADATA \n} from './abstract-class.utils.js';\nimport { registry } from '../registry.js';\n\n/**\n * @Implements() decorator\n * \n * Marks a class as the implementation of an abstract class.\n * This enables automatic resolution of abstract class dependencies.\n * \n * Use this decorator when you have an abstract class contract and want\n * to specify which concrete class should be injected when the abstract\n * class is requested.\n * \n * @param abstractClass - The abstract class that this class implements\n * \n * @example Basic usage:\n * ```typescript\n * // Define abstract contract\n * abstract class PaymentGateway {\n * abstract charge(amount: number): Promise<PaymentResult>;\n * abstract refund(txId: string): Promise<void>;\n * }\n * \n * // Implement with @Implements decorator\n * @Injectable()\n * @Implements(PaymentGateway)\n * export class StripeGateway extends PaymentGateway {\n * async charge(amount: number): Promise<PaymentResult> {\n * // Stripe implementation...\n * }\n * \n * async refund(txId: string): Promise<void> {\n * // Stripe refund...\n * }\n * }\n * \n * // Now you can inject PaymentGateway directly:\n * @Controller()\n * class CheckoutController {\n * @Autowired()\n * private gateway!: PaymentGateway; // Resolves to StripeGateway\n * }\n * ```\n * \n * @example Multiple implementations with @Primary:\n * ```typescript\n * @Injectable()\n * @Implements(PaymentGateway)\n * @Primary() // This will be the default\n * export class StripeGateway extends PaymentGateway { }\n * \n * @Injectable()\n * @Implements(PaymentGateway)\n * export class PayPalGateway extends PaymentGateway { }\n * ```\n */\nexport function Implements<T extends AnyConstructor>(abstractClass: T): ClassDecorator {\n return (target: Function) => {\n // Store metadata about which abstract class this implements\n setImplementsMetadata(target as Constructor, abstractClass as Constructor);\n \n // Mark the abstract class as abstract for detection\n markAsAbstract(abstractClass as Constructor);\n \n // Check if this class was already marked with @Named (decorator order flexibility)\n const name = Reflect.getMetadata('rikta:named', target) as string | undefined;\n \n // Register the mapping in the registry for auto-discovery\n registry.registerAbstractImplementation(abstractClass as Constructor, target as Constructor, name);\n \n // Check if this class was already marked as @Primary (decorator order flexibility)\n const isPrimary = Reflect.getMetadata('rikta:is-primary', target) === true;\n if (isPrimary) {\n registry.setPrimaryImplementation(abstractClass as Constructor, target as Constructor);\n }\n };\n}\n\n/**\n * @Primary() decorator\n * \n * Marks an implementation as the primary/default when multiple implementations\n * exist for the same abstract class.\n * \n * When the container encounters an abstract class with multiple implementations,\n * it will use the one marked with @Primary.\n * \n * @example\n * ```typescript\n * abstract class Mailer {\n * abstract send(to: string, body: string): Promise<void>;\n * }\n * \n * @Injectable()\n * @Implements(Mailer)\n * @Primary() // This will be injected by default\n * export class SmtpMailer extends Mailer {\n * async send(to: string, body: string): Promise<void> {\n * // SMTP implementation\n * }\n * }\n * \n * @Injectable()\n * @Implements(Mailer)\n * export class SendGridMailer extends Mailer {\n * async send(to: string, body: string): Promise<void> {\n * // SendGrid implementation\n * }\n * }\n * \n * // Injects SmtpMailer (the primary)\n * @Autowired()\n * private mailer!: Mailer;\n * ```\n */\nexport function Primary(): ClassDecorator {\n return (target: Function) => {\n setPrimaryMetadata(target as Constructor);\n \n // If already registered via @Implements, update the primary flag\n const abstractClass = Reflect.getMetadata(IMPLEMENTS_METADATA, target);\n if (abstractClass) {\n registry.setPrimaryImplementation(abstractClass, target as Constructor);\n }\n \n // Also store on the class itself so @Implements can check later\n Reflect.defineMetadata('rikta:is-primary', true, target);\n };\n}\n\n/**\n * @Named() decorator\n * \n * Assigns a name to an implementation for qualified injection.\n * Use this when you have multiple implementations of the same abstract class\n * and want to inject a specific one by name.\n * \n * @param name - The unique name for this implementation\n * \n * @example\n * ```typescript\n * abstract class Mailer {\n * abstract send(to: string, body: string): Promise<void>;\n * }\n * \n * @Injectable()\n * @Implements(Mailer)\n * @Named('smtp')\n * export class SmtpMailer extends Mailer {\n * async send(to: string, body: string): Promise<void> {\n * // SMTP implementation\n * }\n * }\n * \n * @Injectable()\n * @Implements(Mailer)\n * @Named('sendgrid')\n * export class SendGridMailer extends Mailer {\n * async send(to: string, body: string): Promise<void> {\n * // SendGrid implementation\n * }\n * }\n * \n * // Inject specific implementation by name\n * @Controller()\n * class MailController {\n * @Autowired(Mailer, 'smtp')\n * private smtpMailer!: Mailer;\n * \n * @Autowired(Mailer, 'sendgrid')\n * private sendgridMailer!: Mailer;\n * }\n * ```\n */\nexport function Named(name: string): ClassDecorator {\n return (target: Function) => {\n // Store the name on the class\n Reflect.defineMetadata('rikta:named', name, target);\n \n // If already registered via @Implements, update the name\n const abstractClass = Reflect.getMetadata(IMPLEMENTS_METADATA, target);\n if (abstractClass) {\n registry.setImplementationName(abstractClass, target as Constructor, name);\n }\n };\n}\n\n/**\n * @AbstractClass() decorator (optional)\n * \n * Explicitly marks a class as abstract for the DI system.\n * This is usually not needed as the @Implements decorator\n * automatically marks the base class as abstract.\n * \n * Use this when you want to ensure a class is recognized\n * as abstract even before any implementations are registered.\n * \n * @example\n * ```typescript\n * @AbstractClass()\n * abstract class Repository<T> {\n * abstract findById(id: string): Promise<T | null>;\n * abstract save(entity: T): Promise<T>;\n * }\n * ```\n */\nexport function AbstractClass(): ClassDecorator {\n return (target: Function) => {\n markAsAbstract(target as Constructor);\n };\n}\n","import fg from 'fast-glob';\r\nimport fs from 'fs/promises';\r\nimport path from 'path';\r\nimport { DiscoveryException, DiscoveryFailure, DiscoveryOptions } from './exceptions/discovery.exception.js';\r\n\r\n/**\r\n * Default patterns to exclude from discovery\r\n */\r\nconst DEFAULT_IGNORE_PATTERNS = [\r\n '**/node_modules/**',\r\n '**/dist/**',\r\n '**/build/**',\r\n '**/benchmarks/**',\r\n '**/*.test.ts',\r\n '**/*.spec.ts',\r\n '**/*.d.ts',\r\n];\r\n\r\n/**\r\n * Get the entry point directory of the application.\r\n * \r\n * Uses process.argv[1] which contains the path to the main script being executed.\r\n * This is the cleanest way to determine the user's project directory when\r\n * rikta-core is installed in node_modules.\r\n * \r\n * Falls back to process.cwd() if argv[1] is not available.\r\n */\r\nfunction getEntryPointDirectory(): string {\r\n const mainScript = process.argv[1];\r\n \r\n if (mainScript) {\r\n // Handle file:// URLs (ESM) and regular paths\r\n const filePath = mainScript.startsWith('file://') \r\n ? new URL(mainScript).pathname \r\n : mainScript;\r\n return path.dirname(filePath);\r\n }\r\n \r\n // Fallback to current working directory\r\n return process.cwd();\r\n}\r\n\r\n/**\r\n * Regex patterns to detect Rikta decorators\r\n * Supports both TypeScript source and compiled JavaScript patterns\r\n */\r\nconst DECORATOR_PATTERNS = [\r\n // TypeScript source patterns\r\n /@Controller\\s*\\(/, // @Controller() or @Controller('/path')\r\n /@Injectable\\s*\\(/, // @Injectable() or @Injectable({ scope: 'singleton' })\r\n /@Provider\\s*\\(/, // @Provider(TOKEN)\r\n // Compiled JavaScript CommonJS patterns (e.g., (0, core_1.Controller)('/path'))\r\n /\\.\\s*Controller\\s*\\)\\s*\\(/,\r\n /\\.\\s*Injectable\\s*\\)\\s*\\(/,\r\n /\\.\\s*Provider\\s*\\)\\s*\\(/,\r\n /\\.\\s*ProviderConfig\\s*\\)\\s*\\(/,\r\n // ESM compiled patterns - import statements with decorators\r\n /import\\s*{\\s*[^}]*\\bController\\b[^}]*}\\s*from\\s*['\"]@riktajs\\/core['\"]/,\r\n /import\\s*{\\s*[^}]*\\bInjectable\\b[^}]*}\\s*from\\s*['\"]@riktajs\\/core['\"]/,\r\n /import\\s*{\\s*[^}]*\\bProvider\\b[^}]*}\\s*from\\s*['\"]@riktajs\\/core['\"]/,\r\n];\r\n\r\n/**\r\n * Check if a file contains Rikta decorators (@Controller, @Injectable, or @Provider)\r\n */\r\nasync function containsRiktaDecorators(filePath: string): Promise<boolean> {\r\n try {\r\n const content = await fs.readFile(filePath, 'utf-8');\r\n return DECORATOR_PATTERNS.some(pattern => pattern.test(content));\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Discover and import modules matching the given patterns\r\n * \r\n * Only imports files that contain @Controller, @Injectable, or @Provider decorators.\r\n * \r\n * @param options - Discovery options or glob patterns for backward compatibility\r\n * @param cwd - Base directory (deprecated, use options.cwd instead)\r\n * @returns Promise resolving to list of imported files\r\n * \r\n * @example\r\n * ```typescript\r\n * // Scan specific directories (relative paths resolved from caller's location)\r\n * await discoverModules({ patterns: ['./src/controllers', './src/services'] });\r\n * \r\n * // Enable strict mode to throw on import errors\r\n * await discoverModules({ \r\n * patterns: ['./src'],\r\n * strict: true \r\n * });\r\n * \r\n * // With error callback\r\n * await discoverModules({\r\n * patterns: ['./src'],\r\n * onImportError: (file, err) => console.warn(`Failed: ${file}`)\r\n * });\r\n * \r\n * // Legacy API (still supported)\r\n * await discoverModules(['./src/controllers'], '/path/to/project');\r\n * ```\r\n */\r\nexport async function discoverModules(\r\n optionsOrPatterns: DiscoveryOptions | string[] = ['./**/*.{ts,js}'],\r\n cwd?: string\r\n): Promise<string[]> {\r\n // Normalize input to DiscoveryOptions\r\n const options: DiscoveryOptions = Array.isArray(optionsOrPatterns)\r\n ? { patterns: optionsOrPatterns, cwd }\r\n : optionsOrPatterns;\r\n\r\n const patterns = options.patterns ?? ['./**/*.{ts,js}'];\r\n const strict = options.strict ?? false;\r\n const onImportError = options.onImportError;\r\n \r\n // If no cwd provided, use the entry point directory (where the main script is)\r\n // This is crucial when rikta-core is installed in node_modules\r\n const baseDir = options.cwd ?? cwd ?? getEntryPointDirectory();\r\n \r\n // Resolve the base directory to absolute if needed\r\n const absoluteBaseDir = path.isAbsolute(baseDir) \r\n ? baseDir \r\n : path.resolve(process.cwd(), baseDir);\r\n\r\n // Normalize patterns to include file extensions if not present\r\n const normalizedPatterns = patterns.map(pattern => {\r\n // Resolve the pattern if it's an absolute path\r\n // For absolute paths, we need to make them relative to cwd for fast-glob\r\n let normalizedPattern = pattern;\r\n \r\n if (path.isAbsolute(pattern)) {\r\n // Convert absolute path to relative from baseDir\r\n normalizedPattern = path.relative(absoluteBaseDir, pattern);\r\n if (!normalizedPattern.startsWith('.')) {\r\n normalizedPattern = './' + normalizedPattern;\r\n }\r\n }\r\n \r\n // If pattern already has extension, use as-is\r\n if (/\\.\\w+$/.test(normalizedPattern) || normalizedPattern.endsWith('*')) {\r\n return normalizedPattern;\r\n }\r\n // Add file extension pattern\r\n return normalizedPattern.endsWith('/') \r\n ? `${normalizedPattern}**/*.{ts,js}` \r\n : `${normalizedPattern}/**/*.{ts,js}`;\r\n });\r\n\r\n // Find all matching files\r\n const files = await fg(normalizedPatterns, {\r\n cwd: absoluteBaseDir,\r\n absolute: true,\r\n ignore: DEFAULT_IGNORE_PATTERNS,\r\n onlyFiles: true,\r\n });\r\n\r\n // Filter files that contain Rikta decorators (parallelized for performance)\r\n const decoratorChecks = await Promise.all(\r\n files.map(async file => ({ file, hasDecorators: await containsRiktaDecorators(file) }))\r\n );\r\n const riktaFiles = decoratorChecks\r\n .filter(({ hasDecorators }) => hasDecorators)\r\n .map(({ file }) => file);\r\n\r\n // Import only files with decorators\r\n const importedFiles: string[] = [];\r\n const failedImports: DiscoveryFailure[] = [];\r\n \r\n for (const file of riktaFiles) {\r\n try {\r\n // Convert to proper import path for ESM\r\n // For .js files, use the file:// URL format which works in ESM\r\n // For .ts files (dev mode), remove the extension as ts-node handles it\r\n let importPath: string;\r\n if (file.endsWith('.js')) {\r\n // ESM requires file:// URLs for absolute paths\r\n importPath = `file://${file}`;\r\n } else {\r\n // TypeScript files - remove extension for ts-node compatibility\r\n importPath = file.replace(/\\.ts$/, '');\r\n }\r\n await import(importPath);\r\n importedFiles.push(file);\r\n } catch (err) {\r\n const error = err instanceof Error ? err : new Error(String(err));\r\n \r\n // Call error callback if provided\r\n onImportError?.(file, error);\r\n \r\n // Log in debug mode\r\n if (process.env.DEBUG) {\r\n console.warn(`[Rikta] Failed to import ${file}:`, error.message);\r\n }\r\n \r\n // Track failure for strict mode\r\n failedImports.push({ filePath: file, error });\r\n }\r\n }\r\n\r\n // In strict mode, throw if any imports failed\r\n if (strict && failedImports.length > 0) {\r\n throw new DiscoveryException(failedImports);\r\n }\r\n\r\n return importedFiles;\r\n}\r\n\r\n/**\r\n * Get the entry point directory (where the main script is located)\r\n * \r\n * This uses process.argv[1] to determine the directory of the script\r\n * that started the Node.js process. This works correctly when rikta-core\r\n * is installed as an external library in node_modules.\r\n * \r\n * @returns The directory of the main script, or process.cwd() as fallback\r\n */\r\nexport function getCallerDirectory(): string {\r\n return getEntryPointDirectory();\r\n}\r\n","/**\r\n * Discovery Exception\r\n * \r\n * Thrown when auto-discovery of modules fails and strict mode is enabled.\r\n * Contains detailed information about the failed import.\r\n * \r\n * @example\r\n * ```typescript\r\n * // This is thrown when strictDiscovery is enabled and a file fails to import\r\n * throw new DiscoveryException(\r\n * '/path/to/file.ts',\r\n * new SyntaxError('Unexpected token')\r\n * );\r\n * ```\r\n */\r\nexport class DiscoveryException extends Error {\r\n /**\r\n * The file path that failed to import\r\n */\r\n readonly filePath: string;\r\n\r\n /**\r\n * The original error that caused the failure\r\n */\r\n readonly originalError: Error;\r\n\r\n /**\r\n * List of all failed imports (for batch reporting)\r\n */\r\n readonly failedImports: DiscoveryFailure[];\r\n\r\n constructor(filePath: string, originalError: Error);\r\n constructor(failures: DiscoveryFailure[]);\r\n constructor(filePathOrFailures: string | DiscoveryFailure[], originalError?: Error) {\r\n if (typeof filePathOrFailures === 'string') {\r\n const filePath = filePathOrFailures;\r\n const error = originalError!;\r\n \r\n super(\r\n `[Rikta Discovery] Failed to import module: ${filePath}\\n` +\r\n `Reason: ${error.message}`\r\n );\r\n \r\n this.filePath = filePath;\r\n this.originalError = error;\r\n this.failedImports = [{ filePath, error }];\r\n } else {\r\n const failures = filePathOrFailures;\r\n const fileList = failures.map(f => ` - ${f.filePath}: ${f.error.message}`).join('\\n');\r\n \r\n super(\r\n `[Rikta Discovery] Failed to import ${failures.length} module(s):\\n${fileList}`\r\n );\r\n \r\n this.filePath = failures[0]?.filePath ?? '';\r\n this.originalError = failures[0]?.error ?? new Error('Unknown error');\r\n this.failedImports = failures;\r\n }\r\n\r\n this.name = 'DiscoveryException';\r\n Error.captureStackTrace(this, this.constructor);\r\n }\r\n\r\n /**\r\n * Get a formatted report of all failed imports\r\n */\r\n getReport(): string {\r\n const lines = ['Discovery Failures:', ''];\r\n \r\n for (const { filePath, error } of this.failedImports) {\r\n lines.push(`📁 ${filePath}`);\r\n lines.push(` Error: ${error.message}`);\r\n if (error.stack) {\r\n const stackLines = error.stack.split('\\n').slice(1, 4);\r\n lines.push(` Stack: ${stackLines.join('\\n ')}`);\r\n }\r\n lines.push('');\r\n }\r\n \r\n return lines.join('\\n');\r\n }\r\n}\r\n\r\n/**\r\n * Represents a single failed import during discovery\r\n */\r\nexport interface DiscoveryFailure {\r\n /** The file path that failed to import */\r\n filePath: string;\r\n \r\n /** The error that occurred during import */\r\n error: Error;\r\n}\r\n\r\n/**\r\n * Options for module discovery\r\n */\r\nexport interface DiscoveryOptions {\r\n /**\r\n * Glob patterns to search for modules\r\n * @default ['./**\\/*.{ts,js}']\r\n */\r\n patterns?: string[];\r\n\r\n /**\r\n * Base directory for pattern matching\r\n * If not provided, uses the entry point directory\r\n */\r\n cwd?: string;\r\n\r\n /**\r\n * If true, throws DiscoveryException when any import fails\r\n * If false (default), logs warnings and continues\r\n * \r\n * @default false\r\n */\r\n strict?: boolean;\r\n\r\n /**\r\n * Callback for handling individual import failures\r\n * Called for each failed import regardless of strict mode\r\n */\r\n onImportError?: (filePath: string, error: Error) => void;\r\n}\r\n","import 'reflect-metadata';\r\nimport { INJECTABLE_METADATA } from '../constants.js';\r\nimport { InjectableOptions } from '../types.js';\r\nimport { container } from '../container/container.js';\r\nimport { registry } from '../registry.js';\r\n\r\n/**\r\n * @Injectable() decorator\r\n * \r\n * Marks a class as injectable, allowing it to be managed by the DI container.\r\n * Classes decorated with @Injectable() can be injected into other classes\r\n * via constructor injection or @Autowired() property injection.\r\n * \r\n * The class is automatically registered in the global registry for lifecycle hooks.\r\n * \r\n * @example\r\n * ```typescript\r\n * @Injectable()\r\n * class UserService {\r\n * getUsers() { return []; }\r\n * }\r\n * \r\n * @Injectable()\r\n * class UserController {\r\n * constructor(private userService: UserService) {}\r\n * }\r\n * ```\r\n */\r\nexport function Injectable(options: InjectableOptions = {}): ClassDecorator {\r\n return (target: Function) => {\r\n // Store injectable metadata\r\n Reflect.defineMetadata(INJECTABLE_METADATA, options, target);\r\n \r\n // Register in DI container\r\n container.register(target as new (...args: unknown[]) => unknown, options);\r\n \r\n // Register in global registry for lifecycle hooks\r\n registry.registerProvider(target as new (...args: unknown[]) => unknown);\r\n };\r\n}\r\n","import { Injectable } from '../decorators/injectable.decorator.js';\r\nimport { Constructor } from '../types.js';\r\n\r\n/**\r\n * Event payload types for built-in lifecycle events\r\n */\r\nexport interface EventPayload {\r\n 'app:discovery': { files: string[] };\r\n 'app:providers': { count: number };\r\n 'provider:init': { provider: Constructor; name: string; priority: number };\r\n 'app:routes': { count: number };\r\n 'app:bootstrap': { providerCount: number };\r\n 'app:listen': { address: string; port: number };\r\n 'app:shutdown': { signal?: string };\r\n 'provider:destroy': { provider: Constructor; name: string };\r\n 'app:destroy': { uptime: number };\r\n}\r\n\r\nexport type LifecycleEvent = keyof EventPayload;\r\n\r\ntype Listener<E extends LifecycleEvent> = (payload: EventPayload[E]) => void | Promise<void>;\r\n\r\n/**\r\n * Represents a tracked listener with its owner for cleanup\r\n */\r\ninterface TrackedListener {\r\n listener: (payload: unknown) => void | Promise<void>;\r\n owner?: string; // Provider class name for tracking\r\n}\r\n\r\n/**\r\n * EventBus - Central event system for lifecycle and custom events\r\n * \r\n * Provides a flexible pub/sub mechanism that works alongside\r\n * the interface-based lifecycle hooks.\r\n * \r\n * Features:\r\n * - Subscribe/unsubscribe to events\r\n * - One-time listeners\r\n * - Promise-based waitFor\r\n * - Listener tracking by owner for cleanup\r\n * - Memory leak prevention with automatic cleanup\r\n * \r\n * @example\r\n * ```typescript\r\n * @Injectable()\r\n * class MonitoringService {\r\n * constructor(private events: EventBus) {\r\n * events.on('app:listen', ({ address }) => {\r\n * console.log(`Server started at ${address}`);\r\n * });\r\n * }\r\n * }\r\n * ```\r\n */\r\n@Injectable()\r\nexport class EventBus {\r\n private listeners = new Map<string, Set<TrackedListener>>();\r\n private onceListeners = new Map<string, Set<TrackedListener>>();\r\n \r\n /** Track unsubscribe functions by owner for cleanup */\r\n private ownerUnsubscribers = new Map<string, Set<() => void>>();\r\n\r\n /**\r\n * Subscribe to an event\r\n * @param event - Event name to subscribe to\r\n * @param listener - Callback function\r\n * @param owner - Optional owner identifier for cleanup tracking\r\n * @returns Unsubscribe function\r\n */\r\n on<E extends LifecycleEvent>(event: E, listener: Listener<E>, owner?: string): () => void;\r\n on<T = unknown>(event: string, listener: (payload: T) => void | Promise<void>, owner?: string): () => void;\r\n on(event: string, listener: (payload: unknown) => void | Promise<void>, owner?: string): () => void {\r\n if (!this.listeners.has(event)) {\r\n this.listeners.set(event, new Set());\r\n }\r\n \r\n const tracked: TrackedListener = { listener, owner };\r\n this.listeners.get(event)!.add(tracked);\r\n \r\n const unsubscribe = () => {\r\n this.listeners.get(event)?.delete(tracked);\r\n if (owner) {\r\n this.ownerUnsubscribers.get(owner)?.delete(unsubscribe);\r\n }\r\n };\r\n \r\n // Track unsubscribe by owner for bulk cleanup\r\n if (owner) {\r\n if (!this.ownerUnsubscribers.has(owner)) {\r\n this.ownerUnsubscribers.set(owner, new Set());\r\n }\r\n this.ownerUnsubscribers.get(owner)!.add(unsubscribe);\r\n }\r\n \r\n return unsubscribe;\r\n }\r\n\r\n /**\r\n * Subscribe to an event once\r\n * @param event - Event name to subscribe to\r\n * @param listener - Callback function\r\n * @param owner - Optional owner identifier for cleanup tracking\r\n */\r\n once<E extends LifecycleEvent>(event: E, listener: Listener<E>, owner?: string): void;\r\n once<T = unknown>(event: string, listener: (payload: T) => void | Promise<void>, owner?: string): void;\r\n once(event: string, listener: (payload: unknown) => void | Promise<void>, owner?: string): void {\r\n if (!this.onceListeners.has(event)) {\r\n this.onceListeners.set(event, new Set());\r\n }\r\n \r\n const tracked: TrackedListener = { listener, owner };\r\n this.onceListeners.get(event)!.add(tracked);\r\n \r\n // Track for owner cleanup\r\n if (owner) {\r\n if (!this.ownerUnsubscribers.has(owner)) {\r\n this.ownerUnsubscribers.set(owner, new Set());\r\n }\r\n const unsubscribe = () => {\r\n this.onceListeners.get(event)?.delete(tracked);\r\n };\r\n this.ownerUnsubscribers.get(owner)!.add(unsubscribe);\r\n }\r\n }\r\n\r\n /**\r\n * Emit an event to all subscribers\r\n */\r\n async emit<E extends LifecycleEvent>(event: E, payload: EventPayload[E]): Promise<void>;\r\n async emit<T = unknown>(event: string, payload: T): Promise<void>;\r\n async emit(event: string, payload: unknown): Promise<void> {\r\n // Call regular listeners\r\n const listeners = this.listeners.get(event);\r\n if (listeners) {\r\n for (const { listener } of listeners) {\r\n await listener(payload);\r\n }\r\n }\r\n\r\n // Call and remove once listeners\r\n const onceListeners = this.onceListeners.get(event);\r\n if (onceListeners) {\r\n for (const { listener } of onceListeners) {\r\n await listener(payload);\r\n }\r\n this.onceListeners.delete(event);\r\n }\r\n }\r\n\r\n /**\r\n * Wait for an event (Promise-based)\r\n */\r\n waitFor<E extends LifecycleEvent>(event: E): Promise<EventPayload[E]>;\r\n waitFor<T = unknown>(event: string): Promise<T>;\r\n waitFor(event: string): Promise<unknown> {\r\n return new Promise(resolve => this.once(event, resolve as any));\r\n }\r\n\r\n /**\r\n * Remove all listeners for an event\r\n */\r\n off(event: string): void {\r\n this.listeners.delete(event);\r\n this.onceListeners.delete(event);\r\n }\r\n\r\n /**\r\n * Remove all listeners registered by a specific owner\r\n * Useful for cleaning up when a provider is destroyed\r\n * \r\n * @param owner - The owner identifier (usually class name)\r\n */\r\n removeByOwner(owner: string): void {\r\n const unsubscribers = this.ownerUnsubscribers.get(owner);\r\n if (unsubscribers) {\r\n for (const unsubscribe of unsubscribers) {\r\n unsubscribe();\r\n }\r\n this.ownerUnsubscribers.delete(owner);\r\n }\r\n }\r\n\r\n /**\r\n * Remove all listeners\r\n */\r\n clear(): void {\r\n this.listeners.clear();\r\n this.onceListeners.clear();\r\n this.ownerUnsubscribers.clear();\r\n }\r\n\r\n /**\r\n * Get listener count for an event\r\n */\r\n listenerCount(event: string): number {\r\n return (this.listeners.get(event)?.size ?? 0) + \r\n (this.onceListeners.get(event)?.size ?? 0);\r\n }\r\n\r\n /**\r\n * Get total listener count across all events\r\n * Useful for debugging memory leaks\r\n */\r\n totalListenerCount(): number {\r\n let count = 0;\r\n for (const listeners of this.listeners.values()) {\r\n count += listeners.size;\r\n }\r\n for (const listeners of this.onceListeners.values()) {\r\n count += listeners.size;\r\n }\r\n return count;\r\n }\r\n\r\n /**\r\n * Get listener count by owner\r\n * Useful for debugging which providers have the most listeners\r\n */\r\n listenerCountByOwner(owner: string): number {\r\n return this.ownerUnsubscribers.get(owner)?.size ?? 0;\r\n }\r\n\r\n /**\r\n * Get all registered owners\r\n */\r\n getOwners(): string[] {\r\n return [...this.ownerUnsubscribers.keys()];\r\n }\r\n}\r\n\r\n","import 'reflect-metadata';\r\nimport { LifecycleEvent } from './event-bus.js';\r\n\r\nexport const ON_EVENT_METADATA = Symbol('on:event:metadata');\r\n\r\n/**\r\n * Metadata for @On() decorated methods\r\n */\r\nexport interface OnEventMetadata {\r\n event: string;\r\n methodName: string;\r\n priority: number;\r\n}\r\n\r\n/**\r\n * @On() decorator - Listen to lifecycle or custom events\r\n * \r\n * Marks a method to be called when a specific event is emitted.\r\n * Can be used for built-in lifecycle events or custom events.\r\n * \r\n * @param event - The event name to listen for\r\n * @param options - Optional configuration (priority)\r\n * \r\n * @example Built-in lifecycle events:\r\n * ```typescript\r\n * @Injectable()\r\n * class MonitoringService {\r\n * @On('app:listen')\r\n * onServerStart({ address, port }: EventPayload['app:listen']) {\r\n * console.log(`Server listening on ${address}:${port}`);\r\n * }\r\n * \r\n * @On('app:shutdown')\r\n * async onShutdown({ signal }: EventPayload['app:shutdown']) {\r\n * await this.flushMetrics();\r\n * }\r\n * }\r\n * ```\r\n * \r\n * @example Custom events:\r\n * ```typescript\r\n * @Injectable()\r\n * class NotificationService {\r\n * @On('user:created')\r\n * async sendWelcome(user: User) {\r\n * await this.email.send(user.email, 'Welcome!');\r\n * }\r\n * }\r\n * ```\r\n * \r\n * @example With priority (higher = called first):\r\n * ```typescript\r\n * @Injectable()\r\n * class CriticalService {\r\n * @On('app:shutdown', { priority: 100 })\r\n * async saveState() {\r\n * // Called before other shutdown handlers\r\n * }\r\n * }\r\n * ```\r\n */\r\nexport function On(\r\n event: LifecycleEvent | string, \r\n options?: { priority?: number }\r\n): MethodDecorator {\r\n return (target, propertyKey) => {\r\n const existing: OnEventMetadata[] = \r\n Reflect.getMetadata(ON_EVENT_METADATA, target.constructor) ?? [];\r\n \r\n existing.push({\r\n event,\r\n methodName: String(propertyKey),\r\n priority: options?.priority ?? 0,\r\n });\r\n \r\n Reflect.defineMetadata(ON_EVENT_METADATA, existing, target.constructor);\r\n };\r\n}\r\n\r\n","import 'reflect-metadata';\r\nimport { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';\r\nimport { Container } from '../container/container.js';\r\nimport { requestScopeStorage } from '../container/request-scope.js';\r\nimport { \r\n CONTROLLER_METADATA, \r\n ROUTES_METADATA, \r\n PARAM_METADATA, \r\n HTTP_CODE_METADATA,\r\n ParamType \r\n} from '../constants.js';\r\nimport { Constructor, RouteDefinition, RouteContext } from '../types.js';\r\nimport { ParamMetadata } from '../decorators/param.decorator.js';\r\nimport { getCustomParamMetadata, CustomParamMetadata } from '../decorators/create-param-decorator.js';\r\nimport { ValidationException } from '../exceptions/validation.exception.js';\r\nimport { ForbiddenException } from '../exceptions/exceptions.js';\r\nimport { ExecutionContext, ExecutionContextImpl } from '../guards/execution-context.js';\r\nimport { getGuardsMetadata, GuardClass } from '../guards/use-guards.decorator.js';\r\nimport type { CanActivate } from '../guards/can-activate.interface.js';\r\nimport { getMiddlewareMetadata, MiddlewareClass } from '../middleware/use-middleware.decorator.js';\r\nimport type { RiktaMiddleware } from '../middleware/rikta-middleware.interface.js';\r\nimport { getInterceptorsMetadata, InterceptorClass } from '../interceptors/use-interceptors.decorator.js';\r\nimport type { Interceptor, CallHandler } from '../interceptors/interceptor.interface.js';\r\n\r\n/**\r\n * Compiled parameter extractor function type\r\n * Pre-compiled for maximum performance\r\n */\r\n\r\n/**\r\n * Compiled parameter extractor function type\r\n * Pre-compiled for maximum performance\r\n */\r\ntype ParamExtractor = (context: RouteContext) => unknown;\r\n\r\n/**\r\n * Compiled route handler type\r\n */\r\ntype CompiledHandler = (request: FastifyRequest, reply: FastifyReply) => Promise<unknown>;\r\n\r\n/**\r\n * Pre-compiled parameter resolver\r\n */\r\ninterface CompiledParamResolver {\r\n index: number;\r\n extract: ParamExtractor;\r\n zodSchema?: ParamMetadata['zodSchema'];\r\n validationLabel: string;\r\n}\r\n\r\n/**\r\n * Router class\r\n * \r\n * Responsible for:\r\n * - Scanning controllers for route metadata\r\n * - Registering routes with Fastify\r\n * - Handling parameter injection\r\n * \r\n * Performance optimizations:\r\n * - Pre-compiled parameter extractors\r\n * - Guard instance caching\r\n * - Middleware instance caching\r\n * - Interceptor instance caching\r\n * - Fast path for simple routes\r\n */\r\nexport class Router {\r\n /** Cache for guard instances (singleton per guard class) */\r\n private readonly guardCache = new Map<GuardClass, CanActivate>();\r\n \r\n /** Cache for middleware instances (singleton per middleware class) */\r\n private readonly middlewareCache = new Map<MiddlewareClass, RiktaMiddleware>();\r\n\r\n /** Cache for interceptor instances (singleton per interceptor class) */\r\n private readonly interceptorCache = new Map<InterceptorClass, Interceptor>();\r\n \r\n constructor(\r\n private readonly server: FastifyInstance,\r\n private readonly container: Container,\r\n private readonly globalPrefix: string = ''\r\n ) {}\r\n\r\n /**\r\n * Clear the guard instance cache\r\n * Useful for testing when you need fresh guard instances\r\n */\r\n clearGuardCache(): void {\r\n this.guardCache.clear();\r\n }\r\n\r\n /**\r\n * Clear the middleware instance cache\r\n * Useful for testing when you need fresh middleware instances\r\n */\r\n clearMiddlewareCache(): void {\r\n this.middlewareCache.clear();\r\n }\r\n\r\n /**\r\n * Clear the interceptor instance cache\r\n * Useful for testing when you need fresh interceptor instances\r\n */\r\n clearInterceptorCache(): void {\r\n this.interceptorCache.clear();\r\n }\r\n\r\n /**\r\n * Clear all caches (guards, middleware, and interceptors)\r\n * Useful for testing or hot-reload scenarios\r\n */\r\n clearAllCaches(): void {\r\n this.guardCache.clear();\r\n this.middlewareCache.clear();\r\n this.interceptorCache.clear();\r\n }\r\n\r\n /**\r\n * Get the number of cached guard instances\r\n */\r\n getGuardCacheSize(): number {\r\n return this.guardCache.size;\r\n }\r\n\r\n /**\r\n * Get the number of cached middleware instances\r\n */\r\n getMiddlewareCacheSize(): number {\r\n return this.middlewareCache.size;\r\n }\r\n\r\n /**\r\n * Get the number of cached interceptor instances\r\n */\r\n getInterceptorCacheSize(): number {\r\n return this.interceptorCache.size;\r\n }\r\n\r\n /**\r\n * Register all routes from a controller\r\n */\r\n registerController(controllerClass: Constructor, silent: boolean = false): void {\r\n // Get controller metadata\r\n const controllerMeta = Reflect.getMetadata(CONTROLLER_METADATA, controllerClass);\r\n if (!controllerMeta) {\r\n throw new Error(\r\n `${controllerClass.name} is not decorated with @Controller(). ` +\r\n `Make sure to add the decorator.`\r\n );\r\n }\r\n\r\n // Resolve controller instance from container\r\n const controllerInstance = this.container.resolve(controllerClass);\r\n\r\n // Get routes metadata\r\n const routes: RouteDefinition[] = \r\n Reflect.getMetadata(ROUTES_METADATA, controllerClass) ?? [];\r\n\r\n // Register each route\r\n for (const route of routes) {\r\n this.registerRoute(controllerClass, controllerInstance, controllerMeta.prefix, route, silent);\r\n }\r\n }\r\n\r\n /**\r\n * Register a single route\r\n */\r\n private registerRoute(\r\n controllerClass: Constructor,\r\n controllerInstance: unknown,\r\n controllerPrefix: string,\r\n route: RouteDefinition,\r\n silent: boolean = false\r\n ): void {\r\n // Build full path\r\n const fullPath = this.buildPath(controllerPrefix, route.path);\r\n \r\n // Get the handler method\r\n const handler = (controllerInstance as Record<string | symbol, Function>)[route.handlerName];\r\n if (typeof handler !== 'function') {\r\n throw new Error(\r\n `Handler ${String(route.handlerName)} not found on ${controllerClass.name}`\r\n );\r\n }\r\n\r\n // Get parameter metadata\r\n const paramsMeta: ParamMetadata[] = \r\n Reflect.getMetadata(PARAM_METADATA, controllerClass, route.handlerName) ?? [];\r\n\r\n // Get custom parameter metadata (from createParamDecorator)\r\n const customParamsMeta: CustomParamMetadata[] = \r\n getCustomParamMetadata(controllerClass, route.handlerName);\r\n\r\n // Get HTTP status code if set\r\n const statusCode = Reflect.getMetadata(HTTP_CODE_METADATA, controllerClass, route.handlerName);\r\n\r\n // Get guards for this route (controller-level + method-level)\r\n const guards = getGuardsMetadata(controllerClass, route.handlerName);\r\n\r\n // Get middleware for this route (controller-level + method-level)\r\n const middleware = getMiddlewareMetadata(controllerClass, route.handlerName);\r\n\r\n // Get interceptors for this route (controller-level + method-level)\r\n const interceptors = getInterceptorsMetadata(controllerClass, route.handlerName);\r\n\r\n // ============================================\r\n // OPTIMIZATION: Pre-compile parameter resolvers\r\n // ============================================\r\n const compiledResolvers = this.compileParamResolvers(paramsMeta);\r\n const hasBuiltinParams = compiledResolvers.length > 0;\r\n const hasCustomParams = customParamsMeta.length > 0;\r\n const hasParams = hasBuiltinParams || hasCustomParams;\r\n const allParamIndexes = [\r\n ...compiledResolvers.map(r => r.index),\r\n ...customParamsMeta.map(r => r.index)\r\n ];\r\n const maxParamIndex = hasParams ? Math.max(...allParamIndexes) : -1;\r\n\r\n // ============================================\r\n // OPTIMIZATION: Pre-resolve guard instances\r\n // ============================================\r\n const guardInstances = this.resolveGuardInstances(guards);\r\n const hasGuards = guardInstances.length > 0;\r\n\r\n // ============================================\r\n // OPTIMIZATION: Pre-resolve middleware instances\r\n // ============================================\r\n const middlewareInstances = this.resolveMiddlewareInstances(middleware);\r\n const hasMiddleware = middlewareInstances.length > 0;\r\n\r\n // ============================================\r\n // OPTIMIZATION: Pre-resolve interceptor instances\r\n // ============================================\r\n const interceptorInstances = this.resolveInterceptorInstances(interceptors);\r\n const hasInterceptors = interceptorInstances.length > 0;\r\n\r\n // Pre-create execution context factory (needed for guards, interceptors, or custom params)\r\n const needsContext = hasGuards || hasCustomParams || hasInterceptors;\r\n const createContext = needsContext\r\n ? (req: FastifyRequest, rep: FastifyReply) => \r\n new ExecutionContextImpl(req, rep, controllerClass, route.handlerName)\r\n : null;\r\n\r\n // Inner handler logic (extracted for request scope wrapping)\r\n const executeHandler = async (request: FastifyRequest, reply: FastifyReply) => {\r\n // Create execution context if needed (shared between guards, interceptors, and custom params)\r\n const executionContext = createContext ? createContext(request, reply) : null;\r\n \r\n // 1. Execute guards (if any)\r\n if (hasGuards && executionContext) {\r\n await this.executeGuardsOptimized(guardInstances, executionContext);\r\n }\r\n \r\n // 2. Execute middleware (if any)\r\n if (hasMiddleware) {\r\n await this.executeMiddlewareChain(middlewareInstances, request, reply);\r\n }\r\n \r\n // 3. Prepare the core handler function\r\n const coreHandler = async (): Promise<unknown> => {\r\n let args: unknown[] | undefined;\r\n if (hasParams) {\r\n args = await this.resolveAllParams(\r\n compiledResolvers,\r\n customParamsMeta,\r\n maxParamIndex,\r\n request,\r\n reply,\r\n executionContext\r\n );\r\n }\r\n \r\n const result = args\r\n ? await handler.apply(controllerInstance, args)\r\n : await handler.call(controllerInstance);\r\n \r\n return result;\r\n };\r\n\r\n // 4. Execute with interceptors or directly\r\n let result: unknown;\r\n if (hasInterceptors && executionContext) {\r\n result = await this.executeInterceptorChain(\r\n interceptorInstances,\r\n executionContext,\r\n coreHandler\r\n );\r\n } else {\r\n result = await coreHandler();\r\n }\r\n \r\n // 5. Set status code if specified\r\n if (statusCode) reply.status(statusCode);\r\n \r\n return result;\r\n };\r\n\r\n // Unified route handler - wraps execution in request scope for request-scoped DI\r\n const routeHandler: CompiledHandler = async (request, reply) => {\r\n return requestScopeStorage.runAsync(() => executeHandler(request, reply));\r\n };\r\n\r\n // Register with Fastify\r\n const method = route.method.toLowerCase() as 'get' | 'post' | 'put' | 'delete' | 'patch' | 'options' | 'head';\r\n this.server[method](fullPath, routeHandler);\r\n\r\n // Log route registration\r\n if (!silent) console.log(` → ${route.method.padEnd(7)} ${fullPath}`);\r\n }\r\n\r\n /**\r\n * OPTIMIZATION: Compile parameter resolvers at route registration time\r\n * Each resolver is a pre-built extractor function\r\n */\r\n private compileParamResolvers(paramsMeta: ParamMetadata[]): CompiledParamResolver[] {\r\n if (paramsMeta.length === 0) return [];\r\n\r\n return paramsMeta.map(param => {\r\n const extractor = this.createParamExtractor(param);\r\n return {\r\n index: param.index,\r\n extract: extractor,\r\n zodSchema: param.zodSchema,\r\n validationLabel: `${param.type}${param.key ? ` (${param.key})` : ''}`\r\n };\r\n });\r\n }\r\n\r\n /**\r\n * OPTIMIZATION: Create a specialized extractor function for each param type\r\n * This avoids switch statements at runtime\r\n */\r\n private createParamExtractor(param: ParamMetadata): ParamExtractor {\r\n const key = param.key;\r\n\r\n switch (param.type) {\r\n case ParamType.BODY:\r\n return key\r\n ? (ctx) => (ctx.body as Record<string, unknown>)?.[key]\r\n : (ctx) => ctx.body;\r\n \r\n case ParamType.QUERY:\r\n return key\r\n ? (ctx) => ctx.query[key]\r\n : (ctx) => ctx.query;\r\n \r\n case ParamType.PARAM:\r\n return key\r\n ? (ctx) => ctx.params[key]\r\n : (ctx) => ctx.params;\r\n \r\n case ParamType.HEADERS:\r\n const headerKey = key?.toLowerCase();\r\n return headerKey\r\n ? (ctx) => ctx.request.headers[headerKey]\r\n : (ctx) => ctx.request.headers;\r\n \r\n case ParamType.REQUEST:\r\n return (ctx) => ctx.request;\r\n \r\n case ParamType.REPLY:\r\n return (ctx) => ctx.reply;\r\n \r\n case ParamType.CONTEXT:\r\n return (ctx) => ctx;\r\n \r\n default:\r\n return () => undefined;\r\n }\r\n }\r\n\r\n /**\r\n * Resolve all parameters including both built-in and custom param decorators\r\n */\r\n private async resolveAllParams(\r\n compiledResolvers: CompiledParamResolver[],\r\n customParams: CustomParamMetadata[],\r\n maxIndex: number,\r\n request: FastifyRequest,\r\n reply: FastifyReply,\r\n executionContext: ExecutionContext | null\r\n ): Promise<unknown[]> {\r\n // Build route context once for built-in resolvers\r\n const routeContext: RouteContext = {\r\n request,\r\n reply,\r\n params: request.params as Record<string, string>,\r\n query: request.query as Record<string, unknown>,\r\n body: request.body,\r\n };\r\n\r\n // Pre-allocate array\r\n const args = new Array(maxIndex + 1);\r\n\r\n // Resolve built-in params synchronously\r\n for (let i = 0; i < compiledResolvers.length; i++) {\r\n const resolver = compiledResolvers[i];\r\n let value = resolver.extract(routeContext);\r\n\r\n // Validate if schema present\r\n if (resolver.zodSchema) {\r\n const result = resolver.zodSchema.safeParse(value);\r\n if (!result.success) {\r\n throw new ValidationException(\r\n result.error,\r\n `Validation failed for ${resolver.validationLabel}`\r\n );\r\n }\r\n value = result.data;\r\n }\r\n\r\n args[resolver.index] = value;\r\n }\r\n\r\n // Resolve custom params (potentially async)\r\n if (customParams.length > 0) {\r\n // Create execution context if not already created\r\n const ctx = executionContext ?? new ExecutionContextImpl(\r\n request,\r\n reply,\r\n {} as Constructor,\r\n ''\r\n );\r\n\r\n // Execute custom param factories (support async)\r\n for (const customParam of customParams) {\r\n const value = await customParam.factory(customParam.data, ctx);\r\n args[customParam.index] = value;\r\n }\r\n }\r\n\r\n return args;\r\n }\r\n\r\n /**\r\n * OPTIMIZATION: Pre-resolve guard instances at route registration\r\n */\r\n private resolveGuardInstances(guards: GuardClass[]): CanActivate[] {\r\n return guards.map(GuardClass => {\r\n // Check cache first\r\n let instance = this.guardCache.get(GuardClass);\r\n if (instance) return instance;\r\n\r\n // Resolve from container\r\n try {\r\n instance = this.container.resolve(GuardClass) as CanActivate;\r\n } catch (error) {\r\n throw new Error(\r\n `Failed to resolve guard ${GuardClass.name}. ` +\r\n `Make sure it is decorated with @Injectable(). ` +\r\n `Original error: ${error instanceof Error ? error.message : String(error)}`\r\n );\r\n }\r\n\r\n // Verify interface\r\n if (typeof instance.canActivate !== 'function') {\r\n throw new Error(\r\n `${GuardClass.name} does not implement CanActivate interface. ` +\r\n `The guard must have a canActivate(context: ExecutionContext) method.`\r\n );\r\n }\r\n\r\n // Cache for future use\r\n this.guardCache.set(GuardClass, instance);\r\n return instance;\r\n });\r\n }\r\n\r\n /**\r\n * OPTIMIZATION: Execute guards using pre-resolved instances\r\n */\r\n private async executeGuardsOptimized(\r\n guardInstances: CanActivate[],\r\n context: ExecutionContextImpl\r\n ): Promise<void> {\r\n for (let i = 0; i < guardInstances.length; i++) {\r\n const result = await guardInstances[i].canActivate(context);\r\n if (result !== true) {\r\n throw new ForbiddenException(\r\n `Access denied by guard`\r\n );\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * OPTIMIZATION: Pre-resolve middleware instances at route registration\r\n */\r\n private resolveMiddlewareInstances(middleware: MiddlewareClass[]): RiktaMiddleware[] {\r\n return middleware.map(MiddlewareClass => {\r\n // Check cache first\r\n let instance = this.middlewareCache.get(MiddlewareClass);\r\n if (instance) return instance;\r\n\r\n // Resolve from container\r\n try {\r\n instance = this.container.resolve(MiddlewareClass) as RiktaMiddleware;\r\n } catch (error) {\r\n throw new Error(\r\n `Failed to resolve middleware ${MiddlewareClass.name}. ` +\r\n `Make sure it is decorated with @Injectable(). ` +\r\n `Original error: ${error instanceof Error ? error.message : String(error)}`\r\n );\r\n }\r\n\r\n // Verify interface\r\n if (typeof instance.use !== 'function') {\r\n throw new Error(\r\n `${MiddlewareClass.name} does not implement RiktaMiddleware interface. ` +\r\n `The middleware must have a use(req, res, next) method.`\r\n );\r\n }\r\n\r\n // Cache for future use\r\n this.middlewareCache.set(MiddlewareClass, instance);\r\n return instance;\r\n });\r\n }\r\n\r\n /**\r\n * Execute middleware chain in order\r\n * Each middleware must call next() to continue\r\n */\r\n private async executeMiddlewareChain(\r\n middlewareInstances: RiktaMiddleware[],\r\n request: FastifyRequest,\r\n reply: FastifyReply\r\n ): Promise<void> {\r\n let index = 0;\r\n\r\n const next = async (): Promise<void> => {\r\n if (index < middlewareInstances.length) {\r\n const middleware = middlewareInstances[index++];\r\n await middleware.use(request, reply, next);\r\n }\r\n };\r\n\r\n await next();\r\n }\r\n\r\n /**\r\n * OPTIMIZATION: Pre-resolve interceptor instances at route registration\r\n */\r\n private resolveInterceptorInstances(interceptors: InterceptorClass[]): Interceptor[] {\r\n return interceptors.map(InterceptorClass => {\r\n // Check cache first\r\n let instance = this.interceptorCache.get(InterceptorClass);\r\n if (instance) return instance;\r\n\r\n // Resolve from container\r\n try {\r\n instance = this.container.resolve(InterceptorClass) as Interceptor;\r\n } catch (error) {\r\n throw new Error(\r\n `Failed to resolve interceptor ${InterceptorClass.name}. ` +\r\n `Make sure it is decorated with @Injectable(). ` +\r\n `Original error: ${error instanceof Error ? error.message : String(error)}`\r\n );\r\n }\r\n\r\n // Verify interface\r\n if (typeof instance.intercept !== 'function') {\r\n throw new Error(\r\n `${InterceptorClass.name} does not implement Interceptor interface. ` +\r\n `The interceptor must have an intercept(context, next) method.`\r\n );\r\n }\r\n\r\n // Cache for future use\r\n this.interceptorCache.set(InterceptorClass, instance);\r\n return instance;\r\n });\r\n }\r\n\r\n /**\r\n * Execute interceptor chain\r\n * Each interceptor wraps around the next, creating an onion-like execution\r\n */\r\n private async executeInterceptorChain(\r\n interceptorInstances: Interceptor[],\r\n context: ExecutionContext,\r\n coreHandler: () => Promise<unknown>\r\n ): Promise<unknown> {\r\n // Build the chain from the inside out\r\n // Last interceptor wraps the core handler\r\n // First interceptor is the outermost wrapper\r\n let handler = coreHandler;\r\n\r\n for (let i = interceptorInstances.length - 1; i >= 0; i--) {\r\n const interceptor = interceptorInstances[i];\r\n const nextHandler = handler;\r\n \r\n handler = () => {\r\n const callHandler: CallHandler = {\r\n handle: () => nextHandler()\r\n };\r\n return interceptor.intercept(context, callHandler);\r\n };\r\n }\r\n\r\n return handler();\r\n }\r\n\r\n /**\r\n * Build the full route path\r\n */\r\n private buildPath(controllerPrefix: string, routePath: string): string {\r\n const parts = [this.globalPrefix, controllerPrefix, routePath]\r\n .filter(Boolean)\r\n .join('');\r\n \r\n // Normalize multiple slashes\r\n return parts.replace(/\\/+/g, '/') || '/';\r\n }\r\n}\r\n\r\n","import 'reflect-metadata';\nimport { ExecutionContext } from '../guards/execution-context.js';\n\n/**\n * Metadata key for custom parameter decorators\n */\nexport const CUSTOM_PARAM_METADATA = Symbol.for('rikta:custom:param:metadata');\n\n/**\n * Custom parameter decorator metadata structure\n */\nexport interface CustomParamMetadata<T = unknown> {\n /** Parameter index in the method signature */\n index: number;\n /** Factory function that extracts/transforms the parameter value */\n factory: CustomParamFactory<T, unknown>;\n /** Optional data passed to the decorator */\n data?: T;\n}\n\n/**\n * Factory function type for custom parameter decorators.\n * \n * @template TData - Type of the data passed to the decorator\n * @template TResult - Type of the value returned by the factory\n * \n * @param data - Optional data passed when using the decorator (e.g., @User('email'))\n * @param ctx - Execution context providing access to request, reply, and metadata\n * @returns The value to inject as the parameter\n */\nexport type CustomParamFactory<TData = unknown, TResult = unknown> = (\n data: TData,\n ctx: ExecutionContext\n) => TResult | Promise<TResult>;\n\n/**\n * Creates a custom parameter decorator.\n * \n * This function allows you to define custom decorators that extract data from\n * the request context. The factory function receives the optional data passed\n * to the decorator and the ExecutionContext, which provides access to the\n * request, reply, and handler metadata.\n * \n * @template TData - Type of the data passed to the decorator\n * @template TResult - Type of the value returned by the factory\n * \n * @param factory - Function that receives data and ExecutionContext and returns the parameter value\n * @returns A decorator factory that can be used with optional data\n * \n * @example\n * ```typescript\n * // Create a @User() decorator to extract user from request\n * export const User = createParamDecorator<string | undefined, UserEntity>(\n * (data, ctx) => {\n * const request = ctx.getRequest<FastifyRequest & { user: UserEntity }>();\n * const user = request.user;\n * \n * // If data is provided, return that specific property\n * return data ? user?.[data as keyof UserEntity] : user;\n * }\n * );\n * \n * // Usage in controller\n * @Controller('/users')\n * export class UserController {\n * @Get('/profile')\n * getProfile(@User() user: UserEntity) {\n * return user;\n * }\n * \n * @Get('/email')\n * getEmail(@User('email') email: string) {\n * return { email };\n * }\n * }\n * ```\n * \n * @example\n * ```typescript\n * // Create a @ClientIp() decorator\n * export const ClientIp = createParamDecorator<void, string>((_, ctx) => {\n * const request = ctx.getRequest();\n * return request.ip || request.headers['x-forwarded-for'] as string || 'unknown';\n * });\n * \n * // Usage\n * @Get('/log')\n * logVisit(@ClientIp() ip: string) {\n * console.log(`Visit from ${ip}`);\n * }\n * ```\n */\nexport function createParamDecorator<TData = unknown, TResult = unknown>(\n factory: CustomParamFactory<TData, TResult>\n): (data?: TData) => ParameterDecorator {\n return (data?: TData): ParameterDecorator => {\n return (\n target: Object,\n propertyKey: string | symbol | undefined,\n parameterIndex: number\n ): void => {\n if (propertyKey === undefined) return;\n\n // Get existing custom param metadata or initialize empty array\n const existingParams: CustomParamMetadata<TData>[] =\n Reflect.getMetadata(CUSTOM_PARAM_METADATA, target.constructor, propertyKey) ?? [];\n\n // Build metadata object\n const metadata: CustomParamMetadata<TData> = {\n index: parameterIndex,\n factory: factory as CustomParamFactory<TData, unknown>,\n data,\n };\n\n // Add this param\n existingParams.push(metadata);\n\n // Store updated params\n Reflect.defineMetadata(CUSTOM_PARAM_METADATA, existingParams, target.constructor, propertyKey);\n };\n };\n}\n\n/**\n * Gets custom parameter metadata for a method.\n * \n * @param target - The controller class\n * @param propertyKey - The method name\n * @returns Array of custom parameter metadata\n */\nexport function getCustomParamMetadata<T = unknown>(\n target: Function,\n propertyKey: string | symbol\n): CustomParamMetadata<T>[] {\n return Reflect.getMetadata(CUSTOM_PARAM_METADATA, target, propertyKey) ?? [];\n}\n","/**\r\n * HTTP Exception Base Class\r\n * \r\n * Base class for all HTTP exceptions in Rikta.\r\n * Provides a standard structure for error responses.\r\n * \r\n * @example\r\n * ```typescript\r\n * // Throw directly\r\n * throw new HttpException('Something went wrong', 500);\r\n * \r\n * // With additional details\r\n * throw new HttpException({\r\n * message: 'Validation failed',\r\n * error: 'Bad Request',\r\n * details: { field: 'email', reason: 'Invalid format' }\r\n * }, 400);\r\n * ```\r\n */\r\nexport class HttpException extends Error {\r\n /**\r\n * HTTP status code\r\n */\r\n readonly statusCode: number;\r\n\r\n /**\r\n * Error response object\r\n */\r\n readonly response: HttpExceptionResponse;\r\n\r\n /**\r\n * Timestamp when the exception was created\r\n */\r\n readonly timestamp: string;\r\n\r\n constructor(\r\n response: string | HttpExceptionBody,\r\n statusCode: number = 500\r\n ) {\r\n const message = typeof response === 'string' \r\n ? response \r\n : response.message;\r\n \r\n super(message);\r\n \r\n this.name = this.constructor.name;\r\n this.statusCode = statusCode;\r\n this.timestamp = new Date().toISOString();\r\n \r\n // Build response object\r\n if (typeof response === 'string') {\r\n this.response = {\r\n statusCode,\r\n message,\r\n error: this.getDefaultError(statusCode),\r\n timestamp: this.timestamp,\r\n };\r\n } else {\r\n this.response = {\r\n statusCode,\r\n message: response.message,\r\n error: response.error ?? this.getDefaultError(statusCode),\r\n timestamp: this.timestamp,\r\n ...(response.details ? { details: response.details } : {}),\r\n ...(response.code ? { code: response.code } : {}),\r\n };\r\n }\r\n\r\n // Capture stack trace\r\n Error.captureStackTrace(this, this.constructor);\r\n }\r\n\r\n /**\r\n * Get the response object for JSON serialization\r\n */\r\n getResponse(): HttpExceptionResponse {\r\n return this.response;\r\n }\r\n\r\n /**\r\n * Get the HTTP status code\r\n */\r\n getStatus(): number {\r\n return this.statusCode;\r\n }\r\n\r\n /**\r\n * Get default error name for status code\r\n */\r\n private getDefaultError(statusCode: number): string {\r\n const errors: Record<number, string> = {\r\n 400: 'Bad Request',\r\n 401: 'Unauthorized',\r\n 403: 'Forbidden',\r\n 404: 'Not Found',\r\n 405: 'Method Not Allowed',\r\n 406: 'Not Acceptable',\r\n 408: 'Request Timeout',\r\n 409: 'Conflict',\r\n 410: 'Gone',\r\n 413: 'Payload Too Large',\r\n 415: 'Unsupported Media Type',\r\n 422: 'Unprocessable Entity',\r\n 429: 'Too Many Requests',\r\n 500: 'Internal Server Error',\r\n 501: 'Not Implemented',\r\n 502: 'Bad Gateway',\r\n 503: 'Service Unavailable',\r\n 504: 'Gateway Timeout',\r\n };\r\n return errors[statusCode] ?? 'Error';\r\n }\r\n}\r\n\r\n/**\r\n * Exception body structure for custom responses\r\n */\r\nexport interface HttpExceptionBody {\r\n /** Error message */\r\n message: string;\r\n \r\n /** Error type/name (e.g., \"Bad Request\", \"Validation Error\") */\r\n error?: string;\r\n \r\n /** Additional error details */\r\n details?: unknown;\r\n \r\n /** Application-specific error code */\r\n code?: string;\r\n}\r\n\r\n/**\r\n * Standard HTTP exception response format\r\n */\r\nexport interface HttpExceptionResponse {\r\n /** HTTP status code */\r\n statusCode: number;\r\n \r\n /** Error message */\r\n message: string;\r\n \r\n /** Error type/name */\r\n error: string;\r\n \r\n /** ISO timestamp */\r\n timestamp: string;\r\n \r\n /** Additional error details (optional) */\r\n details?: unknown;\r\n \r\n /** Application-specific error code (optional) */\r\n code?: string;\r\n \r\n /** Request path (added by filter) */\r\n path?: string;\r\n}\r\n","import type { ZodError, ZodIssue } from 'zod';\r\nimport { HttpException } from './http-exception.js';\r\n\r\n/**\r\n * Structured validation error details\r\n */\r\nexport interface ValidationErrorDetails {\r\n /** The field path where the error occurred */\r\n path: (string | number)[];\r\n /** Human-readable error message */\r\n message: string;\r\n /** Zod error code */\r\n code: string;\r\n /** Expected type/value (if applicable) */\r\n expected?: string;\r\n /** Received type/value (if applicable) */\r\n received?: string;\r\n}\r\n\r\n/**\r\n * Validation Exception\r\n * \r\n * Thrown when request validation fails using Zod schemas.\r\n * Provides detailed error information for each validation issue.\r\n * \r\n * @example\r\n * ```typescript\r\n * // The framework throws this automatically when @Body(schema) validation fails\r\n * // But you can also throw it manually:\r\n * \r\n * const result = MySchema.safeParse(data);\r\n * if (!result.success) {\r\n * throw new ValidationException(result.error);\r\n * }\r\n * ```\r\n */\r\nexport class ValidationException extends HttpException {\r\n /**\r\n * The original Zod error object\r\n */\r\n readonly zodError: ZodError;\r\n\r\n /**\r\n * Structured validation error details\r\n */\r\n readonly errors: ValidationErrorDetails[];\r\n\r\n constructor(zodError: ZodError, message: string = 'Validation failed') {\r\n // Transform Zod issues to structured format\r\n const errors = zodError.issues.map((issue: ZodIssue): ValidationErrorDetails => ({\r\n path: issue.path as (string | number)[],\r\n message: issue.message,\r\n code: issue.code,\r\n ...(('expected' in issue) ? { expected: String(issue.expected) } : {}),\r\n ...(('received' in issue) ? { received: String(issue.received) } : {}),\r\n }));\r\n\r\n super(\r\n {\r\n message,\r\n error: 'Validation Error',\r\n details: {\r\n errors,\r\n errorCount: errors.length,\r\n },\r\n },\r\n 400\r\n );\r\n\r\n this.zodError = zodError;\r\n this.errors = errors;\r\n }\r\n\r\n /**\r\n * Get formatted errors for client response\r\n */\r\n getValidationErrors(): ValidationErrorDetails[] {\r\n return this.errors;\r\n }\r\n\r\n /**\r\n * Get the flattened Zod error format\r\n */\r\n getFlattenedErrors() {\r\n return this.zodError.flatten();\r\n }\r\n\r\n /**\r\n * Get the formatted Zod error\r\n */\r\n getFormattedErrors() {\r\n return this.zodError.format();\r\n }\r\n}\r\n","import { HttpException, HttpExceptionBody } from './http-exception.js';\r\n\r\n/** 400 Bad Request - server cannot process due to client error. */\r\nexport class BadRequestException extends HttpException {\r\n constructor(response: string | HttpExceptionBody = 'Bad Request') {\r\n super(response, 400);\r\n }\r\n}\r\n\r\n/**\r\n * 401 Unauthorized\r\n * \r\n * Authentication is required and has failed or not been provided.\r\n * \r\n * @example\r\n * ```typescript\r\n * throw new UnauthorizedException('Invalid credentials');\r\n * throw new UnauthorizedException('Token expired');\r\n * ```\r\n */\r\nexport class UnauthorizedException extends HttpException {\r\n constructor(response: string | HttpExceptionBody = 'Unauthorized') {\r\n super(response, 401);\r\n }\r\n}\r\n\r\n/** 403 Forbidden - server refuses to authorize. */\r\nexport class ForbiddenException extends HttpException {\r\n constructor(response: string | HttpExceptionBody = 'Forbidden') {\r\n super(response, 403);\r\n }\r\n}\r\n\r\n/** 404 Not Found - requested resource not found. */\r\nexport class NotFoundException extends HttpException {\r\n constructor(response: string | HttpExceptionBody = 'Not Found') {\r\n super(response, 404);\r\n }\r\n}\r\n\r\n/** 405 Method Not Allowed - request method not supported. */\r\nexport class MethodNotAllowedException extends HttpException {\r\n constructor(response: string | HttpExceptionBody = 'Method Not Allowed') {\r\n super(response, 405);\r\n }\r\n}\r\n\r\n/** 406 Not Acceptable - cannot generate acceptable content per Accept headers. */\r\nexport class NotAcceptableException extends HttpException {\r\n constructor(response: string | HttpExceptionBody = 'Not Acceptable') {\r\n super(response, 406);\r\n }\r\n}\r\n\r\n/** 408 Request Timeout - server timed out waiting for request. */\r\nexport class RequestTimeoutException extends HttpException {\r\n constructor(response: string | HttpExceptionBody = 'Request Timeout') {\r\n super(response, 408);\r\n }\r\n}\r\n\r\n/**\r\n * 409 Conflict\r\n * \r\n * The request conflicts with the current state of the server.\r\n * \r\n * @example\r\n * ```typescript\r\n * throw new ConflictException('Email already exists');\r\n * throw new ConflictException('Version conflict');\r\n * ```\r\n */\r\nexport class ConflictException extends HttpException {\r\n constructor(response: string | HttpExceptionBody = 'Conflict') {\r\n super(response, 409);\r\n }\r\n}\r\n\r\n/**\r\n * 410 Gone\r\n * \r\n * The resource is no longer available and will not be available again.\r\n */\r\nexport class GoneException extends HttpException {\r\n constructor(response: string | HttpExceptionBody = 'Gone') {\r\n super(response, 410);\r\n }\r\n}\r\n\r\n/**\r\n * 413 Payload Too Large\r\n * \r\n * The request entity is larger than limits defined by the server.\r\n */\r\nexport class PayloadTooLargeException extends HttpException {\r\n constructor(response: string | HttpExceptionBody = 'Payload Too Large') {\r\n super(response, 413);\r\n }\r\n}\r\n\r\n/**\r\n * 415 Unsupported Media Type\r\n * \r\n * The media format of the requested data is not supported by the server.\r\n */\r\nexport class UnsupportedMediaTypeException extends HttpException {\r\n constructor(response: string | HttpExceptionBody = 'Unsupported Media Type') {\r\n super(response, 415);\r\n }\r\n}\r\n\r\n/**\r\n * 422 Unprocessable Entity\r\n * \r\n * The server understands the content type, but was unable to process the contained instructions.\r\n * \r\n * @example\r\n * ```typescript\r\n * throw new UnprocessableEntityException({\r\n * message: 'Validation failed',\r\n * details: [\r\n * { field: 'email', message: 'Invalid email format' },\r\n * { field: 'age', message: 'Must be a positive number' }\r\n * ]\r\n * });\r\n * ```\r\n */\r\nexport class UnprocessableEntityException extends HttpException {\r\n constructor(response: string | HttpExceptionBody = 'Unprocessable Entity') {\r\n super(response, 422);\r\n }\r\n}\r\n\r\n/**\r\n * 429 Too Many Requests\r\n * \r\n * The user has sent too many requests in a given amount of time.\r\n * \r\n * @example\r\n * ```typescript\r\n * throw new TooManyRequestsException('Rate limit exceeded. Try again in 60 seconds.');\r\n * ```\r\n */\r\nexport class TooManyRequestsException extends HttpException {\r\n constructor(response: string | HttpExceptionBody = 'Too Many Requests') {\r\n super(response, 429);\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// 5xx Server Errors\r\n// ============================================================================\r\n\r\n/**\r\n * 500 Internal Server Error\r\n * \r\n * A generic server error occurred.\r\n * \r\n * @example\r\n * ```typescript\r\n * throw new InternalServerErrorException('An unexpected error occurred');\r\n * ```\r\n */\r\nexport class InternalServerErrorException extends HttpException {\r\n constructor(response: string | HttpExceptionBody = 'Internal Server Error') {\r\n super(response, 500);\r\n }\r\n}\r\n\r\n/**\r\n * 501 Not Implemented\r\n * \r\n * The server does not support the functionality required to fulfill the request.\r\n */\r\nexport class NotImplementedException extends HttpException {\r\n constructor(response: string | HttpExceptionBody = 'Not Implemented') {\r\n super(response, 501);\r\n }\r\n}\r\n\r\n/**\r\n * 502 Bad Gateway\r\n * \r\n * The server received an invalid response from an upstream server.\r\n */\r\nexport class BadGatewayException extends HttpException {\r\n constructor(response: string | HttpExceptionBody = 'Bad Gateway') {\r\n super(response, 502);\r\n }\r\n}\r\n\r\n/**\r\n * 503 Service Unavailable\r\n * \r\n * The server is not ready to handle the request.\r\n * \r\n * @example\r\n * ```typescript\r\n * throw new ServiceUnavailableException('Service is under maintenance');\r\n * ```\r\n */\r\nexport class ServiceUnavailableException extends HttpException {\r\n constructor(response: string | HttpExceptionBody = 'Service Unavailable') {\r\n super(response, 503);\r\n }\r\n}\r\n\r\n/**\r\n * 504 Gateway Timeout\r\n * \r\n * The server did not receive a timely response from an upstream server.\r\n */\r\nexport class GatewayTimeoutException extends HttpException {\r\n constructor(response: string | HttpExceptionBody = 'Gateway Timeout') {\r\n super(response, 504);\r\n }\r\n}\r\n","import type { FastifyRequest, FastifyReply } from 'fastify';\r\nimport type { Constructor } from '../types.js';\r\n\r\n/**\r\n * HTTP argument host interface\r\n * Provides access to HTTP-specific request/response objects\r\n */\r\nexport interface HttpArgumentsHost {\r\n /**\r\n * Get the Fastify request object\r\n */\r\n getRequest<T = FastifyRequest>(): T;\r\n \r\n /**\r\n * Get the Fastify reply object\r\n */\r\n getResponse<T = FastifyReply>(): T;\r\n}\r\n\r\n/**\r\n * ExecutionContext Interface\r\n * \r\n * Provides access to the current request context, including\r\n * request/reply objects and handler metadata. Used by guards\r\n * and interceptors to access request details.\r\n * \r\n * @example\r\n * ```typescript\r\n * @Injectable()\r\n * class AuthGuard implements CanActivate {\r\n * async canActivate(context: ExecutionContext): Promise<boolean> {\r\n * const request = context.switchToHttp().getRequest();\r\n * const authHeader = request.headers.authorization;\r\n * return !!authHeader;\r\n * }\r\n * }\r\n * ```\r\n */\r\nexport interface ExecutionContext {\r\n /**\r\n * Switch to HTTP context to access request/response\r\n * \r\n * @returns HTTP arguments host\r\n */\r\n switchToHttp(): HttpArgumentsHost;\r\n\r\n /**\r\n * Get the Fastify request object\r\n * \r\n * @returns The current request instance\r\n * @deprecated Use switchToHttp().getRequest() instead\r\n */\r\n getRequest<T = FastifyRequest>(): T;\r\n\r\n /**\r\n * Get the Fastify reply object\r\n * \r\n * @returns The current reply instance\r\n * @deprecated Use switchToHttp().getResponse() instead\r\n */\r\n getReply<T = FastifyReply>(): T;\r\n\r\n /**\r\n * Get the controller class that handles the route\r\n * \r\n * @returns The controller constructor\r\n */\r\n getClass(): Constructor;\r\n\r\n /**\r\n * Get the handler method name\r\n * \r\n * @returns The method name being invoked\r\n */\r\n getHandler(): string | symbol;\r\n\r\n /**\r\n * Get handler metadata by key\r\n * \r\n * @param key - Metadata key to retrieve\r\n * @returns The metadata value if found\r\n */\r\n getMetadata<T = unknown>(key: string | symbol): T | undefined;\r\n}\r\n\r\n/**\r\n * Default ExecutionContext implementation\r\n * \r\n * @internal\r\n */\r\nexport class ExecutionContextImpl implements ExecutionContext {\r\n private readonly httpHost: HttpArgumentsHost;\r\n\r\n constructor(\r\n private readonly request: FastifyRequest,\r\n private readonly reply: FastifyReply,\r\n private readonly controllerClass: Constructor,\r\n private readonly handlerName: string | symbol,\r\n ) {\r\n // Create HTTP host once\r\n this.httpHost = {\r\n getRequest: <T = FastifyRequest>() => this.request as T,\r\n getResponse: <T = FastifyReply>() => this.reply as T,\r\n };\r\n }\r\n\r\n switchToHttp(): HttpArgumentsHost {\r\n return this.httpHost;\r\n }\r\n\r\n getRequest<T = FastifyRequest>(): T {\r\n return this.request as T;\r\n }\r\n\r\n getReply<T = FastifyReply>(): T {\r\n return this.reply as T;\r\n }\r\n\r\n getClass(): Constructor {\r\n return this.controllerClass;\r\n }\r\n\r\n getHandler(): string | symbol {\r\n return this.handlerName;\r\n }\r\n\r\n getMetadata<T = unknown>(key: string | symbol): T | undefined {\r\n return Reflect.getMetadata(key, this.controllerClass, this.handlerName as string) as T | undefined;\r\n }\r\n}\r\n","import 'reflect-metadata';\r\nimport { GUARDS_METADATA } from '../constants.js';\r\nimport type { Constructor } from '../types.js';\r\nimport type { CanActivate } from './can-activate.interface.js';\r\n\r\n/**\r\n * Type for guard constructors\r\n */\r\nexport type GuardClass = Constructor<CanActivate>;\r\n\r\n/**\r\n * @UseGuards() Decorator\r\n * \r\n * Applies one or more guards to a controller or route handler.\r\n * Guards are executed in order before the handler runs.\r\n * \r\n * Guards are resolved from the DI container, so they can have\r\n * injected dependencies. Make sure guards are decorated with @Injectable().\r\n * \r\n * @param guards - Guard classes to apply\r\n * \r\n * @example Apply guard to entire controller\r\n * ```typescript\r\n * @Controller('/admin')\r\n * @UseGuards(AuthGuard)\r\n * class AdminController {\r\n * @Get('/dashboard')\r\n * getDashboard() {\r\n * return { message: 'Admin dashboard' };\r\n * }\r\n * }\r\n * ```\r\n * \r\n * @example Apply guard to specific route\r\n * ```typescript\r\n * @Controller('/users')\r\n * class UserController {\r\n * @Get()\r\n * findAll() {\r\n * return []; // Public route\r\n * }\r\n * \r\n * @Post()\r\n * @UseGuards(AuthGuard)\r\n * create() {\r\n * return {}; // Protected route\r\n * }\r\n * }\r\n * ```\r\n * \r\n * @example Multiple guards (AND logic - all must pass)\r\n * ```typescript\r\n * @Controller('/admin')\r\n * @UseGuards(AuthGuard, RolesGuard)\r\n * class AdminController {\r\n * // User must be authenticated AND have correct role\r\n * }\r\n * ```\r\n * \r\n * @example Combined controller and method guards\r\n * ```typescript\r\n * @Controller('/api')\r\n * @UseGuards(AuthGuard) // Applied to all routes\r\n * class ApiController {\r\n * @Get('/public')\r\n * // Only AuthGuard runs\r\n * getPublic() {}\r\n * \r\n * @Post('/admin')\r\n * @UseGuards(AdminGuard) // Additional guard\r\n * // Both AuthGuard AND AdminGuard run\r\n * adminAction() {}\r\n * }\r\n * ```\r\n */\r\nexport function UseGuards(...guards: GuardClass[]): ClassDecorator & MethodDecorator {\r\n return (\r\n target: object,\r\n propertyKey?: string | symbol,\r\n // descriptor?: PropertyDescriptor\r\n ): void => {\r\n if (propertyKey !== undefined) {\r\n // Method decorator - store on the method\r\n const existingGuards: GuardClass[] = \r\n Reflect.getMetadata(GUARDS_METADATA, target.constructor, propertyKey) ?? [];\r\n Reflect.defineMetadata(\r\n GUARDS_METADATA, \r\n [...existingGuards, ...guards], \r\n target.constructor, \r\n propertyKey\r\n );\r\n } else {\r\n // Class decorator - store on the class\r\n const existingGuards: GuardClass[] = \r\n Reflect.getMetadata(GUARDS_METADATA, target) ?? [];\r\n Reflect.defineMetadata(\r\n GUARDS_METADATA, \r\n [...existingGuards, ...guards], \r\n target\r\n );\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Get guards metadata from a controller class and/or method\r\n * \r\n * @param target - Controller class\r\n * @param propertyKey - Method name (optional)\r\n * @returns Combined array of guard classes (controller + method)\r\n */\r\nexport function getGuardsMetadata(\r\n target: Constructor, \r\n propertyKey?: string | symbol\r\n): GuardClass[] {\r\n // Get class-level guards\r\n const classGuards: GuardClass[] = \r\n Reflect.getMetadata(GUARDS_METADATA, target) ?? [];\r\n \r\n if (!propertyKey) {\r\n return classGuards;\r\n }\r\n \r\n // Get method-level guards\r\n const methodGuards: GuardClass[] = \r\n Reflect.getMetadata(GUARDS_METADATA, target, propertyKey) ?? [];\r\n \r\n // Combine: class guards run first, then method guards\r\n return [...classGuards, ...methodGuards];\r\n}\r\n","import 'reflect-metadata';\r\nimport { MIDDLEWARE_METADATA } from '../constants.js';\r\nimport type { Constructor } from '../types.js';\r\nimport type { RiktaMiddleware } from './rikta-middleware.interface.js';\r\n\r\n/**\r\n * Type for middleware constructors\r\n */\r\nexport type MiddlewareClass = Constructor<RiktaMiddleware>;\r\n\r\n/**\r\n * @UseMiddleware() Decorator\r\n * \r\n * Applies one or more middleware to a controller or route handler.\r\n * Middleware are executed in order AFTER guards and BEFORE the handler runs.\r\n * \r\n * Middleware are resolved from the DI container, so they can have\r\n * injected dependencies. Make sure middleware are decorated with @Injectable().\r\n * \r\n * @param middleware - Middleware classes to apply\r\n * \r\n * @example Apply middleware to entire controller\r\n * ```typescript\r\n * @Controller('/api')\r\n * @UseMiddleware(LoggerMiddleware)\r\n * class ApiController {\r\n * @Get('/users')\r\n * getUsers() {\r\n * return [];\r\n * }\r\n * }\r\n * ```\r\n * \r\n * @example Apply middleware to specific route\r\n * ```typescript\r\n * @Controller('/users')\r\n * class UserController {\r\n * @Get()\r\n * findAll() {\r\n * return []; // No middleware\r\n * }\r\n * \r\n * @Post()\r\n * @UseMiddleware(RequestIdMiddleware)\r\n * create() {\r\n * return {}; // Has middleware\r\n * }\r\n * }\r\n * ```\r\n * \r\n * @example Multiple middleware (executed in order)\r\n * ```typescript\r\n * @Controller('/api')\r\n * @UseMiddleware(LoggerMiddleware, RequestIdMiddleware)\r\n * class ApiController {\r\n * // LoggerMiddleware runs first, then RequestIdMiddleware\r\n * }\r\n * ```\r\n * \r\n * @example Combined with guards (guards run first, then middleware)\r\n * ```typescript\r\n * @Controller('/admin')\r\n * @UseGuards(AuthGuard) // 1. Guards execute first\r\n * @UseMiddleware(AuditMiddleware) // 2. Middleware executes after\r\n * class AdminController {\r\n * @Get('/dashboard')\r\n * getDashboard() {\r\n * // 3. Handler executes last\r\n * return { message: 'Admin dashboard' };\r\n * }\r\n * }\r\n * ```\r\n */\r\nexport function UseMiddleware(...middleware: MiddlewareClass[]): ClassDecorator & MethodDecorator {\r\n return (\r\n target: object,\r\n propertyKey?: string | symbol,\r\n ): void => {\r\n if (propertyKey !== undefined) {\r\n // Method decorator - store on the method\r\n const existingMiddleware: MiddlewareClass[] = \r\n Reflect.getMetadata(MIDDLEWARE_METADATA, target.constructor, propertyKey) ?? [];\r\n Reflect.defineMetadata(\r\n MIDDLEWARE_METADATA, \r\n [...existingMiddleware, ...middleware], \r\n target.constructor, \r\n propertyKey\r\n );\r\n } else {\r\n // Class decorator - store on the class\r\n const existingMiddleware: MiddlewareClass[] = \r\n Reflect.getMetadata(MIDDLEWARE_METADATA, target) ?? [];\r\n Reflect.defineMetadata(\r\n MIDDLEWARE_METADATA, \r\n [...existingMiddleware, ...middleware], \r\n target\r\n );\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Get middleware metadata for a route\r\n * Combines controller-level and method-level middleware\r\n * \r\n * @param target - Controller class\r\n * @param propertyKey - Method name (optional)\r\n * @returns Array of middleware classes (controller-level first, then method-level)\r\n */\r\nexport function getMiddlewareMetadata(\r\n target: Constructor,\r\n propertyKey?: string | symbol\r\n): MiddlewareClass[] {\r\n // Get controller-level middleware\r\n const controllerMiddleware: MiddlewareClass[] = \r\n Reflect.getMetadata(MIDDLEWARE_METADATA, target) ?? [];\r\n\r\n if (!propertyKey) {\r\n return controllerMiddleware;\r\n }\r\n\r\n // Get method-level middleware\r\n const methodMiddleware: MiddlewareClass[] = \r\n Reflect.getMetadata(MIDDLEWARE_METADATA, target, propertyKey) ?? [];\r\n\r\n // Controller middleware runs first, then method middleware\r\n return [...controllerMiddleware, ...methodMiddleware];\r\n}\r\n","import 'reflect-metadata';\r\nimport { INTERCEPTORS_METADATA } from '../constants.js';\r\nimport { Constructor } from '../types.js';\r\nimport type { Interceptor } from './interceptor.interface.js';\r\n\r\n/**\r\n * Type for interceptor classes\r\n */\r\nexport type InterceptorClass = Constructor<Interceptor>;\r\n\r\n/**\r\n * Decorator to apply interceptors to a controller or route handler\r\n * \r\n * Interceptors are executed in order and can:\r\n * - Transform the response\r\n * - Add extra logic before/after the handler\r\n * - Measure execution time\r\n * - Cache responses\r\n * - Handle errors\r\n * \r\n * @param interceptors - Interceptor classes to apply\r\n * \r\n * @example\r\n * ```typescript\r\n * // Apply to entire controller\r\n * @Controller('/users')\r\n * @UseInterceptors(LoggingInterceptor, CacheInterceptor)\r\n * class UserController { ... }\r\n * \r\n * // Apply to specific route\r\n * @Controller('/users')\r\n * class UserController {\r\n * @Get('/')\r\n * @UseInterceptors(CacheInterceptor)\r\n * findAll() { ... }\r\n * }\r\n * ```\r\n */\r\nexport function UseInterceptors(...interceptors: InterceptorClass[]): ClassDecorator & MethodDecorator {\r\n return (\r\n target: object | Function,\r\n propertyKey?: string | symbol,\r\n descriptor?: PropertyDescriptor\r\n ): void => {\r\n if (propertyKey && descriptor) {\r\n // Method decorator - apply to specific route\r\n const existingInterceptors: InterceptorClass[] = \r\n Reflect.getMetadata(INTERCEPTORS_METADATA, target.constructor, propertyKey) ?? [];\r\n Reflect.defineMetadata(\r\n INTERCEPTORS_METADATA, \r\n [...existingInterceptors, ...interceptors], \r\n target.constructor, \r\n propertyKey\r\n );\r\n } else {\r\n // Class decorator - apply to all routes in controller\r\n const existingInterceptors: InterceptorClass[] = \r\n Reflect.getMetadata(INTERCEPTORS_METADATA, target) ?? [];\r\n Reflect.defineMetadata(\r\n INTERCEPTORS_METADATA, \r\n [...existingInterceptors, ...interceptors], \r\n target\r\n );\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Get interceptors metadata for a route handler\r\n * Combines controller-level and method-level interceptors\r\n * \r\n * @param controllerClass - The controller class\r\n * @param methodName - The route handler method name\r\n * @returns Array of interceptor classes (controller-level first, then method-level)\r\n */\r\nexport function getInterceptorsMetadata(\r\n controllerClass: Constructor,\r\n methodName: string | symbol\r\n): InterceptorClass[] {\r\n // Get controller-level interceptors\r\n const controllerInterceptors: InterceptorClass[] = \r\n Reflect.getMetadata(INTERCEPTORS_METADATA, controllerClass) ?? [];\r\n \r\n // Get method-level interceptors\r\n const methodInterceptors: InterceptorClass[] = \r\n Reflect.getMetadata(INTERCEPTORS_METADATA, controllerClass, methodName) ?? [];\r\n \r\n // Controller interceptors run first, then method interceptors\r\n return [...controllerInterceptors, ...methodInterceptors];\r\n}\r\n","import 'reflect-metadata';\r\nimport Fastify, { FastifyInstance } from 'fastify';\r\nimport { Container } from './container/container.js';\r\nimport { Router } from './router/router.js';\r\nimport { registry } from './registry.js';\r\nimport { discoverModules, getCallerDirectory } from './discovery.js';\r\nimport { ProviderMetadata } from './decorators/provider.decorator.js';\r\nimport { EventBus } from './lifecycle/event-bus.js';\r\nimport { OnEventMetadata, ON_EVENT_METADATA } from './lifecycle/on.decorator.js';\r\nimport { \r\n OnProviderInit,\r\n OnProviderDestroy,\r\n OnApplicationListen,\r\n OnApplicationShutdown \r\n} from './lifecycle/interfaces.js';\r\nimport { Constructor, RiktaConfig, RiktaApplication, InjectableOptions } from './types.js';\r\nimport { DEFAULT_CONFIG, PROVIDER_METADATA, INJECTABLE_METADATA } from './constants.js';\r\nimport { \r\n GlobalExceptionFilter, \r\n ExceptionFilter, \r\n createExceptionHandler,\r\n getCatchMetadata\r\n} from './exceptions/index.js';\r\nimport { loadEnvFiles } from './config/env-loader.js';\r\n\r\n/**\r\n * RiktaFactory - Bootstrap the application\r\n * \r\n * Creates and initializes the Rikta application with auto-discovery.\r\n * All classes decorated with @Controller are automatically registered.\r\n * \r\n * .env files are loaded automatically at the start of create(), so environment\r\n * variables are immediately available in your main script.\r\n */\r\nexport class RiktaFactory {\r\n /**\r\n * Create and bootstrap the application\r\n * \r\n * .env files are loaded automatically before any initialization,\r\n * making environment variables available immediately.\r\n * \r\n * @example\r\n * ```typescript\r\n * // Auto-discovery from current directory (default)\r\n * // process.env variables are available immediately after this line\r\n * const app = await Rikta.create({ port: 3000 });\r\n * \r\n * // Auto-discovery from specific paths\r\n * const app = await Rikta.create({\r\n * autowired: ['./src/controllers', './src/services'],\r\n * port: 3000\r\n * });\r\n * ```\r\n */\r\n static async create(config: RiktaConfig = {}): Promise<RiktaApplication> {\r\n // Load .env files FIRST, before anything else\r\n // This ensures environment variables are available immediately\r\n loadEnvFiles();\r\n \r\n const silent = config.silent ?? false;\r\n if (!silent) console.log('\\n🚀 Rikta Framework Starting...\\n');\r\n const callerDir = getCallerDirectory();\r\n let discoveredFiles: string[] = [];\r\n \r\n // Auto-discovery: scan for controllers and services\r\n if (!config.controllers && config.autowired !== false) {\r\n const patterns = Array.isArray(config.autowired) && config.autowired.length > 0 \r\n ? config.autowired \r\n : ['./**'];\r\n discoveredFiles = await discoverModules({\r\n patterns,\r\n cwd: callerDir,\r\n strict: config.strictDiscovery ?? false,\r\n onImportError: config.onDiscoveryError,\r\n });\r\n }\r\n \r\n const app = new RiktaApplicationImpl(config);\r\n await app.init(discoveredFiles);\r\n return app;\r\n }\r\n}\r\n\r\n/**\r\n * Internal application implementation\r\n */\r\nclass RiktaApplicationImpl implements RiktaApplication {\r\n readonly server: FastifyInstance;\r\n private readonly container: Container;\r\n private readonly config: Required<Omit<RiktaConfig, 'controllers' | 'providers' | 'autowired' | 'exceptionFilter' | 'exceptionFilters' | 'strictDiscovery' | 'onDiscoveryError'>> & Pick<RiktaConfig, 'controllers' | 'providers' | 'exceptionFilter' | 'exceptionFilters'> & { silent: boolean };\r\n private readonly router: Router;\r\n private readonly events: EventBus;\r\n private readonly initializedProviders: Array<{ instance: unknown; priority: number; name: string }> = [];\r\n private readonly customExceptionFilters = new Map<Function, ExceptionFilter>();\r\n private readonly startTime = Date.now();\r\n private isListening = false;\r\n private address = '';\r\n\r\n constructor(config: RiktaConfig) {\r\n const silent = config.silent ?? false;\r\n this.config = {\r\n port: config.port ?? DEFAULT_CONFIG.port,\r\n host: config.host ?? DEFAULT_CONFIG.host,\r\n // If silent mode, disable logger unless explicitly set\r\n logger: config.logger ?? (silent ? false : DEFAULT_CONFIG.logger),\r\n prefix: config.prefix ?? DEFAULT_CONFIG.prefix,\r\n silent: silent,\r\n controllers: config.controllers,\r\n providers: config.providers,\r\n exceptionFilter: config.exceptionFilter,\r\n exceptionFilters: config.exceptionFilters,\r\n };\r\n\r\n this.server = Fastify({ logger: this.config.logger });\r\n this.container = Container.getInstance();\r\n this.router = new Router(this.server, this.container, this.config.prefix);\r\n \r\n // Create and register EventBus\r\n this.events = new EventBus();\r\n this.container.registerInstance(EventBus, this.events);\r\n \r\n // Setup global exception handler\r\n this.setupExceptionHandler();\r\n }\r\n\r\n /**\r\n * Setup global exception handler\r\n */\r\n private setupExceptionHandler(): void {\r\n // Create global exception filter with config\r\n // When silent mode is enabled, also disable exception logging unless explicitly enabled\r\n const silent = this.config.silent ?? false;\r\n const globalFilter = new GlobalExceptionFilter({\r\n includeStack: this.config.exceptionFilter?.includeStack,\r\n logErrors: this.config.exceptionFilter?.logErrors ?? (silent ? false : true),\r\n });\r\n\r\n // Register custom exception filters\r\n const customFilters = this.config.exceptionFilters ?? [];\r\n for (const FilterClass of customFilters) {\r\n const metadata = getCatchMetadata(FilterClass);\r\n const filterInstance = this.container.resolve(FilterClass) as ExceptionFilter;\r\n \r\n if (metadata && metadata.exceptions.length > 0) {\r\n // Register for specific exception types\r\n for (const ExceptionType of metadata.exceptions) {\r\n this.customExceptionFilters.set(ExceptionType, filterInstance);\r\n }\r\n } else {\r\n // Catch-all filter (registered as Error)\r\n this.customExceptionFilters.set(Error, filterInstance);\r\n }\r\n }\r\n\r\n // Set Fastify error handler\r\n this.server.setErrorHandler(\r\n createExceptionHandler(globalFilter, this.customExceptionFilters)\r\n );\r\n }\r\n\r\n /**\r\n * Initialize the application\r\n */\r\n async init(discoveredFiles: string[] = []): Promise<void> {\r\n // Note: .env files are already loaded in create() before this point\r\n \r\n // Emit discovery event\r\n await this.events.emit('app:discovery', { files: discoveredFiles });\r\n\r\n // 1. Process config providers (register them in the container)\r\n await this.processConfigProviders();\r\n\r\n // 2. Process @Provider classes\r\n await this.processCustomProviders();\r\n await this.events.emit('app:providers', { \r\n count: registry.getCustomProviders().length \r\n });\r\n\r\n // 3. Get and sort providers by priority\r\n const providers = this.getSortedProviders();\r\n \r\n // 3. Register additional explicit providers\r\n const additionalProviders = this.config.providers ?? [];\r\n for (const provider of additionalProviders) {\r\n this.registerProvider(provider);\r\n }\r\n\r\n // 4. Initialize all @Injectable providers\r\n for (const { target, priority } of providers) {\r\n await this.initializeProvider(target, priority);\r\n }\r\n\r\n // 5. Register routes\r\n const controllers = this.config.controllers ?? registry.getControllers();\r\n if (!this.config.silent) console.log('📡 Registering routes:');\r\n for (const controller of controllers) {\r\n this.router.registerController(controller, this.config.silent);\r\n }\r\n await this.events.emit('app:routes', { count: controllers.length });\r\n\r\n // 6. Call onApplicationBootstrap hooks\r\n await this.callHook('onApplicationBootstrap');\r\n await this.events.emit('app:bootstrap', { \r\n providerCount: this.initializedProviders.length \r\n });\r\n\r\n if (!this.config.silent) console.log('\\n✅ Rikta is ready\\n');\r\n }\r\n\r\n /**\r\n * Process all config providers and register them in the container\r\n */\r\n private async processConfigProviders(): Promise<void> {\r\n const configProviders = registry.getConfigProviderRegistrations();\r\n if (configProviders.length === 0) return;\r\n\r\n for (const { token, providerClass } of configProviders) {\r\n // Register the config provider class in the container\r\n // This allows it to be resolved via @Autowired(token)\r\n this.container.registerProvider({\r\n provide: token,\r\n useClass: providerClass,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Process all @Provider decorated classes\r\n */\r\n private async processCustomProviders(): Promise<void> {\r\n const customProviders = registry.getCustomProviders();\r\n if (customProviders.length === 0) return;\r\n\r\n for (const ProviderClass of customProviders) {\r\n const metadata: ProviderMetadata | undefined = Reflect.getMetadata(\r\n PROVIDER_METADATA, \r\n ProviderClass\r\n );\r\n\r\n if (!metadata) continue;\r\n\r\n const providerInstance = this.container.resolve(ProviderClass) as { \r\n provide: () => unknown | Promise<unknown> \r\n };\r\n\r\n const value = await providerInstance.provide();\r\n this.container.registerValue(metadata.token, value);\r\n }\r\n }\r\n\r\n /**\r\n * Get providers sorted by priority (higher = first)\r\n */\r\n private getSortedProviders(): Array<{ target: Constructor; priority: number }> {\r\n const providers = registry.getProviders();\r\n \r\n return providers\r\n .map(target => ({\r\n target,\r\n priority: this.getProviderPriority(target),\r\n }))\r\n .sort((a, b) => b.priority - a.priority);\r\n }\r\n\r\n /**\r\n * Get priority from @Injectable() metadata\r\n */\r\n private getProviderPriority(target: Constructor): number {\r\n const options: InjectableOptions | undefined = \r\n Reflect.getMetadata(INJECTABLE_METADATA, target);\r\n return options?.priority ?? 0;\r\n }\r\n\r\n /**\r\n * Initialize a single provider\r\n */\r\n private async initializeProvider(target: Constructor, priority: number): Promise<void> {\r\n const instance = this.container.resolve(target);\r\n const name = target.name;\r\n \r\n // Track initialized provider\r\n this.initializedProviders.push({ instance, priority, name });\r\n \r\n // Call onProviderInit hook\r\n if (this.hasHook(instance, 'onProviderInit')) {\r\n await (instance as OnProviderInit).onProviderInit();\r\n }\r\n \r\n // Emit provider:init event\r\n await this.events.emit('provider:init', { provider: target, name, priority });\r\n \r\n // Register @On() event listeners from this instance\r\n this.registerEventListeners(target, instance);\r\n }\r\n\r\n /**\r\n * Register @On() decorated methods as event listeners\r\n * Tracks listeners by provider name for cleanup during shutdown\r\n */\r\n private registerEventListeners(target: Constructor, instance: unknown): void {\r\n const metadata: OnEventMetadata[] = \r\n Reflect.getMetadata(ON_EVENT_METADATA, target) ?? [];\r\n \r\n for (const { event, methodName } of metadata) {\r\n const method = (instance as Record<string, Function>)[methodName];\r\n if (typeof method === 'function') {\r\n // Register with owner tracking for cleanup\r\n this.events.on(event, method.bind(instance), target.name);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Register a provider in the container\r\n */\r\n private registerProvider(provider: Constructor): void {\r\n const instance = this.container.resolve(provider);\r\n const priority = this.getProviderPriority(provider);\r\n this.initializedProviders.push({ instance, priority, name: provider.name });\r\n }\r\n\r\n /**\r\n * Call a lifecycle hook on all initialized providers\r\n */\r\n private async callHook(hookName: string): Promise<void> {\r\n for (const { instance } of this.initializedProviders) {\r\n if (this.hasHook(instance, hookName)) {\r\n await (instance as Record<string, () => Promise<void> | void>)[hookName]();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Check if an instance has a lifecycle hook\r\n */\r\n private hasHook(instance: unknown, hookName: string): boolean {\r\n return (\r\n instance !== null &&\r\n typeof instance === 'object' &&\r\n hookName in instance &&\r\n typeof (instance as Record<string, unknown>)[hookName] === 'function'\r\n );\r\n }\r\n\r\n /**\r\n * Start listening for requests\r\n */\r\n async listen(): Promise<string> {\r\n if (this.isListening) {\r\n return this.address;\r\n }\r\n\r\n this.address = await this.server.listen({\r\n port: this.config.port,\r\n host: this.config.host,\r\n });\r\n\r\n this.isListening = true;\r\n\r\n // Call onApplicationListen hooks\r\n for (const { instance } of this.initializedProviders) {\r\n if (this.hasHook(instance, 'onApplicationListen')) {\r\n await (instance as OnApplicationListen).onApplicationListen(this.address);\r\n }\r\n }\r\n\r\n // Emit app:listen event\r\n await this.events.emit('app:listen', { \r\n address: this.address, \r\n port: this.config.port \r\n });\r\n\r\n return this.address;\r\n }\r\n\r\n /**\r\n * Close the application\r\n */\r\n async close(signal?: string): Promise<void> {\r\n // Emit app:shutdown event\r\n await this.events.emit('app:shutdown', { signal });\r\n\r\n // Call hooks in REVERSE priority order\r\n const reversed = [...this.initializedProviders].reverse();\r\n \r\n for (const { instance, name } of reversed) {\r\n // Call onApplicationShutdown\r\n if (this.hasHook(instance, 'onApplicationShutdown')) {\r\n await (instance as OnApplicationShutdown).onApplicationShutdown(signal);\r\n }\r\n \r\n // Call onProviderDestroy\r\n if (this.hasHook(instance, 'onProviderDestroy')) {\r\n await (instance as OnProviderDestroy).onProviderDestroy();\r\n }\r\n \r\n // Cleanup event listeners registered by this provider\r\n this.events.removeByOwner(name);\r\n }\r\n\r\n // Close Fastify\r\n await this.server.close();\r\n this.isListening = false;\r\n\r\n // Emit app:destroy event\r\n await this.events.emit('app:destroy', { \r\n uptime: Date.now() - this.startTime \r\n });\r\n \r\n // Final cleanup - clear all remaining listeners\r\n this.events.clear();\r\n\r\n if (!this.config.silent) console.log('\\n👋 Application closed\\n');\r\n }\r\n\r\n /**\r\n * Get the server URL\r\n */\r\n getUrl(): string {\r\n return this.address;\r\n }\r\n\r\n /**\r\n * Get the EventBus instance\r\n */\r\n getEventBus(): EventBus {\r\n return this.events;\r\n }\r\n\r\n /**\r\n * Get the DI Container instance\r\n */\r\n getContainer(): Container {\r\n return this.container;\r\n }\r\n\r\n /**\r\n * Get the Router instance\r\n * Useful for accessing router cache management methods\r\n */\r\n getRouter(): Router {\r\n return this.router;\r\n }\r\n\r\n /**\r\n * Clear all router caches (guards and middleware)\r\n * Useful for testing or hot-reload scenarios\r\n * \r\n * @example\r\n * ```typescript\r\n * // In tests\r\n * afterEach(() => {\r\n * app.clearRouterCaches();\r\n * });\r\n * ```\r\n */\r\n clearRouterCaches(): void {\r\n this.router.clearAllCaches();\r\n }\r\n}\r\n\r\nexport { RiktaFactory as Rikta };\r\n","import type { FastifyRequest, FastifyReply, FastifyError } from 'fastify';\r\nimport { HttpException } from './http-exception.js';\r\n\r\n/**\r\n * Exception context passed to filters\r\n */\r\nexport interface ExceptionContext {\r\n /** The caught exception */\r\n exception: Error;\r\n \r\n /** Fastify request object */\r\n request: FastifyRequest;\r\n \r\n /** Fastify reply object */\r\n reply: FastifyReply;\r\n \r\n /** Request path */\r\n path: string;\r\n \r\n /** HTTP method */\r\n method: string;\r\n \r\n /** Request ID (if available) */\r\n requestId?: string;\r\n}\r\n\r\n/**\r\n * Exception Filter Interface\r\n * \r\n * Implement this interface to create custom exception handlers.\r\n * Filters can catch specific exception types or handle all exceptions.\r\n * \r\n * @example\r\n * ```typescript\r\n * @Catch(ValidationException)\r\n * class ValidationExceptionFilter implements ExceptionFilter {\r\n * catch(exception: ValidationException, context: ExceptionContext) {\r\n * const { reply } = context;\r\n * reply.status(422).send({\r\n * statusCode: 422,\r\n * errors: exception.errors,\r\n * timestamp: new Date().toISOString()\r\n * });\r\n * }\r\n * }\r\n * ```\r\n */\r\nexport interface ExceptionFilter<T extends Error = Error> {\r\n /**\r\n * Handle the caught exception\r\n * \r\n * @param exception - The caught exception\r\n * @param context - Exception context with request/reply\r\n */\r\n catch(exception: T, context: ExceptionContext): void | Promise<void>;\r\n}\r\n\r\n/**\r\n * Standard error response format\r\n */\r\nexport interface ErrorResponse {\r\n /** HTTP status code */\r\n statusCode: number;\r\n \r\n /** Error message */\r\n message: string;\r\n \r\n /** Error type/name (e.g., \"Bad Request\", \"Not Found\") */\r\n error: string;\r\n \r\n /** ISO timestamp when the error occurred */\r\n timestamp: string;\r\n \r\n /** Request path that caused the error */\r\n path: string;\r\n \r\n /** Request ID for tracing (optional) */\r\n requestId?: string;\r\n \r\n /** Additional error details (optional) */\r\n details?: unknown;\r\n \r\n /** Application-specific error code (optional) */\r\n code?: string;\r\n \r\n /** Stack trace (only in development mode) */\r\n stack?: string;\r\n}\r\n\r\n/**\r\n * Global Exception Filter\r\n * \r\n * Default exception handler that catches all errors and returns\r\n * a standardized JSON response.\r\n * \r\n * Features:\r\n * - Handles HttpException with proper status codes\r\n * - Handles Fastify validation errors\r\n * - Handles unknown errors as 500 Internal Server Error\r\n * - Includes stack traces in development mode\r\n * \r\n * @example\r\n * ```typescript\r\n * // The filter is automatically registered by Rikta\r\n * // But you can customize behavior via options:\r\n * const app = await Rikta.create({\r\n * exceptionFilter: {\r\n * includeStack: process.env.NODE_ENV !== 'production',\r\n * logErrors: true\r\n * }\r\n * });\r\n * ```\r\n */\r\nexport class GlobalExceptionFilter implements ExceptionFilter {\r\n private readonly includeStack: boolean;\r\n private readonly logErrors: boolean;\r\n\r\n constructor(options: GlobalExceptionFilterOptions = {}) {\r\n this.includeStack = options.includeStack ?? process.env.NODE_ENV !== 'production';\r\n this.logErrors = options.logErrors ?? true;\r\n }\r\n\r\n /**\r\n * Handle any exception and send standardized response\r\n */\r\n catch(exception: Error, context: ExceptionContext): void {\r\n const { request, reply, path, method } = context;\r\n const requestId = (request.id as string) ?? undefined;\r\n\r\n // Log the error\r\n if (this.logErrors) {\r\n this.logError(exception, method, path, requestId);\r\n }\r\n\r\n // Build error response\r\n const response = this.buildResponse(exception, path, requestId);\r\n\r\n // Send response\r\n reply.status(response.statusCode).send(response);\r\n }\r\n\r\n /**\r\n * Build standardized error response\r\n */\r\n private buildResponse(\r\n exception: Error, \r\n path: string, \r\n requestId?: string\r\n ): ErrorResponse {\r\n // Handle HttpException\r\n if (exception instanceof HttpException) {\r\n const httpResponse = exception.getResponse();\r\n return {\r\n statusCode: httpResponse.statusCode,\r\n message: httpResponse.message,\r\n error: httpResponse.error,\r\n timestamp: httpResponse.timestamp,\r\n path,\r\n ...(requestId ? { requestId } : {}),\r\n ...(httpResponse.details ? { details: httpResponse.details } : {}),\r\n ...(httpResponse.code ? { code: httpResponse.code } : {}),\r\n ...(this.includeStack ? { stack: exception.stack } : {}),\r\n };\r\n }\r\n\r\n // Handle Fastify validation errors\r\n if (this.isFastifyValidationError(exception)) {\r\n return {\r\n statusCode: 400,\r\n message: 'Validation failed',\r\n error: 'Bad Request',\r\n timestamp: new Date().toISOString(),\r\n path,\r\n ...(requestId && { requestId }),\r\n details: (exception as FastifyError).validation,\r\n ...(this.includeStack && { stack: exception.stack }),\r\n };\r\n }\r\n\r\n // Handle Fastify errors with statusCode\r\n if (this.isFastifyError(exception)) {\r\n const fastifyError = exception as FastifyError;\r\n return {\r\n statusCode: fastifyError.statusCode ?? 500,\r\n message: fastifyError.message,\r\n error: fastifyError.code ?? 'Error',\r\n timestamp: new Date().toISOString(),\r\n path,\r\n ...(requestId && { requestId }),\r\n ...(this.includeStack && { stack: exception.stack }),\r\n };\r\n }\r\n\r\n // Handle unknown errors as 500\r\n return {\r\n statusCode: 500,\r\n message: this.includeStack ? exception.message : 'Internal Server Error',\r\n error: 'Internal Server Error',\r\n timestamp: new Date().toISOString(),\r\n path,\r\n ...(requestId && { requestId }),\r\n ...(this.includeStack && { stack: exception.stack }),\r\n };\r\n }\r\n\r\n /**\r\n * Check if error is a Fastify validation error\r\n */\r\n private isFastifyValidationError(error: Error): boolean {\r\n return 'validation' in error && Array.isArray((error as FastifyError).validation);\r\n }\r\n\r\n /**\r\n * Check if error is a Fastify error with statusCode\r\n */\r\n private isFastifyError(error: Error): boolean {\r\n return 'statusCode' in error;\r\n }\r\n\r\n /**\r\n * Log error to console\r\n */\r\n private logError(\r\n exception: Error, \r\n method: string, \r\n path: string, \r\n requestId?: string\r\n ): void {\r\n const timestamp = new Date().toISOString();\r\n const status = exception instanceof HttpException \r\n ? exception.getStatus() \r\n : 500;\r\n \r\n const prefix = status >= 500 ? '❌' : '⚠️';\r\n const reqIdStr = requestId ? ` [${requestId}]` : '';\r\n \r\n console.error(\r\n `${prefix} [${timestamp}]${reqIdStr} ${method} ${path} - ${status} ${exception.message}`\r\n );\r\n \r\n // Log stack trace for 5xx errors in development\r\n if (status >= 500 && this.includeStack && exception.stack) {\r\n console.error(exception.stack);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Options for GlobalExceptionFilter\r\n */\r\nexport interface GlobalExceptionFilterOptions {\r\n /** Include stack trace in response (default: true in development) */\r\n includeStack?: boolean;\r\n \r\n /** Log errors to console (default: true) */\r\n logErrors?: boolean;\r\n}\r\n\r\n/**\r\n * Create exception handler function for Fastify\r\n */\r\nexport function createExceptionHandler(\r\n filter: ExceptionFilter,\r\n customFilters: Map<Function, ExceptionFilter> = new Map()\r\n) {\r\n return async (\r\n error: FastifyError | Error,\r\n request: FastifyRequest,\r\n reply: FastifyReply\r\n ) => {\r\n const context: ExceptionContext = {\r\n exception: error,\r\n request,\r\n reply,\r\n path: request.url,\r\n method: request.method,\r\n requestId: request.id as string,\r\n };\r\n\r\n // Try to find a custom filter for this exception type\r\n for (const [ExceptionType, customFilter] of customFilters) {\r\n if (error instanceof ExceptionType) {\r\n return customFilter.catch(error, context);\r\n }\r\n }\r\n\r\n // Use global filter\r\n return filter.catch(error, context);\r\n };\r\n}\r\n","import 'reflect-metadata';\r\nimport { Constructor } from '../types.js';\r\n\r\n/**\r\n * Metadata key for @Catch() decorator\r\n */\r\nexport const CATCH_METADATA = Symbol('catch:metadata');\r\n\r\n/**\r\n * Metadata stored by @Catch() decorator\r\n */\r\nexport interface CatchMetadata {\r\n /** Exception types this filter handles */\r\n exceptions: Constructor<Error>[];\r\n}\r\n\r\n/**\r\n * @Catch() Decorator\r\n * \r\n * Marks a class as an exception filter and specifies which\r\n * exception types it should handle.\r\n * \r\n * If no exception types are provided, the filter catches all exceptions.\r\n * \r\n * @param exceptions - Exception types to catch (optional)\r\n * \r\n * @example Catch specific exception\r\n * ```typescript\r\n * @Catch(NotFoundException)\r\n * class NotFoundExceptionFilter implements ExceptionFilter {\r\n * catch(exception: NotFoundException, context: ExceptionContext) {\r\n * const { reply, path } = context;\r\n * reply.status(404).send({\r\n * statusCode: 404,\r\n * message: exception.message,\r\n * path,\r\n * timestamp: new Date().toISOString()\r\n * });\r\n * }\r\n * }\r\n * ```\r\n * \r\n * @example Catch multiple exceptions\r\n * ```typescript\r\n * @Catch(BadRequestException, UnprocessableEntityException)\r\n * class ValidationExceptionFilter implements ExceptionFilter {\r\n * catch(exception: HttpException, context: ExceptionContext) {\r\n * const { reply } = context;\r\n * const response = exception.getResponse();\r\n * \r\n * reply.status(exception.getStatus()).send({\r\n * ...response,\r\n * type: 'VALIDATION_ERROR'\r\n * });\r\n * }\r\n * }\r\n * ```\r\n * \r\n * @example Catch all exceptions\r\n * ```typescript\r\n * @Catch()\r\n * class AllExceptionsFilter implements ExceptionFilter {\r\n * catch(exception: Error, context: ExceptionContext) {\r\n * // Handle any exception\r\n * }\r\n * }\r\n * ```\r\n */\r\nexport function Catch(...exceptions: Constructor<Error>[]): ClassDecorator {\r\n return (target) => {\r\n const metadata: CatchMetadata = {\r\n exceptions: exceptions.length > 0 ? exceptions : [],\r\n };\r\n \r\n Reflect.defineMetadata(CATCH_METADATA, metadata, target);\r\n };\r\n}\r\n\r\n/**\r\n * Get catch metadata from a filter class\r\n */\r\nexport function getCatchMetadata(target: Constructor): CatchMetadata | undefined {\r\n return Reflect.getMetadata(CATCH_METADATA, target);\r\n}\r\n","import { config as loadEnv } from 'dotenv';\nimport { existsSync } from 'fs';\nimport { resolve } from 'path';\n\n/** Ensures .env files are loaded only once. */\nlet envLoaded = false;\n\n/**\n * Load .env files with precedence: .env < .env.{NODE_ENV}\n * Called automatically at Rikta.create() start. @internal\n */\nexport function loadEnvFiles(): void {\n if (envLoaded) {\n return;\n }\n\n const env = process.env.NODE_ENV || 'development';\n const cwd = process.cwd();\n\n const baseEnvPath = resolve(cwd, '.env');\n if (existsSync(baseEnvPath)) {\n loadEnv({ path: baseEnvPath, override: false });\n }\n\n const envSpecificPath = resolve(cwd, `.env.${env}`);\n if (existsSync(envSpecificPath)) {\n loadEnv({ path: envSpecificPath, override: true });\n }\n\n envLoaded = true;\n}\n\n/** @internal */\nexport function isEnvLoaded(): boolean {\n return envLoaded;\n}\n\n/** Reset flag for testing. @internal */\nexport function resetEnvLoaded(): void {\n envLoaded = false;\n}\n","import 'reflect-metadata';\r\nimport { CONTROLLER_METADATA, INJECTABLE_METADATA } from '../constants.js';\r\nimport { container } from '../container/container.js';\r\nimport { registry } from '../registry.js';\r\n\r\n/**\r\n * Controller options\r\n */\r\nexport interface ControllerOptions {\r\n /** Route prefix for all routes in this controller */\r\n prefix?: string;\r\n}\r\n\r\n/**\r\n * @Controller() decorator\r\n * \r\n * Marks a class as a controller that handles HTTP requests.\r\n * Controllers are automatically:\r\n * - Registered in the global registry for auto-discovery\r\n * - Injectable and registered in the DI container\r\n * \r\n * @example\r\n * ```typescript\r\n * @Controller('/users')\r\n * class UserController {\r\n * @Autowired()\r\n * private userService!: UserService;\r\n * \r\n * @Get('/')\r\n * getUsers() { return []; }\r\n * \r\n * @Get('/:id')\r\n * getUser(@Param('id') id: string) { return { id }; }\r\n * }\r\n * ```\r\n */\r\nexport function Controller(prefixOrOptions?: string | ControllerOptions): ClassDecorator {\r\n return (target: Function) => {\r\n const prefix = typeof prefixOrOptions === 'string' \r\n ? prefixOrOptions \r\n : prefixOrOptions?.prefix ?? '';\r\n \r\n // Normalize prefix (ensure it starts with / if not empty)\r\n const normalizedPrefix = prefix \r\n ? (prefix.startsWith('/') ? prefix : `/${prefix}`)\r\n : '';\r\n\r\n // Store controller metadata\r\n Reflect.defineMetadata(CONTROLLER_METADATA, { prefix: normalizedPrefix }, target);\r\n \r\n // Mark as injectable\r\n Reflect.defineMetadata(INJECTABLE_METADATA, { scope: 'singleton' }, target);\r\n \r\n // Register in DI container\r\n container.register(target as new (...args: unknown[]) => unknown, { scope: 'singleton' });\r\n \r\n // Auto-register in global registry for discovery\r\n registry.registerController(target as new (...args: unknown[]) => unknown);\r\n };\r\n}\r\n","import 'reflect-metadata';\r\nimport { ROUTES_METADATA, HTTP_CODE_METADATA } from '../constants.js';\r\nimport { HttpMethod, RouteDefinition } from '../types.js';\r\n\r\n/**\r\n * Creates a route decorator for a specific HTTP method\r\n */\r\nfunction createRouteDecorator(method: HttpMethod) {\r\n return (path: string = ''): MethodDecorator => {\r\n return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {\r\n // Normalize path\r\n const normalizedPath = path.startsWith('/') ? path : `/${path}`;\r\n \r\n // Get existing routes or initialize empty array\r\n const routes: RouteDefinition[] = \r\n Reflect.getMetadata(ROUTES_METADATA, target.constructor) ?? [];\r\n \r\n // Add this route\r\n routes.push({\r\n method,\r\n path: normalizedPath === '/' ? '' : normalizedPath,\r\n handlerName: propertyKey,\r\n });\r\n \r\n // Store updated routes\r\n Reflect.defineMetadata(ROUTES_METADATA, routes, target.constructor);\r\n \r\n return descriptor;\r\n };\r\n };\r\n}\r\n\r\n/**\r\n * @Get() decorator - Handles HTTP GET requests\r\n * \r\n * @example\r\n * ```typescript\r\n * @Get('/users')\r\n * getUsers() { return []; }\r\n * ```\r\n */\r\nexport const Get = createRouteDecorator('GET');\r\n\r\n/**\r\n * @Post() decorator - Handles HTTP POST requests\r\n * \r\n * @example\r\n * ```typescript\r\n * @Post('/users')\r\n * createUser(@Body() data: CreateUserDto) { return data; }\r\n * ```\r\n */\r\nexport const Post = createRouteDecorator('POST');\r\n\r\n/**\r\n * @Put() decorator - Handles HTTP PUT requests\r\n */\r\nexport const Put = createRouteDecorator('PUT');\r\n\r\n/**\r\n * @Patch() decorator - Handles HTTP PATCH requests\r\n */\r\nexport const Patch = createRouteDecorator('PATCH');\r\n\r\n/**\r\n * @Delete() decorator - Handles HTTP DELETE requests\r\n */\r\nexport const Delete = createRouteDecorator('DELETE');\r\n\r\n/**\r\n * @Options() decorator - Handles HTTP OPTIONS requests\r\n */\r\nexport const Options = createRouteDecorator('OPTIONS');\r\n\r\n/**\r\n * @Head() decorator - Handles HTTP HEAD requests\r\n */\r\nexport const Head = createRouteDecorator('HEAD');\r\n\r\n/**\r\n * @HttpCode() decorator - Sets the HTTP status code for a route\r\n * \r\n * @example\r\n * ```typescript\r\n * @Post('/users')\r\n * @HttpCode(201)\r\n * createUser() { return { created: true }; }\r\n * ```\r\n */\r\nexport function HttpCode(statusCode: number): MethodDecorator {\r\n return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {\r\n Reflect.defineMetadata(HTTP_CODE_METADATA, statusCode, target.constructor, propertyKey);\r\n return descriptor;\r\n };\r\n}\r\n\r\n","import 'reflect-metadata';\r\nimport type { ZodType } from 'zod';\r\nimport { PARAM_METADATA, ParamType } from '../constants.js';\r\n\r\n/**\r\n * Parameter metadata structure\r\n */\r\nexport interface ParamMetadata {\r\n index: number;\r\n type: ParamType;\r\n key?: string;\r\n /** Optional Zod schema for validation and type inference */\r\n zodSchema?: ZodType<unknown>;\r\n}\r\n\r\n/**\r\n * Type guard to check if a value is a Zod schema\r\n * Uses duck typing to detect Zod schemas without importing the full library\r\n * Compatible with both Zod v3 (_def) and Zod v4 (_zod)\r\n */\r\nfunction isZodType(value: unknown): value is ZodType<unknown> {\r\n return (\r\n value !== null &&\r\n typeof value === 'object' &&\r\n ('_zod' in value || '_def' in value) &&\r\n 'safeParse' in value &&\r\n typeof (value as { safeParse: unknown }).safeParse === 'function'\r\n );\r\n}\r\n\r\n/**\r\n * Creates a type-safe parameter decorator factory with Zod schema support\r\n * \r\n * Supports three overloads:\r\n * 1. @Decorator() - Inject the full value\r\n * 2. @Decorator('key') - Inject a specific property by key\r\n * 3. @Decorator(zodSchema) - Inject with validation and type inference\r\n */\r\nfunction createParamDecorator(type: ParamType) {\r\n // Overload signatures for type inference\r\n function decorator(): ParameterDecorator;\r\n function decorator(key: string): ParameterDecorator;\r\n function decorator<T>(schema: ZodType<T>): ParameterDecorator;\r\n function decorator<T>(keyOrSchema?: string | ZodType<T>): ParameterDecorator {\r\n return (target: Object, propertyKey: string | symbol | undefined, parameterIndex: number) => {\r\n if (propertyKey === undefined) return;\r\n \r\n // Get existing params or initialize empty array\r\n const existingParams: ParamMetadata[] = \r\n Reflect.getMetadata(PARAM_METADATA, target.constructor, propertyKey) ?? [];\r\n \r\n // Determine if we have a key string or a Zod schema\r\n const isSchema = isZodType(keyOrSchema);\r\n \r\n // Build metadata object\r\n const metadata: ParamMetadata = {\r\n index: parameterIndex,\r\n type,\r\n key: isSchema ? undefined : keyOrSchema,\r\n zodSchema: isSchema ? keyOrSchema : undefined,\r\n };\r\n \r\n // Add this param\r\n existingParams.push(metadata);\r\n \r\n // Store updated params\r\n Reflect.defineMetadata(PARAM_METADATA, existingParams, target.constructor, propertyKey);\r\n };\r\n }\r\n \r\n return decorator;\r\n}\r\n\r\n/**\r\n * @Body() decorator - Injects the request body\r\n * \r\n * Supports three modes:\r\n * 1. `@Body()` - Inject the entire request body\r\n * 2. `@Body('propertyName')` - Inject a specific property from the body\r\n * 3. `@Body(zodSchema)` - Validate and inject with type inference\r\n * \r\n * @example\r\n * ```typescript\r\n * // Inject entire body (untyped)\r\n * @Post('/users')\r\n * createUser(@Body() data: unknown) { return data; }\r\n * \r\n * // Inject specific property\r\n * @Post('/users')\r\n * createUser(@Body('name') name: string) { return { name }; }\r\n * \r\n * // Validate with Zod schema (type-safe!)\r\n * const CreateUserSchema = z.object({ name: z.string(), email: z.string().email() });\r\n * @Post('/users')\r\n * createUser(@Body(CreateUserSchema) data: z.infer<typeof CreateUserSchema>) {\r\n * // data is fully typed as { name: string; email: string }\r\n * return data;\r\n * }\r\n * ```\r\n */\r\nexport const Body = createParamDecorator(ParamType.BODY);\r\n\r\n/**\r\n * @Query() decorator - Injects query parameters\r\n * \r\n * Supports three modes:\r\n * 1. `@Query()` - Inject all query parameters\r\n * 2. `@Query('paramName')` - Inject a specific query parameter\r\n * 3. `@Query(zodSchema)` - Validate and inject with type inference\r\n * \r\n * @example\r\n * ```typescript\r\n * // Inject specific query param\r\n * @Get('/users')\r\n * getUsers(@Query('page') page: string) { return { page }; }\r\n * \r\n * // Inject all query params\r\n * @Get('/users')\r\n * getUsers(@Query() query: Record<string, unknown>) { return query; }\r\n * \r\n * // Validate with Zod schema\r\n * const PaginationSchema = z.object({ page: z.coerce.number(), limit: z.coerce.number() });\r\n * @Get('/users')\r\n * getUsers(@Query(PaginationSchema) query: z.infer<typeof PaginationSchema>) {\r\n * // query is { page: number; limit: number }\r\n * return query;\r\n * }\r\n * ```\r\n */\r\nexport const Query = createParamDecorator(ParamType.QUERY);\r\n\r\n/**\r\n * @Param() decorator - Injects route parameters\r\n * \r\n * Supports three modes:\r\n * 1. `@Param()` - Inject all route parameters\r\n * 2. `@Param('paramName')` - Inject a specific route parameter\r\n * 3. `@Param(zodSchema)` - Validate and inject with type inference\r\n * \r\n * @example\r\n * ```typescript\r\n * // Inject specific param\r\n * @Get('/users/:id')\r\n * getUser(@Param('id') id: string) { return { id }; }\r\n * \r\n * // Validate with Zod schema\r\n * const IdSchema = z.object({ id: z.string().uuid() });\r\n * @Get('/users/:id')\r\n * getUser(@Param(IdSchema) params: z.infer<typeof IdSchema>) {\r\n * // params.id is validated as UUID\r\n * return params;\r\n * }\r\n * ```\r\n */\r\nexport const Param = createParamDecorator(ParamType.PARAM);\r\n\r\n/**\r\n * @Headers() decorator - Injects request headers\r\n * \r\n * Supports three modes:\r\n * 1. `@Headers()` - Inject all headers\r\n * 2. `@Headers('headerName')` - Inject a specific header\r\n * 3. `@Headers(zodSchema)` - Validate and inject with type inference\r\n * \r\n * @example\r\n * ```typescript\r\n * // Inject specific header\r\n * @Get('/protected')\r\n * getData(@Headers('authorization') auth: string) { return { auth }; }\r\n * \r\n * // Validate with Zod schema\r\n * const AuthHeadersSchema = z.object({ authorization: z.string().startsWith('Bearer ') });\r\n * @Get('/protected')\r\n * getData(@Headers(AuthHeadersSchema) headers: z.infer<typeof AuthHeadersSchema>) {\r\n * return headers;\r\n * }\r\n * ```\r\n */\r\nexport const Headers = createParamDecorator(ParamType.HEADERS);\r\n\r\n/**\r\n * @Req() decorator - Injects the raw Fastify request object\r\n */\r\nexport const Req = createParamDecorator(ParamType.REQUEST);\r\nexport const Request = Req;\r\n\r\n/**\r\n * @Res() decorator - Injects the raw Fastify reply object\r\n */\r\nexport const Res = createParamDecorator(ParamType.REPLY);\r\nexport const Reply = Res;\r\n\r\n/**\r\n * @Ctx() decorator - Injects the full route context\r\n */\r\nexport const Ctx = createParamDecorator(ParamType.CONTEXT);\r\nexport const Context = Ctx;\r\n\r\n","import 'reflect-metadata';\r\nimport { INJECT_METADATA, AUTOWIRED_METADATA } from '../constants.js';\r\nimport { Token } from '../container/injection-token.js';\r\n\r\n/**\r\n * Metadata for autowired parameters/properties\r\n */\r\nexport interface AutowiredMetadata {\r\n token: Token;\r\n index?: number; // For constructor parameters\r\n propertyKey?: string; // For property injection\r\n optional?: boolean; // If true, undefined is injected when not found\r\n name?: string; // For named implementation injection\r\n}\r\n\r\n/**\r\n * @Autowired() decorator\r\n * \r\n * Universal dependency injection decorator for both:\r\n * - Constructor parameters\r\n * - Class properties\r\n * \r\n * Automatically infers the type when no token is provided.\r\n * \r\n * @param token - Optional injection token (class, InjectionToken, string, or symbol)\r\n * @param name - Optional name for qualified injection of named implementations\r\n * \r\n * @example Property injection (most common):\r\n * ```typescript\r\n * @Controller('/users')\r\n * export class UserController {\r\n * @Autowired()\r\n * private userService!: UserService;\r\n * \r\n * @Autowired(LOGGER) // With token for interfaces\r\n * private logger!: Logger;\r\n * }\r\n * ```\r\n * \r\n * @example Named implementation injection:\r\n * ```typescript\r\n * @Controller()\r\n * export class MailController {\r\n * @Autowired(Mailer, 'smtp')\r\n * private smtpMailer!: Mailer;\r\n * \r\n * @Autowired(Mailer, 'sendgrid')\r\n * private sendgridMailer!: Mailer;\r\n * }\r\n * ```\r\n * \r\n * @example Constructor injection:\r\n * ```typescript\r\n * @Injectable()\r\n * class ApiService {\r\n * constructor(\r\n * @Autowired() private userService: UserService,\r\n * @Autowired(CONFIG) private config: AppConfig,\r\n * @Autowired(Mailer, 'smtp') private mailer: Mailer\r\n * ) {}\r\n * }\r\n * ```\r\n */\r\nexport function Autowired(token?: Token, name?: string): ParameterDecorator & PropertyDecorator {\r\n return (\r\n target: Object,\r\n propertyKey: string | symbol | undefined,\r\n parameterIndex?: number\r\n ) => {\r\n if (typeof parameterIndex === 'number') {\r\n // Constructor parameter injection\r\n const paramTypes: (new (...args: unknown[]) => unknown)[] = \r\n Reflect.getMetadata('design:paramtypes', target) ?? [];\r\n const inferredType = paramTypes[parameterIndex];\r\n const resolvedToken = token ?? inferredType;\r\n \r\n if (!resolvedToken) {\r\n throw new Error(\r\n `@Autowired() on constructor parameter ${parameterIndex} of ${(target as Function).name} ` +\r\n `could not infer type. Please provide a token explicitly.`\r\n );\r\n }\r\n \r\n const existingInjects: AutowiredMetadata[] = \r\n Reflect.getMetadata(INJECT_METADATA, target) ?? [];\r\n \r\n existingInjects.push({\r\n token: resolvedToken as Token,\r\n index: parameterIndex,\r\n name,\r\n });\r\n \r\n Reflect.defineMetadata(INJECT_METADATA, existingInjects, target);\r\n } else if (propertyKey !== undefined) {\r\n // Property injection\r\n const inferredType = Reflect.getMetadata('design:type', target, propertyKey);\r\n const resolvedToken = token ?? inferredType;\r\n \r\n if (!resolvedToken) {\r\n throw new Error(\r\n `@Autowired() on ${target.constructor.name}.${String(propertyKey)} ` +\r\n `could not infer type. Please provide a token explicitly.`\r\n );\r\n }\r\n \r\n const existingAutowires: AutowiredMetadata[] = \r\n Reflect.getMetadata(AUTOWIRED_METADATA, target.constructor) ?? [];\r\n \r\n existingAutowires.push({\r\n token: resolvedToken,\r\n propertyKey: String(propertyKey),\r\n name,\r\n });\r\n \r\n Reflect.defineMetadata(AUTOWIRED_METADATA, existingAutowires, target.constructor);\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * @Optional() decorator\r\n * \r\n * Marks an injection as optional. If the dependency is not found,\r\n * undefined will be injected instead of throwing an error.\r\n * \r\n * @example Property injection:\r\n * ```typescript\r\n * @Controller()\r\n * export class AppController {\r\n * @Optional()\r\n * @Autowired()\r\n * private analytics?: AnalyticsService;\r\n * }\r\n * ```\r\n * \r\n * @example Constructor injection:\r\n * ```typescript\r\n * @Injectable()\r\n * class NotificationService {\r\n * constructor(\r\n * @Optional() @Autowired(SLACK) private slack?: SlackClient\r\n * ) {}\r\n * }\r\n * ```\r\n */\r\nexport function Optional(): ParameterDecorator & PropertyDecorator {\r\n return (\r\n target: Object,\r\n propertyKey: string | symbol | undefined,\r\n parameterIndex?: number\r\n ) => {\r\n if (typeof parameterIndex === 'number') {\r\n // Constructor parameter\r\n const existingInjects: AutowiredMetadata[] = \r\n Reflect.getMetadata(INJECT_METADATA, target) ?? [];\r\n \r\n let meta = existingInjects.find(m => m.index === parameterIndex);\r\n \r\n if (meta) {\r\n meta.optional = true;\r\n } else {\r\n const paramTypes: (new (...args: unknown[]) => unknown)[] = \r\n Reflect.getMetadata('design:paramtypes', target) ?? [];\r\n const paramType = paramTypes[parameterIndex];\r\n \r\n if (paramType) {\r\n existingInjects.push({\r\n token: paramType as Token,\r\n index: parameterIndex,\r\n optional: true,\r\n });\r\n }\r\n }\r\n \r\n Reflect.defineMetadata(INJECT_METADATA, existingInjects, target);\r\n } else if (propertyKey !== undefined) {\r\n // Property injection\r\n const existingAutowires: AutowiredMetadata[] = \r\n Reflect.getMetadata(AUTOWIRED_METADATA, target.constructor) ?? [];\r\n \r\n let meta = existingAutowires.find(m => m.propertyKey === String(propertyKey));\r\n \r\n if (meta) {\r\n meta.optional = true;\r\n } else {\r\n const propType = Reflect.getMetadata('design:type', target, propertyKey) as Token | undefined;\r\n \r\n if (propType) {\r\n existingAutowires.push({\r\n token: propType,\r\n propertyKey: String(propertyKey),\r\n optional: true,\r\n });\r\n }\r\n }\r\n \r\n Reflect.defineMetadata(AUTOWIRED_METADATA, existingAutowires, target.constructor);\r\n }\r\n };\r\n}\r\n\r\n","import 'reflect-metadata';\r\nimport { PROVIDER_METADATA, CONFIG_PROVIDER_METADATA } from '../constants.js';\r\nimport { Token } from '../container/injection-token.js';\r\nimport { registry } from '../registry.js';\r\nimport { Constructor } from '../types.js';\r\n\r\n/**\r\n * Provider metadata stored on the class\r\n */\r\nexport interface ProviderMetadata {\r\n token: Token;\r\n}\r\n\r\n/**\r\n * Config provider metadata stored on the class\r\n */\r\nexport interface ConfigProviderMetadata {\r\n /**\r\n * The injection token for this config provider\r\n * @example 'APP_CONFIG', 'DATABASE_CONFIG'\r\n */\r\n token: string;\r\n}\r\n\r\n/**\r\n * Convert a class name to an uppercase config token\r\n * \r\n * @param className - The class name to convert\r\n * @returns Uppercase token name\r\n * \r\n * @example\r\n * ```typescript\r\n * generateToken('AppConfigProvider') // Returns 'APP_CONFIG'\r\n * generateToken('DatabaseConfigProvider') // Returns 'DATABASE_CONFIG'\r\n * generateToken('MyCustomConfig') // Returns 'MY_CUSTOM_CONFIG'\r\n * ```\r\n */\r\nfunction generateTokenFromClassName(className: string): string {\r\n // Remove 'Provider' suffix if present\r\n let tokenName = className.replace(/Provider$/, '');\r\n \r\n // Convert camelCase/PascalCase to UPPER_SNAKE_CASE\r\n tokenName = tokenName\r\n .replace(/([A-Z])/g, '_$1')\r\n .toUpperCase()\r\n .replace(/^_/, '');\r\n \r\n // Ensure it ends with _CONFIG if not already present\r\n // But don't add it if the name already ends with CONFIG (after conversion)\r\n if (!tokenName.endsWith('_CONFIG') && tokenName !== 'CONFIG') {\r\n tokenName = `${tokenName}_CONFIG`;\r\n }\r\n \r\n return tokenName;\r\n}\r\n\r\n/**\r\n * @Provider() decorator\r\n * \r\n * Marks a class as a custom provider or config provider that will be auto-discovered.\r\n * \r\n * For **custom providers**, the class must implement a `provide()` method that returns the value.\r\n * Providers can inject dependencies via constructor or @Autowired properties,\r\n * making them perfect for complex factory logic.\r\n * \r\n * For **config providers**, the class extends AbstractConfigProvider and manages\r\n * environment variables with Zod validation and @ConfigProperty decorators.\r\n * If no token is provided for config providers, it will be auto-generated from the class name.\r\n * \r\n * @param token - The injection token this provider supplies. Required for custom providers, optional for config providers.\r\n * \r\n * @example Custom provider with provide() method:\r\n * ```typescript\r\n * const APP_CONFIG = new InjectionToken<AppConfig>('app.config');\r\n * \r\n * @Provider(APP_CONFIG)\r\n * export class AppConfigProvider {\r\n * provide(): AppConfig {\r\n * return {\r\n * name: 'My App',\r\n * version: '1.0.0',\r\n * };\r\n * }\r\n * }\r\n * ```\r\n * \r\n * @example Config provider extending AbstractConfigProvider:\r\n * ```typescript\r\n * import { AbstractConfigProvider, Provider, ConfigProperty } from '@riktajs/core';\r\n * import { z } from 'zod';\r\n * \r\n * export const APP_CONFIG = 'APP_CONFIG' as const;\r\n * \r\n * @Provider(APP_CONFIG)\r\n * export class AppConfigProvider extends AbstractConfigProvider {\r\n * schema() {\r\n * return z.object({\r\n * PORT: z.coerce.number().int().default(3000),\r\n * HOST: z.string().default('localhost'),\r\n * });\r\n * }\r\n * \r\n * @ConfigProperty() port!: number;\r\n * @ConfigProperty() host!: string;\r\n * \r\n * constructor() {\r\n * super();\r\n * this.populate();\r\n * }\r\n * }\r\n * ```\r\n * \r\n * @example Provider with dependencies:\r\n * ```typescript\r\n * const LOGGER = new InjectionToken<Logger>('logger');\r\n * \r\n * @Provider(LOGGER)\r\n * export class LoggerProvider {\r\n * constructor(@Autowired(APP_CONFIG) private config: AppConfig) {}\r\n * \r\n * provide(): Logger {\r\n * return createLogger({\r\n * appName: this.config.name,\r\n * level: this.config.debug ? 'debug' : 'info',\r\n * });\r\n * }\r\n * }\r\n * ```\r\n */\r\nexport function Provider(token?: Token): ClassDecorator {\r\n return (target: Function) => {\r\n const className = target.name;\r\n \r\n // Check if this is a config provider (extends AbstractConfigProvider)\r\n // by checking if it has a schema() method in its prototype\r\n const isConfigProvider = typeof (target.prototype as any).schema === 'function';\r\n \r\n if (isConfigProvider) {\r\n // This is a config provider - use string token and CONFIG_PROVIDER_METADATA\r\n let configToken: string;\r\n \r\n if (typeof token === 'string') {\r\n // Validate non-empty string\r\n if (token.trim() === '') {\r\n throw new Error(\r\n `@Provider: Config provider \"${className}\" token must be a non-empty string.`\r\n );\r\n }\r\n configToken = token;\r\n } else if (token === undefined) {\r\n // Auto-generate token from class name\r\n configToken = generateTokenFromClassName(className);\r\n } else {\r\n throw new Error(\r\n `@Provider: Config provider \"${className}\" requires a string token or no token for auto-generation.`\r\n );\r\n }\r\n \r\n // Validate token format for config providers\r\n if (configToken !== configToken.toUpperCase()) {\r\n throw new Error(\r\n `@Provider: Token \"${configToken}\" for config provider \"${className}\" must be UPPERCASE. ` +\r\n `Use \"${configToken.toUpperCase()}\" instead.`\r\n );\r\n }\r\n \r\n // Store config provider metadata\r\n const configMetadata: ConfigProviderMetadata = { token: configToken };\r\n Reflect.defineMetadata(CONFIG_PROVIDER_METADATA, configMetadata, target);\r\n \r\n // Register config provider in the registry\r\n registry.registerConfigProvider(\r\n configToken,\r\n target as Constructor\r\n );\r\n } else {\r\n // This is a custom provider - use PROVIDER_METADATA\r\n if (token === undefined) {\r\n throw new Error(\r\n `@Provider: Custom provider \"${className}\" requires a token parameter.`\r\n );\r\n }\r\n \r\n const metadata: ProviderMetadata = { token };\r\n Reflect.defineMetadata(PROVIDER_METADATA, metadata, target);\r\n \r\n // Register in global registry for auto-discovery\r\n registry.registerCustomProvider(target as new (...args: unknown[]) => unknown);\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Helper to retrieve config provider metadata from a class\r\n * \r\n * @param target - The class to retrieve metadata from\r\n * @returns The config provider metadata or undefined\r\n */\r\nexport function getConfigProviderMetadata(\r\n target: Constructor\r\n): ConfigProviderMetadata | undefined {\r\n return Reflect.getMetadata(CONFIG_PROVIDER_METADATA, target);\r\n}\r\n\r\n/**\r\n * Check if a class has config provider metadata\r\n * \r\n * @param target - The class to check\r\n * @returns True if the class is a config provider\r\n */\r\nexport function isConfigProvider(target: Constructor): boolean {\r\n return Reflect.hasMetadata(CONFIG_PROVIDER_METADATA, target);\r\n}\r\n\r\n","import 'reflect-metadata';\r\nimport { CONFIG_PROPERTY_METADATA } from '../constants.js';\r\n\r\n/**\r\n * Metadata for a single config property mapping\r\n */\r\nexport interface ConfigPropertyMapping {\r\n /**\r\n * The property name on the class\r\n */\r\n propertyKey: string;\r\n \r\n /**\r\n * The environment variable name to map from\r\n */\r\n envKey: string;\r\n}\r\n\r\n/**\r\n * Cache for converted property names to avoid recomputation\r\n * Map<propertyKey, envKey>\r\n */\r\nconst propertyNameCache = new Map<string, string>();\r\n\r\n/**\r\n * Convert a camelCase property name to UPPER_SNAKE_CASE\r\n * \r\n * @param propertyName - The property name to convert\r\n * @returns The converted UPPER_SNAKE_CASE name\r\n * \r\n * @example\r\n * ```typescript\r\n * toUpperSnakeCase('dbHost') // 'DB_HOST'\r\n * toUpperSnakeCase('apiKey') // 'API_KEY'\r\n * toUpperSnakeCase('port') // 'PORT'\r\n * toUpperSnakeCase('maxRetries') // 'MAX_RETRIES'\r\n * ```\r\n */\r\nfunction toUpperSnakeCase(propertyName: string): string {\r\n // Check cache first (tip: cache derived names)\r\n if (propertyNameCache.has(propertyName)) {\r\n return propertyNameCache.get(propertyName)!;\r\n }\r\n\r\n // Convert camelCase/PascalCase to UPPER_SNAKE_CASE\r\n const envKey = propertyName\r\n .replace(/([A-Z])/g, '_$1')\r\n .toUpperCase()\r\n .replace(/^_/, '');\r\n\r\n // Cache for future use\r\n propertyNameCache.set(propertyName, envKey);\r\n \r\n return envKey;\r\n}\r\n\r\n/**\r\n * @ConfigProperty() decorator\r\n * \r\n * Maps a class property to an environment variable. If no explicit env key is provided,\r\n * automatically converts the property name from camelCase to UPPER_SNAKE_CASE.\r\n * \r\n * This decorator stores metadata that will be read by AbstractConfigProvider\r\n * during the populate() phase to assign validated environment values to properties.\r\n * \r\n * @param envKey - Optional explicit environment variable name (must be UPPERCASE)\r\n * \r\n * @example Auto-mapping (property name → UPPER_SNAKE_CASE):\r\n * ```typescript\r\n * import { ConfigProperty, Provider, AbstractConfigProvider } from '@riktajs/core';\r\n * import { z } from 'zod';\r\n * \r\n * @Provider()\r\n * export class DatabaseConfigProvider extends AbstractConfigProvider {\r\n * schema() {\r\n * return z.object({\r\n * DB_HOST: z.string(),\r\n * DB_PORT: z.coerce.number().int(),\r\n * DB_NAME: z.string(),\r\n * });\r\n * }\r\n * \r\n * @ConfigProperty() // Maps to 'DB_HOST'\r\n * dbHost!: string;\r\n * \r\n * @ConfigProperty() // Maps to 'DB_PORT'\r\n * dbPort!: number;\r\n * \r\n * @ConfigProperty() // Maps to 'DB_NAME'\r\n * dbName!: string;\r\n * }\r\n * ```\r\n * \r\n * @example Custom env key mapping:\r\n * ```typescript\r\n * @Provider()\r\n * export class AppConfigProvider extends AbstractConfigProvider {\r\n * schema() {\r\n * return z.object({\r\n * PORT: z.coerce.number().int(),\r\n * NODE_ENV: z.enum(['development', 'production', 'test']),\r\n * API_SECRET_KEY: z.string(),\r\n * });\r\n * }\r\n * \r\n * @ConfigProperty('PORT')\r\n * serverPort!: number;\r\n * \r\n * @ConfigProperty('NODE_ENV')\r\n * environment!: 'development' | 'production' | 'test';\r\n * \r\n * @ConfigProperty('API_SECRET_KEY')\r\n * secret!: string;\r\n * }\r\n * ```\r\n * \r\n * @example Mixed auto and custom mapping:\r\n * ```typescript\r\n * @Provider()\r\n * export class ApiConfigProvider extends AbstractConfigProvider {\r\n * schema() {\r\n * return z.object({\r\n * API_KEY: z.string(),\r\n * API_URL: z.string().url(),\r\n * TIMEOUT: z.coerce.number().int(),\r\n * });\r\n * }\r\n * \r\n * @ConfigProperty() // Auto: apiKey → API_KEY\r\n * apiKey!: string;\r\n * \r\n * @ConfigProperty() // Auto: apiUrl → API_URL\r\n * apiUrl!: string;\r\n * \r\n * @ConfigProperty('TIMEOUT') // Custom mapping\r\n * requestTimeout!: number;\r\n * }\r\n * ```\r\n */\r\nexport function ConfigProperty(envKey?: string): PropertyDecorator {\r\n return (target: Object, propertyKey: string | symbol) => {\r\n if (typeof propertyKey === 'symbol') {\r\n throw new Error(\r\n `@ConfigProperty: Symbol properties are not supported. ` +\r\n `Property \"${String(propertyKey)}\" must be a string.`\r\n );\r\n }\r\n\r\n // Determine the environment variable name\r\n const finalEnvKey = envKey ?? toUpperSnakeCase(propertyKey);\r\n\r\n // Validate env key format\r\n if (!finalEnvKey || typeof finalEnvKey !== 'string') {\r\n throw new Error(\r\n `@ConfigProperty: Invalid env key for property \"${propertyKey}\". ` +\r\n `Env key must be a non-empty string.`\r\n );\r\n }\r\n\r\n // Ensure env key is uppercase (convention)\r\n if (finalEnvKey !== finalEnvKey.toUpperCase()) {\r\n throw new Error(\r\n `@ConfigProperty: Env key \"${finalEnvKey}\" for property \"${propertyKey}\" must be UPPERCASE. ` +\r\n `Use \"${finalEnvKey.toUpperCase()}\" instead.`\r\n );\r\n }\r\n\r\n // Get existing metadata or initialize\r\n const constructor = target.constructor;\r\n const existingMappings: ConfigPropertyMapping[] =\r\n Reflect.getMetadata(CONFIG_PROPERTY_METADATA, constructor) || [];\r\n\r\n // Check for duplicate property decorations\r\n const duplicate = existingMappings.find(m => m.propertyKey === propertyKey);\r\n if (duplicate) {\r\n throw new Error(\r\n `@ConfigProperty: Property \"${propertyKey}\" on class \"${constructor.name}\" ` +\r\n `is already decorated. Remove the duplicate @ConfigProperty decorator.`\r\n );\r\n }\r\n\r\n // Check for duplicate env key mappings\r\n const duplicateEnvKey = existingMappings.find(m => m.envKey === finalEnvKey);\r\n if (duplicateEnvKey) {\r\n throw new Error(\r\n `@ConfigProperty: Env key \"${finalEnvKey}\" is already mapped to property \"${duplicateEnvKey.propertyKey}\" ` +\r\n `on class \"${constructor.name}\". Each env key can only be mapped to one property.`\r\n );\r\n }\r\n\r\n // Add the new mapping\r\n const newMapping: ConfigPropertyMapping = {\r\n propertyKey,\r\n envKey: finalEnvKey,\r\n };\r\n\r\n const updatedMappings = [...existingMappings, newMapping];\r\n\r\n // Store metadata\r\n Reflect.defineMetadata(CONFIG_PROPERTY_METADATA, updatedMappings, constructor);\r\n };\r\n}\r\n\r\n/**\r\n * Helper to retrieve all config property mappings from a class\r\n * \r\n * @param target - The class constructor to retrieve mappings from\r\n * @returns Array of property mappings, or empty array if none defined\r\n * \r\n * @example\r\n * ```typescript\r\n * const mappings = getConfigPropertyMappings(AppConfigProvider);\r\n * console.log(mappings);\r\n * // [\r\n * // { propertyKey: 'dbHost', envKey: 'DB_HOST' },\r\n * // { propertyKey: 'dbPort', envKey: 'DB_PORT' }\r\n * // ]\r\n * ```\r\n */\r\nexport function getConfigPropertyMappings(target: Function): ConfigPropertyMapping[] {\r\n return Reflect.getMetadata(CONFIG_PROPERTY_METADATA, target) || [];\r\n}\r\n\r\n/**\r\n * Check if a class has any @ConfigProperty decorated properties\r\n * \r\n * @param target - The class constructor to check\r\n * @returns True if the class has at least one @ConfigProperty\r\n */\r\nexport function hasConfigProperties(target: Function): boolean {\r\n const mappings = getConfigPropertyMappings(target);\r\n return mappings.length > 0;\r\n}\r\n\r\n/**\r\n * Clear the property name conversion cache\r\n * \r\n * @internal Used for testing\r\n */\r\nexport function clearPropertyNameCache(): void {\r\n propertyNameCache.clear();\r\n}\r\n","import 'reflect-metadata';\n\n/**\n * Type for class decorators\n */\ntype ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;\n\n/**\n * Type for method decorators\n */\ntype MethodDecorator = <T>(\n target: Object,\n propertyKey: string | symbol,\n descriptor: TypedPropertyDescriptor<T>\n) => TypedPropertyDescriptor<T> | void;\n\n/**\n * Type for property decorators\n */\ntype PropertyDecorator = (target: Object, propertyKey: string | symbol) => void;\n\n/**\n * Union type for all decorator types that can be composed\n */\ntype AnyDecorator = ClassDecorator | MethodDecorator | PropertyDecorator;\n\n/**\n * Applies multiple decorators to a single target.\n * \n * This utility function allows you to compose multiple decorators into a single\n * decorator, making it easier to create reusable decorator combinations.\n * Decorators are applied in reverse order (last to first), matching TypeScript's\n * decorator application order.\n * \n * @param decorators - The decorators to compose\n * @returns A composed decorator that applies all the provided decorators\n * \n * @example\n * ```typescript\n * // Create a composed @Auth decorator\n * import { applyDecorators, UseGuards, SetMetadata } from '@riktajs/core';\n * import { ApiBearerAuth, ApiUnauthorizedResponse } from '@riktajs/swagger';\n * \n * export function Auth(...roles: Role[]) {\n * return applyDecorators(\n * SetMetadata('roles', roles),\n * UseGuards(AuthGuard, RolesGuard),\n * ApiBearerAuth(),\n * ApiUnauthorizedResponse({ description: 'Unauthorized' })\n * );\n * }\n * \n * // Usage in controller\n * @Controller('/admin')\n * export class AdminController {\n * @Auth('admin')\n * @Get('/dashboard')\n * getDashboard() {\n * return { message: 'Admin dashboard' };\n * }\n * }\n * ```\n * \n * @example\n * ```typescript\n * // Compose validation decorators\n * export const ValidatedBody = (schema: ZodSchema) => applyDecorators(\n * ApiBody({ type: schema }),\n * UsePipes(new ZodValidationPipe(schema))\n * );\n * ```\n * \n * @example\n * ```typescript\n * // Create a public endpoint decorator\n * export const Public = () => applyDecorators(\n * SetMetadata('isPublic', true),\n * ApiOperation({ summary: 'Public endpoint' })\n * );\n * ```\n */\nexport function applyDecorators(\n ...decorators: AnyDecorator[]\n): MethodDecorator & ClassDecorator & PropertyDecorator {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return ((\n target: any,\n propertyKey?: string | symbol,\n descriptor?: TypedPropertyDescriptor<any>\n ) => {\n // Apply decorators in reverse order to match TypeScript's decorator application order\n for (const decorator of decorators.reverse()) {\n if (descriptor) {\n // Method decorator\n const result = (decorator as MethodDecorator)(target, propertyKey!, descriptor);\n if (result) {\n descriptor = result;\n }\n } else if (propertyKey !== undefined) {\n // Property decorator\n (decorator as PropertyDecorator)(target, propertyKey);\n } else {\n // Class decorator\n const result = (decorator as ClassDecorator)(target);\n if (result) {\n return result;\n }\n }\n }\n\n if (descriptor) {\n return descriptor;\n }\n }) as MethodDecorator & ClassDecorator & PropertyDecorator;\n}\n\n/**\n * Sets metadata on a class or method.\n * \n * This is a utility decorator for storing custom metadata that can be\n * retrieved later using ExecutionContext.getMetadata() or Reflect.getMetadata().\n * \n * @param key - The metadata key (string or Symbol)\n * @param value - The metadata value\n * @returns A decorator that sets the metadata\n * \n * @example\n * ```typescript\n * // Define roles for authorization\n * @SetMetadata('roles', ['admin', 'moderator'])\n * @Get('/admin')\n * adminEndpoint() {\n * return { admin: true };\n * }\n * \n * // Read in guard\n * class RolesGuard implements CanActivate {\n * canActivate(context: ExecutionContext) {\n * const roles = context.getMetadata<string[]>('roles');\n * // Check user has required role...\n * }\n * }\n * ```\n * \n * @example\n * ```typescript\n * // Create a custom @Roles decorator using SetMetadata\n * export const Roles = (...roles: string[]) => SetMetadata('roles', roles);\n * \n * // Usage\n * @Roles('admin')\n * @Get('/admin')\n * adminOnly() {}\n * ```\n */\nexport function SetMetadata<T = unknown>(\n key: string | symbol,\n value: T\n): MethodDecorator & ClassDecorator {\n const decoratorFactory = (\n target: Object,\n propertyKey?: string | symbol,\n descriptor?: TypedPropertyDescriptor<unknown>\n ): void => {\n if (descriptor) {\n // Method decorator - set metadata on the method\n Reflect.defineMetadata(key, value, target.constructor, propertyKey!);\n } else {\n // Class decorator - set metadata on the class\n Reflect.defineMetadata(key, value, target);\n }\n };\n\n return decoratorFactory as MethodDecorator & ClassDecorator;\n}\n","import 'reflect-metadata';\r\n\r\n/**\r\n * @Middleware() Decorator\r\n * \r\n * Marks a class as a middleware that can be used with @UseMiddleware().\r\n * Classes decorated with @Middleware() are automatically registered as\r\n * injectable singletons in the DI container.\r\n * \r\n * Middleware execute AFTER guards and BEFORE the route handler.\r\n * They have access to the raw Fastify Request and Reply objects.\r\n * \r\n * @example Basic logger middleware\r\n * ```typescript\r\n * import { Middleware, RiktaMiddleware, NextFunction } from '@riktajs/core';\r\n * import type { FastifyRequest, FastifyReply } from 'fastify';\r\n * \r\n * @Middleware()\r\n * export class LoggerMiddleware implements RiktaMiddleware {\r\n * use(req: FastifyRequest, res: FastifyReply, next: NextFunction): void {\r\n * console.log(`${req.method} ${req.url}`);\r\n * next();\r\n * }\r\n * }\r\n * ```\r\n * \r\n * @example Middleware with dependency injection\r\n * ```typescript\r\n * import { Middleware, RiktaMiddleware, NextFunction, Autowired } from '@riktajs/core';\r\n * \r\n * @Middleware()\r\n * export class MetricsMiddleware implements RiktaMiddleware {\r\n * constructor(@Autowired() private metricsService: MetricsService) {}\r\n * \r\n * use(req: FastifyRequest, res: FastifyReply, next: NextFunction): void {\r\n * const start = Date.now();\r\n * res.raw.on('finish', () => {\r\n * this.metricsService.recordLatency(req.url, Date.now() - start);\r\n * });\r\n * next();\r\n * }\r\n * }\r\n * ```\r\n * \r\n * @example Using middleware on controller\r\n * ```typescript\r\n * @Controller('/api')\r\n * @UseMiddleware(LoggerMiddleware, MetricsMiddleware)\r\n * export class ApiController {\r\n * // Middleware runs for all routes in this controller\r\n * }\r\n * ```\r\n */\r\nexport function Middleware(): ClassDecorator {\r\n return (target: Function) => {\r\n // Mark as middleware\r\n Reflect.defineMetadata('middleware', true, target);\r\n \r\n // Also mark as injectable for DI resolution\r\n Reflect.defineMetadata('injectable', true, target);\r\n };\r\n}\r\n","import { z, ZodSchema } from 'zod';\r\nimport { getConfigPropertyMappings } from '../decorators/config-property.decorator.js';\r\nimport { loadEnvFiles } from './env-loader.js';\r\n\r\n/**\r\n * Exception thrown when config validation fails\r\n */\r\nexport class ConfigValidationException extends Error {\r\n constructor(\r\n public readonly errors: z.ZodError,\r\n providerName: string\r\n ) {\r\n // Zod v4 uses .issues instead of .errors\r\n const errorMessages = errors.issues\r\n .map(err => ` - ${err.path.join('.')}: ${err.message}`)\r\n .join('\\n');\r\n \r\n super(\r\n `Configuration validation failed for ${providerName}:\\n${errorMessages}\\n\\n` +\r\n `Please check your .env file and ensure all required variables are set correctly.`\r\n );\r\n this.name = 'ConfigValidationException';\r\n }\r\n}\r\n\r\n/**\r\n * Abstract base class for configuration providers\r\n * \r\n * This class handles:\r\n * - Validating environment variables against a Zod schema\r\n * - Populating decorated properties with validated values\r\n * - Caching validated configuration\r\n * \r\n * Note: .env files are loaded automatically at the start of Rikta.create(),\r\n * so they are available immediately in your main script and before any\r\n * config provider is instantiated.\r\n * \r\n * Child classes must:\r\n * 1. Extend this class\r\n * 2. Implement the abstract schema() method\r\n * 3. Decorate properties with @ConfigProperty()\r\n * 4. Call populate() in their constructor\r\n * \r\n * @example\r\n * ```typescript\r\n * import { AbstractConfigProvider, Provider, ConfigProperty } from '@riktajs/core';\r\n * import { z } from 'zod';\r\n * \r\n * @Provider('APP_CONFIG')\r\n * export class AppConfigProvider extends AbstractConfigProvider {\r\n * schema() {\r\n * return z.object({\r\n * PORT: z.coerce.number().int().min(1).max(65535),\r\n * HOST: z.string().default('localhost'),\r\n * NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),\r\n * });\r\n * }\r\n * \r\n * @ConfigProperty()\r\n * port!: number;\r\n * \r\n * @ConfigProperty()\r\n * host!: string;\r\n * \r\n * @ConfigProperty('NODE_ENV')\r\n * environment!: 'development' | 'production' | 'test';\r\n * \r\n * constructor() {\r\n * super();\r\n * this.populate();\r\n * }\r\n * }\r\n * ```\r\n */\r\nexport abstract class AbstractConfigProvider {\r\n /**\r\n * Cache for validated configuration\r\n * Frozen to prevent accidental mutations\r\n */\r\n private _cache?: Readonly<Record<string, unknown>>;\r\n\r\n /**\r\n * Define the Zod schema for this configuration\r\n * \r\n * @returns A Zod schema that validates the environment variables\r\n * \r\n * @example\r\n * ```typescript\r\n * schema() {\r\n * return z.object({\r\n * DATABASE_URL: z.string().url(),\r\n * DB_POOL_SIZE: z.coerce.number().int().min(1).max(100).default(10),\r\n * DB_TIMEOUT: z.coerce.number().int().default(30000),\r\n * });\r\n * }\r\n * ```\r\n */\r\n protected abstract schema(): ZodSchema;\r\n\r\n /**\r\n * Constructor ensures .env files are loaded (for standalone usage)\r\n * \r\n * Note: When using Rikta.create(), .env files are loaded automatically\r\n * during bootstrap, so this is a safety measure for standalone usage.\r\n */\r\n constructor() {\r\n // Ensure .env files are loaded (idempotent operation)\r\n loadEnvFiles();\r\n }\r\n\r\n /**\r\n * Validate and cache the configuration\r\n * \r\n * This method runs the Zod schema validation against process.env\r\n * and caches the result. Subsequent calls return the cached value.\r\n * \r\n * @returns The validated and frozen configuration object\r\n * @throws {ConfigValidationException} If validation fails\r\n * \r\n * @private\r\n */\r\n private validateAndCache(): Readonly<Record<string, unknown>> {\r\n if (this._cache) {\r\n return this._cache;\r\n }\r\n\r\n try {\r\n const schema = this.schema();\r\n const validated = schema.parse(process.env);\r\n \r\n // Freeze the cache to make it immutable (tip from plan)\r\n this._cache = Object.freeze(validated as Record<string, unknown>);\r\n \r\n return this._cache;\r\n } catch (error) {\r\n if (error instanceof z.ZodError) {\r\n throw new ConfigValidationException(error, this.constructor.name);\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Populate decorated properties with validated values\r\n * \r\n * This method reads the @ConfigProperty metadata and assigns\r\n * the corresponding validated environment values to class properties.\r\n * \r\n * Must be called in the child class constructor after super().\r\n * \r\n * @throws {ConfigValidationException} If validation fails\r\n * \r\n * @example\r\n * ```typescript\r\n * constructor() {\r\n * super();\r\n * this.populate(); // Must call this!\r\n * }\r\n * ```\r\n */\r\n protected populate(): void {\r\n // Validate and get cached config\r\n const config = this.validateAndCache();\r\n\r\n // Get property mappings from metadata\r\n const mappings = getConfigPropertyMappings(this.constructor);\r\n\r\n // Assign values to properties\r\n for (const mapping of mappings) {\r\n const value = config[mapping.envKey];\r\n \r\n // Use type assertion since we know the property exists\r\n (this as any)[mapping.propertyKey] = value;\r\n }\r\n }\r\n\r\n /**\r\n * Get the raw validated configuration object\r\n * \r\n * This is useful for accessing config values that aren't mapped\r\n * to properties, or for passing the entire config to other services.\r\n * \r\n * @returns The validated and frozen configuration object\r\n * \r\n * @example\r\n * ```typescript\r\n * const config = this.getConfig();\r\n * console.log('All env vars:', config);\r\n * ```\r\n */\r\n protected getConfig(): Readonly<Record<string, unknown>> {\r\n return this.validateAndCache();\r\n }\r\n\r\n /**\r\n * Get a specific configuration value by key\r\n * \r\n * @param key - The environment variable name\r\n * @returns The validated value, or undefined if not found\r\n * \r\n * @example\r\n * ```typescript\r\n * const port = this.get<number>('PORT');\r\n * const apiKey = this.get<string>('API_KEY');\r\n * ```\r\n */\r\n protected get<T = unknown>(key: string): T | undefined {\r\n const config = this.validateAndCache();\r\n return config[key] as T | undefined;\r\n }\r\n}\r\n","import 'reflect-metadata';\nimport {\n CONTROLLER_METADATA,\n ROUTES_METADATA,\n PARAM_METADATA,\n HTTP_CODE_METADATA,\n GUARDS_METADATA,\n ZOD_SCHEMA_METADATA,\n} from './constants.js';\nimport type { RouteDefinition, ControllerMetadata } from './types.js';\nimport type { ParamMetadata } from './decorators/param.decorator.js';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype Constructor<T = unknown> = new (...args: any[]) => T;\n\nexport function getControllerMetadata(target: Constructor): ControllerMetadata | undefined {\n return Reflect.getMetadata(CONTROLLER_METADATA, target);\n}\n\nexport function isController(target: Constructor): boolean {\n return Reflect.hasMetadata(CONTROLLER_METADATA, target);\n}\n\nexport function getControllerPath(target: Constructor): string {\n const meta = getControllerMetadata(target);\n return meta?.prefix ?? '';\n}\n\nexport function getRoutes(target: Constructor): RouteDefinition[] {\n return Reflect.getMetadata(ROUTES_METADATA, target) || [];\n}\n\n/**\n * Check if a controller has any routes\n */\nexport function hasRoutes(target: Constructor): boolean {\n const routes = getRoutes(target);\n return routes.length > 0;\n}\n\n// ============================================================================\n// Parameter Metadata\n// ============================================================================\n\n/**\n * Get parameter metadata for a specific method\n */\nexport function getParamMetadata(\n target: Constructor,\n methodName: string | symbol\n): ParamMetadata[] {\n return Reflect.getMetadata(PARAM_METADATA, target.prototype, methodName) || [];\n}\n\nexport function getParamMetadataByIndex(\n target: Constructor,\n methodName: string | symbol,\n paramIndex: number\n): ParamMetadata | undefined {\n const params = getParamMetadata(target, methodName);\n return params.find(p => p.index === paramIndex);\n}\n\nexport function getHttpCode(\n target: Constructor,\n methodName: string | symbol\n): number | undefined {\n return Reflect.getMetadata(HTTP_CODE_METADATA, target.prototype, methodName);\n}\n\nexport function getGuards(\n target: Constructor,\n methodName?: string | symbol\n): Function[] {\n if (methodName) {\n // Method-level guards\n const methodGuards = Reflect.getMetadata(GUARDS_METADATA, target.prototype, methodName) || [];\n // Controller-level guards\n const controllerGuards = Reflect.getMetadata(GUARDS_METADATA, target) || [];\n return [...controllerGuards, ...methodGuards];\n }\n // Controller-level only\n return Reflect.getMetadata(GUARDS_METADATA, target) || [];\n}\n\nexport function getZodSchema(\n target: Constructor,\n methodName: string | symbol\n): unknown {\n return Reflect.getMetadata(ZOD_SCHEMA_METADATA, target.prototype, methodName);\n}\n\nexport function getClassMetadata<T = unknown>(\n metadataKey: symbol,\n target: Constructor\n): T | undefined {\n return Reflect.getMetadata(metadataKey, target);\n}\n\nexport function getMethodMetadata<T = unknown>(\n metadataKey: symbol,\n target: Constructor,\n methodName: string | symbol\n): T | undefined {\n return Reflect.getMetadata(metadataKey, target.prototype, methodName);\n}\n\nexport function hasClassMetadata(\n metadataKey: symbol,\n target: Constructor\n): boolean {\n return Reflect.hasMetadata(metadataKey, target);\n}\n\n/**\n * Check if a method has specific metadata\n */\nexport function hasMethodMetadata(\n metadataKey: symbol,\n target: Constructor,\n methodName: string | symbol\n): boolean {\n return Reflect.hasMetadata(metadataKey, target.prototype, methodName);\n}\n\n/**\n * Get all method names that have a specific metadata key\n */\nexport function getMethodsWithMetadata(\n metadataKey: symbol,\n target: Constructor\n): (string | symbol)[] {\n const methods: (string | symbol)[] = [];\n const prototype = target.prototype;\n \n // Get all property names including symbols\n const propertyNames = Object.getOwnPropertyNames(prototype);\n const propertySymbols = Object.getOwnPropertySymbols(prototype);\n \n for (const name of [...propertyNames, ...propertySymbols]) {\n if (name !== 'constructor' && Reflect.hasMetadata(metadataKey, prototype, name)) {\n methods.push(name);\n }\n }\n \n return methods;\n}\n","import { EventBus } from '../lifecycle/event-bus.js';\r\n\r\n/**\r\n * Performance metrics for a single operation\r\n */\r\nexport interface PerformanceMetric {\r\n /** Name of the operation */\r\n name: string;\r\n /** Duration in milliseconds */\r\n duration: number;\r\n /** Timestamp when the operation started */\r\n startTime: number;\r\n /** Additional context data */\r\n metadata?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Route performance metrics\r\n */\r\nexport interface RouteMetric extends PerformanceMetric {\r\n /** HTTP method */\r\n method: string;\r\n /** Route path */\r\n path: string;\r\n /** HTTP status code */\r\n statusCode: number;\r\n}\r\n\r\n/**\r\n * Bootstrap performance metrics\r\n */\r\nexport interface BootstrapMetrics {\r\n /** Total bootstrap time */\r\n total: number;\r\n /** Time for discovery phase */\r\n discovery: number;\r\n /** Time for container initialization */\r\n containerInit: number;\r\n /** Time for route registration */\r\n routeRegistration: number;\r\n /** Time for lifecycle hooks */\r\n lifecycleHooks: number;\r\n}\r\n\r\n/**\r\n * Performance profiler for measuring application performance\r\n * \r\n * @example\r\n * ```typescript\r\n * const profiler = new PerformanceProfiler();\r\n * \r\n * // Measure an operation\r\n * const end = profiler.startTimer('database-query');\r\n * await db.query('SELECT ...');\r\n * end({ table: 'users' });\r\n * \r\n * // Listen for metrics\r\n * profiler.onMetric((metric) => {\r\n * console.log(`${metric.name}: ${metric.duration}ms`);\r\n * });\r\n * ```\r\n */\r\nexport class PerformanceProfiler {\r\n private enabled: boolean = true;\r\n private eventBus?: EventBus;\r\n private listeners: ((metric: PerformanceMetric) => void)[] = [];\r\n private bootstrapMetrics: Partial<BootstrapMetrics> = {};\r\n\r\n constructor(options?: { enabled?: boolean; eventBus?: EventBus }) {\r\n this.enabled = options?.enabled ?? true;\r\n this.eventBus = options?.eventBus;\r\n }\r\n\r\n /**\r\n * Enable or disable profiling\r\n */\r\n setEnabled(enabled: boolean): void {\r\n this.enabled = enabled;\r\n }\r\n\r\n /**\r\n * Check if profiling is enabled\r\n */\r\n isEnabled(): boolean {\r\n return this.enabled;\r\n }\r\n\r\n /**\r\n * Start a timer for measuring an operation\r\n * \r\n * @param name - Name of the operation\r\n * @returns A function to call when the operation completes\r\n */\r\n startTimer(name: string): (metadata?: Record<string, unknown>) => PerformanceMetric | null {\r\n if (!this.enabled) {\r\n return () => null;\r\n }\r\n\r\n const startTime = performance.now();\r\n const startTimestamp = Date.now();\r\n\r\n return (metadata?: Record<string, unknown>) => {\r\n const duration = performance.now() - startTime;\r\n const metric: PerformanceMetric = {\r\n name,\r\n duration,\r\n startTime: startTimestamp,\r\n metadata,\r\n };\r\n\r\n this.emitMetric(metric);\r\n return metric;\r\n };\r\n }\r\n\r\n /**\r\n * Measure the execution time of a function\r\n * \r\n * @param name - Name of the operation\r\n * @param fn - Function to measure\r\n * @returns The result of the function\r\n */\r\n async measure<T>(name: string, fn: () => T | Promise<T>): Promise<T> {\r\n const end = this.startTimer(name);\r\n try {\r\n const result = await fn();\r\n end();\r\n return result;\r\n } catch (error) {\r\n end({ error: true });\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Record a route request metric\r\n */\r\n recordRouteMetric(metric: RouteMetric): void {\r\n if (!this.enabled) return;\r\n \r\n this.emitMetric(metric);\r\n this.eventBus?.emit('profiler:route', metric);\r\n }\r\n\r\n /**\r\n * Record bootstrap phase timing\r\n */\r\n recordBootstrapPhase(phase: keyof BootstrapMetrics, duration: number): void {\r\n this.bootstrapMetrics[phase] = duration;\r\n }\r\n\r\n /**\r\n * Get bootstrap metrics\r\n */\r\n getBootstrapMetrics(): Partial<BootstrapMetrics> {\r\n return { ...this.bootstrapMetrics };\r\n }\r\n\r\n /**\r\n * Subscribe to metric events\r\n * \r\n * @param listener - Callback for each metric\r\n * @returns Unsubscribe function\r\n */\r\n onMetric(listener: (metric: PerformanceMetric) => void): () => void {\r\n this.listeners.push(listener);\r\n return () => {\r\n const index = this.listeners.indexOf(listener);\r\n if (index !== -1) {\r\n this.listeners.splice(index, 1);\r\n }\r\n };\r\n }\r\n\r\n /**\r\n * Emit a metric to all listeners\r\n */\r\n private emitMetric(metric: PerformanceMetric): void {\r\n for (const listener of this.listeners) {\r\n try {\r\n listener(metric);\r\n } catch {\r\n // Ignore listener errors\r\n }\r\n }\r\n \r\n this.eventBus?.emit('profiler:metric', metric);\r\n }\r\n\r\n /**\r\n * Create a timer that automatically logs to console\r\n */\r\n createConsoleTimer(prefix: string = '[Rikta]'): (name: string) => (metadata?: Record<string, unknown>) => void {\r\n return (name: string) => {\r\n const end = this.startTimer(name);\r\n return (metadata?: Record<string, unknown>) => {\r\n const metric = end(metadata);\r\n if (metric) {\r\n console.log(`${prefix} ${metric.name}: ${metric.duration.toFixed(2)}ms`);\r\n }\r\n };\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Global profiler instance\r\n * Can be replaced with a custom instance if needed\r\n */\r\nexport let profiler = new PerformanceProfiler();\r\n\r\n/**\r\n * Replace the global profiler instance\r\n */\r\nexport function setGlobalProfiler(newProfiler: PerformanceProfiler): void {\r\n profiler = newProfiler;\r\n}\r\n\r\n/**\r\n * Get the global profiler instance\r\n */\r\nexport function getGlobalProfiler(): PerformanceProfiler {\r\n return profiler;\r\n}\r\n","// Core exports\r\nexport * from './types.js';\r\nexport * from './constants.js';\r\nexport * from './container/index.js';\r\nexport * from './registry.js';\r\nexport * from './discovery.js';\r\nexport * from './lifecycle/index.js';\r\nexport * from './router/router.js';\r\nexport * from './application.js';\r\nexport * from './decorators/index.js';\r\nexport * from './exceptions/index.js';\r\nexport * from './guards/index.js';\r\nexport * from './middleware/index.js';\r\nexport * from './interceptors/index.js';\r\nexport * from './config/index.js';\r\nexport * from './metadata.js';\r\nexport * from './profiler/index.js';\r\n\r\n// Re-export Zod for convenience\r\n// This allows users to import everything from '@riktajs/core':\r\n// import { z, Body, Controller } from '@riktajs/core';\r\nexport { z } from 'zod';\r\nexport type { ZodError, ZodIssue, infer as ZodInfer, input as ZodInput, output as ZodOutput } from 'zod';\r\n\r\n// Re-export Fastify types for convenience\r\n// This allows users to import Fastify types directly from '@riktajs/core':\r\nexport type {FastifyInstance, FastifyRequest, FastifyReply} from 'fastify';"],"mappings":"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","names":["CONTROLLER_METADATA","Symbol","for","ROUTES_METADATA","INJECTABLE_METADATA","PARAM_METADATA","GUARDS_METADATA","INTERCEPTORS_METADATA","MIDDLEWARE_METADATA","HTTP_CODE_METADATA","HEADERS_METADATA","INJECT_METADATA","ZOD_SCHEMA_METADATA","AUTOWIRED_METADATA","PROVIDER_METADATA","CONFIG_PROVIDER_METADATA","CONFIG_PROPERTY_METADATA","ParamType","DEFAULT_CONFIG","port","host","logger","prefix","InjectionToken","description","options","toString","ConfigProviderAlreadyRegisteredException","Error","token","existingClass","newClass","name","ConfigProviderNotFoundException","availableTokens","suggestion","length","join","ConfigProviderInstantiationException","className","cause","message","Registry","instance","controllers","Set","providers","customProviders","configProviderMap","Map","abstractImplementations","getInstance","reset","newInstance","registerController","target","add","registerProvider","getControllers","getProviders","hasController","has","hasProvider","registerCustomProvider","getCustomProviders","hasCustomProvider","registerConfigProvider","token","providerClass","existingClass","get","ConfigProviderAlreadyRegisteredException","name","set","getConfigProviderRegistrations","Array","from","entries","map","clearConfigProviders","clear","registerAbstractImplementation","abstractClass","implementation","implementations","existing","find","i","push","isPrimary","setImplementationName","impl","setPrimaryImplementation","getImplementations","hasImplementation","length","clearAbstractImplementations","registry","IMPLEMENTS_METADATA","Symbol","PRIMARY_METADATA","isAbstractClass","target","isMarkedAbstract","Reflect","getMetadata","undefined","hasMetadata","extendsFrom","derived","base","current","Object","getPrototypeOf","Function","prototype","getImplementedAbstract","isPrimaryImplementation","setImplementsMetadata","abstractClass","defineMetadata","setPrimaryMetadata","markAsAbstract","RequestScopeStorage","instance","asyncLocalStorage","AsyncLocalStorage","getInstance","reset","run","fn","store","Map","runAsync","isInRequestScope","getStore","undefined","get","token","set","Error","has","requestScopeStorage","Container","instance","singletons","Map","providers","resolutionStack","Set","getInstance","reset","register","target","options","scope","set","registerProvider","provider","token","provide","useValue","registerValue","value","registerFactory","factory","inject","useFactory","has","resolve","resolveToken","resolveOptional","optional","chain","map","t","getTokenName","join","Error","get","config","implementation","resolveAbstractClass","resolveClass","isAbstractClass","undefined","resolveProvider","abstractClass","name","useClass","implementations","registry","getImplementations","length","named","find","i","filter","primary","isPrimary","implNames","factoryProvider","deps","dep","result","classProvider","useExisting","providerConfig","requestScopeStorage","isInRequestScope","existingInstance","add","injectMeta","Reflect","getMetadata","INJECT_METADATA","paramTypes","maxIndex","Math","max","m","index","paramCount","dependencies","paramType","injectOverride","isOptional","push","isPrimitive","resolveWithNameOptional","resolveWithName","injectProperties","delete","autowireMeta","AUTOWIRED_METADATA","meta","propertyKey","error","registerInstance","getProviders","keys","clearSingletons","clear","type","primitives","String","Number","Boolean","Object","Array","Function","includes","InjectionToken","toString","container","import_reflect_metadata","Implements","abstractClass","target","setImplementsMetadata","markAsAbstract","name","Reflect","getMetadata","registry","registerAbstractImplementation","isPrimary","setPrimaryImplementation","Primary","setPrimaryMetadata","IMPLEMENTS_METADATA","defineMetadata","Named","setImplementationName","AbstractClass","DiscoveryException","Error","filePath","originalError","failedImports","filePathOrFailures","error","message","failures","fileList","map","f","join","length","name","captureStackTrace","getReport","lines","push","stack","stackLines","split","slice","DEFAULT_IGNORE_PATTERNS","getEntryPointDirectory","mainScript","process","argv","filePath","startsWith","URL","pathname","path","dirname","cwd","DECORATOR_PATTERNS","containsRiktaDecorators","content","fs","readFile","some","pattern","test","discoverModules","optionsOrPatterns","options","Array","isArray","patterns","strict","onImportError","baseDir","absoluteBaseDir","isAbsolute","resolve","normalizedPatterns","map","normalizedPattern","relative","endsWith","files","fg","absolute","ignore","onlyFiles","decoratorChecks","Promise","all","file","hasDecorators","riktaFiles","filter","importedFiles","failedImports","importPath","replace","push","err","error","Error","String","env","DEBUG","console","warn","message","length","DiscoveryException","getCallerDirectory","import_reflect_metadata","Injectable","options","target","Reflect","defineMetadata","INJECTABLE_METADATA","container","register","registry","registerProvider","EventBus","listeners","Map","onceListeners","ownerUnsubscribers","on","event","listener","owner","has","set","Set","tracked","get","add","unsubscribe","delete","once","emit","payload","waitFor","Promise","resolve","off","removeByOwner","unsubscribers","clear","listenerCount","size","totalListenerCount","count","values","listenerCountByOwner","getOwners","keys","import_reflect_metadata","ON_EVENT_METADATA","Symbol","On","event","options","target","propertyKey","existing","Reflect","getMetadata","push","methodName","String","priority","defineMetadata","import_reflect_metadata","import_reflect_metadata","CUSTOM_PARAM_METADATA","Symbol","for","createParamDecorator","factory","data","target","propertyKey","parameterIndex","undefined","existingParams","Reflect","getMetadata","metadata","index","push","defineMetadata","getCustomParamMetadata","HttpException","Error","statusCode","response","timestamp","message","name","Date","toISOString","error","getDefaultError","details","code","captureStackTrace","getResponse","getStatus","errors","ValidationException","HttpException","zodError","errors","message","issues","map","issue","path","code","expected","String","received","error","details","errorCount","length","getValidationErrors","getFlattenedErrors","flatten","getFormattedErrors","format","BadRequestException","HttpException","response","UnauthorizedException","ForbiddenException","NotFoundException","MethodNotAllowedException","NotAcceptableException","RequestTimeoutException","ConflictException","GoneException","PayloadTooLargeException","UnsupportedMediaTypeException","UnprocessableEntityException","TooManyRequestsException","InternalServerErrorException","NotImplementedException","BadGatewayException","ServiceUnavailableException","GatewayTimeoutException","ExecutionContextImpl","httpHost","request","reply","controllerClass","handlerName","getRequest","getResponse","switchToHttp","getReply","getClass","getHandler","getMetadata","key","Reflect","import_reflect_metadata","UseGuards","guards","target","propertyKey","undefined","existingGuards","Reflect","getMetadata","GUARDS_METADATA","defineMetadata","getGuardsMetadata","classGuards","methodGuards","import_reflect_metadata","UseMiddleware","middleware","target","propertyKey","undefined","existingMiddleware","Reflect","getMetadata","MIDDLEWARE_METADATA","defineMetadata","getMiddlewareMetadata","controllerMiddleware","methodMiddleware","import_reflect_metadata","UseInterceptors","interceptors","target","propertyKey","descriptor","existingInterceptors","Reflect","getMetadata","INTERCEPTORS_METADATA","defineMetadata","getInterceptorsMetadata","controllerClass","methodName","controllerInterceptors","methodInterceptors","Router","guardCache","Map","middlewareCache","interceptorCache","server","container","globalPrefix","clearGuardCache","clear","clearMiddlewareCache","clearInterceptorCache","clearAllCaches","getGuardCacheSize","size","getMiddlewareCacheSize","getInterceptorCacheSize","registerController","controllerClass","silent","controllerMeta","Reflect","getMetadata","CONTROLLER_METADATA","Error","name","controllerInstance","resolve","routes","ROUTES_METADATA","route","registerRoute","prefix","controllerPrefix","fullPath","buildPath","path","handler","handlerName","String","paramsMeta","PARAM_METADATA","customParamsMeta","getCustomParamMetadata","statusCode","HTTP_CODE_METADATA","guards","getGuardsMetadata","middleware","getMiddlewareMetadata","interceptors","getInterceptorsMetadata","compiledResolvers","compileParamResolvers","hasBuiltinParams","length","hasCustomParams","hasParams","allParamIndexes","map","r","index","maxParamIndex","Math","max","guardInstances","resolveGuardInstances","hasGuards","middlewareInstances","resolveMiddlewareInstances","hasMiddleware","interceptorInstances","resolveInterceptorInstances","hasInterceptors","needsContext","createContext","req","rep","ExecutionContextImpl","executeHandler","request","reply","executionContext","executeGuardsOptimized","executeMiddlewareChain","coreHandler","args","resolveAllParams","result","apply","call","executeInterceptorChain","status","routeHandler","requestScopeStorage","runAsync","method","toLowerCase","console","log","padEnd","param","extractor","createParamExtractor","extract","zodSchema","validationLabel","type","key","ParamType","BODY","ctx","body","QUERY","query","PARAM","params","HEADERS","headerKey","headers","REQUEST","REPLY","CONTEXT","undefined","customParams","maxIndex","routeContext","Array","i","resolver","value","safeParse","success","ValidationException","error","data","customParam","factory","GuardClass","instance","get","message","canActivate","set","context","ForbiddenException","MiddlewareClass","use","next","InterceptorClass","intercept","interceptor","nextHandler","callHandler","handle","routePath","parts","filter","Boolean","join","replace","import_reflect_metadata","GlobalExceptionFilter","includeStack","logErrors","options","process","env","NODE_ENV","catch","exception","context","request","reply","path","method","requestId","id","undefined","logError","response","buildResponse","status","statusCode","send","HttpException","httpResponse","getResponse","message","error","timestamp","details","code","stack","isFastifyValidationError","Date","toISOString","validation","isFastifyError","fastifyError","Array","isArray","getStatus","prefix","reqIdStr","console","createExceptionHandler","filter","customFilters","Map","url","ExceptionType","customFilter","import_reflect_metadata","CATCH_METADATA","Symbol","Catch","exceptions","target","metadata","length","Reflect","defineMetadata","getCatchMetadata","getMetadata","import_path","envLoaded","loadEnvFiles","env","process","NODE_ENV","cwd","baseEnvPath","resolve","existsSync","loadEnv","path","override","envSpecificPath","isEnvLoaded","resetEnvLoaded","RiktaFactory","create","config","loadEnvFiles","silent","console","log","callerDir","getCallerDirectory","discoveredFiles","controllers","autowired","patterns","Array","isArray","length","discoverModules","cwd","strict","strictDiscovery","onImportError","onDiscoveryError","app","RiktaApplicationImpl","init","server","container","router","events","initializedProviders","customExceptionFilters","Map","startTime","Date","now","isListening","address","port","DEFAULT_CONFIG","host","logger","prefix","providers","exceptionFilter","exceptionFilters","Fastify","Container","getInstance","Router","EventBus","registerInstance","setupExceptionHandler","globalFilter","GlobalExceptionFilter","includeStack","logErrors","customFilters","FilterClass","metadata","getCatchMetadata","filterInstance","resolve","exceptions","ExceptionType","set","Error","setErrorHandler","createExceptionHandler","emit","files","processConfigProviders","processCustomProviders","count","registry","getCustomProviders","getSortedProviders","additionalProviders","provider","registerProvider","target","priority","initializeProvider","getControllers","controller","registerController","callHook","providerCount","configProviders","getConfigProviderRegistrations","token","providerClass","provide","useClass","customProviders","ProviderClass","Reflect","getMetadata","PROVIDER_METADATA","providerInstance","value","registerValue","getProviders","map","getProviderPriority","sort","a","b","options","INJECTABLE_METADATA","instance","name","push","hasHook","onProviderInit","registerEventListeners","ON_EVENT_METADATA","event","methodName","method","on","bind","hookName","listen","onApplicationListen","close","signal","reversed","reverse","onApplicationShutdown","onProviderDestroy","removeByOwner","uptime","clear","getUrl","getEventBus","getContainer","getRouter","clearRouterCaches","clearAllCaches","import_reflect_metadata","Controller","prefixOrOptions","target","prefix","normalizedPrefix","startsWith","Reflect","defineMetadata","CONTROLLER_METADATA","INJECTABLE_METADATA","scope","container","register","registry","registerController","import_reflect_metadata","createRouteDecorator","method","path","target","propertyKey","descriptor","normalizedPath","startsWith","routes","Reflect","getMetadata","ROUTES_METADATA","push","handlerName","defineMetadata","Get","Post","Put","Patch","Delete","Options","Head","HttpCode","statusCode","HTTP_CODE_METADATA","import_reflect_metadata","isZodType","value","safeParse","createParamDecorator","type","decorator","keyOrSchema","target","propertyKey","parameterIndex","undefined","existingParams","Reflect","getMetadata","PARAM_METADATA","isSchema","metadata","index","key","zodSchema","push","defineMetadata","Body","ParamType","BODY","Query","QUERY","Param","PARAM","Headers","HEADERS","Req","REQUEST","Request","Res","REPLY","Reply","Ctx","CONTEXT","Context","import_reflect_metadata","Autowired","token","name","target","propertyKey","parameterIndex","paramTypes","Reflect","getMetadata","inferredType","resolvedToken","Error","existingInjects","INJECT_METADATA","push","index","defineMetadata","undefined","String","existingAutowires","AUTOWIRED_METADATA","Optional","meta","find","m","optional","paramType","propType","import_reflect_metadata","generateTokenFromClassName","className","tokenName","replace","toUpperCase","endsWith","Provider","token","target","name","isConfigProvider","prototype","schema","configToken","trim","Error","undefined","configMetadata","Reflect","defineMetadata","CONFIG_PROVIDER_METADATA","registry","registerConfigProvider","metadata","PROVIDER_METADATA","registerCustomProvider","getConfigProviderMetadata","getMetadata","hasMetadata","import_reflect_metadata","propertyNameCache","Map","toUpperSnakeCase","propertyName","has","get","envKey","replace","toUpperCase","set","ConfigProperty","target","propertyKey","Error","String","finalEnvKey","constructor","existingMappings","Reflect","getMetadata","CONFIG_PROPERTY_METADATA","duplicate","find","m","name","duplicateEnvKey","newMapping","updatedMappings","defineMetadata","getConfigPropertyMappings","hasConfigProperties","mappings","length","clearPropertyNameCache","clear","import_reflect_metadata","applyDecorators","decorators","target","propertyKey","descriptor","decorator","reverse","result","undefined","SetMetadata","key","value","decoratorFactory","Reflect","defineMetadata","import_reflect_metadata","Middleware","target","Reflect","defineMetadata","ConfigValidationException","Error","errors","providerName","errorMessages","issues","map","err","path","join","message","name","AbstractConfigProvider","_cache","loadEnvFiles","validateAndCache","schema","validated","parse","process","env","Object","freeze","error","z","ZodError","populate","config","mappings","getConfigPropertyMappings","mapping","value","envKey","propertyKey","getConfig","get","key","import_reflect_metadata","getControllerMetadata","target","Reflect","getMetadata","CONTROLLER_METADATA","isController","hasMetadata","getControllerPath","meta","prefix","getRoutes","ROUTES_METADATA","hasRoutes","routes","length","getParamMetadata","methodName","PARAM_METADATA","prototype","getParamMetadataByIndex","paramIndex","params","find","p","index","getHttpCode","HTTP_CODE_METADATA","getGuards","methodGuards","GUARDS_METADATA","controllerGuards","getZodSchema","ZOD_SCHEMA_METADATA","getClassMetadata","metadataKey","getMethodMetadata","hasClassMetadata","hasMethodMetadata","getMethodsWithMetadata","methods","propertyNames","Object","getOwnPropertyNames","propertySymbols","getOwnPropertySymbols","name","push","PerformanceProfiler","enabled","eventBus","listeners","bootstrapMetrics","options","setEnabled","isEnabled","startTimer","name","startTime","performance","now","startTimestamp","Date","metadata","duration","metric","emitMetric","measure","fn","end","result","error","recordRouteMetric","emit","recordBootstrapPhase","phase","getBootstrapMetrics","onMetric","listener","push","index","indexOf","splice","createConsoleTimer","prefix","console","log","toFixed","profiler","setGlobalProfiler","newProfiler","getGlobalProfiler","import_zod"]}