feat(services): Add comprehensive development services management (v1.17.0)
- Implemented gitzone services command for managing MongoDB and MinIO containers - Added smart port assignment (20000-30000 range) to avoid conflicts - Project-specific container names for complete isolation - Data persistence in .nogit/ directories - MongoDB Compass connection string generation with network IP detection - Auto-configuration via .nogit/env.json with secure defaults - Commands: start, stop, restart, status, config, compass, logs, remove, clean - Interactive confirmations for destructive operations - Comprehensive documentation and Task Venture Capital GmbH legal update
This commit is contained in:
245
ts/mod_services/classes.serviceconfiguration.ts
Normal file
245
ts/mod_services/classes.serviceconfiguration.ts
Normal file
@@ -0,0 +1,245 @@
|
||||
import * as plugins from './mod.plugins.js';
|
||||
import * as helpers from './helpers.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<IServiceConfig> {
|
||||
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<void> {
|
||||
await plugins.smartfile.memory.toFs(
|
||||
JSON.stringify(this.config, null, 2),
|
||||
this.configPath
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure .nogit directory exists
|
||||
*/
|
||||
private async ensureNogitDirectory(): Promise<void> {
|
||||
const nogitPath = plugins.path.join(process.cwd(), '.nogit');
|
||||
await plugins.smartfile.fs.ensureDir(nogitPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if configuration file exists
|
||||
*/
|
||||
private async configExists(): Promise<boolean> {
|
||||
return plugins.smartfile.fs.fileExists(this.configPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load configuration from file
|
||||
*/
|
||||
private async loadConfig(): Promise<void> {
|
||||
const configContent = await plugins.smartfile.fs.toStringSync(this.configPath);
|
||||
this.config = JSON.parse(configContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create default configuration
|
||||
*/
|
||||
private async createDefaultConfig(): Promise<void> {
|
||||
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();
|
||||
|
||||
helpers.printMessage('✅ Created .nogit/env.json with project defaults', 'green');
|
||||
helpers.printMessage(`📍 MongoDB port: ${mongoPort}`, 'blue');
|
||||
helpers.printMessage(`📍 S3 API port: ${s3Port}`, 'blue');
|
||||
helpers.printMessage(`📍 S3 Console port: ${s3ConsolePort}`, 'blue');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update missing fields in existing configuration
|
||||
*/
|
||||
private async updateMissingFields(): Promise<void> {
|
||||
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();
|
||||
helpers.printMessage(`✅ Added missing fields: ${fieldsAdded.join(', ')}`, 'green');
|
||||
} else {
|
||||
helpers.printMessage('✅ Configuration complete', 'green');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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')
|
||||
};
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user