import * as plugins from './mod.plugins.js'; import * as helpers from './helpers.js'; import { logger } from '../gitzone.logging.js'; export interface IServiceConfig { PROJECT_NAME: string; MONGODB_HOST: string; MONGODB_NAME: string; MONGODB_PORT: string; MONGODB_USER: string; MONGODB_PASS: string; S3_HOST: string; S3_PORT: string; S3_CONSOLE_PORT: string; S3_USER: string; S3_PASS: string; S3_BUCKET: string; } export class ServiceConfiguration { private configPath: string; private config: IServiceConfig; constructor() { this.configPath = plugins.path.join(process.cwd(), '.nogit', 'env.json'); } /** * Load or create the configuration */ public async loadOrCreate(): Promise { await this.ensureNogitDirectory(); if (await this.configExists()) { await this.loadConfig(); await this.updateMissingFields(); } else { await this.createDefaultConfig(); } return this.config; } /** * Get the current configuration */ public getConfig(): IServiceConfig { return this.config; } /** * Save the configuration to file */ public async saveConfig(): Promise { await plugins.smartfile.memory.toFs( JSON.stringify(this.config, null, 2), this.configPath ); } /** * Ensure .nogit directory exists */ private async ensureNogitDirectory(): Promise { const nogitPath = plugins.path.join(process.cwd(), '.nogit'); await plugins.smartfile.fs.ensureDir(nogitPath); } /** * Check if configuration file exists */ private async configExists(): Promise { return plugins.smartfile.fs.fileExists(this.configPath); } /** * Load configuration from file */ private async loadConfig(): Promise { const configContent = await plugins.smartfile.fs.toStringSync(this.configPath); this.config = JSON.parse(configContent); } /** * Create default configuration */ private async createDefaultConfig(): Promise { const projectName = helpers.getProjectName(); const mongoPort = await helpers.getRandomAvailablePort(); const s3Port = await helpers.getRandomAvailablePort(); let s3ConsolePort = s3Port + 1; // Ensure console port is also available while (!(await helpers.isPortAvailable(s3ConsolePort))) { s3ConsolePort++; } this.config = { PROJECT_NAME: projectName, MONGODB_HOST: 'localhost', MONGODB_NAME: projectName, MONGODB_PORT: mongoPort.toString(), MONGODB_USER: 'defaultadmin', MONGODB_PASS: 'defaultpass', S3_HOST: 'localhost', S3_PORT: s3Port.toString(), S3_CONSOLE_PORT: s3ConsolePort.toString(), S3_USER: 'defaultadmin', S3_PASS: 'defaultpass', S3_BUCKET: `${projectName}-documents` }; await this.saveConfig(); logger.log('ok', '✅ Created .nogit/env.json with project defaults'); logger.log('info', `📍 MongoDB port: ${mongoPort}`); logger.log('info', `📍 S3 API port: ${s3Port}`); logger.log('info', `📍 S3 Console port: ${s3ConsolePort}`); } /** * Update missing fields in existing configuration */ private async updateMissingFields(): Promise { const projectName = helpers.getProjectName(); let updated = false; const fieldsAdded: string[] = []; // Check and add missing fields if (!this.config.PROJECT_NAME) { this.config.PROJECT_NAME = projectName; fieldsAdded.push('PROJECT_NAME'); updated = true; } if (!this.config.MONGODB_HOST) { this.config.MONGODB_HOST = 'localhost'; fieldsAdded.push('MONGODB_HOST'); updated = true; } if (!this.config.MONGODB_NAME) { this.config.MONGODB_NAME = projectName; fieldsAdded.push('MONGODB_NAME'); updated = true; } if (!this.config.MONGODB_PORT) { const port = await helpers.getRandomAvailablePort(); this.config.MONGODB_PORT = port.toString(); fieldsAdded.push(`MONGODB_PORT(${port})`); updated = true; } if (!this.config.MONGODB_USER) { this.config.MONGODB_USER = 'defaultadmin'; fieldsAdded.push('MONGODB_USER'); updated = true; } if (!this.config.MONGODB_PASS) { this.config.MONGODB_PASS = 'defaultpass'; fieldsAdded.push('MONGODB_PASS'); updated = true; } if (!this.config.S3_HOST) { this.config.S3_HOST = 'localhost'; fieldsAdded.push('S3_HOST'); updated = true; } if (!this.config.S3_PORT) { const port = await helpers.getRandomAvailablePort(); this.config.S3_PORT = port.toString(); fieldsAdded.push(`S3_PORT(${port})`); updated = true; } if (!this.config.S3_CONSOLE_PORT) { const s3Port = parseInt(this.config.S3_PORT); let consolePort = s3Port + 1; while (!(await helpers.isPortAvailable(consolePort))) { consolePort++; } this.config.S3_CONSOLE_PORT = consolePort.toString(); fieldsAdded.push(`S3_CONSOLE_PORT(${consolePort})`); updated = true; } if (!this.config.S3_USER) { this.config.S3_USER = 'defaultadmin'; fieldsAdded.push('S3_USER'); updated = true; } if (!this.config.S3_PASS) { this.config.S3_PASS = 'defaultpass'; fieldsAdded.push('S3_PASS'); updated = true; } if (!this.config.S3_BUCKET) { this.config.S3_BUCKET = `${projectName}-documents`; fieldsAdded.push('S3_BUCKET'); updated = true; } if (updated) { await this.saveConfig(); logger.log('ok', `✅ Added missing fields: ${fieldsAdded.join(', ')}`); } else { logger.log('ok', '✅ Configuration complete'); } } /** * Get MongoDB connection string */ public getMongoConnectionString(useNetworkIp: boolean = false): string { const host = useNetworkIp ? '${networkIp}' : this.config.MONGODB_HOST; return `mongodb://${this.config.MONGODB_USER}:${this.config.MONGODB_PASS}@${host}:${this.config.MONGODB_PORT}/${this.config.MONGODB_NAME}?authSource=admin`; } /** * Get container names */ public getContainerNames() { return { mongo: `${this.config.PROJECT_NAME}-mongodb`, minio: `${this.config.PROJECT_NAME}-minio` }; } /** * Get data directories */ public getDataDirectories() { return { mongo: plugins.path.join(process.cwd(), '.nogit', 'mongodata'), minio: plugins.path.join(process.cwd(), '.nogit', 'miniodata') }; } }