import { SecretBundle } from 'ts/manager.secret/classes.secretbundle.js'; import * as plugins from '../plugins.js'; import { ServiceManager } from './classes.servicemanager.js'; @plugins.smartdata.managed() export class Service extends plugins.smartdata.SmartDataDbDoc< Service, plugins.servezoneInterfaces.data.IService, ServiceManager > { // STATIC public static async getServiceById(serviceIdArg: string) { const service = await this.getInstance({ id: serviceIdArg, }); return service; } public static async getServices() { const services = await this.getInstances({}); return services; } public static async createService(serviceDataArg: Partial) { const service = new Service(); service.id = await Service.getNewId(); Object.assign(service, serviceDataArg); await service.save(); // Create DNS entries if service has web port and domains configured if (service.data.ports?.web && service.data.domains?.length > 0) { await service.createDnsEntries(); } return service; } // INSTANCE @plugins.smartdata.svDb() public id: string; @plugins.smartdata.svDb() public data: plugins.servezoneInterfaces.data.IService['data']; /** * a service runs in a specific environment * so -> this method returns the secret bundles as a flat object accordingly. * in other words, it resolves secret groups for the relevant environment * @param environmentArg */ public async getSecretBundlesAsFlatObject(environmentArg: string = 'production') { const secreBundleIds = this.data.additionalSecretBundleIds || []; secreBundleIds.push(this.data.secretBundleId); // put this last, so it overwrites any other secret bundles. let finalFlatObject = {}; for (const secretBundleId of secreBundleIds) { const secretBundle = await SecretBundle.getInstance({ id: secretBundleId, }); const flatObject = await secretBundle.getFlatKeyValueObject(environmentArg); Object.assign(finalFlatObject, flatObject); } return finalFlatObject; } /** * Creates DNS entries for this service (in inactive state) * These will be activated when the service is deployed */ public async createDnsEntries() { const dnsManager = this.manager.cloudlyRef.dnsManager; for (const domain of this.data.domains) { const dnsEntryData: plugins.servezoneInterfaces.data.IDnsEntry['data'] = { type: 'A', // Default to A record, could be made configurable name: domain.name, value: '0.0.0.0', // Placeholder, will be updated on deployment ttl: 3600, zone: '', // Will be set based on domainId domainId: domain.domainId, active: false, // Created as inactive description: `Auto-generated DNS entry for service ${this.data.name}`, createdAt: Date.now(), isAutoGenerated: true, sourceServiceId: this.id, sourceType: 'service', }; // Create the DNS entry await dnsManager.createServiceDnsEntry(dnsEntryData); } } /** * Removes DNS entries for this service */ public async removeDnsEntries() { const dnsManager = this.manager.cloudlyRef.dnsManager; await dnsManager.removeServiceDnsEntries(this.id); } }