Swift Configuration
repository·main·Indexed 21 days ago
https://github.com/apple/swift-configurationA library providing a consistent API for reading configuration across Swift applications and libraries. It abstracts configuration sources (providers) from consumption logic (readers) and supports a provider hierarchy for value resolution. Built-in providers include EnvironmentVariablesProvider, CommandLineArgumentsProvider, and various FileProviders for JSON, YAML, and Property List files. Optional features like dynamic reloading via ReloadingFileProvider and logging are available through Swift Package Manager traits.
What's inside Swift Configuration
- Swift Configuration is a library designed for reading configuration data within Swift applications and libraries. It provides a structured way to manage settings through various providers and readers.
Explore Swift Configuration examples catalog
mainThe repository provides several examples categorized by complexity and use case:
- hello-world-cli-example: A simple CLI demonstrating provider hierarchy, environment variables, command-line arguments, and type-safe configuration reading.
- reloading-example: A simple web server demonstrating live-reloading from a Kubernetes configMap, file providers, and multi-phase initialization.
Use ConfigurationTesting for custom provider validation
mainTheConfigurationTestinglibrary provides a suite of testing utilities designed for developers implementing customConfigProvidertypes. It uses the Swift Testing framework to provide a compatibility suite that ensures your custom provider adheres to the expected behavior and interface requirements of the Swift Configuration ecosystem.Choose between static and reloading providers
mainSelecting the right provider type depends on whether your configuration needs to change during runtime:
- Reloading Providers: Use these when configuration changes must take effect without restarting the application. This is ideal for long-running services, development environments, or applications receiving updates via file deployments.
- Static Providers: Use these when configuration is immutable once the application starts. This is ideal for containerized applications or scenarios where configuration is set once at startup.
Convert integer configuration values using ExpressibleByConfigInt
mainYou can automatically convert integer-backed configuration values into richer domain types (like
Duration, enums, or custom types) by conforming those types to theExpressibleByConfigIntprotocol.Once a type conforms, you can use integer-based accessor methods on
ConfigReaderorConfigSnapshotReader(such asint(forKey:as:),requiredInt(forKey:as:), orintArray(forKey:as:)) to perform the conversion in a single step.Built-in Support
Swift.Duration: Conforms toExpressibleByConfigInt. The integer value is interpreted as the number of seconds. An invalid value results innilfor failable accessors.RawRepresentable<Int>: Any enum conforming toRawRepresentablewith anIntraw value automatically works with these conversion methods.
// Example: Using built-in Duration support let timeout: Duration? = config.int(forKey: "timeout_seconds", as: Duration.self) // Example: Using an Int-backed enum enum Priority: Int, RawRepresentable { case low = 0 case high = 1 } let priority: Priority? = config.int(forKey: "priority", as: Priority.self)Choose the right ConfigProvider type
mainWhen implementing a custom configuration source, select a provider type based on how the data behaves:
Type Use case Examples File-based Custom file formats JSON, YAML, TOML, XML, plist files Immutable Values loaded once, never change Command-line arguments, in-memory values, test fixtures Dynamic Values change over time Remote servers, watched files Use the
Providersuffix for all implementations. For dynamic variants, use theReloadingprefix for disk-based sources orRefetchingfor network-based sources (e.g.,ReloadingFileProviderorRefetchingLunarProvider).Proposal review states in Swift Configuration
mainProposals for API changes move through several lifecycle states during the review process:
Awaiting ReviewIn ReviewReady for ImplementationIn PreviewApprovedDeferred
Implement a custom configuration provider
mainTo create a custom source of configuration, you must implement the
ConfigProviderprotocol. This involves working with several core types:ConfigProvider: The main interface you implement to define how configuration is retrieved.ConfigSnapshot: Represents a point-in-time view of the configuration data.ConfigContent: The raw data structure containing the configuration values.ConfigValue: The individual values stored within the content.ConfigType: Defines the type system used for configuration values.LookupResult: The result of a configuration lookup (e.g., success with a value or a failure).ConfigUpdatesAsyncSequence: Used to provide a stream of configuration updates to consumers.SecretsSpecifier: Used to handle sensitive data within the provider implementation.
How key delimiters work in Swift Configuration
mainSwift Configuration uses a fixed dot (
.) delimiter for splitting string-based keys into components. This behavior is hardcoded to ensure consistency across different modules and libraries.Because the delimiter is fixed, you should always use dots to represent hierarchy in your configuration keys. This prevents breaking changes when passing a
ConfigReaderfrom one module (e.g., an App) to another (e.g., a library), as both will interpret the dot delimiter identically.// Correct usage: components are split by dots let client = Client(config: config.scoped(to: "http.client")) // Inside the library: self.timeout = config.int(forKey: "read.timeout", default: 30) // This correctly reads components: ["http", "client", "read", "timeout"]Monitor file changes with snapshot types
mainThe
ReloadingFileProvideruses specific snapshot types to represent the state of the configuration file. When the file is modified on disk, the provider parses the new content into one of the following snapshot formats:FileConfigSnapshot: The general abstraction for a configuration snapshot.JSONSnapshot: A snapshot parsed from a JSON file.YAMLSnapshot: A snapshot parsed from a YAML file.PropertyListSnapshot: A snapshot parsed from a macOS/iOS Property List (.plist) file.
Implement the ConfigSnapshot protocol
mainFileConfigSnapshotconforms to theConfigSnapshotprotocol. Any type conforming toConfigSnapshotrepresents a static, immutable view of configuration data at a specific moment, allowing the system to work with consistent values even if the underlying source changes.Handle provider and missing value errors
mainProvider errors
- Required methods (e.g.,
requiredString): If a provider throws an error during lookup, the method immediately throws that error to the caller. - Optional methods (with or without defaults): The library handles provider errors gracefully by returning
nilor the provided default value.
Missing values
- Methods with defaults: Return the provided default value if no provider has the key.
- Methods without defaults: Return
nilif no provider has the key. - Required methods: Throw an error if no provider has the key.
- Required methods (e.g.,