Totally experimental `.swift` configuration provider

While the topic has been discussed before and is admittedly rather esoteric, I wanted to try and see if the technique for defining configuration using Swift itself could somehow be encapsulated in a Configuration provider.

The mentioned technique requires the runtime to be able to execute Swift scripts and also involves including the custom manifest DSL as a resource of the project so it can be prepended to the manifest (aka configuration file).

Finally the configuration is serialized to JSON which can either be used to regenerate the original struct or simply passed along unmodified so that Swift Configuration can do its thing. Both seem to work quite consistently.

So here's the fully implemented SwiftSnapshot doing all the heavy lifting:

The name of the resource is hard-coded at the moment but everything is totally agnostic of the DSL/types defined for the configuration file.

To use it, you declare it as a regular FileProvider<SwiftSnapshot> and add it to your config reader hierarchy.

let filePathJSON = configPath.appending("config.json")
let fileProviderJSON: FileProvider<JSONSnapshot>
do {
    fileProviderJSON = try await FileProvider<JSONSnapshot>(filePath: filePathJSON, allowMissing: true)
} catch {
    throw ValidationError("Error opening/reading \(filePathJSON) file.\n\n\(error)")
}

let filePathSwift = configPath.appending("config.swift")
let fileProviderSwift: FileProvider<SwiftSnapshot>
do {
    fileProviderSwift = try await FileProvider<SwiftSnapshot>(filePath: filePathSwift, allowMissing: true)
} catch {
    throw ValidationError("Error opening/reading \(filePathSwift) file.\n\n\(error)")
}

let config = ConfigReader(providers: [
    CommandLineArgumentsProvider(),
    EnvironmentVariablesProvider(),
    fileProviderJSON,
    fileProviderSwift,
    InMemoryProvider(values: […]
])
let nodeConfig: NodeConfig
do {
    nodeConfig = try NodeConfig(config)
} catch {
    throw ValidationError(error)
}

There's obviously many caveats to doing this including reliability and maybe even some security concerns (?). Also the benefits are curtailed by the fact that DSL is missing during the creation of the manifest, making the experience very different from that of SPM.

For now I've decided to experiment with it although I wouldn't necessarily offer it as standalone package.

Cheers!

1 Like