Initial upload with CI/CD workflow
Some checks failed
CI / test (push) Has been cancelled

This commit is contained in:
2026-02-05 19:31:50 +00:00
parent 449631f055
commit e69cbc1145

View File

@@ -0,0 +1,94 @@
import * as path from 'path';
import * as fs from 'fs-extra';
import { Layout, Template, TemplateVariable } from '../models/types';
export class TemplateUtils {
private readonly variablePattern = /\$\{([^}]+)\}/g;
extractVariables(template: Template): string[] {
const variables: string[] = [];
const layoutJson = JSON.stringify(template.layout);
let match: RegExpExecArray | null;
while ((match = this.variablePattern.exec(layoutJson)) !== null) {
if (!variables.includes(match[1])) {
variables.push(match[1]);
}
}
return variables;
}
substituteVariables(layout: Layout, variables: Record<string, string>): Layout {
const layoutStr = JSON.stringify(layout);
let substituted = layoutStr;
for (const [key, value] of Object.entries(variables)) {
const patterns = [`\\$\\{${key}\\}`, `\\$\\{${key}:([^}]*)\\}`];
for (const pattern of patterns) {
substituted = substituted.replace(new RegExp(pattern, 'g'), value);
}
}
return JSON.parse(substituted) as Layout;
}
async createTemplateFromLayout(
name: string,
displayName: string,
description: string,
layout: Layout,
variableDefaults?: Record<string, string>
): Promise<Template> {
const variables: TemplateVariable[] = [];
const extractedVars = this.extractVariables({ name, displayName, description, variables: [], layout });
for (const varName of extractedVars) {
const isRequired = !variableDefaults || !variableDefaults[varName];
variables.push({
name: varName,
description: `Variable: ${varName}`,
defaultValue: variableDefaults?.[varName],
required: isRequired,
});
}
return {
name,
displayName,
description,
variables,
layout,
};
}
validateTemplateVariables(template: Template, providedVars: Record<string, string>): string[] {
const missing: string[] = [];
for (const variable of template.variables) {
if (variable.required && !(variable.name in providedVars) && !variable.defaultValue) {
missing.push(variable.name);
}
}
return missing;
}
async saveTemplate(template: Template, templatesDir: string): Promise<string> {
const filePath = path.join(templatesDir, `${template.name}.json`);
await fs.writeJson(filePath, template, { spaces: 2 });
return filePath;
}
async loadTemplate(filePath: string): Promise<Template> {
const content = await fs.readFile(filePath, 'utf-8');
return JSON.parse(content) as Template;
}
generateTemplatePreview(template: Template, variables: Record<string, string>): string {
const substitutedLayout = this.substituteVariables(template.layout, variables);
return JSON.stringify(substitutedLayout, null, 2);
}
}
export const templateUtils = new TemplateUtils();