#!/usr/bin/env nu # [command] # name = "forminquire integration" # group = "infrastructure" # tags = ["forminquire", "forms", "interactive", "templates"] # version = "1.0.0" # requires = ["nu_plugin_tera", "forminquire:1.0.0"] # note = "Dynamic form generation using Jinja2 templates rendered with nu_plugin_tera" # ============================================================================ # FormInquire Integration System # Version: 1.0.0 # Purpose: Generate interactive forms dynamically from templates and config data # ============================================================================ # Get form cache directory def get-form-cache-dir [] : nothing -> string { let cache_dir = ( if ($env.XDG_CACHE_HOME? | is-empty) { $"($env.HOME)/.cache/provisioning/forms" } else { $"($env.XDG_CACHE_HOME)/provisioning/forms" } ) $cache_dir } # Ensure cache directory exists def ensure-form-cache-dir [] : nothing -> string { let cache_dir = (get-form-cache-dir) let _mkdir_result = (do { if not (($cache_dir | path exists)) { ^mkdir -p $cache_dir } } | complete) $cache_dir } # Get template directory def get-template-dir [] : nothing -> string { let proj_root = ( if (($env.PROVISIONING_ROOT? | is-empty)) { $"($env.HOME)/project-provisioning" } else { $env.PROVISIONING_ROOT } ) $"($proj_root)/provisioning/core/forminquire/templates" } # Load TOML configuration file def load-toml-config [path: string] : nothing -> record { let result = (do { open $path | from toml } | complete) if ($result.exit_code == 0) { $result.stdout } else { {} } } # Load YAML configuration file def load-yaml-config [path: string] : nothing -> record { let result = (do { open $path | from yaml } | complete) if ($result.exit_code == 0) { $result.stdout } else { {} } } # Render Jinja2 template with data export def render-template [ template_name: string data: record = {} ] : nothing -> record { let template_dir = (get-template-dir) let template_path = $"($template_dir)/($template_name).j2" if not (($template_path | path exists)) { return { error: $"Template not found: ($template_path)" content: "" } } let template_content_result = (do { ^cat $template_path } | complete) if ($template_content_result.exit_code != 0) { return { error: "Failed to read template file" content: "" } } let template_content = $template_content_result.stdout let enriched_data = ( $data | merge { now_iso: (date now | format date "%Y-%m-%dT%H:%M:%SZ") home_dir: $env.HOME username: (whoami) provisioning_root: ( if (($env.PROVISIONING_ROOT? | is-empty)) { $"($env.HOME)/project-provisioning" } else { $env.PROVISIONING_ROOT } ) } ) let render_result = (do { tera -t $template_content --data ($enriched_data | to json) } | complete) if ($render_result.exit_code == 0) { { error: "" content: $render_result.stdout } } else { { error: "Template rendering failed" content: "" } } } # Generate form from template and save to cache export def generate-form [ form_name: string template_name: string data: record = {} ] : nothing -> record { let cache_dir = (ensure-form-cache-dir) let form_path = $"($cache_dir)/($form_name).toml" let render_result = (render-template $template_name $data) if not (($render_result.error | is-empty)) { return { success: false error: $render_result.error form_path: "" } } let write_result = (do { $render_result.content | ^tee $form_path > /dev/null } | complete) if ($write_result.exit_code == 0) { { success: true error: "" form_path: $form_path } } else { { success: false error: "Failed to write form file" form_path: "" } } } # Execute FormInquire with generated form export def run-form [form_path: string] : nothing -> record { if not (($form_path | path exists)) { return { success: false error: $"Form file not found: ($form_path)" values: {} } } let forminquire_result = (do { ^forminquire --from-file $form_path --output json } | complete) if ($forminquire_result.exit_code != 0) { return { success: false error: "FormInquire execution failed" values: {} } } let parse_result = (do { $forminquire_result.stdout | from json } | complete) if ($parse_result.exit_code == 0) { { success: true error: "" values: $parse_result.stdout } } else { { success: false error: "Failed to parse FormInquire output" values: {} } } } # Complete flow: generate form from template and run it export def interactive-form [ form_name: string template_name: string data: record = {} ] : nothing -> record { let generate_result = (generate-form $form_name $template_name $data) if not $generate_result.success { return { success: false error: $generate_result.error form_path: "" values: {} } } let run_result = (run-form $generate_result.form_path) { success: $run_result.success error: $run_result.error form_path: $generate_result.form_path values: $run_result.values } } # Load user preferences from config export def load-user-preferences [] : nothing -> record { let config_path = $"($env.HOME)/.config/provisioning/user_config.yaml" load-yaml-config $config_path } # Load workspace config export def load-workspace-config [workspace_name: string] : nothing -> record { let workspace_dir = ( if (($env.PROVISIONING_WORKSPACE? | is-empty)) { $"($env.HOME)/workspaces/($workspace_name)" } else { $env.PROVISIONING_WORKSPACE } ) let config_file = $"($workspace_dir)/config.toml" load-toml-config $config_file } # Load system defaults export def load-system-defaults [] : nothing -> record { let proj_root = ( if (($env.PROVISIONING_ROOT? | is-empty)) { $"($env.HOME)/project-provisioning" } else { $env.PROVISIONING_ROOT } ) let defaults_file = $"($proj_root)/provisioning/config/config.defaults.toml" load-toml-config $defaults_file } # Merge multiple config sources with priority export def merge-config-sources [ defaults: record = {} workspace: record = {} user: record = {} overrides: record = {} ] : nothing -> record { $defaults | merge $workspace | merge $user | merge $overrides } # Get form context with all available data export def get-form-context [ workspace_name: string = "" custom_data: record = {} ] : nothing -> record { let defaults = (load-system-defaults) let user_prefs = (load-user-preferences) let workspace_config = ( if (($workspace_name | is-empty)) { {} } else { load-workspace-config $workspace_name } ) let merged = (merge-config-sources $defaults $workspace_config $user_prefs $custom_data) $merged } # Settings update form - loads current settings as defaults export def settings-update-form [] : nothing -> record { let context = (get-form-context) let data = { config_source: "system defaults + user preferences" editor: ($context.preferences.editor? // "vim") output_format: ($context.preferences.output_format? // "yaml") default_log_level: ($context.preferences.default_log_level? // "info") preferred_provider: ($context.preferences.preferred_provider? // "upcloud") confirm_delete: ($context.preferences.confirm_delete? // true) confirm_deploy: ($context.preferences.confirm_deploy? // true) } interactive-form "settings-update" "settings-update" $data } # Setup wizard form export def setup-wizard-form [] : nothing -> record { let context = (get-form-context) let data = { system_name: ($context.system_name? // "provisioning") admin_email: ($context.admin_email? // "") deployment_mode: ($context.deployment_mode? // "solo") infrastructure_provider: ($context.infrastructure_provider? // "upcloud") cpu_cores: ($context.resources.cpu_cores? // "4") memory_gb: ($context.resources.memory_gb? // "8") disk_gb: ($context.resources.disk_gb? // "50") workspace_path: ($context.workspace_path? // $"($env.HOME)/provisioning-workspace") } interactive-form "setup-wizard" "setup-wizard" $data } # Workspace init form export def workspace-init-form [workspace_name: string = ""] : nothing -> record { let context = (get-form-context $workspace_name) let data = { workspace_name: ( if (($workspace_name | is-empty)) { "default" } else { $workspace_name } ) workspace_description: ($context.description? // "") workspace_path: ($context.path? // $"($env.HOME)/workspaces/($workspace_name)") default_provider: ($context.default_provider? // "upcloud") default_region: ($context.default_region? // "") init_git: ($context.init_git? // true) create_example_configs: ($context.create_example_configs? // true) setup_secrets: ($context.setup_secrets? // true) enable_testing: ($context.enable_testing? // true) enable_monitoring: ($context.enable_monitoring? // false) enable_orchestrator: ($context.enable_orchestrator? // true) } interactive-form "workspace-init" "workspace-init" $data } # Server delete confirmation form export def server-delete-confirm-form [ server_name: string server_ip: string = "" server_status: string = "" ] : nothing -> record { let data = { server_name: $server_name server_ip: $server_ip server_status: $server_status } interactive-form "server-delete-confirm" "server-delete-confirm" $data } # Clean up old form files from cache (older than 1 day) export def cleanup-form-cache [] : nothing -> record { let cache_dir = (get-form-cache-dir) if not (($cache_dir | path exists)) { return {cleaned: 0, error: ""} } let find_result = (do { ^find $cache_dir -name "*.toml" -type f -mtime +1 -delete } | complete) {cleaned: 0, error: ""} } # List available templates export def list-templates [] : nothing -> list { let template_dir = (get-template-dir) if not (($template_dir | path exists)) { return [] } let find_result = (do { ^find $template_dir -name "*.j2" -type f } | complete) if ($find_result.exit_code == 0) { $find_result.stdout | lines | each {|path| let name = ($path | path basename | str replace ".j2" "") { name: $name path: $path template_file: ($path | path basename) } } } else { [] } } # List generated forms in cache export def list-cached-forms [] : nothing -> list { let cache_dir = (ensure-form-cache-dir) let find_result = (do { ^find $cache_dir -name "*.toml" -type f } | complete) if ($find_result.exit_code == 0) { $find_result.stdout | lines | each {|path| { name: ($path | path basename) path: $path } } } else { [] } } # ============================================================================ # DELETE CONFIRMATION HELPERS # ============================================================================ # Run server delete confirmation export def server-delete-confirm [ server_name: string server_ip?: string server_status?: string ] : nothing -> record { let context = { server_name: $server_name server_ip: (if ($server_ip | is-empty) { "" } else { $server_ip }) server_status: (if ($server_status | is-empty) { "running" } else { $server_status }) } run-forminquire-form "provisioning/core/shlib/forms/infrastructure/server_delete_confirm.toml" $context } # Run taskserv delete confirmation export def taskserv-delete-confirm [ taskserv_name: string taskserv_type?: string taskserv_server?: string taskserv_status?: string dependent_services?: string ] : nothing -> record { let context = { taskserv_name: $taskserv_name taskserv_type: (if ($taskserv_type | is-empty) { "" } else { $taskserv_type }) taskserv_server: (if ($taskserv_server | is-empty) { "" } else { $taskserv_server }) taskserv_status: (if ($taskserv_status | is-empty) { "unknown" } else { $taskserv_status }) dependent_services: (if ($dependent_services | is-empty) { "none" } else { $dependent_services }) } run-forminquire-form "provisioning/core/shlib/forms/infrastructure/taskserv_delete_confirm.toml" $context } # Run cluster delete confirmation export def cluster-delete-confirm [ cluster_name: string cluster_type?: string node_count?: string total_resources?: string deployments_count?: string services_count?: string volumes_count?: string ] : nothing -> record { let context = { cluster_name: $cluster_name cluster_type: (if ($cluster_type | is-empty) { "" } else { $cluster_type }) node_count: (if ($node_count | is-empty) { "unknown" } else { $node_count }) total_resources: (if ($total_resources | is-empty) { "" } else { $total_resources }) deployments_count: (if ($deployments_count | is-empty) { "0" } else { $deployments_count }) services_count: (if ($services_count | is-empty) { "0" } else { $services_count }) volumes_count: (if ($volumes_count | is-empty) { "0" } else { $volumes_count }) } run-forminquire-form "provisioning/core/shlib/forms/infrastructure/cluster_delete_confirm.toml" $context } # Generic delete confirmation export def generic-delete-confirm [ resource_type: string resource_name: string resource_id?: string resource_status?: string ] : nothing -> record { let context = { resource_type: $resource_type resource_name: $resource_name resource_id: (if ($resource_id | is-empty) { "" } else { $resource_id }) resource_status: (if ($resource_status | is-empty) { "unknown" } else { $resource_status }) } run-forminquire-form "provisioning/core/shlib/forms/infrastructure/generic_delete_confirm.toml" $context } # Validate delete confirmation result export def validate-delete-confirmation [result: record] : nothing -> bool { # Must have success = true let success = ($result.success // false) if not $success { return false } let values = ($result.values // {}) # Must have typed "DELETE" or "DELETE CLUSTER" let confirm_text = ($values.confirmation_text // "") let is_confirmed = (($confirm_text == "DELETE") or ($confirm_text == "DELETE CLUSTER")) # Must have checked final confirmation checkbox let final_checked = ($values.final_confirm // false) # Must have checked proceed checkbox let proceed_checked = ($values.proceed // false) ($is_confirmed and $final_checked and $proceed_checked) }