import * as plugins from '../../plugins.js'; import { AsyncFileSystem } from '../../core/utils/fs-utils.js'; import type { ICertificateData } from './certificate-manager.js'; export class CertStore { constructor(private certDir: string) {} public async initialize(): Promise { await AsyncFileSystem.ensureDir(this.certDir); } public async getCertificate(routeName: string): Promise { const certPath = this.getCertPath(routeName); const metaPath = `${certPath}/meta.json`; if (!await AsyncFileSystem.exists(metaPath)) { return null; } try { const meta = await AsyncFileSystem.readJSON(metaPath); const [cert, key] = await Promise.all([ AsyncFileSystem.readFile(`${certPath}/cert.pem`), AsyncFileSystem.readFile(`${certPath}/key.pem`) ]); let ca: string | undefined; const caPath = `${certPath}/ca.pem`; if (await AsyncFileSystem.exists(caPath)) { ca = await AsyncFileSystem.readFile(caPath); } return { cert, key, ca, expiryDate: new Date(meta.expiryDate), issueDate: new Date(meta.issueDate) }; } catch (error) { console.error(`Failed to load certificate for ${routeName}: ${error}`); return null; } } public async saveCertificate( routeName: string, certData: ICertificateData ): Promise { const certPath = this.getCertPath(routeName); await AsyncFileSystem.ensureDir(certPath); // Save certificate files in parallel const savePromises = [ AsyncFileSystem.writeFile(`${certPath}/cert.pem`, certData.cert), AsyncFileSystem.writeFile(`${certPath}/key.pem`, certData.key) ]; if (certData.ca) { savePromises.push( AsyncFileSystem.writeFile(`${certPath}/ca.pem`, certData.ca) ); } // Save metadata const meta = { expiryDate: certData.expiryDate.toISOString(), issueDate: certData.issueDate.toISOString(), savedAt: new Date().toISOString() }; savePromises.push( AsyncFileSystem.writeJSON(`${certPath}/meta.json`, meta) ); await Promise.all(savePromises); } public async deleteCertificate(routeName: string): Promise { const certPath = this.getCertPath(routeName); if (await AsyncFileSystem.isDirectory(certPath)) { await AsyncFileSystem.removeDir(certPath); } } private getCertPath(routeName: string): string { // Sanitize route name for filesystem const safeName = routeName.replace(/[^a-zA-Z0-9-_]/g, '_'); return `${this.certDir}/${safeName}`; } }