Contents

0111b/Conf

Config made easy

Contents ##

Creating the config Load configurations Data representation Reading the value Require the value Updating values Creating the keys Working with process environment

Adding data format Custom parsing

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~~
  • [x] Github mirror

Package Metadata

Repository: 0111b/Conf

Stars: 2

Forks: 0

Open issues: 0

Default branch: master

Primary language: swift

License: MIT

Topics: cli, config, swift

README: README.md