Skip to content

Type-safe access to your environment leveraging Swift's Decodable

License

Notifications You must be signed in to change notification settings

SwiftScream/swift-environment-decoder

Repository files navigation

Swift Environment Decoder

Type-safe access to your environment leveraging Swift's Decodable

CI Codecov branch

license GitHub release

Getting Started

Swift Package Manager

Add .package(url: "https://github.com/SwiftScream/swift-environment-decoder.git", from: "0.4.0") to your Package.swift dependencies

Usage

Decoding the Environment

import EnvironmentDecoder

struct MyEnvironmentFeatureFlags: Decodable {
    let enableA: Bool
    let enableB: Bool
}

struct MyEnvironment: Decodable {
    let port: UInt16
    let allowedRegions: [String]
    let featureFlags: MyEnvironmentFeatureFlags
}

let environment = try EnvironmentDecoder().decode(MyEnvironment.self)

print("\(environment.allowedRegions.count) allowed region(s)")
print("listening on port \(environment.port)")
if environment.featureFlags.enableA {
    print("A is enabled")
}
if environment.featureFlags.enableB {
    print("B is enabled")
}

The above code expects an environment of the form:

PORT=1234
ALLOWED_REGIONS=regionA,regionB,regionC
FEATURE_FLAGS_ENABLE_A=true
FEATURE_FLAGS_ENABLE_B=false

When Things Go Wrong

If the environment cannot be decoded into the specified type, a Swift.DecodingError is thrown.

This is a great way to catch issues with the environment early. In some cases it may be appropriate to output a message, and terminate the process.

Some examples of why this may occur:

  • a required environment variable is not specified
  • the value of an environment variable cannot be decoded as the specified type
let environment: MyEnvironment
do {
    environment = try EnvironmentDecoder().decode(MyEnvironment.self)
} catch {
    fatalError(error.localizedDescription)
}

Alternative Environment

By default EnvironmentDecoder will decode ProcessInfo.processInfo.environment. If that's not what you want, you can pass in a [String: String] instead.

let someEnvDictionary: [String: String] = //...
let environment = try EnvironmentDecoder().decode(MyEnvironment.self, from: someEnvDictionary)