Setup Framework
Wizard-based automated initialization with checkpointing, resume, and cross-platform adapters
Source of truth (2026)
DataManagementEngineStandard/SetUp/SetupWizard.csDataManagementEngineStandard/SetUp/SetupWizardBuilder.csDataManagementEngineStandard/SetUp/SetupContext.csDataManagementEngineStandard/SetUp/SetupState.csDataManagementEngineStandard/SetUp/SetupOptions.csDataManagementEngineStandard/SetUp/SetupReport.csDataManagementEngineStandard/SetUp/ISetupStep.csDataManagementEngineStandard/SetUp/Steps/DataManagementEngineStandard/SetUp/Adapters/
Table of Contents
Overview
The Setup Framework automates the end-to-end initialization of BeepDM applications. It provides:
- Step-based execution - Each step handles one responsibility (drivers, connections, schema, seeding)
- Idempotency - Steps detect when work is done and skip safely
- Checkpointing - State persisted after each step for resume after interruption
- Cross-platform - Adapters for WinForms, WPF, Blazor, MAUI, CLI, Web API
- Progress reporting -
IProgress<PassedArgs>per-step - SHA-256 verified reports - Tamper-evident outcome with per-step timings
Architecture
SetupWizard (orchestrator)
├── SetupWizardBuilder (fluent configuration)
├── SetupContext (shared state)
│ ├── IDMEEditor
│ ├── SetupOptions
│ └── SetupState
├── SetupState (checkpoint)
│ ├── CompletedStepIds
│ ├── SkippedStepIds
│ ├── FailedStepId
│ └── CompletedSeederIds
├── ISetupStep[] (steps)
│ ├── DriverProvisionStep
│ ├── ConnectionConfigStep
│ ├── SchemaSetupStep
│ └── SeedingStep
└── ISetupWizardAdapter (platform bridge)
├── DesktopSetupWizardAdapter
├── WebSetupWizardAdapter
├── BlazorSetupWizardAdapter
├── MauiSetupWizardAdapter
└── CliSetupWizardAdapter
SetupWizard
Core orchestrator that runs registered steps in sequence:
public class SetupWizard : ISetupWizard
{
public SetupWizard(
string wizardId,
IEnumerable<ISetupStep> steps,
SetupOptions options);
// Properties
public IReadOnlyList<ISetupStep> Steps { get; }
public SetupState State { get; }
public SetupOptions Options { get; }
// Execution
public IErrorsInfo Run(
SetupContext context,
IProgress<PassedArgs> progress = null);
// Resume from checkpoint
public IErrorsInfo Resume(
SetupContext context,
IProgress<PassedArgs> progress = null);
// Report
public SetupReport GetReport();
}
Execution Flow
- Load persisted checkpoint if state is empty
- Validate step definitions (unique IDs, valid dependencies)
- For each incomplete step:
- Check dependencies are completed
- Validate step configuration
- Check CanSkip (idempotency)
- Execute step
- Mark as completed
- Persist checkpoint
- Build SHA-256 verified report
SetupWizardBuilder
var wizard = new SetupWizardBuilder()
.WithId("app-setup")
.WithEnvironment("Development")
.AddStep(new DriverProvisionStep(driverOpts))
.AddStep(new ConnectionConfigStep(connOpts))
.AddStep(new SchemaSetupStep(schemaOpts))
.AddStep(new SeedingStep(seedingOpts))
.Build();
SetupContext
Shared state read/written by all steps:
public class SetupContext
{
public IDMEEditor Editor { get; set; }
public SetupOptions Options { get; set; }
public SetupState State { get; set; }
public ISetupProgressReporter ProgressReporter { get; set; }
// Step-specific data
public Dictionary<string, object> StepData { get; set; }
}
SetupOptions
| Property | Default | Description |
|---|---|---|
StateFilePath | null | Path to persist checkpoint JSON |
Environment | "Production" | Environment name |
EnableRetry | true | Retry failed steps |
MaxRetries | 3 | Max retry attempts |
RetryDelayMs | 1000 | Delay between retries |
SetupState
Persisted checkpoint state:
public class SetupState
{
public string WizardId { get; set; }
public List<string> CompletedStepIds { get; set; }
public List<string> SkippedStepIds { get; set; }
public string FailedStepId { get; set; }
public List<string> CompletedSeederIds { get; set; }
public DateTimeOffset? StartedAt { get; set; }
public DateTimeOffset? LastUpdatedAt { get; set; }
public bool IsStepCompleted(string stepId);
public bool IsStepSkipped(string stepId);
}
Built-in Steps
ISetupStep Interface
public interface ISetupStep
{
string StepId { get; }
string StepName { get; }
string Description { get; }
IReadOnlyList<string> DependsOn { get; }
// Validation
IErrorsInfo Validate(SetupContext context);
// Idempotency check
bool CanSkip(SetupContext context);
// Execution
IErrorsInfo Execute(
SetupContext context,
IProgress<PassedArgs> progress);
}
DriverProvisionStep
Downloads and installs required drivers from NuGet or local sources.
public class DriverProvisionStep : ISetupStep
{
public DriverProvisionStep(DriverProvisionStepOptions options);
// Options
public string PackageName { get; set; }
public string Version { get; set; }
public string Source { get; set; } // "nuget" or "local"
public string LocalPath { get; set; }
}
ConnectionConfigStep
Configures data connections with validation and testing.
public class ConnectionConfigStep : ISetupStep
{
public ConnectionConfigStep(ConnectionConfigStepOptions options);
// Options
public ConnectionProperties ConnectionProperties { get; set; }
public bool TestConnection { get; set; } = true;
public bool OpenConnection { get; set; } = false;
}
SchemaSetupStep
Creates database schema based on entity definitions.
public class SchemaSetupStep : ISetupStep
{
public SchemaSetupStep(SchemaSetupStepOptions options);
// Options
public List<Type> EntityTypes { get; set; }
public List<EntityStructure> EntityStructures { get; set; }
public bool DropExisting { get; set; } = false;
public bool ValidateSchema { get; set; } = true;
}
SeedingStep
Populates initial data from seeders.
public class SeedingStep : ISetupStep
{
public SeedingStep(SeedingStepOptions options);
// Options
public ISeederRegistry Registry { get; set; }
public List<string> SeederIds { get; set; }
public bool ClearExisting { get; set; } = false;
}
Platform Adapters
Bridge between wizard and platform-specific UI/runtime:
| Adapter | Platform | UI Pattern |
|---|---|---|
DesktopSetupWizardAdapter | WinForms / WPF | Progress dialog, message boxes |
ConsoleSetupWizardAdapter | CLI / Shell | Console output, progress bars |
WebApiSetupWizardAdapter | ASP.NET Core | API endpoints, SignalR |
BlazorServerSetupWizardAdapter | Blazor Server | Component-based progress, SignalR |
BlazorWasmSetupWizardAdapter | Blazor WASM | Client-side component progress |
MauiSetupWizardAdapter | .NET MAUI | Mobile/desktop native UI |
ISetupWizardAdapter Interface
public interface ISetupWizardAdapter
{
Task<SetupReport> RunAsync(SetupWizard wizard, SetupContext context);
void OnStepStart(string stepId, string stepName, int stepNumber, int total);
void OnStepComplete(string stepId, bool succeeded, string message);
void OnWizardComplete(SetupReport report);
}
// Adapter status tracking
public enum SetupAdapterStatus { NotStarted, Running, Completed, Failed }
ISetupProgressReporter
public interface ISetupProgressReporter
{
void ReportStepStart(string stepId, string stepName, int stepNumber, int total);
void ReportStepProgress(string stepId, string message, int percentComplete);
void ReportStepComplete(string stepId, bool succeeded, TimeSpan elapsed);
void ReportWizardComplete(SetupReport report);
}
SetupWizardFactory
public interface ISetupWizardFactory
{
(ISetupWizard wizard, SetupContext context) CreateDefault(IDMEEditor editor);
(ISetupWizard wizard, SetupContext context) Create(IDMEEditor editor,
Action<SetupWizardBuilder> configure);
}
// Default factory: returns empty wizard (applications register custom factory)
public class DefaultSetupWizardFactory : ISetupWizardFactory
{
public (ISetupWizard wizard, SetupContext context) CreateDefault(IDMEEditor editor)
{
var options = new SetupOptions();
var context = new SetupContext { Editor = editor, Options = options };
var wizard = new SetupWizardBuilder().WithId("default-setup")
.WithOptions(options).Build();
return (wizard, context);
}
}
Seeding Subsystem
public interface ISeeder
{
string SeederId { get; }
string SeederName { get; }
int Priority { get; }
IErrorsInfo Seed(SetupContext context, IProgress<PassedArgs> progress);
}
public interface ISeederRegistry
{
void Register(ISeeder seeder);
IReadOnlyList<ISeeder> GetOrderedSeeders();
}
public class SeederRegistry : ISeederRegistry
{
public void Register(ISeeder seeder);
public IReadOnlyList<ISeeder> GetOrderedSeeders(); // By Priority, then name
}
// Base classes for common seeding patterns
public abstract class SeederBase : ISeeder { /* Priority=0, default impl */ }
public abstract class ReferenceDataSeederBase : SeederBase { /* Static ref data */ }
Seed Execution
var registry = new SeederRegistry();
registry.Register(new CustomerSeeder());
registry.Register(new ProductSeeder());
var step = new SeedingStep(new SeedingStepOptions { Registry = registry });
var result = step.Execute(context, progress);
Checkpointing & Resume
The framework automatically checkpoints state after each step:
// State file (JSON)
{
"wizardId": "app-setup",
"completedStepIds": ["driver-provision", "connection-config"],
"skippedStepIds": [],
"failedStepId": null,
"completedSeederIds": [],
"startedAt": "2024-01-15T10:30:00Z",
"lastUpdatedAt": "2024-01-15T10:35:00Z"
}
Resume After Failure
// First run — fails at schema setup
var result1 = wizard.Run(context);
// State persisted with FailedStepId = "schema-setup"
// Fix the issue, then resume
var result2 = wizard.Resume(context);
// Loads checkpoint, skips completed steps, continues from schema-setup
Report Verification
var report = wizard.GetReport();
Console.WriteLine($"Success: {report.Succeeded}");
Console.WriteLine($"Duration: {report.FinishedAt - report.StartedAt}");
Console.WriteLine($"SHA-256: {report.ContentHash}");
foreach (var step in report.StepResults)
{
Console.WriteLine($" {step.StepName}: " +
$"{(step.Succeeded ? "OK" : "FAIL")} " +
$"({step.Elapsed.TotalSeconds:F1}s)");
}
Usage Examples
Desktop Application (WinForms)
var editor = new DMEEditor();
var connProps = new ConnectionProperties
{
ConnectionName = "ProductDB",
DatabaseType = DataSourceType.SqlLite,
ConnectionString = "Data Source=./products.db"
};
var wizard = new SetupWizardBuilder()
.WithId("product-app-setup")
.WithEnvironment("Development")
.AddStep(new DriverProvisionStep(new DriverProvisionStepOptions
{
PackageName = "TheTechIdea.Beep.DataSources.SQLite"
}))
.AddStep(new ConnectionConfigStep(new ConnectionConfigStepOptions
{
ConnectionProperties = connProps,
OpenConnection = true
}))
.AddStep(new SchemaSetupStep(new SchemaSetupStepOptions
{
EntityTypes = new[] { typeof(Product), typeof(Category) }
}))
.AddStep(new SeedingStep(new SeedingStepOptions
{
Registry = seederRegistry
}))
.Build();
var adapter = new DesktopSetupWizardAdapter(
onProgress: args => progressLabel.Text = args.Messege,
onComplete: report => MessageBox.Show(
report.Succeeded ? "Setup OK" : "Setup failed"));
var context = new SetupContext
{
Editor = editor,
Options = new SetupOptions
{
StateFilePath = "./setup-checkpoint.json"
}
};
var report = await adapter.RunAsync(wizard, context);
Web API
[ApiController]
[Route("api/[controller]")]
public class SetupController : ControllerBase
{
[HttpPost]
public async Task<IActionResult> RunSetup()
{
var wizard = /* build wizard */;
var adapter = new WebSetupWizardAdapter(
hubContext: _hubContext);
var context = new SetupContext { Editor = _editor };
var report = await adapter.RunAsync(wizard, context);
return Ok(new
{
Success = report.Succeeded,
Steps = report.StepResults.Select(s => new
{
s.StepName,
s.Succeeded,
s.Elapsed
})
});
}
}
CLI Application
var adapter = new CliSetupWizardAdapter(
console: Console.Out,
showProgressBar: true);
var report = await adapter.RunAsync(wizard, context);
if (report.Succeeded)
Console.WriteLine("Setup completed successfully!");
else
Console.WriteLine($"Setup failed at: {report.StepResults.Last(s => !s.Succeeded).StepName}");
Custom Step
public class CustomConfigStep : ISetupStep
{
public string StepId => "custom-config";
public string StepName => "Custom Configuration";
public string Description => "Applies custom app settings";
public IReadOnlyList<string> DependsOn => new[] { "connection-config" };
public IErrorsInfo Validate(SetupContext context)
{
if (context.Editor == null)
return new ErrorsInfo { Flag = Errors.Failed, Message = "Editor required" };
return new ErrorsInfo { Flag = Errors.Ok };
}
public bool CanSkip(SetupContext context)
{
// Check if already configured
return File.Exists("./custom-config.json");
}
public IErrorsInfo Execute(SetupContext context, IProgress<PassedArgs> progress)
{
// Apply custom configuration
File.WriteAllText("./custom-config.json", "{}");
progress?.Report(new PassedArgs { Messege = "Custom config applied" });
return new ErrorsInfo { Flag = Errors.Ok };
}
}
Full API Reference
Step Options — Complete Properties
DriverProvisionStepOptions
| Property | Type | Description |
|---|---|---|
PackageName | string | Driver package name to install |
Version | string? | Specific NuGet version; null → latest stable |
NuGetSources | IList<string> | Additional NuGet feed URLs |
AppInstallPath | string? | Override install path; null → assemblyHandler default |
ConnectionConfigStepOptions
| Property | Type | Default |
|---|---|---|
ConnectionProperties | ConnectionProperties | required |
TestConnection | bool | true |
OpenConnection | bool | false |
SchemaSetupStepOptions
| Property | Type | Default |
|---|---|---|
EntityTypes | List<Type> | null — use Discovery |
EntityStructures | List<EntityStructure> | null |
DropExisting | bool | false |
ValidateSchema | bool | true |
SeedingStepOptions
| Property | Type | Default |
|---|---|---|
Registry | ISeederRegistry | required |
SeederIds | List<string> | null — all registered |
ClearExisting | bool | false |
SetupReport & SetupStepResult
public class SetupReport
{
public string WizardId { get; set; } // From builder
public string RunId { get; set; } = Guid.NewGuid() // Unique run ID
public bool Succeeded { get; set; } // All steps OK
public IReadOnlyList<SetupStepResult> StepResults { get; set; }
public DateTimeOffset StartedAt { get; set; }
public DateTimeOffset FinishedAt { get; set; }
public TimeSpan TotalElapsed => FinishedAt - StartedAt; // Computed
public string ContentHash { get; set; } // SHA-256 of StepResults
public string RollbackReportJson { get; set; } // Phase 6
public string DryRunReportJson { get; set; } // Phase 3/8
public string Environment { get; set; } // Target environment
}
public class SetupStepResult
{
public string StepId { get; set; }
public string StepName { get; set; }
public bool Succeeded { get; set; }
public bool Skipped { get; set; }
public string Message { get; set; }
public TimeSpan Elapsed { get; set; }
public DateTimeOffset ExecutedAt { get; set; }
}
ISetupWizard & ISetupWizardAdapter — Complete
public interface ISetupWizard
{
IReadOnlyList<ISetupStep> Steps { get; }
SetupState State { get; }
SetupOptions Options { get; }
IErrorsInfo Run(SetupContext context, IProgress<PassedArgs> progress = null);
IErrorsInfo Resume(SetupContext context, IProgress<PassedArgs> progress = null);
SetupReport GetReport();
}
public interface ISetupWizardAdapter
{
Task<SetupReport> RunAsync(SetupWizard wizard, SetupContext context);
void OnStepStart(string stepId, string stepName, int stepNumber, int total);
void OnStepComplete(string stepId, bool succeeded, string message);
void OnWizardComplete(SetupReport report);
}
public enum SetupAdapterStatus { NotStarted, Running, Completed, Failed }
public interface ISetupProgressReporter
{
void ReportStepStart(string stepId, string stepName, int stepNumber, int total);
void ReportStepProgress(string stepId, string message, int percentComplete);
void ReportStepComplete(string stepId, bool succeeded, TimeSpan elapsed);
void ReportWizardComplete(SetupReport report);
}
public interface ISetupWizardFactory
{
(ISetupWizard wizard, SetupContext context) CreateDefault(IDMEEditor editor);
(ISetupWizard wizard, SetupContext context) Create(
IDMEEditor editor, Action<SetupWizardBuilder> configure);
}
SetupWizardBuilder — Complete API
public class SetupWizardBuilder
{
public SetupWizardBuilder WithId(string wizardId);
public SetupWizardBuilder WithEnvironment(string environment);
public SetupWizardBuilder WithOptions(SetupOptions options);
public SetupWizardBuilder AddStep(ISetupStep step);
public SetupWizardBuilder AddSteps(IEnumerable<ISetupStep> steps);
public SetupWizardBuilder WithSteps(params ISetupStep[] steps);
public SetupWizard Build();
}
Source File Map (30 files)
| Category | File | Content |
|---|---|---|
| Core | SetupWizard.cs | Orchestrator: Run, Resume, checkpoint loop, validation |
SetupWizardBuilder.cs | Fluent builder: WithId, WithEnvironment, AddStep, Build | |
DefaultSetupWizardFactory.cs | Empty default factory (apps replace) | |
ISetupWizardFactory.cs | Factory contract | |
| Interfaces | ISetupWizard.cs | Wizard contract: Run, Resume, GetReport |
ISetupStep.cs | Step contract: Validate, CanSkip, Execute | |
ISetupWizardAdapter.cs | Platform adapter contract | |
ISetupProgressReporter.cs | Progress reporting contract | |
ISetupWizardFactory.cs | Factory contract (duplicate listing) | |
Adapters/SetupAdapterStatus.cs | NotStarted, Running, Completed, Failed | |
| Context/State | SetupContext.cs | Shared state: Editor, Options, State, StepData |
SetupState.cs | Checkpoint: step IDs, seeders, timestamps | |
SetupOptions.cs | StateFilePath, retry, environment | |
| Report | SetupReport.cs | Report + StepResult: hash, dry-run, rollback |
| — (nested) | SetupStepResult: per-step timing | |
| Steps | Steps/DriverProvisionStep.cs | NuGet/local driver install |
Steps/DriverProvisionStepOptions.cs | PackageName, Version, NuGetSources, AppInstallPath | |
Steps/ConnectionConfigStep.cs | Connection save + test + open | |
Steps/ConnectionConfigStepOptions.cs | ConnectionProperties, TestConnection, OpenConnection | |
Steps/SchemaSetupStep.cs | Entity discovery, DDL generation, validation | |
Steps/SchemaSetupStepOptions.cs | EntityTypes, DropExisting, ValidateSchema | |
Steps/SeedingStep.cs | Seed data population | |
Steps/SeedingStepOptions.cs | Registry, SeederIds, ClearExisting | |
| Adapters | Adapters/DesktopSetupWizardAdapter.cs | WinForms/WPF: progress dialog, message boxes |
Adapters/ConsoleSetupWizardAdapter.cs | CLI: console output, progress bars | |
Adapters/WebApiSetupWizardAdapter.cs | ASP.NET Core: API endpoints, SignalR | |
Adapters/BlazorServerSetupWizardAdapter.cs | Blazor Server: component progress, SignalR | |
Adapters/BlazorWasmSetupWizardAdapter.cs | Blazor WASM: client-side progress | |
Adapters/MauiSetupWizardAdapter.cs | .NET MAUI: native UI | |
Adapters/SetupAdapterStatus.cs | Adapter status enum | |
| Seeding | Seeding/ISeeder.cs | Seeder contract: SeederId, Priority, Seed |
Seeding/ISeederRegistry.cs | Registry contract: Register, GetOrderedSeeders | |
Seeding/SeederRegistry.cs | Concrete: priority-sorted registration | |
Seeding/SeederBase.cs | Abstract base: Priority=0 default | |
Seeding/ReferenceDataSeederBase.cs | Static reference data base |