212 lines
5.2 KiB
TypeScript
212 lines
5.2 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 {
|
|
// If template is empty, initialize with empty object
|
|
if (!this.template.content || !this.template.content.trim()) {
|
|
this.template = new ConfigTemplate('{}');
|
|
}
|
|
|
|
// Try to parse existing template
|
|
let templateObj: Record<string, any> = {};
|
|
let hasExistingContent = false;
|
|
|
|
try {
|
|
if (this.template.content.trim()) {
|
|
templateObj = JSON.parse(this.template.content);
|
|
hasExistingContent = Object.keys(templateObj).length > 0;
|
|
}
|
|
} catch {
|
|
// If invalid JSON, preserve the raw content and don't modify
|
|
return;
|
|
}
|
|
|
|
// Add placeholders for params that don't exist yet
|
|
let hasChanges = false;
|
|
for (const param of env.params) {
|
|
if (param.name && param.name.trim()) {
|
|
const paramName = param.name.trim();
|
|
const placeholder = `@${paramName}@`;
|
|
const templateKey = `!!! ${paramName}`;
|
|
|
|
// Check if placeholder exists anywhere in template
|
|
if (!this.template.content.includes(placeholder)) {
|
|
// Only add if not already in templateObj
|
|
if (!templateObj[templateKey]) {
|
|
templateObj[templateKey] = placeholder;
|
|
hasChanges = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Only update if there are actual changes
|
|
if (hasChanges || !hasExistingContent) {
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* Checks if config is empty (no environments or only DEFAULT with no params and empty template)
|
|
*/
|
|
public isEmpty(): boolean {
|
|
if (this.envs.length === 0) {
|
|
return true;
|
|
}
|
|
|
|
// Check if only DEFAULT exists with no params
|
|
if (this.envs.length === 1 && this.envs[0].name === 'DEFAULT') {
|
|
const hasParams = this.envs[0].params.length > 0;
|
|
const hasTemplate = this.template.content.trim() && this.template.content !== '{}';
|
|
return !hasParams && !hasTemplate;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|