2026-01-11 22:35:49 +00:00
..
2026-01-11 22:35:49 +00:00

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, ... },
}
```text

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
```bash
typedialog-provisioning-gen nickel \
  --input examples/11-provisioning-generation/mode-d-nickel/existing-config.ncl \
  --output /tmp/service-provisioning
```text

### Inspect Conversion
```bash
# 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
```text

### Test Generated Forms
```bash
# 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
```text

## 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:**
```nickel
Server = {
  hostname | String,
  port | Number,
  tls_enabled | Bool | optional,
}
```text

**Generated Schema** (`schemas/server.ncl`):
```nickel
{
  Server = {
    hostname | String,
    port | Number,
    tls_enabled | Bool | optional,
  },
}
```text

**Generated Fragment** (`fragments/server-section.toml`):
```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
```text

**Generated Validator** (`validators/server.ncl`):
```nickel
{
  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),
}
```text

## Handling Complex Types

### Nested Records
When a record contains another record:

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

Generated as separate features with relationships documented.

### Optional Fields
Nickel `optional` modifier:

```nickel
certificate_path | String | optional,
```text

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

### Array Types
Repeating items:

```nickel
tags | [String],
```text

Generated as `RepeatingGroup` field with array validation.

## Extending Converted Schema

After conversion, you can:

1. **Add New Fields**: Modify generated fragments
   ```toml
   [[section.server.fields]]
   name = "max_connections"
   type = "number"
  1. Add Validation: Enhance validators

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

    defaults.server = {
      port = 8080,
      tls_enabled = false,
    }
    
  3. 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)?;
```text

### 2. Provide Configuration UI
```bash
# Use generated TypeDialog forms for configuration
typedialog provisioning/fragments/database-section.toml \
  --backend web --port 3000
```text

### 3. Add Validation Layer
```bash
# Validate user input against Nickel schema
./provisioning/scripts/validate-nickel.sh < user-config.ncl
```text

## Migration Path

To migrate an existing configuration system:

1. **Define Nickel Schema**
   ```bash
   # Write or extract your configuration types
   cat > config.ncl << 'EOF'
   { MyService = { ... } }
   EOF
  1. Convert with Mode D

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

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

    # Use validation in your service
    ./provisioning/scripts/validate-nickel.sh < config.ncl
    
  4. 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.