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"
-
Add Validation: Enhance validators
validate_port = fun value => (value >= 1) && (value <= 65535) && (value % 2 == 0) -
Add Defaults: Fill in missing defaults
defaults.server = { port = 8080, tls_enabled = false, } -
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
-
Convert with Mode D
typedialog-provisioning-gen nickel --input config.ncl --output ./provisioning -
Test Generated Forms
typedialog provisioning/fragments/*.toml --backend cli -
Integrate Validation
# Use validation in your service ./provisioning/scripts/validate-nickel.sh < config.ncl -
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
- Analyze Your Schema: Run Mode D on your Nickel file
- Review Generated Artifacts: Check schemas, forms, validators
- Test Forms: Use TypeDialog CLI to test UX
- Enhance: Add custom fields and validation
- Deploy: Use generated scripts for provisioning
- Iterate: Modify and regenerate as needed
For more control, use Mode B (Config File) examples to define features explicitly.