import { parseVariables } from './parser'; import { resolveVariable } from './resolver'; import type { ResolutionContext, TemplateResolveResult } from './types'; /** * Convert secret variables to Jinja2 format for Ansible * * Execution function (Rule 10.1) - may perform database access * * Converts $secret:name to {{ name }} for Ansible templates * Resolves non-secret variables normally ($self:, $system:, $capability:) * * @param content - Template content with variables * @param context - Resolution context * @param db - Database connection (required for capability variables) * @returns Resolved template with Jinja2 variables for secrets */ export async function convertSecretsToJinja( content: string, context: ResolutionContext, db: ReturnType, ): Promise { // Parse all variables const variables = parseVariables(content); if (variables.length === 0) { return { success: true, content }; } const errors: Array<{ variable: string; error: string }> = []; let resolvedContent = content; // Process each variable for (const variable of variables) { if (variable.type === 'secret') { // Convert secret variables to Jinja2 format // $secret:vesync_username -> {{ vesync_username }} const jinjaVar = `{{ ${variable.path} }}`; resolvedContent = resolvedContent.replaceAll(variable.raw, jinjaVar); } else { // Resolve non-secret variables normally const result = await resolveVariable(variable, context, db); if (!result.success) { errors.push({ variable: result.variable, error: result.error }); } else { resolvedContent = resolvedContent.replaceAll(variable.raw, result.value); } } } if (errors.length > 0) { return { success: false, errors }; } return { success: true, content: resolvedContent }; } /** * Check if file is an Ansible template * * Policy function - validation only * * @param path - File path * @returns True if file is Ansible template (.j2 extension or in ansible/ directory) */ export function isAnsibleTemplate(path: string): boolean { return path.endsWith('.j2') || path.includes('/ansible/') || path.startsWith('ansible/'); }