TypeDialog/examples/07-nickel-generation
Jesús Pérez 82e52fc632
feat(nickel): implement roundtrip and contract parsing
Add contract parsing, i18n extraction, template rendering, and roundtrip
support for Nickel. Update backends and form parser for integration.
Add testing and build infrastructure.
2025-12-19 03:18:48 +00:00
..

Nickel Schema to TOML Form Generation Examples

This directory contains complete, runnable examples of the TypeDialog Nickel integration workflow:

Nickel Schema → TOML Form → User Input → JSON Results → Nickel Output

Quick Start

Example 1: Simple Schema (Learning)

Generate a TOML form from a basic Nickel schema:

# Generate form
just nickel::nickel-to-form schemas/simple.ncl generated/simple/

# Execute form interactively
typedialog form generated/simple/form.toml -o results/simple_results.json

# View results
cat results/simple_results.json | jq .

What it demonstrates:

  • Basic type mapping (String, Number, Bool)
  • Doc comment extraction
  • Default value handling
  • Simple form generation

Example 2: Complex Schema (Fragmentation)

Generate fragmented forms from a schema with multiple sections:

# Generate with automatic fragmentation
just nickel::nickel-to-form schemas/complex.ncl generated/complex/

# List generated files
ls -la generated/complex/
ls -la generated/complex/fragments/

# Execute main form
typedialog form generated/complex/main_form.toml -o results/complex_results.json

What it demonstrates:

  • Fragment markers (# @fragment: name)
  • Multi-file form composition
  • Fragment includes in main form
  • Large schema organization

Generated structure:

generated/complex/
├── main_form.toml                # Form with includes
└── fragments/
    ├── app_config.toml
    ├── server_config.toml
    ├── database_config.toml
    └── cache_config.toml

Example 3: Conditional Fields (Smart Visibility)

Generate conditionals automatically from optional fields:

# Generate with conditionals
just nickel::nickel-to-form schemas/conditional.ncl generated/conditional/

# View generated conditionals
grep -A 2 'when =' generated/conditional/form.toml

# Execute form - notice conditional visibility
typedialog form generated/conditional/form.toml

What it demonstrates:

  • Optional field handling
  • Automatic conditional generation from contracts
  • Boolean dependency detection
  • Dynamic form visibility

Example generated conditionals:

[[fields]]
name = "tls_cert_path"
when = "tls_enabled == true"  # Auto-generated!

[[fields]]
name = "database_url"
when = "database_enabled == true"  # Auto-generated!

Example 4: i18n Extraction (Multi-Language)

Generate Fluent translation files from schema:

# Extract i18n only
just nickel::nickel-i18n schemas/i18n.ncl generated/i18n/

# View generated translations
ls -la generated/i18n/locales/
cat generated/i18n/locales/en/forms.ftl
cat generated/i18n/locales/es/forms.ftl

# Execute with Spanish locale
LOCALE=es typedialog form generated/i18n/form.toml

What it demonstrates:

  • Multi-language doc comment parsing
  • Fluent (.ftl) file generation
  • Locale-specific form generation
  • Translation key mapping

Generated translations:

# en/forms.ftl
app-name-prompt = Application name
app-name-help = Enter the application display name

# es/forms.ftl
app-name-prompt = Nombre de la aplicación
app-name-help = Ingrese el nombre de la aplicación

Example 5: Full Workflow (Schema → Results → Nickel)

Complete workflow: generate form, execute with results, render Nickel output:

# Full workflow: schema → form → results → Nickel
just nickel::nickel-workflow \
  schemas/simple.ncl \
  templates/config.ncl.j2 \
  generated/output_config.ncl

# Validate generated Nickel
nickel typecheck generated/output_config.ncl

# View generated configuration
cat generated/output_config.ncl

What it demonstrates:

  • End-to-end workflow automation
  • Form execution with user input
  • Template rendering with results
  • Nickel validation
  • Configuration generation

Directory Structure

examples/07-nickel-generation/
├── README.md                          # This file
├── schemas/                           # Nickel schema files
│   ├── simple.ncl                     # Basic types only
│   ├── complex.ncl                    # With fragment markers
│   ├── conditional.ncl                # With optional fields + boolean deps
│   └── i18n.ncl                       # With English/Spanish docs
├── templates/                         # Jinja2 templates for rendering
│   ├── config.ncl.j2                  # Basic config template
│   ├── service_spec.ncl.j2            # Kubernetes service template
│   └── deployment.ncl.j2              # Kubernetes deployment template
├── generated/                         # Example outputs (reference)
│   ├── simple/
│   │   └── form.toml
│   ├── complex/
│   │   ├── main_form.toml
│   │   └── fragments/
│   ├── conditional/
│   │   └── form.toml
│   └── i18n/
│       ├── form.toml
│       └── locales/
└── results/                           # Example results (reference)
    └── simple_results.json

Schema Features Explained

Fragment Markers

Mark sections for automatic splitting:

# @fragment: database_config
database = { ... }

Generates separate file: fragments/database_config.toml

When to use:

  • Schemas with 20+ fields
  • Logical section boundaries
  • Independent configuration areas

Optional Fields with Dependencies

Automatically generate conditionals:

tls_enabled | doc "Enable TLS" : Bool,

tls_cert | optional
  | doc "Certificate path"
  : String,

Generates:

[[fields]]
name = "tls_cert"
when = "tls_enabled == true"

Pattern: <feature>_enabled → dependent fields

Multi-Language Docs

Support multiple languages in doc comments:

field_name
  | doc "English text"
  | doc.es "Texto en español"
  : String

Generates .ftl files for each locale with translations

Templates

config.ncl.j2

Basic application configuration template:

  • Renders app metadata
  • Server configuration
  • Database connection (optional)
  • Cache settings (conditional)

Usage:

just nickel::nickel-workflow \
  schemas/simple.ncl \
  templates/config.ncl.j2 \
  config.ncl

service_spec.ncl.j2

Kubernetes service specification:

  • Service metadata
  • Port configuration
  • Selector rules
  • Service type (ClusterIP, NodePort, LoadBalancer)

Usage:

typedialog form <form> -o results.json
typedialog nickel-template templates/service_spec.ncl.j2 results.json -o service.ncl
nickel export service.ncl

deployment.ncl.j2

Kubernetes deployment configuration:

  • Deployment metadata
  • Pod replica count
  • Container specification
  • Resource limits and requests
  • Health checks (liveness, readiness probes)
  • Environment variables

Usage:

just nickel::nickel-workflow \
  <schema> \
  templates/deployment.ncl.j2 \
  deployment.ncl

Common Workflows

Preview Form Before Generation

# Preview without writing files
just nickel::nickel-preview schemas/complex.ncl

# Then generate with full options
just nickel::nickel-to-form schemas/complex.ncl generated/complex/

Extract i18n Only

# Generate only translation files
just nickel::nickel-i18n schemas/i18n.ncl translations/

# Review translations
cat translations/locales/en/forms.ftl
cat translations/locales/es/forms.ftl

Render Template with Sample Data

# Use example results to render template
typedialog nickel-template templates/config.ncl.j2 \
  results/simple_results.json \
  -o sample_output.ncl

# Review output
cat sample_output.ncl

Full Interactive Workflow

# 1. Generate form
just nickel::nickel-to-form schemas/simple.ncl /tmp/form_gen/

# 2. Execute form interactively
typedialog form /tmp/form_gen/form.toml -o /tmp/results.json

# 3. Review results
cat /tmp/results.json | jq .

# 4. Render template
typedialog nickel-template templates/config.ncl.j2 \
  /tmp/results.json \
  -o /tmp/generated_config.ncl

# 5. Validate Nickel
nickel typecheck /tmp/generated_config.ncl

# 6. Export to JSON
nickel export /tmp/generated_config.ncl

Testing Examples

Run All Examples

#!/bin/bash

EXAMPLES_DIR="examples/07-nickel-generation"

# Test 1: Simple
echo "Testing simple schema..."
just nickel::nickel-to-form "$EXAMPLES_DIR/schemas/simple.ncl" /tmp/test_simple
[ -f /tmp/test_simple/form.toml ] && echo "✓ Simple form generated"

# Test 2: Complex
echo "Testing complex schema..."
just nickel::nickel-to-form "$EXAMPLES_DIR/schemas/complex.ncl" /tmp/test_complex
[ -f /tmp/test_complex/main_form.toml ] && echo "✓ Complex form generated"
[ -d /tmp/test_complex/fragments ] && echo "✓ Fragments created"

# Test 3: Conditional
echo "Testing conditional schema..."
just nickel::nickel-to-form "$EXAMPLES_DIR/schemas/conditional.ncl" /tmp/test_conditional
grep -q "when =" /tmp/test_conditional/form.toml && echo "✓ Conditionals generated"

# Test 4: i18n
echo "Testing i18n schema..."
just nickel::nickel-i18n "$EXAMPLES_DIR/schemas/i18n.ncl" /tmp/test_i18n
[ -f /tmp/test_i18n/locales/en/forms.ftl ] && echo "✓ English translations generated"
[ -f /tmp/test_i18n/locales/es/forms.ftl ] && echo "✓ Spanish translations generated"

echo ""
echo "All tests passed!"

Extending Examples

Adding New Schemas

  1. Create schemas/my_schema.ncl with Nickel configuration
  2. Add fragment markers (# @fragment: name) for sections
  3. Use optional fields for conditionals
  4. Use multi-language docs for i18n
{
  # @fragment: my_section
  my_field | doc "English" | doc.es "Español" : String,

  feature_enabled | doc "Enable feature" : Bool = false,

  feature_config | optional
    | doc "Feature configuration"
    : String,
}

Adding New Templates

  1. Create templates/my_template.ncl.j2
  2. Use Jinja2 syntax for conditionals and loops
  3. Reference form result variables
  4. Test with sample data
{
  config = {
    {% for item in items %}
    {{ item.name }} : String = "{{ item.value }}",
    {% endfor %}
  },
}

Troubleshooting

Form Generation Fails

# Verify schema syntax
nickel typecheck schemas/simple.ncl

# Check for schema-specific issues
nickel query schemas/simple.ncl

Fragment Includes Not Found

# Verify fragments directory exists
ls -la generated/complex/fragments/

# Check include paths in main form
grep includes generated/complex/main_form.toml

Conditionals Not Generated

# Verify optional fields exist
grep -A 2 "optional" schemas/conditional.ncl

# Check for boolean enable flags
grep "_enabled" schemas/conditional.ncl

i18n Not Working

# Verify locale directories created
find generated/i18n/locales/ -name "*.ftl"

# Check .ftl file format
cat generated/i18n/locales/en/forms.ftl | head

See Also

  • .claude/guidelines/typedialog.md - Complete TypeDialog guide
  • templates/nickel/README.md - Template library documentation
  • just nickel::help - All available recipes
  • /nickel-gen - Interactive slash command