# TypeDialog + Nickel Integration Guide

**Status**: Implementation Guide
**Last Updated**: 2025-12-15
**Project**: TypeDialog at `/Users/Akasha/Development/typedialog`
**Purpose**: Type-safe UI generation from Nickel schemas

---

## What is TypeDialog

TypeDialog generates **type-safe interactive forms** from configuration schemas with **bidirectional Nickel integration**.

```plaintext
Nickel Schema
    ↓
TypeDialog Form (Auto-generated)
    ↓
User fills form interactively
    ↓
Nickel output config (Type-safe)
```plaintext

---

## Architecture

### Three Layers

```plaintext
CLI/TUI/Web Layer
    ↓
TypeDialog Form Engine
    ↓
Nickel Integration
    ↓
Schema Contracts
```plaintext

### Data Flow

```plaintext
Input (Nickel)
    ↓
Form Definition (TOML)
    ↓
Form Rendering (CLI/TUI/Web)
    ↓
User Input
    ↓
Validation (against Nickel contracts)
    ↓
Output (JSON/YAML/TOML/Nickel)
```plaintext

---

## Setup

### Installation

```bash
# Clone TypeDialog
git clone https://github.com/jesusperezlorenzo/typedialog.git
cd typedialog

# Build
cargo build --release

# Install (optional)
cargo install --path ./crates/typedialog
```plaintext

### Verify Installation

```bash
typedialog --version
typedialog --help
```plaintext

---

## Basic Workflow

### Step 1: Define Nickel Schema

```nickel
# server_config.ncl
let contracts = import "./contracts.ncl" in
let defaults = import "./defaults.ncl" in

{
  defaults = defaults,

  make_server | not_exported = fun overrides =>
    defaults.server & overrides,

  DefaultServer = defaults.server,
}
```plaintext

### Step 2: Define TypeDialog Form (TOML)

```toml
# server_form.toml
[form]
title = "Server Configuration"
description = "Create a new server configuration"

[[fields]]
name = "server_name"
label = "Server Name"
type = "text"
required = true
help = "Unique identifier for the server"
placeholder = "web-01"

[[fields]]
name = "cpu_cores"
label = "CPU Cores"
type = "number"
required = true
default = 4
help = "Number of CPU cores (1-32)"

[[fields]]
name = "memory_gb"
label = "Memory (GB)"
type = "number"
required = true
default = 8
help = "Memory in GB (1-256)"

[[fields]]
name = "zone"
label = "Availability Zone"
type = "select"
required = true
options = ["us-nyc1", "eu-fra1", "ap-syd1"]
default = "us-nyc1"

[[fields]]
name = "monitoring"
label = "Enable Monitoring"
type = "confirm"
default = true

[[fields]]
name = "tags"
label = "Tags"
type = "multiselect"
options = ["production", "staging", "testing", "development"]
help = "Select applicable tags"
```plaintext

### Step 3: Render Form (CLI)

```bash
typedialog form --config server_form.toml --backend cli
```plaintext

**Output**:

```plaintext
Server Configuration
Create a new server configuration

? Server Name: web-01
? CPU Cores: 4
? Memory (GB): 8
? Availability Zone: (us-nyc1/eu-fra1/ap-syd1) us-nyc1
? Enable Monitoring: (y/n) y
? Tags: (Select multiple with space)
  ◉ production
  ◯ staging
  ◯ testing
  ◯ development
```plaintext

### Step 4: Validate Against Nickel Schema

```bash
# Validation happens automatically
# If input matches Nickel contract, proceeds to output
```plaintext

### Step 5: Output to Nickel

```bash
typedialog form \
  --config server_form.toml \
  --output nickel \
  --backend cli
```plaintext

**Output file** (`server_config_output.ncl`):

```nickel
{
  server_name = "web-01",
  cpu_cores = 4,
  memory_gb = 8,
  zone = "us-nyc1",
  monitoring = true,
  tags = ["production"],
}
```plaintext

---

## Real-World Example 1: Infrastructure Wizard

### Scenario

You want an interactive CLI wizard for infrastructure provisioning.

### Step 1: Define Nickel Schema for Infrastructure

```nickel
# infrastructure_schema.ncl
{
  InfrastructureConfig = {
    workspace_name | String,
    deployment_mode | [| 'solo, 'multiuser, 'cicd, 'enterprise |],
    provider | [| 'upcloud, 'aws, 'hetzner |],
    taskservs | Array,
    enable_monitoring | Bool,
    enable_backup | Bool,
    backup_retention_days | Number,
  },

  defaults = {
    workspace_name = "",
    deployment_mode = 'solo,
    provider = 'upcloud,
    taskservs = [],
    enable_monitoring = true,
    enable_backup = true,
    backup_retention_days = 7,
  },

  DefaultInfra = defaults,
}
```plaintext

### Step 2: Create Comprehensive Form

```toml
# infrastructure_wizard.toml
[form]
title = "Infrastructure Provisioning Wizard"
description = "Create a complete infrastructure setup"

[[fields]]
name = "workspace_name"
label = "Workspace Name"
type = "text"
required = true
validation_pattern = "^[a-z0-9-]{3,32}$"
help = "3-32 chars, lowercase alphanumeric and hyphens only"
placeholder = "my-workspace"

[[fields]]
name = "deployment_mode"
label = "Deployment Mode"
type = "select"
required = true
options = [
  { value = "solo", label = "Solo (Single user, 2 CPU, 4 GB RAM)" },
  { value = "multiuser", label = "MultiUser (Team, 4 CPU, 8 GB RAM)" },
  { value = "cicd", label = "CI/CD (Pipelines, 8 CPU, 16 GB RAM)" },
  { value = "enterprise", label = "Enterprise (Production, 16 CPU, 32 GB RAM)" },
]
default = "solo"

[[fields]]
name = "provider"
label = "Cloud Provider"
type = "select"
required = true
options = [
  { value = "upcloud", label = "UpCloud (EU)" },
  { value = "aws", label = "AWS (Global)" },
  { value = "hetzner", label = "Hetzner (EU)" },
]
default = "upcloud"

[[fields]]
name = "taskservs"
label = "Task Services"
type = "multiselect"
required = false
options = [
  { value = "kubernetes", label = "Kubernetes (Container orchestration)" },
  { value = "cilium", label = "Cilium (Network policy)" },
  { value = "postgres", label = "PostgreSQL (Database)" },
  { value = "redis", label = "Redis (Cache)" },
  { value = "prometheus", label = "Prometheus (Monitoring)" },
  { value = "etcd", label = "etcd (Distributed config)" },
]
help = "Select task services to deploy"

[[fields]]
name = "enable_monitoring"
label = "Enable Monitoring"
type = "confirm"
default = true
help = "Prometheus + Grafana dashboards"

[[fields]]
name = "enable_backup"
label = "Enable Backup"
type = "confirm"
default = true

[[fields]]
name = "backup_retention_days"
label = "Backup Retention (days)"
type = "number"
required = false
default = 7
help = "How long to keep backups (if enabled)"
visible_if = "enable_backup == true"

[[fields]]
name = "email"
label = "Admin Email"
type = "text"
required = true
validation_pattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
help = "For alerts and notifications"
placeholder = "admin@company.com"
```plaintext

### Step 3: Run Interactive Wizard

```bash
typedialog form \
  --config infrastructure_wizard.toml \
  --backend tui \
  --output nickel
```plaintext

**Output** (`infrastructure_config.ncl`):

```nickel
{
  workspace_name = "production-eu",
  deployment_mode = 'enterprise,
  provider = 'upcloud,
  taskservs = ["kubernetes", "cilium", "postgres", "redis", "prometheus"],
  enable_monitoring = true,
  enable_backup = true,
  backup_retention_days = 30,
  email = "ops@company.com",
}
```plaintext

### Step 4: Use Output in Infrastructure

```nickel
# main_infrastructure.ncl
let config = import "./infrastructure_config.ncl" in
let schemas = import "../../provisioning/schemas/main.ncl" in

{
  # Build infrastructure based on config
  infrastructure = if config.deployment_mode == 'solo then
    {
      servers = [
        schemas.lib.make_server {
          name = config.workspace_name,
          cpu_cores = 2,
          memory_gb = 4,
        },
      ],
      taskservs = config.taskservs,
    }
  else if config.deployment_mode == 'enterprise then
    {
      servers = [
        schemas.lib.make_server { name = "app-01", cpu_cores = 16, memory_gb = 32 },
        schemas.lib.make_server { name = "app-02", cpu_cores = 16, memory_gb = 32 },
        schemas.lib.make_server { name = "db-01", cpu_cores = 16, memory_gb = 32 },
      ],
      taskservs = config.taskservs,
      monitoring = { enabled = config.enable_monitoring, email = config.email },
    }
  else
    # default fallback
    {},
}
```plaintext

---

## Real-World Example 2: Server Configuration Form

### Form Definition (Advanced)

```toml
# server_advanced_form.toml
[form]
title = "Server Configuration"
description = "Configure server settings with validation"

# Section 1: Basic Info
[[sections]]
name = "basic"
title = "Basic Information"

[[fields]]
name = "server_name"
section = "basic"
label = "Server Name"
type = "text"
required = true
validation_pattern = "^[a-z0-9-]{3,32}$"

[[fields]]
name = "description"
section = "basic"
label = "Description"
type = "textarea"
required = false
placeholder = "Server purpose and details"

# Section 2: Resources
[[sections]]
name = "resources"
title = "Resources"

[[fields]]
name = "cpu_cores"
section = "resources"
label = "CPU Cores"
type = "number"
required = true
default = 4
min = 1
max = 32

[[fields]]
name = "memory_gb"
section = "resources"
label = "Memory (GB)"
type = "number"
required = true
default = 8
min = 1
max = 256

[[fields]]
name = "disk_gb"
section = "resources"
label = "Disk (GB)"
type = "number"
required = true
default = 100
min = 10
max = 2000

# Section 3: Network
[[sections]]
name = "network"
title = "Network Configuration"

[[fields]]
name = "zone"
section = "network"
label = "Availability Zone"
type = "select"
required = true
options = ["us-nyc1", "eu-fra1", "ap-syd1"]

[[fields]]
name = "enable_ipv6"
section = "network"
label = "Enable IPv6"
type = "confirm"
default = false

[[fields]]
name = "allowed_ports"
section = "network"
label = "Allowed Ports"
type = "multiselect"
options = [
  { value = "22", label = "SSH (22)" },
  { value = "80", label = "HTTP (80)" },
  { value = "443", label = "HTTPS (443)" },
  { value = "3306", label = "MySQL (3306)" },
  { value = "5432", label = "PostgreSQL (5432)" },
]

# Section 4: Advanced
[[sections]]
name = "advanced"
title = "Advanced Options"

[[fields]]
name = "kernel_version"
section = "advanced"
label = "Kernel Version"
type = "text"
required = false
placeholder = "5.15.0 (or leave blank for latest)"

[[fields]]
name = "enable_monitoring"
section = "advanced"
label = "Enable Monitoring"
type = "confirm"
default = true

[[fields]]
name = "monitoring_interval"
section = "advanced"
label = "Monitoring Interval (seconds)"
type = "number"
required = false
default = 60
visible_if = "enable_monitoring == true"

[[fields]]
name = "tags"
section = "advanced"
label = "Tags"
type = "multiselect"
options = ["production", "staging", "testing", "development"]
```plaintext

### Output Structure

```nickel
{
  # Basic
  server_name = "web-prod-01",
  description = "Primary web server",

  # Resources
  cpu_cores = 16,
  memory_gb = 32,
  disk_gb = 500,

  # Network
  zone = "eu-fra1",
  enable_ipv6 = true,
  allowed_ports = ["22", "80", "443"],

  # Advanced
  kernel_version = "5.15.0",
  enable_monitoring = true,
  monitoring_interval = 30,
  tags = ["production"],
}
```plaintext

---

## API Integration

### TypeDialog REST Endpoints

```bash
# Start TypeDialog server
typedialog server --port 8080

# Render form via HTTP
curl -X POST http://localhost:8080/forms \
  -H "Content-Type: application/json" \
  -d @server_form.toml
```plaintext

### Response Format

```json
{
  "form_id": "srv_abc123",
  "status": "rendered",
  "fields": [
    {
      "name": "server_name",
      "label": "Server Name",
      "type": "text",
      "required": true,
      "placeholder": "web-01"
    }
  ]
}
```plaintext

### Submit Form

```bash
curl -X POST http://localhost:8080/forms/srv_abc123/submit \
  -H "Content-Type: application/json" \
  -d '{
    "server_name": "web-01",
    "cpu_cores": 4,
    "memory_gb": 8,
    "zone": "us-nyc1",
    "monitoring": true,
    "tags": ["production"]
  }'
```plaintext

### Response

```json
{
  "status": "success",
  "validation": "passed",
  "output_format": "nickel",
  "output": {
    "server_name": "web-01",
    "cpu_cores": 4,
    "memory_gb": 8,
    "zone": "us-nyc1",
    "monitoring": true,
    "tags": ["production"]
  }
}
```plaintext

---

## Validation

### Contract-Based Validation

TypeDialog validates user input against Nickel contracts:

```nickel
# Nickel contract
ServerConfig = {
  cpu_cores | Number,  # Must be number
  memory_gb | Number,  # Must be number
  zone | [| 'us-nyc1, 'eu-fra1 |],  # Enum
}

# If user enters invalid value
# TypeDialog rejects before serializing
```plaintext

### Validation Rules in Form

```toml
[[fields]]
name = "cpu_cores"
type = "number"
min = 1
max = 32
help = "Must be 1-32 cores"
# TypeDialog enforces before user can submit
```plaintext

---

## Integration with Provisioning Platform

### Use Case: Infrastructure Initialization

```bash
# 1. User runs initialization
provisioning init --wizard

# 2. Behind the scenes:
#    - Loads infrastructure_wizard.toml
#    - Starts TypeDialog (CLI or TUI)
#    - User fills form interactively

# 3. Output saved as config
#    ~/.config/provisioning/infrastructure_config.ncl

# 4. Provisioning uses output
#    provisioning server create --from-config infrastructure_config.ncl
```plaintext

### Implementation in Nushell

```nushell
# provisioning/core/nulib/provisioning_init.nu

def provisioning_init_wizard [] {
  # Launch TypeDialog form
  let config = (
    typedialog form \
      --config "provisioning/config/infrastructure_wizard.toml" \
      --backend tui \
      --output nickel
  )

  # Save output
  $config | save ~/.config/provisioning/workspace_config.ncl

  # Validate with provisioning schemas
  let provisioning = (import "provisioning/schemas/main.ncl")
  let validated = (
    nickel export ~/.config/provisioning/workspace_config.ncl
      | jq . | to json
  )

  print "Infrastructure configuration created!"
  print "Use: provisioning deploy --from-config"
}
```plaintext

---

## Advanced Features

### Conditional Visibility

Show/hide fields based on user selections:

```toml
[[fields]]
name = "backup_retention"
label = "Backup Retention (days)"
type = "number"
visible_if = "enable_backup == true"  # Only shown if backup enabled
```plaintext

### Dynamic Defaults

Set defaults based on other fields:

```toml
[[fields]]
name = "deployment_mode"
type = "select"
options = ["solo", "enterprise"]

[[fields]]
name = "cpu_cores"
type = "number"
default_from = "deployment_mode"  # Can reference other fields
# solo → default 2, enterprise → default 16
```plaintext

### Custom Validation

```toml
[[fields]]
name = "memory_gb"
type = "number"
validation_rule = "memory_gb >= cpu_cores * 2"
help = "Memory must be at least 2 GB per CPU core"
```plaintext

---

## Output Formats

TypeDialog can output to multiple formats:

```bash
# Output to Nickel (recommended for IaC)
typedialog form --config form.toml --output nickel

# Output to JSON (for APIs)
typedialog form --config form.toml --output json

# Output to YAML (for K8s)
typedialog form --config form.toml --output yaml

# Output to TOML (for application config)
typedialog form --config form.toml --output toml
```plaintext

---

## Backends

TypeDialog supports three rendering backends:

### 1. CLI (Command-line prompts)

```bash
typedialog form --config form.toml --backend cli
```plaintext

**Pros**: Lightweight, SSH-friendly, no dependencies
**Cons**: Basic UI

### 2. TUI (Terminal User Interface - Ratatui)

```bash
typedialog form --config form.toml --backend tui
```plaintext

**Pros**: Rich UI, keyboard navigation, sections
**Cons**: Requires terminal support

### 3. Web (HTTP Server - Axum)

```bash
typedialog form --config form.toml --backend web --port 3000
# Opens http://localhost:3000
```plaintext

**Pros**: Beautiful UI, remote access, multi-user
**Cons**: Requires browser, network

---

## Troubleshooting

### Problem: Form doesn't match Nickel contract

**Cause**: Field names or types don't match contract

**Solution**: Verify field definitions match Nickel schema:

```toml
# Form field
[[fields]]
name = "cpu_cores"  # Must match Nickel field name
type = "number"     # Must match Nickel type
```plaintext

### Problem: Validation fails

**Cause**: User input violates contract constraints

**Solution**: Add help text and validation rules:

```toml
[[fields]]
name = "cpu_cores"
validation_pattern = "^[1-9][0-9]*$"
help = "Must be positive integer"
```plaintext

### Problem: Output not valid Nickel

**Cause**: Missing required fields

**Solution**: Ensure all required fields in form:

```toml
[[fields]]
name = "required_field"
required = true  # User must provide value
```plaintext

---

## Complete Example: End-to-End Workflow

### Step 1: Define Nickel Schema

```nickel
# workspace_schema.ncl
{
  workspace = {
    name = "",
    mode = 'solo,
    provider = 'upcloud,
    monitoring = true,
    email = "",
  },
}
```plaintext

### Step 2: Define Form

```toml
# workspace_form.toml
[[fields]]
name = "name"
type = "text"
required = true

[[fields]]
name = "mode"
type = "select"
options = ["solo", "enterprise"]

[[fields]]
name = "provider"
type = "select"
options = ["upcloud", "aws"]

[[fields]]
name = "monitoring"
type = "confirm"

[[fields]]
name = "email"
type = "text"
required = true
```plaintext

### Step 3: User Interaction

```bash
$ typedialog form --config workspace_form.toml --backend tui
# User fills form interactively
```plaintext

### Step 4: Output

```nickel
{
  workspace = {
    name = "production",
    mode = 'enterprise,
    provider = 'upcloud,
    monitoring = true,
    email = "ops@company.com",
  },
}
```plaintext

### Step 5: Use in Provisioning

```nickel
# main.ncl
let config = import "./workspace.ncl" in
let schemas = import "provisioning/schemas/main.ncl" in

{
  # Build infrastructure
  infrastructure = schemas.deployment.modes.make_mode {
    deployment_type = config.workspace.mode,
    provider = config.workspace.provider,
  },
}
```plaintext

---

## Summary

TypeDialog + Nickel provides:

✅ **Type-Safe UIs**: Forms validated against Nickel contracts
✅ **Auto-Generated**: No UI code to maintain
✅ **Bidirectional**: Nickel → Forms → Nickel
✅ **Multiple Outputs**: JSON, YAML, TOML, Nickel
✅ **Three Backends**: CLI, TUI, Web
✅ **Production-Ready**: Used in real infrastructure

**Key Benefit**: Reduce configuration errors by enforcing schema validation at UI level, not after deployment.

---

**Version**: 1.0.0
**Status**: Implementation Guide
**Last Updated**: 2025-12-15
