Mode D: Existing Nickel Schema Conversion

This example shows how to convert an existing Nickel schema into a complete provisioning structure with forms, validators, and orchestration scripts.

Use Cases

Mode D is useful when:

  • You have existing Nickel schemas from other projects
  • You want to migrate configuration systems
  • You need to add provisioning automation to existing Nickel configs
  • You want to bridge Nickel schemas and TypeDialog forms

Schema Conversion Process

The existing-config.ncl file defines types for a service:

{
  Server = { hostname, port, tls_enabled, ... },
  Database = { engine, host, port, username, ... },
  Authentication = { provider, secret_key, ... },
  Monitoring = { enabled, prometheus_url, ... },
  Application = { name, version, log_level, ... },
}

Mode D analyzes this schema and:

  1. Extracts Records: Identifies type definitions (Server, Database, etc.)
  2. Maps Fields: Converts Nickel types to TypeDialog field types
  3. Infers Features: Groups related records into domain features
  4. Generates Artifacts: Creates complete provisioning structure

Running the Example

Convert Nickel Schema to Provisioning

typedialog-provisioning-gen nickel \
  --input examples/11-provisioning-generation/mode-d-nickel/existing-config.ncl \
  --output /tmp/service-provisioning

Inspect Conversion

# View inferred project spec
cat /tmp/service-provisioning/config.ncl

# View extracted server schema
cat /tmp/service-provisioning/schemas/server.ncl

# View generated form fragment
cat /tmp/service-provisioning/fragments/server-section.toml

# View extracted validators
cat /tmp/service-provisioning/validators/server.ncl

Test Generated Forms

# Test server configuration form
typedialog /tmp/service-provisioning/fragments/server-section.toml --backend cli

# Test database configuration form
typedialog /tmp/service-provisioning/fragments/database-section.toml --backend cli

Schema Extraction Details

Type → Feature Mapping

Nickel Type Feature Name Domain
Server server Infrastructure
Database database Infrastructure
Authentication authentication Security
Monitoring monitoring Observability
Application application Core

Field Type Conversion

Nickel Type TypeDialog Type Example
String Text hostname, database_name
Number Number port (1-65535), timeout
Bool Confirm tls_enabled, debug
[String] MultiSelect ["warn", "error"]
{...} RepeatingGroup Array of records
String | optional Text (optional) certificate_path

Example Conversion

Input Nickel:

Server = {
  hostname | String,
  port | Number,
  tls_enabled | Bool | optional,
}

Generated Schema (schemas/server.ncl):

{
  Server = {
    hostname | String,
    port | Number,
    tls_enabled | Bool | optional,
  },
}

Generated Fragment (fragments/server-section.toml):

[section.server]
description = "Server configuration"

[[section.server.fields]]
name = "hostname"
prompt = "Server hostname"
type = "text"
required = true

[[section.server.fields]]
name = "port"
prompt = "Server port"
type = "number"
required = true
min = 1
max = 65535

[[section.server.fields]]
name = "tls_enabled"
prompt = "Enable TLS?"
type = "confirm"
required = false

Generated Validator (validators/server.ncl):

{
  validate_hostname = fun value =>
    (std.is_string value) && (std.string.length value > 0),

  validate_port = fun value =>
    (std.is_number value) && (value >= 1) && (value <= 65535),

  validate_tls_enabled = fun value =>
    (std.is_bool value),
}

Handling Complex Types

Nested Records

When a record contains another record:

ServiceConfig = {
  server | Server,      # References Server record
  database | Database,  # References Database record
}

Generated as separate features with relationships documented.

Optional Fields

Nickel optional modifier:

certificate_path | String | optional,

Generated as optional form field (not required in TypeDialog form).

Array Types

Repeating items:

tags | [String],

Generated as RepeatingGroup field with array validation.

Extending Converted Schema

After conversion, you can:

  1. Add New Fields: Modify generated fragments

    [[section.server.fields]]
    name = "max_connections"
    type = "number"
    
  2. Add Validation: Enhance validators

    validate_port = fun value =>
      (value >= 1) && (value <= 65535) && (value % 2 == 0)
    
  3. Add Defaults: Fill in missing defaults

    defaults.server = {
      port = 8080,
      tls_enabled = false,
    }
    
  4. Add Constraints: Update constraints.toml

    [constraints.server.port]
    min = 1024
    max = 65535
    

Integration with Existing Services

The converted provisioning can integrate with existing services:

1. Use as Configuration Loader

// Load configuration from generated schema
let config = nickel_eval("provisioning/config.ncl")?;
let parsed: ServiceConfig = serde_json::from_value(config)?;

2. Provide Configuration UI

# Use generated TypeDialog forms for configuration
typedialog provisioning/fragments/database-section.toml \
  --backend web --port 3000

3. Add Validation Layer

# Validate user input against Nickel schema
./provisioning/scripts/validate-nickel.sh < user-config.ncl

Migration Path

To migrate an existing configuration system:

  1. Define Nickel Schema

    # Write or extract your configuration types
    cat > config.ncl << 'EOF'
    { MyService = { ... } }
    EOF
    
  2. Convert with Mode D

    typedialog-provisioning-gen nickel --input config.ncl --output ./provisioning
    
  3. Test Generated Forms

    typedialog provisioning/fragments/*.toml --backend cli
    
  4. Integrate Validation

    # Use validation in your service
    ./provisioning/scripts/validate-nickel.sh < config.ncl
    
  5. Deploy Forms

    # Serve configuration UI
    typedialog-web provisioning/fragments/*.toml
    

What This Demonstrates

Nickel schema extraction and analysis Type inference to TypeDialog field mapping Automatic feature grouping from types Generator adaptation to schema structure Validator generation from type constraints Fragment generation from record fields Integration with existing Nickel code Schema versioning and migration

Limitations

Some conversions have limitations:

Limitation Workaround
Custom Nickel functions Manual validator enhancement
Complex constraints Update constraints.toml
Domain-specific logic Modify generated fragments
Record references Links documented in fragments

Next Steps

  1. Analyze Your Schema: Run Mode D on your Nickel file
  2. Review Generated Artifacts: Check schemas, forms, validators
  3. Test Forms: Use TypeDialog CLI to test UX
  4. Enhance: Add custom fields and validation
  5. Deploy: Use generated scripts for provisioning
  6. Iterate: Modify and regenerate as needed

For more control, use Mode B (Config File) examples to define features explicitly.