@scpxl/nodejs-framework 1.0.48 → 1.0.50

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 (53) hide show
  1. package/dist/application/base-application.d.ts.map +1 -1
  2. package/dist/application/base-application.js +10 -0
  3. package/dist/application/base-application.js.map +2 -2
  4. package/dist/application/index.d.ts +2 -0
  5. package/dist/application/index.d.ts.map +1 -1
  6. package/dist/application/index.js +3 -1
  7. package/dist/application/index.js.map +2 -2
  8. package/dist/application/worker-application.d.ts +72 -0
  9. package/dist/application/worker-application.d.ts.map +1 -0
  10. package/dist/application/worker-application.interface.d.ts +17 -0
  11. package/dist/application/worker-application.interface.d.ts.map +1 -0
  12. package/dist/application/worker-application.interface.js +1 -0
  13. package/dist/application/worker-application.interface.js.map +7 -0
  14. package/dist/application/worker-application.js +99 -0
  15. package/dist/application/worker-application.js.map +7 -0
  16. package/dist/lifecycle/lifecycle-manager.d.ts +6 -0
  17. package/dist/lifecycle/lifecycle-manager.d.ts.map +1 -1
  18. package/dist/lifecycle/lifecycle-manager.js +28 -0
  19. package/dist/lifecycle/lifecycle-manager.js.map +2 -2
  20. package/dist/queue/manager.d.ts +6 -0
  21. package/dist/queue/manager.d.ts.map +1 -1
  22. package/dist/queue/manager.js +39 -4
  23. package/dist/queue/manager.js.map +2 -2
  24. package/dist/queue/worker.d.ts +5 -0
  25. package/dist/queue/worker.d.ts.map +1 -1
  26. package/dist/queue/worker.js +8 -0
  27. package/dist/queue/worker.js.map +2 -2
  28. package/dist/redis/index.d.ts +1 -1
  29. package/dist/redis/index.d.ts.map +1 -1
  30. package/dist/redis/index.js +3 -2
  31. package/dist/redis/index.js.map +2 -2
  32. package/dist/redis/instance.js +1 -1
  33. package/dist/redis/instance.js.map +2 -2
  34. package/dist/redis/manager.d.ts +5 -0
  35. package/dist/redis/manager.d.ts.map +1 -1
  36. package/dist/redis/manager.js +13 -0
  37. package/dist/redis/manager.js.map +2 -2
  38. package/dist/util/file.d.ts +13 -2
  39. package/dist/util/file.d.ts.map +1 -1
  40. package/dist/util/file.js.map +2 -2
  41. package/dist/webserver/controller/entity.d.ts +1 -0
  42. package/dist/webserver/controller/entity.d.ts.map +1 -1
  43. package/dist/webserver/controller/entity.js +7 -0
  44. package/dist/webserver/controller/entity.js.map +2 -2
  45. package/dist/websocket/websocket-client-manager.d.ts +2 -0
  46. package/dist/websocket/websocket-client-manager.d.ts.map +1 -1
  47. package/dist/websocket/websocket-client-manager.js +8 -1
  48. package/dist/websocket/websocket-client-manager.js.map +2 -2
  49. package/dist/websocket/websocket-client.d.ts +5 -0
  50. package/dist/websocket/websocket-client.d.ts.map +1 -1
  51. package/dist/websocket/websocket-client.js +22 -0
  52. package/dist/websocket/websocket-client.js.map +2 -2
  53. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"base-application.d.ts","sourceRoot":"","sources":["../../src/application/base-application.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"base-application.d.ts","sourceRoot":"","sources":["../../src/application/base-application.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,gBAAgB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,YAAY,MAAM,qBAAqB,CAAC;AAC/C,OAAO,YAAY,MAAM,qBAAqB,CAAC;AAC/C,OAAO,KAAK,EACV,iBAAiB,EAEjB,8BAA8B,EAC/B,MAAM,iCAAiC,CAAC;AAEzC,OAAO,KAAK,aAAa,MAAM,sBAAsB,CAAC;AAEtD,OAAO,YAAY,MAAM,qBAAqB,CAAC;AAE/C,OAAO,YAAY,MAAM,qBAAqB,CAAC;AAE/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAGhF,OAAO,EAAwB,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAMnG,YAAY,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAEzE,MAAM,CAAC,OAAO,CAAC,QAAQ,OAAO,eAAe;IAC3C,yBAAyB;IAClB,gBAAgB,EAAE,MAAM,CAAC;IAEhC,6BAA6B;IAC7B,SAAS,CAAC,SAAS,EAAE,MAAM,CAAK;IAEhC,oCAAoC;IACpC,SAAS,CAAC,eAAe,SAAS;IAElC,8DAA8D;IAC9D,OAAO,CAAC,MAAM,CAAC,uBAAuB,CAAqB;IAC3D,OAAO,CAAC,MAAM,CAAC,6BAA6B,CAAS;IACrD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAuC;IAExE,wBAAwB;IACxB,SAAS,CAAC,QAAQ,gBAAiE;IAEnF,yBAAyB;IACzB,SAAS,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAEpC,0BAA0B;IAC1B,SAAS,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAEtC,oBAAoB;IACb,YAAY,EAAE,YAAY,CAAC;IAElC,oBAAoB;IACb,YAAY,EAAE,YAAY,CAAC;IAElC,uBAAuB;IAChB,eAAe,CAAC,EAAE,eAAe,CAAC;IAEzC,oBAAoB;IACb,YAAY,CAAC,EAAE,YAAY,CAAC;IAEnC,oBAAoB;IACb,YAAY,CAAC,EAAE,YAAY,CAAC;IAEnC,0BAA0B;IACnB,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IAE/C,wBAAwB;IACjB,SAAS,EAAE,gBAAgB,CAAC;IAEnC,0BAA0B;IACnB,kBAAkB,EAAE,kBAAkB,CAAC;IAE9C,IAAW,IAAI,WAEd;IAED;;OAEG;gBACS,MAAM,EAAE,iBAAiB;IAiFrC;;OAEG;IACU,qBAAqB,IAAI,OAAO,CAAC,MAAM,CAAC;IAyBrD;;OAEG;IACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA6CnC;;OAEG;YACW,aAAa;IA2F3B;;OAEG;IACH,SAAS,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,YAAY,EAAE,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAEjF;;OAEG;IACH,SAAS,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAErE;;OAEG;YACW,aAAa;IAyG3B,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,EAC9B,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,YAAY,GACb,EAAE;QACD,aAAa,EAAE,aAAa,CAAC;QAC7B,gBAAgB,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;QAC3C,YAAY,EAAE,YAAY,CAAC;QAC3B,YAAY,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;KACpC,GAAG,OAAO,CAAC,IAAI,CAAC;IAEjB,SAAS,CAAC,QAAQ,CAAC,YAAY,IAAI,IAAI;IAEvC,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAM/B,OAAO,CAAC,MAAM,CAAC,kBAAkB;IASjC,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAQlC,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAoBjC,OAAO,CAAC,MAAM,CAAC,2BAA2B;IA0B1C;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAmC7B;;OAEG;YACW,wBAAwB;IA6BtC;;OAEG;IACU,IAAI,CAAC,EAAE,SAAS,EAAE,GAAE,8BAAmC,GAAG,OAAO,CAAC,IAAI,CAAC;IAoCpF;;OAEG;IACH,OAAO,CAAC,YAAY;CAerB"}
@@ -277,6 +277,10 @@ ${formatted}`);
277
277
  }
278
278
  const beforeStartTime = Time.now();
279
279
  const { redisInstance, databaseInstance, queueManager, eventManager } = await this.onBeforeStart();
280
+ this.queueManager = queueManager;
281
+ if (eventManager) {
282
+ this.eventManager = eventManager;
283
+ }
280
284
  if (process.env.DEBUG_TESTS) {
281
285
  const beforeStartElapsed = Time.calculateElapsedTimeMs({ startTime: beforeStartTime });
282
286
  console.log(`[startInstance] Services connected (${beforeStartElapsed}ms)`);
@@ -408,6 +412,12 @@ ${formatted}`);
408
412
  Logger.info({ message: "Executing custom stop callback" });
409
413
  await this.stopCallback();
410
414
  });
415
+ this.lifecycle.onShutdown(async () => {
416
+ if (this.queueManager) {
417
+ Logger.info({ message: "Closing queue manager (workers and queues)" });
418
+ await this.queueManager.disconnect();
419
+ }
420
+ });
411
421
  this.lifecycle.onShutdown(async () => {
412
422
  if (this.redisManager) {
413
423
  Logger.info({ message: "Disconnecting from Redis" });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/application/base-application.ts"],
4
- "sourcesContent": ["import cluster from 'cluster';\nimport { existsSync, readFileSync } from 'fs';\nimport { fileURLToPath } from 'url';\nimport { dirname, join, resolve } from 'path';\nimport { type DatabaseInstance, DatabaseManager } from '../database/index.js';\nimport QueueManager from '../queue/manager.js';\nimport RedisManager from '../redis/manager.js';\nimport type {\n ApplicationConfig,\n ApplicationStartInstanceOptions,\n ApplicationStopInstanceOptions,\n} from './base-application.interface.js';\nimport ClusterManager from '../cluster/cluster-manager.js';\nimport type RedisInstance from '../redis/instance.js';\nimport { OS, Time } from '../util/index.js';\nimport CacheManager from '../cache/manager.js';\nimport os from 'os';\nimport EventManager from '../event/manager.js';\nimport Logger from '../logger/logger.js';\nimport type { PerformanceMonitor } from '../performance/performance-monitor.js';\n// Performance monitoring now pluginized\nimport { PerformanceMonitorPlugin } from '../performance/performance-monitor.plugin.js';\nimport { type LifecycleConfig, LifecycleManager, ShutdownController } from '../lifecycle/index.js';\nimport { ConfigValidationError, formatConfigIssues, validateFrameworkConfig } from '../config/schema.js';\nimport { type ExitOutcome, requestExit } from '../lifecycle/exit.js';\nimport { safeSerializeError } from '../error/error-reporter.js';\n\n// Re-export types for external use\nexport type { ApplicationConfig } from './base-application.interface.js';\n\nexport default abstract class BaseApplication {\n /** Unique instance ID */\n public uniqueInstanceId: string;\n\n /** Application start time */\n protected startTime: number = 0;\n\n /** Shutdown timeout (30 seconds) */\n protected shutdownTimeout = 30000;\n\n /** Cache for application version to avoid repeated imports */\n private static applicationVersionCache: string | undefined;\n private static globalErrorHandlersRegistered = false;\n private static readonly instances = new Set<WeakRef<BaseApplication>>();\n\n /** Cluster worker ID */\n protected workerId = cluster.isWorker && cluster.worker ? cluster.worker.id : null;\n\n /** Application config */\n protected config: ApplicationConfig;\n\n /** Application version */\n protected applicationVersion?: string;\n\n /** Redis manager */\n public redisManager: RedisManager;\n\n /** Cache manager */\n public cacheManager: CacheManager;\n\n /** Database manager */\n public databaseManager?: DatabaseManager;\n\n /** Queue manager */\n public queueManager?: QueueManager;\n\n /** Event manager */\n public eventManager?: EventManager;\n\n /** Performance monitor */\n public performanceMonitor?: PerformanceMonitor;\n\n /** Lifecycle manager */\n public lifecycle: LifecycleManager;\n\n /** Shutdown controller */\n public shutdownController: ShutdownController;\n\n public get Name() {\n return this.config.name;\n }\n\n /**\n * Application constructor\n */\n constructor(config: ApplicationConfig) {\n // Validate configuration early (fail-fast before side effects)\n try {\n const validated = validateFrameworkConfig(config as any);\n config = validated as unknown as ApplicationConfig;\n } catch (err) {\n if (err instanceof ConfigValidationError) {\n const formatted = formatConfigIssues(err.issues);\n throw new Error(`Configuration validation failed:\\n${formatted}`);\n }\n throw err;\n }\n const computerName = os.hostname();\n\n this.uniqueInstanceId = `${config.instanceId}-${computerName}-${OS.getUniqueComputerId()}`;\n this.config = config;\n\n // Configure logger with application settings\n if (this.config.log?.showRequestIdInConsole !== undefined) {\n Logger.configure({ showRequestIdInConsole: this.config.log.showRequestIdInConsole });\n }\n\n // Initialize lifecycle management\n const lifecycleConfig: Partial<LifecycleConfig> = {\n gracefulShutdown: {\n timeoutMs: this.shutdownTimeout,\n },\n readiness: {\n timeoutMs: 30000,\n checkIntervalMs: 100,\n },\n };\n this.lifecycle = new LifecycleManager(lifecycleConfig);\n this.shutdownController = new ShutdownController(this.lifecycle);\n\n // Register shutdown hooks for cleanup\n this.registerShutdownHooks();\n\n // Initialize Redis manager\n this.redisManager = new RedisManager({\n applicationConfig: this.config,\n host: this.config.redis.host,\n port: this.config.redis.port,\n password: this.config.redis.password,\n });\n\n // Initialize cache manager\n this.cacheManager = new CacheManager({\n redisManager: this.redisManager,\n });\n\n // Register performance monitor plugin (idempotent & opt-in)\n PerformanceMonitorPlugin.register(this);\n\n // Track instance and ensure global error handlers are registered once\n BaseApplication.registerInstance(this);\n\n if (this.config.database?.enabled === true) {\n const defaultEntitiesDirectory = join(this.config.rootDirectory, 'src', 'database', 'entities');\n\n if (!this.config.database.entitiesDirectory) {\n this.config.database.entitiesDirectory = defaultEntitiesDirectory;\n }\n\n if (!existsSync(this.config.database.entitiesDirectory)) {\n throw new Error(`Database entities directory not found (Path: ${this.config.database.entitiesDirectory})`);\n }\n\n // Initialize Database manager\n this.databaseManager = new DatabaseManager({\n applicationConfig: this.config,\n host: this.config.database.host,\n port: this.config.database.port,\n username: this.config.database.username,\n password: this.config.database.password,\n databaseName: this.config.database.databaseName,\n entitiesDirectory: this.config.database.entitiesDirectory,\n });\n }\n }\n\n /**\n * Get application version\n */\n public async getApplicationVersion(): Promise<string> {\n // Return cached version if available\n if (BaseApplication.applicationVersionCache !== undefined) {\n return BaseApplication.applicationVersionCache;\n }\n\n // Resolve the path to package.json\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = dirname(__filename);\n const packageJsonPath = resolve(__dirname, '../../package.json');\n\n // Read and parse the file\n const fileContents = readFileSync(packageJsonPath, 'utf-8');\n const packageJson = JSON.parse(fileContents);\n\n if (!packageJson?.version) {\n throw new Error('Application version not found');\n }\n\n // Cache and return the version\n BaseApplication.applicationVersionCache = packageJson.version;\n\n return packageJson.version;\n }\n\n /**\n * Start application\n */\n public async start(): Promise<void> {\n // Start application timer\n this.startTime = Time.now();\n\n // Get application version`\n this.applicationVersion = await this.getApplicationVersion();\n\n // Log initial startup message with version\n Logger.info({\n message: 'Starting application',\n meta: {\n Name: this.config.name,\n 'Instance ID': this.config.instanceId,\n 'PXL Framework Version': this.applicationVersion,\n },\n });\n\n const startInstanceOptions: ApplicationStartInstanceOptions = {\n onStarted: this.onStarted.bind(this),\n };\n\n const stopInstanceOptions: ApplicationStopInstanceOptions = {\n onStopped: this.onStopped.bind(this),\n };\n\n if (this.config.cluster?.enabled) {\n // Initialize clustered application\n const clusterManager = new ClusterManager({\n config: this.config.cluster,\n\n startApplicationCallback: () => this.startInstance(startInstanceOptions),\n stopApplicationCallback: () => this.stop(stopInstanceOptions),\n });\n\n // Start cluster\n clusterManager.start();\n } else {\n // Start standalone application\n await this.startInstance(startInstanceOptions);\n\n // Note: Signal handling should be implemented at the application launcher level\n // The lifecycle manager provides the stop() method for programmatic shutdown\n }\n }\n\n /**\n * Before application start\n */\n private async onBeforeStart(): Promise<{\n redisInstance: RedisInstance;\n databaseInstance: DatabaseInstance | null;\n queueManager: QueueManager;\n eventManager?: EventManager;\n }> {\n const phaseStartTime = Time.now();\n\n // Connect to Redis\n if (process.env.DEBUG_TESTS) {\n console.log('[BaseApplication] Connecting to Redis...');\n }\n const redisInstance = await this.redisManager.connect();\n if (process.env.DEBUG_TESTS) {\n const redisElapsed = Time.calculateElapsedTimeMs({ startTime: phaseStartTime });\n console.log(`[BaseApplication] Redis connected (${redisElapsed}ms)`);\n }\n\n // Connect to database\n let databaseInstance: DatabaseInstance | null = null;\n if (this.databaseManager) {\n if (process.env.DEBUG_TESTS) {\n console.log('[BaseApplication] Connecting to database...');\n }\n const dbStartTime = Time.now();\n databaseInstance = await this.databaseManager.connect();\n if (process.env.DEBUG_TESTS) {\n const dbElapsed = Time.calculateElapsedTimeMs({ startTime: dbStartTime });\n console.log(`[BaseApplication] Database connected (${dbElapsed}ms)`);\n }\n }\n\n let eventManager: EventManager | undefined;\n\n if (this.config.event?.enabled) {\n eventManager = new EventManager({\n applicationConfig: this.config,\n options: this.config.event,\n events: this.config.event.events || [],\n redisInstance,\n databaseInstance,\n // queueManager,\n });\n\n eventManager.load();\n }\n\n // Initialize queue\n const queueManager = new QueueManager({\n applicationConfig: this.config,\n options: {\n processorsDirectory: this.config.queue.processorsDirectory,\n },\n queues: this.config.queue.queues,\n redisInstance,\n databaseInstance,\n eventManager,\n });\n\n // Register queues\n await queueManager.registerQueues({\n queues: this.config.queue.queues,\n });\n\n // Register readiness checks for key services\n this.lifecycle.addReadinessCheck('redis', async () => {\n try {\n return await redisInstance.isConnected();\n } catch {\n return false;\n }\n });\n\n if (databaseInstance) {\n this.lifecycle.addReadinessCheck('database', async () => {\n try {\n return await databaseInstance.isConnected();\n } catch {\n return false;\n }\n });\n }\n\n return {\n redisInstance,\n databaseInstance,\n queueManager,\n eventManager,\n };\n }\n\n /**\n * Application started event\n */\n protected onStarted({ startupTime: _startupTime }: { startupTime: number }): void {}\n\n /**\n * Application stopped event\n */\n protected onStopped({ runtime: _runtime }: { runtime: number }): void {}\n\n /**\n * Start application instance\n */\n private async startInstance(options: ApplicationStartInstanceOptions): Promise<void> {\n try {\n // Phase 1: Initialize (resource setup)\n if (process.env.DEBUG_TESTS) {\n console.log('[startInstance] Phase 1: Initializing lifecycle...');\n }\n const initStartTime = Time.now();\n const initResult = await this.lifecycle.initialize();\n if (process.env.DEBUG_TESTS) {\n const initElapsed = Time.calculateElapsedTimeMs({ startTime: initStartTime });\n console.log(`[startInstance] Phase 1 complete (${initElapsed}ms)`);\n }\n if (initResult.errors.length > 0) {\n Logger.warn({\n message: 'Lifecycle init phase encountered errors',\n meta: { errors: initResult.errors.map(e => (e instanceof Error ? e.message : String(e))) },\n });\n }\n\n // Before application start\n if (process.env.DEBUG_TESTS) {\n console.log('[startInstance] Connecting to services (Redis, Database, Queue, Events)...');\n }\n const beforeStartTime = Time.now();\n const { redisInstance, databaseInstance, queueManager, eventManager } = await this.onBeforeStart();\n if (process.env.DEBUG_TESTS) {\n const beforeStartElapsed = Time.calculateElapsedTimeMs({ startTime: beforeStartTime });\n console.log(`[startInstance] Services connected (${beforeStartElapsed}ms)`);\n }\n\n // Phase 2: Start (component startup)\n if (process.env.DEBUG_TESTS) {\n console.log('[startInstance] Phase 2: Starting lifecycle components...');\n }\n const startStartTime = Time.now();\n const startResult = await this.lifecycle.start();\n if (process.env.DEBUG_TESTS) {\n const startElapsed = Time.calculateElapsedTimeMs({ startTime: startStartTime });\n console.log(`[startInstance] Phase 2 complete (${startElapsed}ms)`);\n }\n if (startResult.errors.length > 0) {\n Logger.warn({\n message: 'Lifecycle start phase encountered errors',\n meta: { errors: startResult.errors.map(e => (e instanceof Error ? e.message : String(e))) },\n });\n }\n\n // Start application\n if (process.env.DEBUG_TESTS) {\n console.log('[startInstance] Starting application handler...');\n }\n const handlerStartTime = Time.now();\n await this.startHandler({\n redisInstance,\n databaseInstance,\n queueManager,\n eventManager,\n });\n if (process.env.DEBUG_TESTS) {\n const handlerElapsed = Time.calculateElapsedTimeMs({ startTime: handlerStartTime });\n console.log(`[startInstance] Application handler started (${handlerElapsed}ms)`);\n }\n\n // Phase 3: Ready (application accepting traffic)\n if (process.env.DEBUG_TESTS) {\n console.log('[startInstance] Phase 3: Waiting for application to be ready...');\n }\n const readyStartTime = Time.now();\n const readyResult = await this.lifecycle.ready();\n if (process.env.DEBUG_TESTS) {\n const readyElapsed = Time.calculateElapsedTimeMs({ startTime: readyStartTime });\n console.log(`[startInstance] Phase 3 complete (${readyElapsed}ms)`);\n }\n if (readyResult.errors.length > 0) {\n Logger.warn({\n message: 'Lifecycle ready phase encountered errors',\n meta: { errors: readyResult.errors.map(e => (e instanceof Error ? e.message : String(e))) },\n });\n }\n\n // Calculate application startup time\n const startupTime = Time.calculateElapsedTimeMs({\n startTime: this.startTime,\n });\n\n // On application started\n if (options.onStarted) {\n await options.onStarted({ startupTime });\n }\n } catch (error) {\n Logger.error({\n error: error instanceof Error ? error : new Error(safeSerializeError(error)),\n message: 'startInstance failure',\n });\n throw error;\n }\n }\n\n protected abstract startHandler({\n redisInstance,\n databaseInstance,\n queueManager,\n eventManager,\n }: {\n redisInstance: RedisInstance;\n databaseInstance?: DatabaseInstance | null;\n queueManager: QueueManager;\n eventManager?: EventManager | null;\n }): Promise<void>;\n\n protected abstract stopCallback(): void;\n\n private static registerInstance(instance: BaseApplication): void {\n BaseApplication.pruneStaleInstances();\n BaseApplication.instances.add(new WeakRef(instance));\n BaseApplication.registerGlobalErrorHandlers();\n }\n\n private static unregisterInstance(instance: BaseApplication): void {\n for (const ref of Array.from(BaseApplication.instances)) {\n const current = ref.deref();\n if (!current || current === instance) {\n BaseApplication.instances.delete(ref);\n }\n }\n }\n\n private static pruneStaleInstances(): void {\n for (const ref of Array.from(BaseApplication.instances)) {\n if (!ref.deref()) {\n BaseApplication.instances.delete(ref);\n }\n }\n }\n\n private static getActiveInstances(): BaseApplication[] {\n const active: BaseApplication[] = [];\n const stale: WeakRef<BaseApplication>[] = [];\n\n for (const ref of BaseApplication.instances) {\n const instance = ref.deref();\n if (instance) {\n active.push(instance);\n } else {\n stale.push(ref);\n }\n }\n\n for (const ref of stale) {\n BaseApplication.instances.delete(ref);\n }\n\n return active;\n }\n\n private static registerGlobalErrorHandlers(): void {\n if (BaseApplication.globalErrorHandlersRegistered) {\n return;\n }\n\n process.on('uncaughtException', error => {\n Logger.error({ error, message: 'Uncaught Exception' });\n for (const app of BaseApplication.getActiveInstances()) {\n app.initiateGracefulShutdown();\n }\n });\n\n process.on('unhandledRejection', (reason, promise) => {\n Logger.error({\n error: reason instanceof Error ? reason : new Error(String(reason)),\n message: 'Unhandled Rejection',\n meta: { promise: String(promise) },\n });\n for (const app of BaseApplication.getActiveInstances()) {\n app.initiateGracefulShutdown();\n }\n });\n\n BaseApplication.globalErrorHandlersRegistered = true;\n }\n\n /**\n * Register shutdown hooks for proper cleanup\n */\n private registerShutdownHooks(): void {\n // Register shutdown hooks in reverse dependency order\n this.lifecycle.onShutdown(() => {\n BaseApplication.unregisterInstance(this);\n });\n\n this.lifecycle.onShutdown(async () => {\n Logger.info({ message: 'Executing custom stop callback' });\n await this.stopCallback();\n });\n\n this.lifecycle.onShutdown(async () => {\n if (this.redisManager) {\n Logger.info({ message: 'Disconnecting from Redis' });\n await this.redisManager.disconnect();\n }\n });\n\n this.lifecycle.onShutdown(async () => {\n if (this.databaseManager) {\n Logger.info({ message: 'Disconnecting from database' });\n await this.databaseManager.disconnect();\n }\n });\n\n // Performance monitor is handled via trackInterval, so it will be cleaned up automatically\n }\n\n /**\n * Initiate graceful shutdown\n */\n private async initiateGracefulShutdown(): Promise<void> {\n if (this.shutdownController.isShuttingDown) {\n return;\n }\n\n Logger.info({ message: 'Initiating graceful shutdown due to error' });\n try {\n const result = await this.shutdownController.initiate('error-triggered');\n if (result.errors.length > 0) {\n Logger.error({\n message: 'Errors during shutdown',\n error: result.errors,\n });\n this.finalizeExit({ code: 1, reason: 'graceful-shutdown-error', error: result.errors });\n } else if (result.timedOut) {\n Logger.warn({ message: 'Shutdown timed out' });\n this.finalizeExit({ code: 1, reason: 'shutdown-timeout' });\n } else {\n this.finalizeExit({ code: 0, reason: 'error-shutdown-complete' });\n }\n } catch (error) {\n Logger.error({\n error: error instanceof Error ? error : new Error(safeSerializeError(error)),\n message: 'Error during graceful shutdown',\n });\n this.finalizeExit({ code: 1, reason: 'graceful-shutdown-error', error });\n }\n }\n\n /**\n * Stop application using lifecycle manager\n */\n public async stop({ onStopped }: ApplicationStopInstanceOptions = {}): Promise<void> {\n if (this.shutdownController.isShuttingDown) {\n return;\n }\n\n // Register the onStopped callback if provided\n if (onStopped) {\n this.lifecycle.onShutdown(() => {\n const runtime = process.uptime() * 1000;\n onStopped({ runtime });\n });\n }\n\n try {\n const result = await this.shutdownController.initiate('manual-stop');\n if (result.errors.length > 0) {\n Logger.error({\n message: 'Errors during shutdown',\n error: result.errors,\n });\n this.finalizeExit({ code: 1, reason: 'shutdown-error', error: result.errors });\n } else if (result.timedOut) {\n Logger.warn({ message: 'Shutdown timed out' });\n this.finalizeExit({ code: 1, reason: 'shutdown-timeout' });\n } else {\n this.finalizeExit({ code: 0, reason: 'shutdown-complete' });\n }\n } catch (error) {\n Logger.error({\n error: error instanceof Error ? error : new Error(safeSerializeError(error)),\n message: 'Error during shutdown',\n });\n this.finalizeExit({ code: 1, reason: 'shutdown-error', error });\n }\n }\n\n /**\n * Finalize exit: during tests, suppress actual process exit to avoid failing vitest runs.\n */\n private finalizeExit(outcome: ExitOutcome): void {\n const nodeEnv = process.env.NODE_ENV ?? '';\n const isTestEnv =\n nodeEnv.toLowerCase() === 'test' ||\n 'VITEST' in process.env ||\n 'VITEST_WORKER_ID' in process.env ||\n process.argv.some(a => a.includes('vitest')) ||\n typeof (globalThis as any).afterAll === 'function';\n\n if (isTestEnv) {\n Logger.info({ message: `Skipping process exit in test environment (${outcome.reason})`, code: outcome.code });\n return;\n }\n requestExit(outcome);\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import cluster from 'cluster';\nimport { existsSync, readFileSync } from 'fs';\nimport { fileURLToPath } from 'url';\nimport { dirname, join, resolve } from 'path';\nimport { type DatabaseInstance, DatabaseManager } from '../database/index.js';\nimport QueueManager from '../queue/manager.js';\nimport RedisManager from '../redis/manager.js';\nimport type {\n ApplicationConfig,\n ApplicationStartInstanceOptions,\n ApplicationStopInstanceOptions,\n} from './base-application.interface.js';\nimport ClusterManager from '../cluster/cluster-manager.js';\nimport type RedisInstance from '../redis/instance.js';\nimport { OS, Time } from '../util/index.js';\nimport CacheManager from '../cache/manager.js';\nimport os from 'os';\nimport EventManager from '../event/manager.js';\nimport Logger from '../logger/logger.js';\nimport type { PerformanceMonitor } from '../performance/performance-monitor.js';\n// Performance monitoring now pluginized\nimport { PerformanceMonitorPlugin } from '../performance/performance-monitor.plugin.js';\nimport { type LifecycleConfig, LifecycleManager, ShutdownController } from '../lifecycle/index.js';\nimport { ConfigValidationError, formatConfigIssues, validateFrameworkConfig } from '../config/schema.js';\nimport { type ExitOutcome, requestExit } from '../lifecycle/exit.js';\nimport { safeSerializeError } from '../error/error-reporter.js';\n\n// Re-export types for external use\nexport type { ApplicationConfig } from './base-application.interface.js';\n\nexport default abstract class BaseApplication {\n /** Unique instance ID */\n public uniqueInstanceId: string;\n\n /** Application start time */\n protected startTime: number = 0;\n\n /** Shutdown timeout (30 seconds) */\n protected shutdownTimeout = 30000;\n\n /** Cache for application version to avoid repeated imports */\n private static applicationVersionCache: string | undefined;\n private static globalErrorHandlersRegistered = false;\n private static readonly instances = new Set<WeakRef<BaseApplication>>();\n\n /** Cluster worker ID */\n protected workerId = cluster.isWorker && cluster.worker ? cluster.worker.id : null;\n\n /** Application config */\n protected config: ApplicationConfig;\n\n /** Application version */\n protected applicationVersion?: string;\n\n /** Redis manager */\n public redisManager: RedisManager;\n\n /** Cache manager */\n public cacheManager: CacheManager;\n\n /** Database manager */\n public databaseManager?: DatabaseManager;\n\n /** Queue manager */\n public queueManager?: QueueManager;\n\n /** Event manager */\n public eventManager?: EventManager;\n\n /** Performance monitor */\n public performanceMonitor?: PerformanceMonitor;\n\n /** Lifecycle manager */\n public lifecycle: LifecycleManager;\n\n /** Shutdown controller */\n public shutdownController: ShutdownController;\n\n public get Name() {\n return this.config.name;\n }\n\n /**\n * Application constructor\n */\n constructor(config: ApplicationConfig) {\n // Validate configuration early (fail-fast before side effects)\n try {\n const validated = validateFrameworkConfig(config as any);\n config = validated as unknown as ApplicationConfig;\n } catch (err) {\n if (err instanceof ConfigValidationError) {\n const formatted = formatConfigIssues(err.issues);\n throw new Error(`Configuration validation failed:\\n${formatted}`);\n }\n throw err;\n }\n const computerName = os.hostname();\n\n this.uniqueInstanceId = `${config.instanceId}-${computerName}-${OS.getUniqueComputerId()}`;\n this.config = config;\n\n // Configure logger with application settings\n if (this.config.log?.showRequestIdInConsole !== undefined) {\n Logger.configure({ showRequestIdInConsole: this.config.log.showRequestIdInConsole });\n }\n\n // Initialize lifecycle management\n const lifecycleConfig: Partial<LifecycleConfig> = {\n gracefulShutdown: {\n timeoutMs: this.shutdownTimeout,\n },\n readiness: {\n timeoutMs: 30000,\n checkIntervalMs: 100,\n },\n };\n this.lifecycle = new LifecycleManager(lifecycleConfig);\n this.shutdownController = new ShutdownController(this.lifecycle);\n\n // Register shutdown hooks for cleanup\n this.registerShutdownHooks();\n\n // Initialize Redis manager\n this.redisManager = new RedisManager({\n applicationConfig: this.config,\n host: this.config.redis.host,\n port: this.config.redis.port,\n password: this.config.redis.password,\n });\n\n // Initialize cache manager\n this.cacheManager = new CacheManager({\n redisManager: this.redisManager,\n });\n\n // Register performance monitor plugin (idempotent & opt-in)\n PerformanceMonitorPlugin.register(this);\n\n // Track instance and ensure global error handlers are registered once\n BaseApplication.registerInstance(this);\n\n if (this.config.database?.enabled === true) {\n const defaultEntitiesDirectory = join(this.config.rootDirectory, 'src', 'database', 'entities');\n\n if (!this.config.database.entitiesDirectory) {\n this.config.database.entitiesDirectory = defaultEntitiesDirectory;\n }\n\n if (!existsSync(this.config.database.entitiesDirectory)) {\n throw new Error(`Database entities directory not found (Path: ${this.config.database.entitiesDirectory})`);\n }\n\n // Initialize Database manager\n this.databaseManager = new DatabaseManager({\n applicationConfig: this.config,\n host: this.config.database.host,\n port: this.config.database.port,\n username: this.config.database.username,\n password: this.config.database.password,\n databaseName: this.config.database.databaseName,\n entitiesDirectory: this.config.database.entitiesDirectory,\n });\n }\n }\n\n /**\n * Get application version\n */\n public async getApplicationVersion(): Promise<string> {\n // Return cached version if available\n if (BaseApplication.applicationVersionCache !== undefined) {\n return BaseApplication.applicationVersionCache;\n }\n\n // Resolve the path to package.json\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = dirname(__filename);\n const packageJsonPath = resolve(__dirname, '../../package.json');\n\n // Read and parse the file\n const fileContents = readFileSync(packageJsonPath, 'utf-8');\n const packageJson = JSON.parse(fileContents);\n\n if (!packageJson?.version) {\n throw new Error('Application version not found');\n }\n\n // Cache and return the version\n BaseApplication.applicationVersionCache = packageJson.version;\n\n return packageJson.version;\n }\n\n /**\n * Start application\n */\n public async start(): Promise<void> {\n // Start application timer\n this.startTime = Time.now();\n\n // Get application version`\n this.applicationVersion = await this.getApplicationVersion();\n\n // Log initial startup message with version\n Logger.info({\n message: 'Starting application',\n meta: {\n Name: this.config.name,\n 'Instance ID': this.config.instanceId,\n 'PXL Framework Version': this.applicationVersion,\n },\n });\n\n const startInstanceOptions: ApplicationStartInstanceOptions = {\n onStarted: this.onStarted.bind(this),\n };\n\n const stopInstanceOptions: ApplicationStopInstanceOptions = {\n onStopped: this.onStopped.bind(this),\n };\n\n if (this.config.cluster?.enabled) {\n // Initialize clustered application\n const clusterManager = new ClusterManager({\n config: this.config.cluster,\n\n startApplicationCallback: () => this.startInstance(startInstanceOptions),\n stopApplicationCallback: () => this.stop(stopInstanceOptions),\n });\n\n // Start cluster\n clusterManager.start();\n } else {\n // Start standalone application\n await this.startInstance(startInstanceOptions);\n\n // Note: Signal handling should be implemented at the application launcher level\n // The lifecycle manager provides the stop() method for programmatic shutdown\n }\n }\n\n /**\n * Before application start\n */\n private async onBeforeStart(): Promise<{\n redisInstance: RedisInstance;\n databaseInstance: DatabaseInstance | null;\n queueManager: QueueManager;\n eventManager?: EventManager;\n }> {\n const phaseStartTime = Time.now();\n\n // Connect to Redis\n if (process.env.DEBUG_TESTS) {\n console.log('[BaseApplication] Connecting to Redis...');\n }\n const redisInstance = await this.redisManager.connect();\n if (process.env.DEBUG_TESTS) {\n const redisElapsed = Time.calculateElapsedTimeMs({ startTime: phaseStartTime });\n console.log(`[BaseApplication] Redis connected (${redisElapsed}ms)`);\n }\n\n // Connect to database\n let databaseInstance: DatabaseInstance | null = null;\n if (this.databaseManager) {\n if (process.env.DEBUG_TESTS) {\n console.log('[BaseApplication] Connecting to database...');\n }\n const dbStartTime = Time.now();\n databaseInstance = await this.databaseManager.connect();\n if (process.env.DEBUG_TESTS) {\n const dbElapsed = Time.calculateElapsedTimeMs({ startTime: dbStartTime });\n console.log(`[BaseApplication] Database connected (${dbElapsed}ms)`);\n }\n }\n\n let eventManager: EventManager | undefined;\n\n if (this.config.event?.enabled) {\n eventManager = new EventManager({\n applicationConfig: this.config,\n options: this.config.event,\n events: this.config.event.events || [],\n redisInstance,\n databaseInstance,\n // queueManager,\n });\n\n eventManager.load();\n }\n\n // Initialize queue\n const queueManager = new QueueManager({\n applicationConfig: this.config,\n options: {\n processorsDirectory: this.config.queue.processorsDirectory,\n },\n queues: this.config.queue.queues,\n redisInstance,\n databaseInstance,\n eventManager,\n });\n\n // Register queues\n await queueManager.registerQueues({\n queues: this.config.queue.queues,\n });\n\n // Register readiness checks for key services\n this.lifecycle.addReadinessCheck('redis', async () => {\n try {\n return await redisInstance.isConnected();\n } catch {\n return false;\n }\n });\n\n if (databaseInstance) {\n this.lifecycle.addReadinessCheck('database', async () => {\n try {\n return await databaseInstance.isConnected();\n } catch {\n return false;\n }\n });\n }\n\n return {\n redisInstance,\n databaseInstance,\n queueManager,\n eventManager,\n };\n }\n\n /**\n * Application started event\n */\n protected onStarted({ startupTime: _startupTime }: { startupTime: number }): void {}\n\n /**\n * Application stopped event\n */\n protected onStopped({ runtime: _runtime }: { runtime: number }): void {}\n\n /**\n * Start application instance\n */\n private async startInstance(options: ApplicationStartInstanceOptions): Promise<void> {\n try {\n // Phase 1: Initialize (resource setup)\n if (process.env.DEBUG_TESTS) {\n console.log('[startInstance] Phase 1: Initializing lifecycle...');\n }\n const initStartTime = Time.now();\n const initResult = await this.lifecycle.initialize();\n if (process.env.DEBUG_TESTS) {\n const initElapsed = Time.calculateElapsedTimeMs({ startTime: initStartTime });\n console.log(`[startInstance] Phase 1 complete (${initElapsed}ms)`);\n }\n if (initResult.errors.length > 0) {\n Logger.warn({\n message: 'Lifecycle init phase encountered errors',\n meta: { errors: initResult.errors.map(e => (e instanceof Error ? e.message : String(e))) },\n });\n }\n\n // Before application start\n if (process.env.DEBUG_TESTS) {\n console.log('[startInstance] Connecting to services (Redis, Database, Queue, Events)...');\n }\n const beforeStartTime = Time.now();\n const { redisInstance, databaseInstance, queueManager, eventManager } = await this.onBeforeStart();\n\n // Store managers on instance for external access\n this.queueManager = queueManager;\n if (eventManager) {\n this.eventManager = eventManager;\n }\n\n if (process.env.DEBUG_TESTS) {\n const beforeStartElapsed = Time.calculateElapsedTimeMs({ startTime: beforeStartTime });\n console.log(`[startInstance] Services connected (${beforeStartElapsed}ms)`);\n }\n\n // Phase 2: Start (component startup)\n if (process.env.DEBUG_TESTS) {\n console.log('[startInstance] Phase 2: Starting lifecycle components...');\n }\n const startStartTime = Time.now();\n const startResult = await this.lifecycle.start();\n if (process.env.DEBUG_TESTS) {\n const startElapsed = Time.calculateElapsedTimeMs({ startTime: startStartTime });\n console.log(`[startInstance] Phase 2 complete (${startElapsed}ms)`);\n }\n if (startResult.errors.length > 0) {\n Logger.warn({\n message: 'Lifecycle start phase encountered errors',\n meta: { errors: startResult.errors.map(e => (e instanceof Error ? e.message : String(e))) },\n });\n }\n\n // Start application\n if (process.env.DEBUG_TESTS) {\n console.log('[startInstance] Starting application handler...');\n }\n const handlerStartTime = Time.now();\n await this.startHandler({\n redisInstance,\n databaseInstance,\n queueManager,\n eventManager,\n });\n if (process.env.DEBUG_TESTS) {\n const handlerElapsed = Time.calculateElapsedTimeMs({ startTime: handlerStartTime });\n console.log(`[startInstance] Application handler started (${handlerElapsed}ms)`);\n }\n\n // Phase 3: Ready (application accepting traffic)\n if (process.env.DEBUG_TESTS) {\n console.log('[startInstance] Phase 3: Waiting for application to be ready...');\n }\n const readyStartTime = Time.now();\n const readyResult = await this.lifecycle.ready();\n if (process.env.DEBUG_TESTS) {\n const readyElapsed = Time.calculateElapsedTimeMs({ startTime: readyStartTime });\n console.log(`[startInstance] Phase 3 complete (${readyElapsed}ms)`);\n }\n if (readyResult.errors.length > 0) {\n Logger.warn({\n message: 'Lifecycle ready phase encountered errors',\n meta: { errors: readyResult.errors.map(e => (e instanceof Error ? e.message : String(e))) },\n });\n }\n\n // Calculate application startup time\n const startupTime = Time.calculateElapsedTimeMs({\n startTime: this.startTime,\n });\n\n // On application started\n if (options.onStarted) {\n await options.onStarted({ startupTime });\n }\n } catch (error) {\n Logger.error({\n error: error instanceof Error ? error : new Error(safeSerializeError(error)),\n message: 'startInstance failure',\n });\n throw error;\n }\n }\n\n protected abstract startHandler({\n redisInstance,\n databaseInstance,\n queueManager,\n eventManager,\n }: {\n redisInstance: RedisInstance;\n databaseInstance?: DatabaseInstance | null;\n queueManager: QueueManager;\n eventManager?: EventManager | null;\n }): Promise<void>;\n\n protected abstract stopCallback(): void;\n\n private static registerInstance(instance: BaseApplication): void {\n BaseApplication.pruneStaleInstances();\n BaseApplication.instances.add(new WeakRef(instance));\n BaseApplication.registerGlobalErrorHandlers();\n }\n\n private static unregisterInstance(instance: BaseApplication): void {\n for (const ref of Array.from(BaseApplication.instances)) {\n const current = ref.deref();\n if (!current || current === instance) {\n BaseApplication.instances.delete(ref);\n }\n }\n }\n\n private static pruneStaleInstances(): void {\n for (const ref of Array.from(BaseApplication.instances)) {\n if (!ref.deref()) {\n BaseApplication.instances.delete(ref);\n }\n }\n }\n\n private static getActiveInstances(): BaseApplication[] {\n const active: BaseApplication[] = [];\n const stale: WeakRef<BaseApplication>[] = [];\n\n for (const ref of BaseApplication.instances) {\n const instance = ref.deref();\n if (instance) {\n active.push(instance);\n } else {\n stale.push(ref);\n }\n }\n\n for (const ref of stale) {\n BaseApplication.instances.delete(ref);\n }\n\n return active;\n }\n\n private static registerGlobalErrorHandlers(): void {\n if (BaseApplication.globalErrorHandlersRegistered) {\n return;\n }\n\n process.on('uncaughtException', error => {\n Logger.error({ error, message: 'Uncaught Exception' });\n for (const app of BaseApplication.getActiveInstances()) {\n app.initiateGracefulShutdown();\n }\n });\n\n process.on('unhandledRejection', (reason, promise) => {\n Logger.error({\n error: reason instanceof Error ? reason : new Error(String(reason)),\n message: 'Unhandled Rejection',\n meta: { promise: String(promise) },\n });\n for (const app of BaseApplication.getActiveInstances()) {\n app.initiateGracefulShutdown();\n }\n });\n\n BaseApplication.globalErrorHandlersRegistered = true;\n }\n\n /**\n * Register shutdown hooks for proper cleanup\n */\n private registerShutdownHooks(): void {\n // Register shutdown hooks in reverse dependency order\n this.lifecycle.onShutdown(() => {\n BaseApplication.unregisterInstance(this);\n });\n\n this.lifecycle.onShutdown(async () => {\n Logger.info({ message: 'Executing custom stop callback' });\n await this.stopCallback();\n });\n\n this.lifecycle.onShutdown(async () => {\n if (this.queueManager) {\n Logger.info({ message: 'Closing queue manager (workers and queues)' });\n await this.queueManager.disconnect();\n }\n });\n\n this.lifecycle.onShutdown(async () => {\n if (this.redisManager) {\n Logger.info({ message: 'Disconnecting from Redis' });\n await this.redisManager.disconnect();\n }\n });\n\n this.lifecycle.onShutdown(async () => {\n if (this.databaseManager) {\n Logger.info({ message: 'Disconnecting from database' });\n await this.databaseManager.disconnect();\n }\n });\n\n // Performance monitor is handled via trackInterval, so it will be cleaned up automatically\n }\n\n /**\n * Initiate graceful shutdown\n */\n private async initiateGracefulShutdown(): Promise<void> {\n if (this.shutdownController.isShuttingDown) {\n return;\n }\n\n Logger.info({ message: 'Initiating graceful shutdown due to error' });\n try {\n const result = await this.shutdownController.initiate('error-triggered');\n if (result.errors.length > 0) {\n Logger.error({\n message: 'Errors during shutdown',\n error: result.errors,\n });\n this.finalizeExit({ code: 1, reason: 'graceful-shutdown-error', error: result.errors });\n } else if (result.timedOut) {\n Logger.warn({ message: 'Shutdown timed out' });\n this.finalizeExit({ code: 1, reason: 'shutdown-timeout' });\n } else {\n this.finalizeExit({ code: 0, reason: 'error-shutdown-complete' });\n }\n } catch (error) {\n Logger.error({\n error: error instanceof Error ? error : new Error(safeSerializeError(error)),\n message: 'Error during graceful shutdown',\n });\n this.finalizeExit({ code: 1, reason: 'graceful-shutdown-error', error });\n }\n }\n\n /**\n * Stop application using lifecycle manager\n */\n public async stop({ onStopped }: ApplicationStopInstanceOptions = {}): Promise<void> {\n if (this.shutdownController.isShuttingDown) {\n return;\n }\n\n // Register the onStopped callback if provided\n if (onStopped) {\n this.lifecycle.onShutdown(() => {\n const runtime = process.uptime() * 1000;\n onStopped({ runtime });\n });\n }\n\n try {\n const result = await this.shutdownController.initiate('manual-stop');\n if (result.errors.length > 0) {\n Logger.error({\n message: 'Errors during shutdown',\n error: result.errors,\n });\n this.finalizeExit({ code: 1, reason: 'shutdown-error', error: result.errors });\n } else if (result.timedOut) {\n Logger.warn({ message: 'Shutdown timed out' });\n this.finalizeExit({ code: 1, reason: 'shutdown-timeout' });\n } else {\n this.finalizeExit({ code: 0, reason: 'shutdown-complete' });\n }\n } catch (error) {\n Logger.error({\n error: error instanceof Error ? error : new Error(safeSerializeError(error)),\n message: 'Error during shutdown',\n });\n this.finalizeExit({ code: 1, reason: 'shutdown-error', error });\n }\n }\n\n /**\n * Finalize exit: during tests, suppress actual process exit to avoid failing vitest runs.\n */\n private finalizeExit(outcome: ExitOutcome): void {\n const nodeEnv = process.env.NODE_ENV ?? '';\n const isTestEnv =\n nodeEnv.toLowerCase() === 'test' ||\n 'VITEST' in process.env ||\n 'VITEST_WORKER_ID' in process.env ||\n process.argv.some(a => a.includes('vitest')) ||\n typeof (globalThis as any).afterAll === 'function';\n\n if (isTestEnv) {\n Logger.info({ message: `Skipping process exit in test environment (${outcome.reason})`, code: outcome.code });\n return;\n }\n requestExit(outcome);\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,7 @@
1
1
  export { default as WebApplication } from './web-application.js';
2
2
  export { default as CommandApplication } from './command-application.js';
3
+ export { default as WorkerApplication } from './worker-application.js';
3
4
  export type { ApplicationConfig } from './base-application.interface.js';
4
5
  export type { WebApplicationConfig } from './web-application.interface.js';
6
+ export type { WorkerApplicationConfig } from './worker-application.interface.js';
5
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/application/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACzE,YAAY,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACzE,YAAY,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/application/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACvE,YAAY,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACzE,YAAY,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,YAAY,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC"}
@@ -1,7 +1,9 @@
1
1
  import { default as default2 } from "./web-application.js";
2
2
  import { default as default3 } from "./command-application.js";
3
+ import { default as default4 } from "./worker-application.js";
3
4
  export {
4
5
  default3 as CommandApplication,
5
- default2 as WebApplication
6
+ default2 as WebApplication,
7
+ default4 as WorkerApplication
6
8
  };
7
9
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/application/index.ts"],
4
- "sourcesContent": ["export { default as WebApplication } from './web-application.js';\nexport { default as CommandApplication } from './command-application.js';\nexport type { ApplicationConfig } from './base-application.interface.js';\nexport type { WebApplicationConfig } from './web-application.interface.js';\n"],
5
- "mappings": "AAAA,SAAoB,WAAXA,gBAAiC;AAC1C,SAAoB,WAAXA,gBAAqC;",
4
+ "sourcesContent": ["export { default as WebApplication } from './web-application.js';\nexport { default as CommandApplication } from './command-application.js';\nexport { default as WorkerApplication } from './worker-application.js';\nexport type { ApplicationConfig } from './base-application.interface.js';\nexport type { WebApplicationConfig } from './web-application.interface.js';\nexport type { WorkerApplicationConfig } from './worker-application.interface.js';\n"],
5
+ "mappings": "AAAA,SAAoB,WAAXA,gBAAiC;AAC1C,SAAoB,WAAXA,gBAAqC;AAC9C,SAAoB,WAAXA,gBAAoC;",
6
6
  "names": ["default"]
7
7
  }
@@ -0,0 +1,72 @@
1
+ import type RedisInstance from '../redis/instance.js';
2
+ import type DatabaseInstance from '../database/instance.js';
3
+ import type QueueManager from '../queue/manager.js';
4
+ import type EventManager from '../event/manager.js';
5
+ import BaseApplication from './base-application.js';
6
+ import type { WorkerApplicationConfig } from './worker-application.interface.js';
7
+ /**
8
+ * WorkerApplication
9
+ *
10
+ * A long-running application focused on queue processing.
11
+ * Unlike WebApplication, it does not start a web server.
12
+ * Unlike CommandApplication, it runs indefinitely.
13
+ *
14
+ * Workers are automatically started by QueueManager during initialization
15
+ * (via BaseApplication.onBeforeStart()) with autorun: true. This class
16
+ * simply provides the appropriate lifecycle management for long-running
17
+ * queue worker processes.
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * import { WorkerApplication } from '@scpxl/nodejs-framework';
22
+ *
23
+ * const app = new WorkerApplication({
24
+ * name: 'my-worker',
25
+ * instanceId: 'worker-1',
26
+ * rootDirectory: __dirname,
27
+ * redis: { host: 'localhost', port: 6379 },
28
+ * queue: {
29
+ * processorsDirectory: './processors',
30
+ * queues: [{ name: 'default', jobs: [{ id: 'my-job' }] }],
31
+ * },
32
+ * auth: { jwtSecretKey: 'secret' },
33
+ * });
34
+ *
35
+ * await app.start(); // Runs indefinitely, processing jobs
36
+ * ```
37
+ */
38
+ export default class WorkerApplication extends BaseApplication {
39
+ /** Worker application config */
40
+ protected config: WorkerApplicationConfig;
41
+ constructor(config: WorkerApplicationConfig);
42
+ /**
43
+ * Start handler - workers are already started by BaseApplication.onBeforeStart()
44
+ * via QueueManager.registerQueues() which creates workers with autorun: true.
45
+ *
46
+ * This method intentionally does minimal work since the queue workers
47
+ * are already running. It registers a readiness check for monitoring.
48
+ */
49
+ protected startHandler({ redisInstance: _redisInstance, databaseInstance: _databaseInstance, queueManager: _queueManager, eventManager: _eventManager, }: {
50
+ redisInstance: RedisInstance;
51
+ databaseInstance: DatabaseInstance | null;
52
+ queueManager: QueueManager;
53
+ eventManager?: EventManager | null;
54
+ }): Promise<void>;
55
+ /**
56
+ * Stop callback - cleanup worker-specific resources
57
+ */
58
+ protected stopCallback(): Promise<void>;
59
+ /**
60
+ * Application started event
61
+ */
62
+ protected onStarted({ startupTime }: {
63
+ startupTime: number;
64
+ }): Promise<void>;
65
+ /**
66
+ * Application stopped event
67
+ */
68
+ protected onStopped({ runtime }: {
69
+ runtime: number;
70
+ }): Promise<void>;
71
+ }
72
+ //# sourceMappingURL=worker-application.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-application.d.ts","sourceRoot":"","sources":["../../src/application/worker-application.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,aAAa,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,gBAAgB,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,YAAY,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,YAAY,MAAM,qBAAqB,CAAC;AACpD,OAAO,eAAe,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAIjF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,CAAC,OAAO,OAAO,iBAAkB,SAAQ,eAAe;IAC5D,gCAAgC;IAChC,SAAS,CAAC,MAAM,EAAE,uBAAuB,CAAC;gBAE9B,MAAM,EAAE,uBAAuB;IAc3C;;;;;;OAMG;cACa,YAAY,CAAC,EAC3B,aAAa,EAAE,cAAc,EAC7B,gBAAgB,EAAE,iBAAiB,EACnC,YAAY,EAAE,aAAa,EAC3B,YAAY,EAAE,aAAa,GAC5B,EAAE;QACD,aAAa,EAAE,aAAa,CAAC;QAC7B,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;QAC1C,YAAY,EAAE,YAAY,CAAC;QAC3B,YAAY,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;KACpC,GAAG,OAAO,CAAC,IAAI,CAAC;IAWjB;;OAEG;cACa,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAO7C;;OAEG;cACa,SAAS,CAAC,EAAE,WAAW,EAAE,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BlF;;OAEG;cACa,SAAS,CAAC,EAAE,OAAO,EAAE,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAqB3E"}
@@ -0,0 +1,17 @@
1
+ import type { ApplicationConfig } from './base-application.interface.js';
2
+ import type WorkerApplication from './worker-application.js';
3
+ export interface WorkerApplicationEventsConfig {
4
+ onStarted?: ({ app, startupTime }: {
5
+ app: WorkerApplication;
6
+ startupTime: number;
7
+ }) => void;
8
+ onStopped?: ({ app, runtime }: {
9
+ app: WorkerApplication;
10
+ runtime: number;
11
+ }) => void;
12
+ }
13
+ export interface WorkerApplicationConfig extends ApplicationConfig {
14
+ /** Worker application events */
15
+ events?: WorkerApplicationEventsConfig;
16
+ }
17
+ //# sourceMappingURL=worker-application.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-application.interface.d.ts","sourceRoot":"","sources":["../../src/application/worker-application.interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,KAAK,iBAAiB,MAAM,yBAAyB,CAAC;AAE7D,MAAM,WAAW,6BAA6B;IAC5C,SAAS,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,WAAW,EAAE,EAAE;QAAE,GAAG,EAAE,iBAAiB,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC5F,SAAS,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;QAAE,GAAG,EAAE,iBAAiB,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CACrF;AAED,MAAM,WAAW,uBAAwB,SAAQ,iBAAiB;IAChE,gCAAgC;IAChC,MAAM,CAAC,EAAE,6BAA6B,CAAC;CACxC"}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=worker-application.interface.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [],
5
+ "mappings": "",
6
+ "names": []
7
+ }
@@ -0,0 +1,99 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+ import BaseApplication from "./base-application.js";
4
+ import { Helper, Time } from "../util/index.js";
5
+ import { Logger } from "../logger/index.js";
6
+ class WorkerApplication extends BaseApplication {
7
+ static {
8
+ __name(this, "WorkerApplication");
9
+ }
10
+ /** Worker application config */
11
+ config;
12
+ constructor(config) {
13
+ super(config);
14
+ const defaultConfig = {
15
+ log: {
16
+ startUp: true,
17
+ shutdown: true
18
+ }
19
+ };
20
+ const mergedConfig = Helper.defaultsDeep(config, defaultConfig);
21
+ this.config = mergedConfig;
22
+ }
23
+ /**
24
+ * Start handler - workers are already started by BaseApplication.onBeforeStart()
25
+ * via QueueManager.registerQueues() which creates workers with autorun: true.
26
+ *
27
+ * This method intentionally does minimal work since the queue workers
28
+ * are already running. It registers a readiness check for monitoring.
29
+ */
30
+ async startHandler({
31
+ redisInstance: _redisInstance,
32
+ databaseInstance: _databaseInstance,
33
+ queueManager: _queueManager,
34
+ eventManager: _eventManager
35
+ }) {
36
+ this.lifecycle.addReadinessCheck("workers", async () => {
37
+ return !!this.queueManager;
38
+ });
39
+ }
40
+ /**
41
+ * Stop callback - cleanup worker-specific resources
42
+ */
43
+ async stopCallback() {
44
+ Logger.info({ message: "Worker application stopping" });
45
+ }
46
+ /**
47
+ * Application started event
48
+ */
49
+ async onStarted({ startupTime }) {
50
+ if (this.config.log?.startUp) {
51
+ const queueCount = this.config.queue?.queues?.length ?? 0;
52
+ Logger.info({
53
+ message: "Worker application started",
54
+ meta: {
55
+ "Startup Time": Time.formatTime({
56
+ time: startupTime,
57
+ format: "s",
58
+ numDecimals: 2,
59
+ showUnit: true
60
+ }),
61
+ "Queues Registered": queueCount
62
+ }
63
+ });
64
+ }
65
+ if (this.config.events?.onStarted) {
66
+ this.config.events.onStarted({
67
+ app: this,
68
+ startupTime
69
+ });
70
+ }
71
+ }
72
+ /**
73
+ * Application stopped event
74
+ */
75
+ async onStopped({ runtime }) {
76
+ if (this.config.log?.shutdown) {
77
+ Logger.info({
78
+ message: "Worker application stopped",
79
+ meta: {
80
+ Name: this.config.name,
81
+ "Instance ID": this.config.instanceId,
82
+ Runtime: Time.formatTime({
83
+ time: runtime,
84
+ format: "s",
85
+ numDecimals: 2,
86
+ showUnit: true
87
+ })
88
+ }
89
+ });
90
+ }
91
+ if (this.config.events?.onStopped) {
92
+ this.config.events.onStopped({ app: this, runtime });
93
+ }
94
+ }
95
+ }
96
+ export {
97
+ WorkerApplication as default
98
+ };
99
+ //# sourceMappingURL=worker-application.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/application/worker-application.ts"],
4
+ "sourcesContent": ["import type RedisInstance from '../redis/instance.js';\nimport type DatabaseInstance from '../database/instance.js';\nimport type QueueManager from '../queue/manager.js';\nimport type EventManager from '../event/manager.js';\nimport BaseApplication from './base-application.js';\nimport type { WorkerApplicationConfig } from './worker-application.interface.js';\nimport { Helper, Time } from '../util/index.js';\nimport { Logger } from '../logger/index.js';\n\n/**\n * WorkerApplication\n *\n * A long-running application focused on queue processing.\n * Unlike WebApplication, it does not start a web server.\n * Unlike CommandApplication, it runs indefinitely.\n *\n * Workers are automatically started by QueueManager during initialization\n * (via BaseApplication.onBeforeStart()) with autorun: true. This class\n * simply provides the appropriate lifecycle management for long-running\n * queue worker processes.\n *\n * @example\n * ```typescript\n * import { WorkerApplication } from '@scpxl/nodejs-framework';\n *\n * const app = new WorkerApplication({\n * name: 'my-worker',\n * instanceId: 'worker-1',\n * rootDirectory: __dirname,\n * redis: { host: 'localhost', port: 6379 },\n * queue: {\n * processorsDirectory: './processors',\n * queues: [{ name: 'default', jobs: [{ id: 'my-job' }] }],\n * },\n * auth: { jwtSecretKey: 'secret' },\n * });\n *\n * await app.start(); // Runs indefinitely, processing jobs\n * ```\n */\nexport default class WorkerApplication extends BaseApplication {\n /** Worker application config */\n protected config: WorkerApplicationConfig;\n\n constructor(config: WorkerApplicationConfig) {\n super(config);\n\n const defaultConfig: Partial<WorkerApplicationConfig> = {\n log: {\n startUp: true,\n shutdown: true,\n },\n };\n\n const mergedConfig = Helper.defaultsDeep(config, defaultConfig);\n this.config = mergedConfig;\n }\n\n /**\n * Start handler - workers are already started by BaseApplication.onBeforeStart()\n * via QueueManager.registerQueues() which creates workers with autorun: true.\n *\n * This method intentionally does minimal work since the queue workers\n * are already running. It registers a readiness check for monitoring.\n */\n protected async startHandler({\n redisInstance: _redisInstance,\n databaseInstance: _databaseInstance,\n queueManager: _queueManager,\n eventManager: _eventManager,\n }: {\n redisInstance: RedisInstance;\n databaseInstance: DatabaseInstance | null;\n queueManager: QueueManager;\n eventManager?: EventManager | null;\n }): Promise<void> {\n // Workers are already running via QueueManager (autorun: true)\n // This handler exists for any additional worker-specific initialization\n\n // Register readiness check for queue processing\n this.lifecycle.addReadinessCheck('workers', async () => {\n // Workers are ready if queueManager exists and has registered queues\n return !!this.queueManager;\n });\n }\n\n /**\n * Stop callback - cleanup worker-specific resources\n */\n protected async stopCallback(): Promise<void> {\n Logger.info({ message: 'Worker application stopping' });\n\n // Note: QueueWorkers are closed automatically by BullMQ when the process exits\n // and Redis connections are cleaned up by BaseApplication shutdown hooks\n }\n\n /**\n * Application started event\n */\n protected async onStarted({ startupTime }: { startupTime: number }): Promise<void> {\n if (this.config.log?.startUp) {\n const queueCount = this.config.queue?.queues?.length ?? 0;\n\n Logger.info({\n message: 'Worker application started',\n meta: {\n 'Startup Time': Time.formatTime({\n time: startupTime,\n format: 's',\n numDecimals: 2,\n showUnit: true,\n }),\n 'Queues Registered': queueCount,\n },\n });\n }\n\n if (this.config.events?.onStarted) {\n this.config.events.onStarted({\n app: this,\n startupTime,\n });\n }\n }\n\n /**\n * Application stopped event\n */\n protected async onStopped({ runtime }: { runtime: number }): Promise<void> {\n if (this.config.log?.shutdown) {\n Logger.info({\n message: 'Worker application stopped',\n meta: {\n Name: this.config.name,\n 'Instance ID': this.config.instanceId,\n Runtime: Time.formatTime({\n time: runtime,\n format: 's',\n numDecimals: 2,\n showUnit: true,\n }),\n },\n });\n }\n\n if (this.config.events?.onStopped) {\n this.config.events.onStopped({ app: this, runtime });\n }\n }\n}\n"],
5
+ "mappings": ";;AAIA,OAAO,qBAAqB;AAE5B,SAAS,QAAQ,YAAY;AAC7B,SAAS,cAAc;AAiCvB,MAAO,0BAAwC,gBAAgB;AAAA,EAxC/D,OAwC+D;AAAA;AAAA;AAAA;AAAA,EAEnD;AAAA,EAEV,YAAY,QAAiC;AAC3C,UAAM,MAAM;AAEZ,UAAM,gBAAkD;AAAA,MACtD,KAAK;AAAA,QACH,SAAS;AAAA,QACT,UAAU;AAAA,MACZ;AAAA,IACF;AAEA,UAAM,eAAe,OAAO,aAAa,QAAQ,aAAa;AAC9D,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAgB,aAAa;AAAA,IAC3B,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,cAAc;AAAA,IACd,cAAc;AAAA,EAChB,GAKkB;AAKhB,SAAK,UAAU,kBAAkB,WAAW,YAAY;AAEtD,aAAO,CAAC,CAAC,KAAK;AAAA,IAChB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAgB,eAA8B;AAC5C,WAAO,KAAK,EAAE,SAAS,8BAA8B,CAAC;AAAA,EAIxD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAgB,UAAU,EAAE,YAAY,GAA2C;AACjF,QAAI,KAAK,OAAO,KAAK,SAAS;AAC5B,YAAM,aAAa,KAAK,OAAO,OAAO,QAAQ,UAAU;AAExD,aAAO,KAAK;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,UACJ,gBAAgB,KAAK,WAAW;AAAA,YAC9B,MAAM;AAAA,YACN,QAAQ;AAAA,YACR,aAAa;AAAA,YACb,UAAU;AAAA,UACZ,CAAC;AAAA,UACD,qBAAqB;AAAA,QACvB;AAAA,MACF,CAAC;AAAA,IACH;AAEA,QAAI,KAAK,OAAO,QAAQ,WAAW;AACjC,WAAK,OAAO,OAAO,UAAU;AAAA,QAC3B,KAAK;AAAA,QACL;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAgB,UAAU,EAAE,QAAQ,GAAuC;AACzE,QAAI,KAAK,OAAO,KAAK,UAAU;AAC7B,aAAO,KAAK;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,UACJ,MAAM,KAAK,OAAO;AAAA,UAClB,eAAe,KAAK,OAAO;AAAA,UAC3B,SAAS,KAAK,WAAW;AAAA,YACvB,MAAM;AAAA,YACN,QAAQ;AAAA,YACR,aAAa;AAAA,YACb,UAAU;AAAA,UACZ,CAAC;AAAA,QACH;AAAA,MACF,CAAC;AAAA,IACH;AAEA,QAAI,KAAK,OAAO,QAAQ,WAAW;AACjC,WAAK,OAAO,OAAO,UAAU,EAAE,KAAK,MAAM,QAAQ,CAAC;AAAA,IACrD;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -62,5 +62,11 @@ export declare class LifecycleManager {
62
62
  ready: boolean;
63
63
  checks: ReadinessCheckResult[];
64
64
  }>;
65
+ /**
66
+ * Reset the lifecycle manager to its initial state.
67
+ * This clears all hooks, tracked resources, and readiness checks.
68
+ * Useful for testing or when reinitializing the application.
69
+ */
70
+ reset(): void;
65
71
  }
66
72
  //# sourceMappingURL=lifecycle-manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycle-manager.d.ts","sourceRoot":"","sources":["../../src/lifecycle/lifecycle-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,oBAAoB,EAC1B,MAAM,YAAY,CAAC;AAEpB,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAA0C;IACxD,OAAO,CAAC,MAAM,CAAkB;IAEhC,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,mBAAmB,CAAuB;IAClD,OAAO,CAAC,aAAa,CAAuB;IAE5C,OAAO,CAAC,WAAW,CAAyB;IAC5C,OAAO,CAAC,SAAS,CAA6B;IAC9C,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,gBAAgB,CAA8B;IAEtD,OAAO,CAAC,eAAe,CAAqC;IAC5D,OAAO,CAAC,QAAQ,CAAS;gBAEb,MAAM,GAAE,OAAO,CAAC,eAAe,CAAM;IAYjD,IAAI,KAAK,IAAI,cAAc,CAE1B;IAED,IAAI,cAAc,IAAI,OAAO,CAE5B;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,MAAM,CAAC,EAAE,EAAE,aAAa,GAAG,MAAM,IAAI;IAQrC,OAAO,CAAC,EAAE,EAAE,aAAa,GAAG,MAAM,IAAI;IAQtC,OAAO,CAAC,EAAE,EAAE,aAAa,GAAG,MAAM,IAAI;IAQtC,gBAAgB,CAAC,EAAE,EAAE,aAAa,GAAG,MAAM,IAAI;IAQ/C,UAAU,CAAC,EAAE,EAAE,aAAa,GAAG,MAAM,IAAI;IAQzC,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,IAAI;IAOlE,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG;QAAE,OAAO,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,GAAG,UAAU;IAO7F,aAAa,CAAC,EAAE,EAAE,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO;IAKjD,YAAY,CAAC,EAAE,EAAE,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO;IAKhD;;;;;OAKG;IACH,oBAAoB,CAAC,UAAU,EAAE,eAAe,GAAG,eAAe;IAKlE;;;;OAIG;IACH,qBAAqB,IAAI,eAAe;IAKlC,UAAU,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC;IAU5C,KAAK,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC;IAUvC,KAAK,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC;IAkBvC,QAAQ,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,EAAE,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;YA2BrD,eAAe;YA4Cf,YAAY;YAYZ,gBAAgB;YAmChB,sBAAsB;IAiC9B,kBAAkB,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,oBAAoB,EAAE,CAAA;KAAE,CAAC;CAKxF"}
1
+ {"version":3,"file":"lifecycle-manager.d.ts","sourceRoot":"","sources":["../../src/lifecycle/lifecycle-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,oBAAoB,EAC1B,MAAM,YAAY,CAAC;AAEpB,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAA0C;IACxD,OAAO,CAAC,MAAM,CAAkB;IAEhC,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,mBAAmB,CAAuB;IAClD,OAAO,CAAC,aAAa,CAAuB;IAE5C,OAAO,CAAC,WAAW,CAAyB;IAC5C,OAAO,CAAC,SAAS,CAA6B;IAC9C,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,gBAAgB,CAA8B;IAEtD,OAAO,CAAC,eAAe,CAAqC;IAC5D,OAAO,CAAC,QAAQ,CAAS;gBAEb,MAAM,GAAE,OAAO,CAAC,eAAe,CAAM;IAYjD,IAAI,KAAK,IAAI,cAAc,CAE1B;IAED,IAAI,cAAc,IAAI,OAAO,CAE5B;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,MAAM,CAAC,EAAE,EAAE,aAAa,GAAG,MAAM,IAAI;IAQrC,OAAO,CAAC,EAAE,EAAE,aAAa,GAAG,MAAM,IAAI;IAQtC,OAAO,CAAC,EAAE,EAAE,aAAa,GAAG,MAAM,IAAI;IAQtC,gBAAgB,CAAC,EAAE,EAAE,aAAa,GAAG,MAAM,IAAI;IAQ/C,UAAU,CAAC,EAAE,EAAE,aAAa,GAAG,MAAM,IAAI;IAQzC,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,IAAI;IAOlE,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG;QAAE,OAAO,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,GAAG,UAAU;IAO7F,aAAa,CAAC,EAAE,EAAE,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO;IAKjD,YAAY,CAAC,EAAE,EAAE,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO;IAKhD;;;;;OAKG;IACH,oBAAoB,CAAC,UAAU,EAAE,eAAe,GAAG,eAAe;IAKlE;;;;OAIG;IACH,qBAAqB,IAAI,eAAe;IAKlC,UAAU,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC;IAU5C,KAAK,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC;IAUvC,KAAK,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC;IAkBvC,QAAQ,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,EAAE,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;YA2BrD,eAAe;YA4Cf,YAAY;YAYZ,gBAAgB;YAmChB,sBAAsB;IAiC9B,kBAAkB,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,oBAAoB,EAAE,CAAA;KAAE,CAAC;IAMvF;;;;OAIG;IACH,KAAK,IAAI,IAAI;CA6Bd"}
@@ -268,6 +268,34 @@ class LifecycleManager {
268
268
  const ready = this._isReady && this._phase === LifecyclePhase.RUNNING && checks.every((c) => c.ready);
269
269
  return { ready, checks };
270
270
  }
271
+ /**
272
+ * Reset the lifecycle manager to its initial state.
273
+ * This clears all hooks, tracked resources, and readiness checks.
274
+ * Useful for testing or when reinitializing the application.
275
+ */
276
+ reset() {
277
+ this.initHooks.length = 0;
278
+ this.startHooks.length = 0;
279
+ this.readyHooks.length = 0;
280
+ this.beforeShutdownHooks.length = 0;
281
+ this.shutdownHooks.length = 0;
282
+ for (const id of this.intervals) {
283
+ clearInterval(id);
284
+ }
285
+ for (const id of this.timeouts) {
286
+ clearTimeout(id);
287
+ }
288
+ for (const controller of this.abortControllers) {
289
+ controller.abort();
290
+ }
291
+ this.disposables.clear();
292
+ this.intervals.clear();
293
+ this.timeouts.clear();
294
+ this.abortControllers.clear();
295
+ this.readinessChecks.clear();
296
+ this._phase = LifecyclePhase.CREATED;
297
+ this._isReady = false;
298
+ }
271
299
  }
272
300
  export {
273
301
  LifecycleManager