Swiftpack.co - Package - 0111b/Conf

Conf

Config made easy

CI Tag

This package provide easy way to work with configs. Mostly usefull in CLI-tools. Extentable and customisable.

Contents

Usage

For more details please refer the tests

Creating the config

let config = Config(useEnvironment: true)

Load configurations

try config.load(.file(name: ".env.dev"))
// or
let url = Bundle.main.url(forResource: "myConfig", withExtension: "plist")!
try config.load(.url(url), format: .plist)
// or
let json = """
{"key": "value"}
"""
try config.load(.string(json), format: .json)

Data representation

All values are stored as Key-String pairs. There are convenience methods to use LosslessStringConvertible.

The Key represents the value position in the provided source.

For basic key-value formats it is just a string.

For nested types key is the array of strings.

Arrays are mapped as multiple key-value pairs:

Key<arrayName, 0> = <first element>
Key<arrayName, 1> = <second element>
...
Key<arrayName, count-1> = <last element>

Reading the value

Values can be accessed via subscripts

let path: String? = config["PATH"]

let port: Int? = config["HTTP_PORT"]

let key = Key("myKey")
let value = config[key]

let value = config[["key", "nested"]]

let value = config[["array", 2]]

extension Key {
    static let clientId = Key("SECRET_CLIENT_ID")
}

let value = config[.clientId]

Require the value

For required values you can use require method which throws ConfigurationError.missing(key:) if value is not found.

let requiredValue = try config.require("secret")

struct MyCredentials {
    let username: String
    let password: String
}

extension Config {
    func credentials() throws -> MyCredentials {
        try MyCredentials(username: require("username"),
                          password: require("password"))
    }
}

Updating values

Values can be updated via subscript

config["foo"] = "bar"
config["answer"] = 42

Creating the keys

let key: Key = "myKey"
let key: Key = 99
let key: Key = Key(23.4)
let key: Key = Key("some")
let key: Key = ["24", 72, 23.4, true]
let key: Key = Key([1, 2, 3])

Working with process environment

Conf can fallback to the environment variables. This is controlled by useEnvironment variable in the constructor.

Env values can be assessed separately with Environment

let env = Environment()
let home = env["HOME"]
let path = env.PATH
env.TMPDIR = "/tmp"

Customisation

Adding data format

If you want to add support for different config format you just need to implement your own parser function and call load with Format.custom.

For example here is how yaml support can be added with Yams

let yamlParser: ParserType = { data in
    guard let rawYaml = String(data: data, encoding: .utf8),
        let values = try Yams.load(yaml: rawYaml) as? [String: Any]
        else {
            struct InvalidYaml: Error {}
            throw InvalidYaml()
    }
    return values
}

try config.load(.file(name: "config.yml"), format: .custom(yamlParser))

Custom parsing

It is also possbile to provide completelly custom implementation of the data fetching behaviour. To do this you need to adopt ConfigurationProvider

struct CustomConfigurationProvider: ConfigurationProvider {
    func configuration() throws -> [Key : String] {
        return ["key": "value"]
    }
}
config.load(from: CustomConfigurationProvider())

TODO

  • ☐ Cocoapods support
  • ☐ Carthage support
  • ☑ Github mirror

Github

link
Stars: 1

Dependencies

Used By

Total: 0