Files
configucci/src/models/Config.tsx

175 lines
3.9 KiB
TypeScript

import { Env } from './Env';
/**
* Configuration template with placeholder support
*/
export class ConfigTemplate {
public static readonly Empty: ConfigTemplate = new ConfigTemplate();
private _contentText: string;
private _params: string[];
constructor(contentText: string = '') {
this._contentText = contentText;
this._params = this.extractParams();
}
public get content(): string {
return this._contentText;
}
/**
* Backward compatibility getter
*/
public get Params(): string[] {
return this.params;
}
public get params(): string[] {
return [...this._params];
}
/**
* Extracts @placeholder@ patterns from template content
*/
private extractParams(): string[] {
const regex = /@(\w+)@/g;
const paramsSet = new Set<string>();
let match;
while ((match = regex.exec(this._contentText)) !== null) {
paramsSet.add(match[1]);
}
return Array.from(paramsSet);
}
}
/**
* Main configuration container
*/
export class Config {
public static readonly ENV_NAME_PARAM = 'env_name';
public envs: Env[] = [];
public template: ConfigTemplate = ConfigTemplate.Empty;
/**
* Sets environments (backward compatibility)
*/
public addEnvs(envs: Env[]): void {
this.envs = envs;
}
/**
* Sets environments
*/
public setEnvs(envs: Env[]): void {
this.envs = envs;
}
/**
* Sets template content (backward compatibility)
*/
public addTemplate(content: string): void {
this.setTemplate(content);
}
/**
* Sets template content
*/
public setTemplate(content: string): void {
this.template = new ConfigTemplate(content);
}
/**
* Gets template as JSON string
*/
public getTemplateAsJson(): string {
try {
return this.template.content;
} catch {
return '{}';
}
}
/**
* Updates template by adding placeholders for environment params
*/
public updateTemplateFromEnv(env: Env): void {
let templateObj: Record<string, any> = {};
// Try to parse existing template
try {
if (this.template.content.trim()) {
templateObj = JSON.parse(this.template.content);
}
} catch {
// Start fresh if invalid JSON
}
// Add placeholders for params that don't exist yet
for (const param of env.params) {
if (param.name && param.name.trim()) {
const placeholder = `@${param.name}@`;
if (!this.template.content.includes(placeholder)) {
templateObj[`!!! ${param.name}`] = placeholder;
}
}
}
this.template = new ConfigTemplate(JSON.stringify(templateObj, null, 4));
}
/**
* Validates that all template placeholders have corresponding params (backward compatibility)
*/
public validateParams(): string[] {
return this.validatePlaceholders();
}
/**
* Validates that all template placeholders have corresponding params
*/
public validatePlaceholders(): string[] {
const defaultEnv = this.envs.find(e => e.name === 'DEFAULT');
const customEnvs = this.envs.filter(e => e.name !== 'DEFAULT');
// Collect param names from DEFAULT
const defaultParamNames = new Set(
defaultEnv?.getParamNames() || []
);
// Collect param names from all custom envs
const customParamNames = new Set(
customEnvs.flatMap(e => e.getParamNames())
);
// Find missing placeholders
const missingParams: string[] = [];
for (const placeholder of this.template.params) {
if (placeholder === Config.ENV_NAME_PARAM) continue;
const inDefault = defaultParamNames.has(placeholder);
const inCustom = customParamNames.has(placeholder);
if (!inDefault && !inCustom) {
missingParams.push(placeholder);
}
}
return missingParams;
}
/**
* Creates a deep copy of the config
*/
public clone(): Config {
const cloned = new Config();
cloned.envs = [...this.envs];
cloned.template = this.template;
return cloned;
}
}