diff --git a/app/env_pro/core/template.py b/app/env_pro/core/template.py new file mode 100644 index 0000000..06f5eb0 --- /dev/null +++ b/app/env_pro/core/template.py @@ -0,0 +1,158 @@ +"""Template management for env-pro.""" + +import os +from pathlib import Path +from typing import Dict, List, Optional + + +class TemplateError(Exception): + """Base exception for template errors.""" + pass + + +BUILTIN_TEMPLATES = { + "fastapi": { + "description": "FastAPI Python application", + "variables": { + "APP_NAME": {"default": "MyFastAPIApp", "description": "Application name"}, + "DEBUG": {"default": "false", "description": "Enable debug mode"}, + "DATABASE_URL": {"default": "postgresql://localhost:5432/app", "description": "Database URL"}, + "SECRET_KEY": {"default": "", "description": "Secret key for JWT", "encrypt": True}, + "ALLOWED_HOSTS": {"default": "*", "description": "Allowed hosts"}, + } + }, + "django": { + "description": "Django Python application", + "variables": { + "APP_NAME": {"default": "MyDjangoApp", "description": "Application name"}, + "DEBUG": {"default": "false", "description": "Enable debug mode"}, + "DATABASE_URL": {"default": "postgresql://localhost:5432/app", "description": "Database URL"}, + "SECRET_KEY": {"default": "", "description": "Secret key", "encrypt": True}, + "ALLOWED_HOSTS": {"default": "localhost,127.0.0.1", "description": "Allowed hosts"}, + } + }, + "nodejs": { + "description": "Node.js application", + "variables": { + "NODE_ENV": {"default": "development", "description": "Environment"}, + "PORT": {"default": "3000", "description": "Port number"}, + "DATABASE_URL": {"default": "mongodb://localhost:27017/app", "description": "Database URL"}, + "JWT_SECRET": {"default": "", "description": "JWT secret", "encrypt": True}, + } + }, + "python": { + "description": "Generic Python application", + "variables": { + "ENVIRONMENT": {"default": "development", "description": "Environment"}, + "LOG_LEVEL": {"default": "INFO", "description": "Logging level"}, + "DATABASE_URL": {"default": "", "description": "Database URL"}, + "API_KEY": {"default": "", "description": "API key", "encrypt": True}, + } + }, + "golang": { + "description": "Go application", + "variables": { + "GO_ENV": {"default": "development", "description": "Environment"}, + "PORT": {"default": "8080", "description": "Port number"}, + "DATABASE_URL": {"default": "postgresql://localhost:5432/app", "description": "Database URL"}, + "API_KEY": {"default": "", "description": "API key", "encrypt": True}, + } + }, + "minimal": { + "description": "Minimal .env template", + "variables": { + "ENVIRONMENT": {"default": "development", "description": "Environment"}, + "DEBUG": {"default": "false", "description": "Enable debug mode"}, + } + }, +} + + +class TemplateManager: + """Manages environment variable templates.""" + + def __init__(self, custom_templates_dir: Optional[Path] = None): + """Initialize template manager.""" + self.custom_templates_dir = custom_templates_dir + + def list_templates(self) -> List[Dict[str, str]]: + """List all available templates.""" + templates = [] + + for name, config in BUILTIN_TEMPLATES.items(): + templates.append({ + "name": name, + "description": config["description"], + "builtin": True + }) + + if self.custom_templates_dir and self.custom_templates_dir.exists(): + for template_dir in self.custom_templates_dir.iterdir(): + if template_dir.is_dir(): + templates.append({ + "name": template_dir.name, + "description": f"Custom template from {template_dir}", + "builtin": False + }) + + return templates + + def get_template(self, name: str) -> Optional[Dict]: + """Get a specific template.""" + if name in BUILTIN_TEMPLATES: + return BUILTIN_TEMPLATES[name] + + if self.custom_templates_dir: + template_file = self.custom_templates_dir / name / "template.yaml" + if template_file.exists(): + import yaml + with open(template_file, 'r') as f: + return yaml.safe_load(f) + + return None + + def apply_template(self, name: str, variables: Dict[str, str] = None, output_file: Optional[Path] = None): + """Apply a template and generate .env content.""" + template = self.get_template(name) + + if template is None: + raise TemplateError(f"Template '{name}' not found") + + if variables is None: + variables = {} + + content_lines = ["# Generated by env-pro", f"# Template: {name}", ""] + + for var_name, var_config in template["variables"].items(): + value = variables.get(var_name, var_config.get("default", "")) + comment = var_config.get("description", "") + + if comment: + content_lines.append(f"# {comment}") + + content_lines.append(f"{var_name}={value}") + content_lines.append("") + + content = "\n".join(content_lines) + + if output_file: + output_file.write_text(content) + + return content + + def create_custom_template(self, name: str, variables: Dict, description: str = ""): + """Create a custom template.""" + if self.custom_templates_dir is None: + raise TemplateError("Custom templates directory not configured") + + template_dir = self.custom_templates_dir / name + template_dir.mkdir(parents=True, exist_ok=True) + + import yaml + template_file = template_dir / "template.yaml" + template_file.write_text(yaml.dump({ + "description": description, + "variables": variables + })) + + return template_dir