import * as plugins from './plugins.js'; import * as paths from './paths.js'; import { PlatformServiceDb } from './classes.platformservicedb.js' import { EmailService } from './mail/services/classes.emailservice.js'; import { SmsService } from './sms/classes.smsservice.js'; import { MtaService } from './mail/delivery/classes.mta.js'; import { logger } from './logger.js'; import { type IPlatformConfig } from './config/index.js'; import { ConfigurationError } from './errors/base.errors.js'; export class SzPlatformService { public projectinfo: plugins.projectinfo.ProjectInfo; public serviceQenv = new plugins.qenv.Qenv('./', './.nogit'); public platformserviceDb: PlatformServiceDb; public typedserver: plugins.typedserver.TypedServer; public typedrouter = new plugins.typedrequest.TypedRouter(); // SubServices public emailService: EmailService; public mtaService: MtaService; public smsService: SmsService; // Platform configuration public config: IPlatformConfig; /** * Create a new platform service instance * * @param config Optional platform configuration */ constructor(config: IPlatformConfig) { // Store configuration this.config = config; // Initialize typed router this.typedrouter = new plugins.typedrequest.TypedRouter(); } /** * Initialize the platform service * Applies configuration provided in constructor */ public async initialize(): Promise { // Simple validation of config - must be provided if (!this.config) { throw new ConfigurationError( 'Platform configuration must be provided in constructor', 'PLATFORM_CONFIG_MISSING', {} ); } // Apply configuration to logger if (this.config.logging) { logger.setContext({ environment: this.config.environment, component: 'PlatformService' }); } // Create project info this.projectinfo = new plugins.projectinfo.ProjectInfo(paths.packageDir); // Initialize database this.platformserviceDb = new PlatformServiceDb(this); logger.info('Platform service initialized successfully'); } /** * Start the platform service */ public async start(): Promise { // Initialize first if needed if (!this.config) { await this.initialize(); } // Check if service is enabled if (this.config.enabled === false) { logger.warn('Platform service is disabled in configuration, not starting services'); return; } logger.info('Starting platform service...'); // Initialize sub-services await this.initializeServices(); // Start the HTTP server await this.startServer(); logger.info('Platform service started successfully'); } /** * Initialize and start sub-services */ private async initializeServices(): Promise { // Initialize email service if (this.config.email?.enabled !== false) { this.emailService = new EmailService(this, this.config.email); await this.emailService.start(); logger.info('Email service started'); // Initialize MTA service if needed if (this.config.email?.useMta) { this.mtaService = new MtaService(this, this.config.email.mtaConfig); logger.info('MTA service initialized'); } } else { logger.info('Email service disabled in configuration'); } // Initialize SMS service if (this.config.sms?.enabled !== false) { // Get API token from config or env var const apiToken = this.config.sms?.apiGatewayApiToken || await this.serviceQenv.getEnvVarOnDemand('SMS_API_TOKEN'); if (!apiToken) { logger.warn('No SMS API token provided, SMS service will not be started'); } else { this.smsService = new SmsService(this, { apiGatewayApiToken: apiToken, ...this.config.sms }); await this.smsService.start(); logger.info('SMS service started'); } } else { logger.info('SMS service disabled in configuration'); } } /** * Start the HTTP server */ private async startServer(): Promise { // Check if server is enabled if (this.config.server?.enabled === false) { logger.info('HTTP server disabled in configuration'); return; } // Create server with configuration this.typedserver = new plugins.typedserver.TypedServer({ cors: this.config.server?.cors === false ? false : true, port: this.config.server?.port || 3000, // hostname is not supported directly, will be set during start }); // Add the router // Note: Using any type to bypass TypeScript restriction (this.typedserver as any).addRouter(this.typedrouter); // Start server await this.typedserver.start(); logger.info(`HTTP server started on ${this.config.server?.host || '0.0.0.0'}:${this.config.server?.port || 3000}`); } /** * Stop the platform service */ public async stop(): Promise { logger.info('Stopping platform service...'); // Stop sub-services if (this.emailService) { await this.emailService.stop(); logger.info('Email service stopped'); } if (this.smsService) { await this.smsService.stop(); logger.info('SMS service stopped'); } // Stop the server if it's running if (this.typedserver) { await this.typedserver.stop(); logger.info('HTTP server stopped'); } logger.info('Platform service stopped successfully'); } }