# 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:

```nickel
{
  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"
   ```

2. **Add Validation**: Enhance validators
   ```nickel
   validate_port = fun value =>
     (value >= 1) && (value <= 65535) && (value % 2 == 0)
   ```

3. **Add Defaults**: Fill in missing defaults
   ```nickel
   defaults.server = {
     port = 8080,
     tls_enabled = false,
   }
   ```

4. **Add Constraints**: Update constraints.toml
   ```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
```rust
// 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
   ```

2. **Convert with Mode D**
   ```bash
   typedialog-provisioning-gen nickel --input config.ncl --output ./provisioning
   ```

3. **Test Generated Forms**
   ```bash
   typedialog provisioning/fragments/*.toml --backend cli
   ```

4. **Integrate Validation**
   ```bash
   # Use validation in your service
   ./provisioning/scripts/validate-nickel.sh < config.ncl
   ```

5. **Deploy Forms**
   ```bash
   # 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.
