diff --git a/Package.swift b/Package.swift index 9e19ff2..71e126b 100644 --- a/Package.swift +++ b/Package.swift @@ -70,9 +70,6 @@ traits.insert( let package = Package( name: "swift-configuration", - platforms: [ - .macOS(.v15), .iOS(.v18), .macCatalyst(.v18), .tvOS(.v18), .watchOS(.v11), .visionOS(.v2), - ], products: [ .library(name: "Configuration", targets: ["Configuration"]), .library(name: "ConfigurationTesting", targets: ["ConfigurationTesting"]), @@ -170,21 +167,21 @@ let package = Package( ) for target in package.targets { - if target.type != .plugin { - var settings = target.swiftSettings ?? [] + var settings = target.swiftSettings ?? [] + + // https://github.com/apple/swift-evolution/blob/main/proposals/0335-existential-any.md + // Require `any` for existential types. + settings.append(.enableUpcomingFeature("ExistentialAny")) - // https://github.com/apple/swift-evolution/blob/main/proposals/0335-existential-any.md - // Require `any` for existential types. - settings.append(.enableUpcomingFeature("ExistentialAny")) + // https://github.com/swiftlang/swift-evolution/blob/main/proposals/0444-member-import-visibility.md + settings.append(.enableUpcomingFeature("MemberImportVisibility")) - // https://github.com/swiftlang/swift-evolution/blob/main/proposals/0444-member-import-visibility.md - settings.append(.enableUpcomingFeature("MemberImportVisibility")) + // https://github.com/swiftlang/swift-evolution/blob/main/proposals/0409-access-level-on-imports.md + settings.append(.enableUpcomingFeature("InternalImportsByDefault")) - // https://github.com/swiftlang/swift-evolution/blob/main/proposals/0409-access-level-on-imports.md - settings.append(.enableUpcomingFeature("InternalImportsByDefault")) + settings.append(.enableExperimentalFeature("AvailabilityMacro=Configuration 1.0:macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0")) - target.swiftSettings = settings - } + target.swiftSettings = settings } if addDoccPlugin { diff --git a/Sources/Configuration/AccessReporter.swift b/Sources/Configuration/AccessReporter.swift index e02f951..2e8f52c 100644 --- a/Sources/Configuration/AccessReporter.swift +++ b/Sources/Configuration/AccessReporter.swift @@ -24,6 +24,7 @@ import Synchronization /// Access reporters track when configuration values are read, fetched, or watched, /// to provide visibility into configuration usage patterns. This is useful for /// debugging, auditing, and understanding configuration dependencies. +@available(Configuration 1.0, *) public protocol AccessReporter: Sendable { /// Processes a configuration access event. @@ -41,6 +42,7 @@ public protocol AccessReporter: Sendable { /// Access events are generated whenever configuration values are accessed through /// ``ConfigReader`` and ``ConfigSnapshotReader`` methods. They contain metadata about /// the access, results from individual providers, and the final outcome of the operation. +@available(Configuration 1.0, *) public struct AccessEvent: Sendable { /// Metadata describing the configuration access operation. @@ -184,6 +186,7 @@ public struct AccessEvent: Sendable { /// Use this reporter to send configuration access events to multiple destinations /// simultaneously. Each upstream reporter receives a copy of every event in the /// order they were provided during initialization. +@available(Configuration 1.0, *) public struct BroadcastingAccessReporter: Sendable { /// The reporters that receive forwarded events. @@ -198,6 +201,7 @@ public struct BroadcastingAccessReporter: Sendable { } } +@available(Configuration 1.0, *) extension BroadcastingAccessReporter: AccessReporter { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public func report(_ event: AccessEvent) { diff --git a/Sources/Configuration/AccessReporters/AccessLogger.swift b/Sources/Configuration/AccessReporters/AccessLogger.swift index 775f0c0..134c971 100644 --- a/Sources/Configuration/AccessReporters/AccessLogger.swift +++ b/Sources/Configuration/AccessReporters/AccessLogger.swift @@ -53,6 +53,7 @@ import Synchronization /// - `value`: The resolved configuration value (redacted for secrets) /// - `counter`: An incrementing counter for tracking access frequency /// - Provider-specific information for each provider in the hierarchy +@available(Configuration 1.0, *) public final class AccessLogger: Sendable { /// The logger used to emit configuration access events. @@ -94,6 +95,7 @@ public final class AccessLogger: Sendable { } } +@available(Configuration 1.0, *) extension AccessLogger: AccessReporter { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public func report(_ event: AccessEvent) { @@ -109,6 +111,7 @@ extension AccessLogger: AccessReporter { } } +@available(Configuration 1.0, *) extension AccessEvent.Metadata { /// Add log metadata. /// - Parameter metadata: The metadata to which to add values. @@ -119,6 +122,7 @@ extension AccessEvent.Metadata { } } +@available(Configuration 1.0, *) extension AccessEvent.ProviderResult { /// Add log metadata. /// - Parameters: @@ -136,6 +140,7 @@ extension AccessEvent.ProviderResult { } } +@available(Configuration 1.0, *) extension AccessEvent { /// Add log metadata. /// - Parameter metadata: The metadata to which to add values. @@ -151,6 +156,7 @@ extension AccessEvent { } } +@available(Configuration 1.0, *) extension Result { /// Add log metadata. /// - Parameter metadata: The metadata to which to add values. diff --git a/Sources/Configuration/AccessReporters/FileAccessLogger.swift b/Sources/Configuration/AccessReporters/FileAccessLogger.swift index df97530..663369a 100644 --- a/Sources/Configuration/AccessReporters/FileAccessLogger.swift +++ b/Sources/Configuration/AccessReporters/FileAccessLogger.swift @@ -64,6 +64,7 @@ import Synchronization /// - Resolved value (redacted for secrets) /// - Provider that supplied the value or error information /// - Access metadata (operation type, value type, source location, timestamp) +@available(Configuration 1.0, *) public final class FileAccessLogger: Sendable { /// The file descriptor used for writing access events to the log file. @@ -199,6 +200,7 @@ public final class FileAccessLogger: Sendable { } } +@available(Configuration 1.0, *) extension FileAccessLogger: AccessReporter { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public func report(_ event: AccessEvent) { @@ -213,6 +215,7 @@ extension FileAccessLogger: AccessReporter { } } +@available(Configuration 1.0, *) extension FileAccessLogger { /// Renders a string summary for the event. /// - Parameter event: The event to render. @@ -222,6 +225,7 @@ extension FileAccessLogger { } } +@available(Configuration 1.0, *) extension AccessEvent { /// Returns a human-readable single line string summarizing the access event. /// - Parameter dateFormatStyle: The format style used for rendering dates. @@ -280,6 +284,7 @@ extension AccessEvent { } } +@available(Configuration 1.0, *) extension ConfigContent { /// Returns a string representation of the config value, formatting complex types appropriately. /// diff --git a/Sources/Configuration/ConfigProvider.swift b/Sources/Configuration/ConfigProvider.swift index 32d535d..ae2d23f 100644 --- a/Sources/Configuration/ConfigProvider.swift +++ b/Sources/Configuration/ConfigProvider.swift @@ -45,6 +45,7 @@ /// /// **Dynamic providers**: Implement `watch` methods to emit real-time updates from /// polling, file system monitoring, or other change detection mechanisms. +@available(Configuration 1.0, *) public protocol ConfigProvider: Sendable { /// The human-readable name of the configuration provider. @@ -137,6 +138,7 @@ public protocol ConfigProvider: Sendable { /// Snapshots enable consistent reads of multiple related configuration keys by /// capturing the provider's state at a specific moment. This prevents the underlying /// data from changing between individual key lookups. +@available(Configuration 1.0, *) public protocol ConfigSnapshotProtocol: Sendable { /// The human-readable name of the configuration provider that created this snapshot. @@ -159,6 +161,7 @@ public protocol ConfigSnapshotProtocol: Sendable { } /// The result of looking up a configuration value in a provider. +@available(Configuration 1.0, *) public struct LookupResult: Sendable, Equatable, Hashable { /// The provider-specific encoding of the configuration key. @@ -181,6 +184,7 @@ public struct LookupResult: Sendable, Equatable, Hashable { } /// The supported configuration value types. +@available(Configuration 1.0, *) @frozen public enum ConfigType: String, Sendable, Equatable, Hashable { /// A string value. @@ -215,6 +219,7 @@ public struct LookupResult: Sendable, Equatable, Hashable { } /// The raw content of a configuration value. +@available(Configuration 1.0, *) @frozen public enum ConfigContent: Sendable, Equatable, Hashable { /// A string value. @@ -433,6 +438,7 @@ public struct LookupResult: Sendable, Equatable, Hashable { /// Configuration values include the actual content and a flag indicating whether /// the value contains sensitive information. Secret values are protected from /// accidental disclosure in logs and debug output. +@available(Configuration 1.0, *) public struct ConfigValue: Sendable, Equatable, Hashable { /// The configuration content. @@ -451,6 +457,7 @@ public struct ConfigValue: Sendable, Equatable, Hashable { } } +@available(Configuration 1.0, *) extension ConfigValue: CustomStringConvertible { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var description: String { @@ -462,6 +469,7 @@ extension ConfigValue: CustomStringConvertible { } } +@available(Configuration 1.0, *) extension ConfigValue: ExpressibleByStringLiteral { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public init(stringLiteral value: String) { @@ -469,6 +477,7 @@ extension ConfigValue: ExpressibleByStringLiteral { } } +@available(Configuration 1.0, *) extension ConfigContent: ExpressibleByStringLiteral { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public init(stringLiteral value: String) { @@ -476,6 +485,7 @@ extension ConfigContent: ExpressibleByStringLiteral { } } +@available(Configuration 1.0, *) extension ConfigValue: ExpressibleByIntegerLiteral { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public init(integerLiteral value: Int) { @@ -483,6 +493,7 @@ extension ConfigValue: ExpressibleByIntegerLiteral { } } +@available(Configuration 1.0, *) extension ConfigContent: ExpressibleByIntegerLiteral { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public init(integerLiteral value: Int) { @@ -490,6 +501,7 @@ extension ConfigContent: ExpressibleByIntegerLiteral { } } +@available(Configuration 1.0, *) extension ConfigValue: ExpressibleByFloatLiteral { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public init(floatLiteral value: Double) { @@ -497,6 +509,7 @@ extension ConfigValue: ExpressibleByFloatLiteral { } } +@available(Configuration 1.0, *) extension ConfigContent: ExpressibleByFloatLiteral { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public init(floatLiteral value: Double) { @@ -504,6 +517,7 @@ extension ConfigContent: ExpressibleByFloatLiteral { } } +@available(Configuration 1.0, *) extension ConfigValue: ExpressibleByBooleanLiteral { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public init(booleanLiteral value: Bool) { @@ -511,6 +525,7 @@ extension ConfigValue: ExpressibleByBooleanLiteral { } } +@available(Configuration 1.0, *) extension ConfigContent: ExpressibleByBooleanLiteral { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public init(booleanLiteral value: Bool) { diff --git a/Sources/Configuration/ConfigProviderHelpers.swift b/Sources/Configuration/ConfigProviderHelpers.swift index eff1f01..3dbef54 100644 --- a/Sources/Configuration/ConfigProviderHelpers.swift +++ b/Sources/Configuration/ConfigProviderHelpers.swift @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +@available(Configuration 1.0, *) extension ConfigProvider { /// Implements `watchValue` by getting the current value and emitting it immediately. @@ -116,6 +117,7 @@ extension ConfigProvider { /// - work: A closure that performs the value lookup and returns the result. /// - Returns: A lookup result containing the encoded key and the value from the closure. /// - Throws: Rethrows any errors thrown by the provided closure. +@available(Configuration 1.0, *) package func withConfigValueLookup( encodedKey: String, work: () throws(Failure) -> ConfigValue? @@ -147,6 +149,7 @@ package func withConfigValueLookup( /// - work: An async closure that performs the value lookup and returns the result. /// - Returns: A lookup result containing the encoded key and the value from the closure. /// - Throws: Rethrows any errors thrown by the provided closure. +@available(Configuration 1.0, *) package func withConfigValueLookup( encodedKey: String, work: () async throws(Failure) -> ConfigValue? diff --git a/Sources/Configuration/ConfigReader+internalHelpers.swift b/Sources/Configuration/ConfigReader+internalHelpers.swift index 73eb282..2ff226e 100644 --- a/Sources/Configuration/ConfigReader+internalHelpers.swift +++ b/Sources/Configuration/ConfigReader+internalHelpers.swift @@ -18,6 +18,7 @@ import FoundationEssentials import Foundation #endif +@available(Configuration 1.0, *) extension ConfigValue { /// Returns a copy of the config value marked as secret. /// @@ -29,6 +30,7 @@ extension ConfigValue { } } +@available(Configuration 1.0, *) extension Result { /// Returns a copy of the result with the value marked as secret. /// @@ -38,6 +40,7 @@ extension Result { } } +@available(Configuration 1.0, *) extension LookupResult { /// Returns a copy of the config value marked as secret. /// @@ -49,6 +52,7 @@ extension LookupResult { } } +@available(Configuration 1.0, *) extension Result { /// Returns a copy of the result with the value marked as secret. /// @@ -58,6 +62,7 @@ extension Result { } } +@available(Configuration 1.0, *) extension AccessEvent.ProviderResult { /// Returns a copy of the result marked as secret. /// @@ -80,6 +85,7 @@ extension AccessEvent.ProviderResult { /// - isSecret: Whether to mark the values as secret. /// - tuple: A tuple containing provider results and a configuration value result. /// - Returns: The tuple with values marked as secret if the flag is true, otherwise unchanged. +@available(Configuration 1.0, *) private func mergingIsSecret( _ isSecret: Bool, _ tuple: ([AccessEvent.ProviderResult], Result) @@ -121,6 +127,7 @@ private func mergingIsSecret( /// - fileID: Source file identifier for access event metadata. /// - line: Source line number for access event metadata. /// - Returns: The converted configuration value, or `nil` if not found or conversion fails. +@available(Configuration 1.0, *) internal func valueFromReader( forKey key: ConfigKey, type: ConfigType, @@ -193,6 +200,7 @@ internal func valueFromReader( /// - fileID: Source file identifier used for event reporting. /// - line: Source line number used for event reporting. /// - Returns: The configuration value converted to the requested type. +@available(Configuration 1.0, *) internal func valueFromReader( forKey key: ConfigKey, type: ConfigType, @@ -269,6 +277,7 @@ internal func valueFromReader( /// - Throws: `ConfigError.missingRequiredConfigValue` if the configuration value is not found, or any error thrown /// by the `unwrap` closure if conversion fails. /// - Returns: The configuration value converted to the requested type. +@available(Configuration 1.0, *) internal func requiredValueFromReader( forKey key: ConfigKey, type: ConfigType, @@ -324,6 +333,7 @@ internal func requiredValueFromReader( return try finalResult.get().0 } +@available(Configuration 1.0, *) extension ConfigReader { /// Gets a config value synchronously. diff --git a/Sources/Configuration/ConfigReader+methods.swift b/Sources/Configuration/ConfigReader+methods.swift index e062762..d63d762 100644 --- a/Sources/Configuration/ConfigReader+methods.swift +++ b/Sources/Configuration/ConfigReader+methods.swift @@ -18,6 +18,7 @@ // # # // ############################################################################# +@available(Configuration 1.0, *) extension ConfigReader { // MARK: - Get diff --git a/Sources/Configuration/ConfigReader+methods.swift.gyb b/Sources/Configuration/ConfigReader+methods.swift.gyb index 8b6b03c..4204569 100644 --- a/Sources/Configuration/ConfigReader+methods.swift.gyb +++ b/Sources/Configuration/ConfigReader+methods.swift.gyb @@ -16,6 +16,7 @@ from gyb_utils import * }% ${autogenerated_warning()} +@available(Configuration 1.0, *) extension ConfigReader { // MARK: - Get diff --git a/Sources/Configuration/ConfigReader.swift b/Sources/Configuration/ConfigReader.swift index 50cb4de..fc5b41b 100644 --- a/Sources/Configuration/ConfigReader.swift +++ b/Sources/Configuration/ConfigReader.swift @@ -235,6 +235,7 @@ import Foundation /// /// The library reports all provider errors to the access reporter through the `providerResults` array, /// even when handled gracefully. +@available(Configuration 1.0, *) public struct ConfigReader: Sendable { /// The key prefix prepended to all configuration lookups. @@ -324,6 +325,7 @@ public struct ConfigReader: Sendable { } } +@available(Configuration 1.0, *) extension ConfigReader { /// Creates a config reader with a single provider. @@ -411,6 +413,7 @@ extension ConfigReader { // MARK: - Internal conveniences +@available(Configuration 1.0, *) extension ConfigReader { /// The decoder the library uses to convert string keys into config keys. @@ -434,6 +437,7 @@ extension ConfigReader { /// An error thrown by Configuration module types. /// /// These errors indicate issues with configuration value retrieval or conversion. +@available(Configuration 1.0, *) package enum ConfigError: Error, CustomStringConvertible, Equatable { /// A required configuration value was not found in any provider. diff --git a/Sources/Configuration/ConfigSnapshotReader+methods.swift b/Sources/Configuration/ConfigSnapshotReader+methods.swift index dd04aae..f9f1fcf 100644 --- a/Sources/Configuration/ConfigSnapshotReader+methods.swift +++ b/Sources/Configuration/ConfigSnapshotReader+methods.swift @@ -18,6 +18,7 @@ // # # // ############################################################################# +@available(Configuration 1.0, *) extension ConfigSnapshotReader { // MARK: - Get diff --git a/Sources/Configuration/ConfigSnapshotReader+methods.swift.gyb b/Sources/Configuration/ConfigSnapshotReader+methods.swift.gyb index 2f2d4f1..e63723a 100644 --- a/Sources/Configuration/ConfigSnapshotReader+methods.swift.gyb +++ b/Sources/Configuration/ConfigSnapshotReader+methods.swift.gyb @@ -16,6 +16,7 @@ from gyb_utils import * }% ${autogenerated_warning()} +@available(Configuration 1.0, *) extension ConfigSnapshotReader { // MARK: - Get diff --git a/Sources/Configuration/ConfigSnapshotReader.swift b/Sources/Configuration/ConfigSnapshotReader.swift index 3e749f5..f3820a9 100644 --- a/Sources/Configuration/ConfigSnapshotReader.swift +++ b/Sources/Configuration/ConfigSnapshotReader.swift @@ -150,6 +150,7 @@ import Synchronization /// When reading from a snapshot, access events are reported to the access reporter from the /// original config reader. This helps debug which config values are accessed, even when /// reading from snapshots. +@available(Configuration 1.0, *) public struct ConfigSnapshotReader: Sendable { /// The prefix of the key for accessing config values in the provider. @@ -294,6 +295,7 @@ public struct ConfigSnapshotReader: Sendable { } } +@available(Configuration 1.0, *) extension ConfigReader { /// Provides a snapshot of the current configuration state and passes it to the provided closure. /// @@ -380,6 +382,7 @@ extension ConfigReader { } } +@available(Configuration 1.0, *) extension ConfigSnapshotReader { /// Gets a value from the snapshot. /// diff --git a/Sources/Configuration/ExpressibleByConfigString.swift b/Sources/Configuration/ExpressibleByConfigString.swift index 84fe529..40948b5 100644 --- a/Sources/Configuration/ExpressibleByConfigString.swift +++ b/Sources/Configuration/ExpressibleByConfigString.swift @@ -57,6 +57,7 @@ public import SystemPackage /// - `Foundation.URL` - Converts from URL strings. /// - `Foundation.UUID` - Converts from UUID strings. /// - `Foundation.Date` - Converts from ISO8601 date strings. +@available(Configuration 1.0, *) public protocol ExpressibleByConfigString: CustomStringConvertible { /// Creates an instance from a configuration string value. @@ -65,6 +66,7 @@ public protocol ExpressibleByConfigString: CustomStringConvertible { init?(configString: String) } +@available(Configuration 1.0, *) extension URL: ExpressibleByConfigString { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public init?(configString: String) { @@ -72,6 +74,7 @@ extension URL: ExpressibleByConfigString { } } +@available(Configuration 1.0, *) extension FilePath: ExpressibleByConfigString { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public init?(configString: String) { @@ -79,6 +82,7 @@ extension FilePath: ExpressibleByConfigString { } } +@available(Configuration 1.0, *) extension UUID: ExpressibleByConfigString { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public init?(configString: String) { @@ -86,6 +90,7 @@ extension UUID: ExpressibleByConfigString { } } +@available(Configuration 1.0, *) extension Date: ExpressibleByConfigString { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public init?(configString: String) { diff --git a/Sources/Configuration/KeyCoders/SeparatorKeyDecoder.swift b/Sources/Configuration/KeyCoders/SeparatorKeyDecoder.swift index dc0b007..0748a94 100644 --- a/Sources/Configuration/KeyCoders/SeparatorKeyDecoder.swift +++ b/Sources/Configuration/KeyCoders/SeparatorKeyDecoder.swift @@ -34,6 +34,7 @@ /// let dotDecoder = ConfigKeyDecoder.dotSeparated /// let colonDecoder = ConfigKeyDecoder.colonSeparated /// ``` +@available(Configuration 1.0, *) public struct SeparatorKeyDecoder: Sendable { /// The string used to separate key components. @@ -56,6 +57,7 @@ public struct SeparatorKeyDecoder: Sendable { } } +@available(Configuration 1.0, *) extension SeparatorKeyDecoder: ConfigKeyDecoder { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public func decode(_ string: String, context: [String: ConfigContextValue]) -> ConfigKey { @@ -63,6 +65,7 @@ extension SeparatorKeyDecoder: ConfigKeyDecoder { } } +@available(Configuration 1.0, *) extension ConfigKeyDecoder where Self == SeparatorKeyDecoder { /// A decoder that uses dot notation for hierarchical keys. /// diff --git a/Sources/Configuration/MultiProvider.swift b/Sources/Configuration/MultiProvider.swift index 2379b44..4770473 100644 --- a/Sources/Configuration/MultiProvider.swift +++ b/Sources/Configuration/MultiProvider.swift @@ -53,6 +53,7 @@ import Synchronization /// /// When any nested provider throws an error, the error is immediately propagated to the caller rather than /// being ignored. This ensures predictable behavior and prevents silent failures that could mask configuration issues. +@available(Configuration 1.0, *) internal struct MultiProvider: Sendable { /// The underlying storage. @@ -72,6 +73,7 @@ internal struct MultiProvider: Sendable { } } +@available(Configuration 1.0, *) extension MultiProvider: CustomStringConvertible { /// A text description of the multi provider. var description: String { @@ -83,6 +85,7 @@ extension MultiProvider: CustomStringConvertible { /// /// This snapshot aggregates the individual snapshots from each nested provider, allowing for /// consistent value resolution across the entire provider hierarchy at a specific moment in time. +@available(Configuration 1.0, *) struct MultiSnapshot { /// The individual snapshots from each nested provider, maintained in precedence order. @@ -121,6 +124,7 @@ struct MultiSnapshot { } } +@available(Configuration 1.0, *) extension MultiProvider { /// Synchronously resolves a configuration value from nested providers. diff --git a/Sources/Configuration/Providers/CLI/CLISnapshot.swift b/Sources/Configuration/Providers/CLI/CLISnapshot.swift index 41c9382..0a2e321 100644 --- a/Sources/Configuration/Providers/CLI/CLISnapshot.swift +++ b/Sources/Configuration/Providers/CLI/CLISnapshot.swift @@ -42,6 +42,7 @@ import Foundation /// // CLI: --hosts server1 server2 server3 /// snapshot.value(forKey: hostsKey, type: .stringArray) // -> ["server1", "server2", "server3"] /// ``` +@available(Configuration 1.0, *) internal struct CLISnapshot { /// The name of the provider that created this snapshot. @@ -153,6 +154,7 @@ internal struct CLISnapshot { } } +@available(Configuration 1.0, *) extension CLISnapshot: ConfigSnapshotProtocol { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation func value(forKey key: AbsoluteConfigKey, type: ConfigType) throws -> LookupResult { diff --git a/Sources/Configuration/Providers/CLI/CommandLineArgumentsProvider.swift b/Sources/Configuration/Providers/CLI/CommandLineArgumentsProvider.swift index 0fc1e4b..08186bd 100644 --- a/Sources/Configuration/Providers/CLI/CommandLineArgumentsProvider.swift +++ b/Sources/Configuration/Providers/CLI/CommandLineArgumentsProvider.swift @@ -70,6 +70,7 @@ /// secretsSpecifier: .dynamic { key, _ in key.contains("--secret") } /// ) /// ``` +@available(Configuration 1.0, *) public struct CommandLineArgumentsProvider { /// The underlying snapshot containing the parsed CLI arguments. @@ -105,6 +106,7 @@ public struct CommandLineArgumentsProvider { } } +@available(Configuration 1.0, *) extension CommandLineArgumentsProvider: CustomStringConvertible { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var description: String { @@ -112,6 +114,7 @@ extension CommandLineArgumentsProvider: CustomStringConvertible { } } +@available(Configuration 1.0, *) extension CommandLineArgumentsProvider: CustomDebugStringConvertible { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var debugDescription: String { @@ -126,6 +129,7 @@ extension CommandLineArgumentsProvider: CustomDebugStringConvertible { } } +@available(Configuration 1.0, *) extension CommandLineArgumentsProvider: ConfigProvider { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var providerName: String { diff --git a/Sources/Configuration/Providers/Common/CommonProviderFileSystem.swift b/Sources/Configuration/Providers/Common/CommonProviderFileSystem.swift index 2c9fe0e..6d95709 100644 --- a/Sources/Configuration/Providers/Common/CommonProviderFileSystem.swift +++ b/Sources/Configuration/Providers/Common/CommonProviderFileSystem.swift @@ -20,6 +20,7 @@ package import Foundation package import SystemPackage /// A file system abstraction used by some of the providers in Configuration. +@available(Configuration 1.0, *) package protocol CommonProviderFileSystem: Sendable { /// Loads the file contents at the specified file path. /// - Parameter filePath: The path to the file. @@ -49,6 +50,7 @@ package protocol CommonProviderFileSystem: Sendable { } /// A file system implementation that uses the local file system. +@available(Configuration 1.0, *) package struct LocalCommonProviderFileSystem: Sendable { /// The error thrown by the file system. package enum FileSystemError: Error, CustomStringConvertible { @@ -79,6 +81,7 @@ package struct LocalCommonProviderFileSystem: Sendable { } } +@available(Configuration 1.0, *) extension LocalCommonProviderFileSystem: CommonProviderFileSystem { package func fileContents(atPath filePath: FilePath) async throws -> Data { do { diff --git a/Sources/Configuration/Providers/Common/ReloadingFileProviderCore.swift b/Sources/Configuration/Providers/Common/ReloadingFileProviderCore.swift index 41ee226..afa7507 100644 --- a/Sources/Configuration/Providers/Common/ReloadingFileProviderCore.swift +++ b/Sources/Configuration/Providers/Common/ReloadingFileProviderCore.swift @@ -31,6 +31,7 @@ import SystemPackage /// This internal type handles all the common reloading logic, state management, /// and service lifecycle for reloading file-based providers. It allows different provider types /// (JSON, YAML, and so on) to reuse the same logic while providing their own format-specific deserialization. +@available(Configuration 1.0, *) internal final class ReloadingFileProviderCore: Sendable { /// The internal storage structure for the provider state. @@ -312,6 +313,7 @@ internal final class ReloadingFileProviderCore LookupResult { diff --git a/Sources/Configuration/Providers/EnvironmentVariables/EnvironmentFileParser.swift b/Sources/Configuration/Providers/EnvironmentVariables/EnvironmentFileParser.swift index 3be21dd..48c3661 100644 --- a/Sources/Configuration/Providers/EnvironmentVariables/EnvironmentFileParser.swift +++ b/Sources/Configuration/Providers/EnvironmentVariables/EnvironmentFileParser.swift @@ -45,6 +45,7 @@ import Foundation /// - Lines where the key is empty (starts with `=`) are ignored /// - When duplicate keys are found, the last occurrence takes precedence /// - Values can contain `=` characters (only the first `=` is used as separator) +@available(Configuration 1.0, *) struct EnvironmentFileParser { /// Parses environment file contents into a dictionary of key-value pairs. /// diff --git a/Sources/Configuration/Providers/EnvironmentVariables/EnvironmentVariablesProvider.swift b/Sources/Configuration/Providers/EnvironmentVariables/EnvironmentVariablesProvider.swift index 6dd7cf0..aeabb03 100644 --- a/Sources/Configuration/Providers/EnvironmentVariables/EnvironmentVariablesProvider.swift +++ b/Sources/Configuration/Providers/EnvironmentVariables/EnvironmentVariablesProvider.swift @@ -116,6 +116,7 @@ import WASILibc /// ### Config context /// /// The environment variables provider ignores the context passed in ``AbsoluteConfigKey/context``. +@available(Configuration 1.0, *) public struct EnvironmentVariablesProvider: Sendable { /// An environment variable value with a flag of whether it's secret. @@ -302,6 +303,7 @@ public struct EnvironmentVariablesProvider: Sendable { /// A decoder of environment variable arrays. /// /// Parses a string by splitting by the specified character and trimming the components. +@available(Configuration 1.0, *) internal struct EnvironmentValueArrayDecoder { /// The separator used to split the string into an array. @@ -332,6 +334,7 @@ extension Error { } } +@available(Configuration 1.0, *) extension EnvironmentVariablesProvider: CustomStringConvertible { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var description: String { @@ -339,6 +342,7 @@ extension EnvironmentVariablesProvider: CustomStringConvertible { } } +@available(Configuration 1.0, *) extension EnvironmentVariablesProvider: CustomDebugStringConvertible { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var debugDescription: String { @@ -350,6 +354,7 @@ extension EnvironmentVariablesProvider: CustomDebugStringConvertible { } } +@available(Configuration 1.0, *) extension EnvironmentVariablesProvider.Snapshot { /// Parses a config value from the provided raw string value. /// - Parameters: @@ -436,6 +441,7 @@ extension EnvironmentVariablesProvider.Snapshot { } } +@available(Configuration 1.0, *) extension EnvironmentVariablesProvider.Snapshot: ConfigSnapshotProtocol { func value( forKey key: AbsoluteConfigKey, @@ -456,6 +462,7 @@ extension EnvironmentVariablesProvider.Snapshot: ConfigSnapshotProtocol { } } +@available(Configuration 1.0, *) extension EnvironmentVariablesProvider: ConfigProvider { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var providerName: String { diff --git a/Sources/Configuration/Providers/Files/DirectoryFilesProvider.swift b/Sources/Configuration/Providers/Files/DirectoryFilesProvider.swift index 6fc9ce5..b5b0ff5 100644 --- a/Sources/Configuration/Providers/Files/DirectoryFilesProvider.swift +++ b/Sources/Configuration/Providers/Files/DirectoryFilesProvider.swift @@ -125,6 +125,7 @@ public import SystemPackage /// /// This provider ignores the context passed in ``AbsoluteConfigKey/context``. /// All keys are resolved using only their component path. +@available(Configuration 1.0, *) public struct DirectoryFilesProvider: Sendable { /// A file value with metadata. @@ -254,6 +255,7 @@ public struct DirectoryFilesProvider: Sendable { /// A decoder of file content arrays. /// /// Parses a string by splitting by the specified character and trimming the components. +@available(Configuration 1.0, *) internal struct DirectoryFilesValueArrayDecoder { /// The separator used to split the string into an array. @@ -267,6 +269,7 @@ internal struct DirectoryFilesValueArrayDecoder { } } +@available(Configuration 1.0, *) extension DirectoryFilesProvider: CustomStringConvertible { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var description: String { @@ -274,6 +277,7 @@ extension DirectoryFilesProvider: CustomStringConvertible { } } +@available(Configuration 1.0, *) extension DirectoryFilesProvider: CustomDebugStringConvertible { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var debugDescription: String { @@ -294,6 +298,7 @@ extension DirectoryFilesProvider: CustomDebugStringConvertible { } } +@available(Configuration 1.0, *) extension DirectoryFilesProvider.Snapshot { /// Parses a config value from the provided file value. /// - Parameters: @@ -375,6 +380,7 @@ extension DirectoryFilesProvider.Snapshot { } } +@available(Configuration 1.0, *) extension DirectoryFilesProvider.Snapshot: ConfigSnapshotProtocol { func value( forKey key: AbsoluteConfigKey, @@ -394,6 +400,7 @@ extension DirectoryFilesProvider.Snapshot: ConfigSnapshotProtocol { } } +@available(Configuration 1.0, *) extension DirectoryFilesProvider: ConfigProvider { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var providerName: String { @@ -443,11 +450,13 @@ extension DirectoryFilesProvider: ConfigProvider { /// Configuration keys are transformed into file names using these rules: /// - Components are joined with dashes /// - Non-alphanumeric characters (except dashes) are replaced with underscores +@available(Configuration 1.0, *) public struct DirectoryFileKeyEncoder { /// Creates a default directory key encoder that follows standard file naming conventions. public init() {} } +@available(Configuration 1.0, *) extension DirectoryFileKeyEncoder: ConfigKeyEncoder { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public func encode(_ key: AbsoluteConfigKey) -> String { @@ -468,6 +477,7 @@ extension DirectoryFileKeyEncoder: ConfigKeyEncoder { } } +@available(Configuration 1.0, *) extension ConfigKeyEncoder where Self == DirectoryFileKeyEncoder { /// An encoder that uses directory paths for hierarachical key encoder. /// diff --git a/Sources/Configuration/Providers/InMemory/InMemoryProvider.swift b/Sources/Configuration/Providers/InMemory/InMemoryProvider.swift index 40a02b1..b5c53ba 100644 --- a/Sources/Configuration/Providers/InMemory/InMemoryProvider.swift +++ b/Sources/Configuration/Providers/InMemory/InMemoryProvider.swift @@ -55,6 +55,7 @@ /// ``` /// /// To learn more about the in-memory providers, check out . +@available(Configuration 1.0, *) public struct InMemoryProvider: Sendable { /// The underlying snapshot of the internal state of the provider. @@ -106,6 +107,7 @@ public struct InMemoryProvider: Sendable { } } +@available(Configuration 1.0, *) extension InMemoryProvider { /// Creates a new in-memory provider from string keys and configuration values. @@ -150,6 +152,7 @@ extension InMemoryProvider { } } +@available(Configuration 1.0, *) extension InMemoryProvider: CustomStringConvertible { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var description: String { @@ -157,6 +160,7 @@ extension InMemoryProvider: CustomStringConvertible { } } +@available(Configuration 1.0, *) extension InMemoryProvider: CustomDebugStringConvertible { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var debugDescription: String { @@ -169,6 +173,7 @@ extension InMemoryProvider: CustomDebugStringConvertible { } } +@available(Configuration 1.0, *) extension InMemoryProvider.Snapshot: ConfigSnapshotProtocol { func value( forKey key: AbsoluteConfigKey, @@ -186,6 +191,7 @@ extension InMemoryProvider.Snapshot: ConfigSnapshotProtocol { } } +@available(Configuration 1.0, *) extension InMemoryProvider: ConfigProvider { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var providerName: String { diff --git a/Sources/Configuration/Providers/InMemory/MutableInMemoryProvider.swift b/Sources/Configuration/Providers/InMemory/MutableInMemoryProvider.swift index d9f2dcc..0173a88 100644 --- a/Sources/Configuration/Providers/InMemory/MutableInMemoryProvider.swift +++ b/Sources/Configuration/Providers/InMemory/MutableInMemoryProvider.swift @@ -68,6 +68,7 @@ import Foundation /// ``` /// /// To learn more about the in-memory providers, check out . +@available(Configuration 1.0, *) public final class MutableInMemoryProvider: Sendable { /// The name of this instance of the provider. @@ -143,6 +144,7 @@ public final class MutableInMemoryProvider: Sendable { } } +@available(Configuration 1.0, *) extension MutableInMemoryProvider { /// Creates a new mutable in-memory provider from string keys and initial values. @@ -270,6 +272,7 @@ extension MutableInMemoryProvider { } } +@available(Configuration 1.0, *) extension MutableInMemoryProvider: CustomStringConvertible { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var description: String { @@ -282,6 +285,7 @@ extension MutableInMemoryProvider: CustomStringConvertible { } } +@available(Configuration 1.0, *) extension MutableInMemoryProvider: CustomDebugStringConvertible { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var debugDescription: String { @@ -299,6 +303,7 @@ extension MutableInMemoryProvider: CustomDebugStringConvertible { } } +@available(Configuration 1.0, *) extension MutableInMemoryProvider.Storage { /// Returns the number of current watchers, summing value and snapshot watchers. func watcherCount() -> Int { @@ -306,6 +311,7 @@ extension MutableInMemoryProvider.Storage { } } +@available(Configuration 1.0, *) extension MutableInMemoryProvider { /// Adds a continuation that gets notified of new values for the provided key. /// - Parameters: @@ -366,6 +372,7 @@ extension MutableInMemoryProvider { } } +@available(Configuration 1.0, *) extension MutableInMemoryProvider.Snapshot: ConfigSnapshotProtocol { func value(forKey key: AbsoluteConfigKey, type: ConfigType) throws -> LookupResult { try MutableInMemoryProvider.parseValue( @@ -383,6 +390,7 @@ private func providerNameFromName(_ name: String?) -> String { "MutableInMemoryProvider\(name.map { "[\($0)]" } ?? "")" } +@available(Configuration 1.0, *) extension MutableInMemoryProvider: ConfigProvider { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var providerName: String { diff --git a/Sources/Configuration/Providers/JSON/JSONProvider.swift b/Sources/Configuration/Providers/JSON/JSONProvider.swift index eaa6466..52de70e 100644 --- a/Sources/Configuration/Providers/JSON/JSONProvider.swift +++ b/Sources/Configuration/Providers/JSON/JSONProvider.swift @@ -83,6 +83,7 @@ import Foundation /// /// This provider ignores the context passed in ``AbsoluteConfigKey/context``. /// All keys are resolved using only their component path. +@available(Configuration 1.0, *) public struct JSONProvider: Sendable { /// A snapshot of the internal state. @@ -181,6 +182,7 @@ public struct JSONProvider: Sendable { } } +@available(Configuration 1.0, *) extension JSONProvider: CustomStringConvertible { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var description: String { @@ -188,6 +190,7 @@ extension JSONProvider: CustomStringConvertible { } } +@available(Configuration 1.0, *) extension JSONProvider: CustomDebugStringConvertible { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var debugDescription: String { @@ -199,6 +202,7 @@ extension JSONProvider: CustomDebugStringConvertible { } } +@available(Configuration 1.0, *) extension JSONProvider: ConfigProvider { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var providerName: String { diff --git a/Sources/Configuration/Providers/JSON/JSONProviderSnapshot.swift b/Sources/Configuration/Providers/JSON/JSONProviderSnapshot.swift index 32ee4b1..07253f4 100644 --- a/Sources/Configuration/Providers/JSON/JSONProviderSnapshot.swift +++ b/Sources/Configuration/Providers/JSON/JSONProviderSnapshot.swift @@ -23,6 +23,7 @@ import Foundation /// /// This structure represents a point-in-time view of configuration values. It handles /// the conversion from JSON types to configuration value types. +@available(Configuration 1.0, *) internal struct JSONProviderSnapshot { /// The key encoder for JSON. static let keyEncoder: SeparatorKeyEncoder = .dotSeparated @@ -300,6 +301,7 @@ internal struct JSONProviderSnapshot { } } +@available(Configuration 1.0, *) extension JSONProviderSnapshot: ConfigSnapshotProtocol { var providerName: String { "JSONProvider" @@ -324,6 +326,7 @@ extension JSONProviderSnapshot: ConfigSnapshotProtocol { /// - secretsSpecifier: The secrets specifier. /// - Throws: When parsing fails. /// - Returns: The parsed and validated JSON config values. +@available(Configuration 1.0, *) internal func parseValues( _ parsedDictionary: [String: any Sendable], keyEncoder: some ConfigKeyEncoder, diff --git a/Sources/Configuration/Providers/JSON/ReloadingJSONProvider.swift b/Sources/Configuration/Providers/JSON/ReloadingJSONProvider.swift index 2ee16ed..df6ce8f 100644 --- a/Sources/Configuration/Providers/JSON/ReloadingJSONProvider.swift +++ b/Sources/Configuration/Providers/JSON/ReloadingJSONProvider.swift @@ -59,6 +59,7 @@ import Foundation /// Check out ``JSONProvider`` to learn more about using JSON for configuration. ``ReloadingJSONProvider`` is /// a reloading variant of ``JSONProvider`` that otherwise follows the same behavior for handling secrets, /// key and context mapping, and so on. +@available(Configuration 1.0, *) public final class ReloadingJSONProvider: Sendable { /// The core implementation that handles all reloading logic. @@ -203,6 +204,7 @@ public final class ReloadingJSONProvider: Sendable { } } +@available(Configuration 1.0, *) extension ReloadingJSONProvider: CustomStringConvertible { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var description: String { @@ -211,6 +213,7 @@ extension ReloadingJSONProvider: CustomStringConvertible { } } +@available(Configuration 1.0, *) extension ReloadingJSONProvider: CustomDebugStringConvertible { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var debugDescription: String { @@ -223,6 +226,7 @@ extension ReloadingJSONProvider: CustomDebugStringConvertible { } } +@available(Configuration 1.0, *) extension ReloadingJSONProvider: ConfigProvider { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var providerName: String { @@ -261,6 +265,7 @@ extension ReloadingJSONProvider: ConfigProvider { } } +@available(Configuration 1.0, *) extension ReloadingJSONProvider: Service { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public func run() async throws { diff --git a/Sources/Configuration/Providers/Wrappers/ConfigProvider+Operators.swift b/Sources/Configuration/Providers/Wrappers/ConfigProvider+Operators.swift index b8de87b..3bd028b 100644 --- a/Sources/Configuration/Providers/Wrappers/ConfigProvider+Operators.swift +++ b/Sources/Configuration/Providers/Wrappers/ConfigProvider+Operators.swift @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +@available(Configuration 1.0, *) extension ConfigProvider { /// Creates a new prefixed configuration provider. /// diff --git a/Sources/Configuration/Providers/Wrappers/KeyMappingProvider.swift b/Sources/Configuration/Providers/Wrappers/KeyMappingProvider.swift index 9ee7e5c..5357568 100644 --- a/Sources/Configuration/Providers/Wrappers/KeyMappingProvider.swift +++ b/Sources/Configuration/Providers/Wrappers/KeyMappingProvider.swift @@ -61,6 +61,7 @@ /// key.prepending(["myapp", "prod"]) /// } /// ``` +@available(Configuration 1.0, *) public struct KeyMappingProvider: Sendable { /// The mapping function applied to each key before a lookup. private let mapKey: @Sendable (AbsoluteConfigKey) -> AbsoluteConfigKey @@ -82,6 +83,7 @@ public struct KeyMappingProvider: Sendable { } } +@available(Configuration 1.0, *) extension KeyMappingProvider: ConfigProvider { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var providerName: String { @@ -132,6 +134,7 @@ extension KeyMappingProvider: ConfigProvider { } /// A configuration snapshot that maps all keys before delegating to an upstream snapshot. +@available(Configuration 1.0, *) private struct MappedKeySnapshot: ConfigSnapshotProtocol { /// The prefix key to prepend to all configuration keys. @@ -149,6 +152,7 @@ private struct MappedKeySnapshot: ConfigSnapshotProtocol { } } +@available(Configuration 1.0, *) extension KeyMappingProvider: CustomStringConvertible { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var description: String { @@ -156,6 +160,7 @@ extension KeyMappingProvider: CustomStringConvertible { } } +@available(Configuration 1.0, *) extension KeyMappingProvider: CustomDebugStringConvertible { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var debugDescription: String { diff --git a/Sources/Configuration/Providers/YAML/ReloadingYAMLProvider.swift b/Sources/Configuration/Providers/YAML/ReloadingYAMLProvider.swift index 85972d1..96c81fe 100644 --- a/Sources/Configuration/Providers/YAML/ReloadingYAMLProvider.swift +++ b/Sources/Configuration/Providers/YAML/ReloadingYAMLProvider.swift @@ -64,6 +64,7 @@ import Foundation /// Check out ``YAMLProvider`` to learn more about using YAML for configuration. ``ReloadingYAMLProvider`` is /// a reloading variant of ``YAMLProvider`` that otherwise follows the same behavior for handling secrets, /// key and context mapping, and so on. +@available(Configuration 1.0, *) public final class ReloadingYAMLProvider: Sendable { /// The core implementation that handles all reloading logic. @@ -207,6 +208,7 @@ public final class ReloadingYAMLProvider: Sendable { } } +@available(Configuration 1.0, *) extension ReloadingYAMLProvider: CustomStringConvertible { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var description: String { @@ -217,6 +219,7 @@ extension ReloadingYAMLProvider: CustomStringConvertible { } } +@available(Configuration 1.0, *) extension ReloadingYAMLProvider: CustomDebugStringConvertible { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var debugDescription: String { @@ -232,6 +235,7 @@ extension ReloadingYAMLProvider: CustomDebugStringConvertible { } } +@available(Configuration 1.0, *) extension ReloadingYAMLProvider: ConfigProvider { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var providerName: String { @@ -270,6 +274,7 @@ extension ReloadingYAMLProvider: ConfigProvider { } } +@available(Configuration 1.0, *) extension ReloadingYAMLProvider: Service { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public func run() async throws { diff --git a/Sources/Configuration/Providers/YAML/YAMLProvider.swift b/Sources/Configuration/Providers/YAML/YAMLProvider.swift index 63c5e56..99e56eb 100644 --- a/Sources/Configuration/Providers/YAML/YAMLProvider.swift +++ b/Sources/Configuration/Providers/YAML/YAMLProvider.swift @@ -86,6 +86,7 @@ import Foundation /// /// This provider ignores the context passed in ``AbsoluteConfigKey/context``. /// All keys are resolved using only their component path. +@available(Configuration 1.0, *) public struct YAMLProvider: Sendable { /// A snapshot of the internal state. @@ -184,6 +185,7 @@ public struct YAMLProvider: Sendable { } } +@available(Configuration 1.0, *) extension YAMLProvider: CustomStringConvertible { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var description: String { @@ -193,6 +195,7 @@ extension YAMLProvider: CustomStringConvertible { } } +@available(Configuration 1.0, *) extension YAMLProvider: CustomDebugStringConvertible { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var debugDescription: String { @@ -207,6 +210,7 @@ extension YAMLProvider: CustomDebugStringConvertible { } } +@available(Configuration 1.0, *) extension YAMLProvider: ConfigProvider { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public var providerName: String { diff --git a/Sources/Configuration/Providers/YAML/YAMLProviderSnapshot.swift b/Sources/Configuration/Providers/YAML/YAMLProviderSnapshot.swift index 4365d00..a50de00 100644 --- a/Sources/Configuration/Providers/YAML/YAMLProviderSnapshot.swift +++ b/Sources/Configuration/Providers/YAML/YAMLProviderSnapshot.swift @@ -27,6 +27,7 @@ import SystemPackage /// /// This class represents a point-in-time view of configuration values. It handles /// the conversion from YAML types to configuration value types. +@available(Configuration 1.0, *) final class YAMLProviderSnapshot: Sendable { /// The key encoder for YAML. private static let keyEncoder: SeparatorKeyEncoder = .dotSeparated @@ -238,6 +239,7 @@ final class YAMLProviderSnapshot: Sendable { } } +@available(Configuration 1.0, *) extension YAMLProviderSnapshot: ConfigSnapshotProtocol { var providerName: String { "YAMLProvider" @@ -268,6 +270,7 @@ extension YAMLProviderSnapshot: ConfigSnapshotProtocol { /// - secretsSpecifier: The secrets specifier. /// - Throws: When parsing fails. /// - Returns: The parsed and validated YAML config values. +@available(Configuration 1.0, *) internal func parseValues( _ parsedDictionary: Yams.Node.Mapping, keyEncoder: some ConfigKeyEncoder, diff --git a/Sources/Configuration/Utilities/AsyncSequences.swift b/Sources/Configuration/Utilities/AsyncSequences.swift index 23fb959..260a981 100644 --- a/Sources/Configuration/Utilities/AsyncSequences.swift +++ b/Sources/Configuration/Utilities/AsyncSequences.swift @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// /// A concrete async sequence for delivering updated configuration values. +@available(Configuration 1.0, *) public struct ConfigUpdatesAsyncSequence { /// The upstream async sequence that this concrete sequence wraps. @@ -29,6 +30,7 @@ public struct ConfigUpdatesAsyncSequence { } } +@available(Configuration 1.0, *) extension ConfigUpdatesAsyncSequence: AsyncSequence { /// An async iterator that wraps an existential async iterator. @@ -57,6 +59,7 @@ extension ConfigUpdatesAsyncSequence: AsyncSequence { // MARK: - AsyncSequence extensions +@available(Configuration 1.0, *) extension AsyncSequence where Failure == Never { /// Maps each element of the sequence using a throwing transform, introducing a failure type. @@ -106,6 +109,7 @@ extension AsyncSequence where Failure == Never { /// - `Failure`: The error type that the transform function can throw. /// - `Value`: The input element type from the upstream sequence. /// - `Upstream`: The upstream async sequence type that never throws. +@available(Configuration 1.0, *) private struct MapThrowingAsyncSequence> { /// The upstream async sequence to transform. @@ -115,6 +119,7 @@ private struct MapThrowingAsyncSequence Element } +@available(Configuration 1.0, *) extension MapThrowingAsyncSequence: AsyncSequence { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation diff --git a/Sources/Configuration/Utilities/FoundationExtensions.swift b/Sources/Configuration/Utilities/FoundationExtensions.swift index d927334..25d92e8 100644 --- a/Sources/Configuration/Utilities/FoundationExtensions.swift +++ b/Sources/Configuration/Utilities/FoundationExtensions.swift @@ -22,6 +22,7 @@ func printToStderr(_ string: String) { _ = try? FileDescriptor.standardError.writeAll(message.utf8) } +@available(Configuration 1.0, *) extension StringProtocol { /// Returns the contents of the string with any whitespace prefix and suffix trimmed. /// - Returns: The trimmed string. diff --git a/Sources/Configuration/Utilities/combineLatestOneOrMore.swift b/Sources/Configuration/Utilities/combineLatestOneOrMore.swift index b108d4e..d4f6a00 100644 --- a/Sources/Configuration/Utilities/combineLatestOneOrMore.swift +++ b/Sources/Configuration/Utilities/combineLatestOneOrMore.swift @@ -19,6 +19,7 @@ import Synchronization /// This class coordinates the "combine latest" operation by storing the most recent /// value from each source sequence and emitting combined arrays only when all sources /// have produced at least one value. +@available(Configuration 1.0, *) private final class Combiner: Sendable { /// The internal state. @@ -101,6 +102,7 @@ private final class Combiner: Sendable { /// - Throws: When any source throws, when the handler throws, or when cancelled. /// - Returns: The value returned by the handler. /// - Precondition: `sources` must not be empty. +@available(Configuration 1.0, *) func combineLatestOneOrMore( elementType: Element.Type = Element.self, sources: [@Sendable ((ConfigUpdatesAsyncSequence) async throws -> Void) async throws -> Void], diff --git a/Sources/ConfigurationTesting/ProviderCompatTest.swift b/Sources/ConfigurationTesting/ProviderCompatTest.swift index 532dea5..8a9cf27 100644 --- a/Sources/ConfigurationTesting/ProviderCompatTest.swift +++ b/Sources/ConfigurationTesting/ProviderCompatTest.swift @@ -61,6 +61,7 @@ import ConfigurationTestingInternal /// "other.byteChunky.array": [[UInt8]]([.magic, .magic2, .magic]), /// ] /// ``` +@available(Configuration 1.0, *) public struct ProviderCompatTest: Sendable { /// Configuration options for customizing test behavior. @@ -147,6 +148,7 @@ public struct ProviderCompatTest: Sendable { ] } +@available(Configuration 1.0, *) extension ProviderCompatTest { private func value() throws { diff --git a/Sources/ConfigurationTestingInternal/AccessReporterTestUtils.swift b/Sources/ConfigurationTestingInternal/AccessReporterTestUtils.swift index 521dc09..3c21673 100644 --- a/Sources/ConfigurationTestingInternal/AccessReporterTestUtils.swift +++ b/Sources/ConfigurationTestingInternal/AccessReporterTestUtils.swift @@ -22,6 +22,7 @@ import Foundation import Testing /// A test-only access reporter that records events for later inspection. +@available(Configuration 1.0, *) package final class TestAccessReporter: Sendable { /// The internal storage. @@ -45,6 +46,7 @@ package final class TestAccessReporter: Sendable { } } +@available(Configuration 1.0, *) extension TestAccessReporter: AccessReporter { package func report(_ event: AccessEvent) { storage.withLock { $0.events.append(event) } diff --git a/Sources/ConfigurationTestingInternal/AsyncSequence+first.swift b/Sources/ConfigurationTestingInternal/AsyncSequence+first.swift index c77a7df..8c9cbe8 100644 --- a/Sources/ConfigurationTestingInternal/AsyncSequence+first.swift +++ b/Sources/ConfigurationTestingInternal/AsyncSequence+first.swift @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +@available(Configuration 1.0, *) extension AsyncSequence where Failure == Never { /// Returns the first element of the async sequence, or nil if the sequence completes before emitting an element. package var first: Element? { @@ -21,6 +22,7 @@ extension AsyncSequence where Failure == Never { } } +@available(Configuration 1.0, *) extension AsyncSequence { /// Returns the first element of the async sequence, or nil if the sequence completes before emitting an element. package var first: Element? { @@ -33,6 +35,7 @@ extension AsyncSequence { /// Returns the first element of the async sequence, or nil if the sequence completes before emitting an element. /// - Parameter updates: The async sequence to get the first element from. /// - Returns: The first element, or nil if empty. +@available(Configuration 1.0, *) package func awaitFirst(updates: any AsyncSequence) async -> Value? { await updates.first } @@ -41,6 +44,7 @@ package func awaitFirst(updates: any AsyncSequence(updates: any AsyncSequence) async throws -> Value? { try await updates.first } diff --git a/Sources/ConfigurationTestingInternal/CannedValues.swift b/Sources/ConfigurationTestingInternal/CannedValues.swift index 108f2ce..928b4ef 100644 --- a/Sources/ConfigurationTestingInternal/CannedValues.swift +++ b/Sources/ConfigurationTestingInternal/CannedValues.swift @@ -33,6 +33,7 @@ import Testing /// /// print(cannedResponses.values) // ["third"] /// ``` +@available(Configuration 1.0, *) package final class CannedValues: Sendable { /// Thread-safe storage for the remaining values. diff --git a/Sources/ConfigurationTestingInternal/CollectingLogHandler.swift b/Sources/ConfigurationTestingInternal/CollectingLogHandler.swift index d8c5740..8687df4 100644 --- a/Sources/ConfigurationTestingInternal/CollectingLogHandler.swift +++ b/Sources/ConfigurationTestingInternal/CollectingLogHandler.swift @@ -18,6 +18,7 @@ package import Logging import Synchronization /// A single logged entry with level, message, and metadata. +@available(Configuration 1.0, *) package struct Entry: Sendable, Equatable { /// The log level. @@ -42,6 +43,7 @@ package struct Entry: Sendable, Equatable { } /// A log handler that collects log entries in memory for inspection. +@available(Configuration 1.0, *) package struct CollectingLogHandler: LogHandler { /// The metadata applied to all log messages from this handler. diff --git a/Sources/ConfigurationTestingInternal/ConfigValueExtensions.swift b/Sources/ConfigurationTestingInternal/ConfigValueExtensions.swift index eb613b4..fa55716 100644 --- a/Sources/ConfigurationTestingInternal/ConfigValueExtensions.swift +++ b/Sources/ConfigurationTestingInternal/ConfigValueExtensions.swift @@ -24,6 +24,7 @@ extension [UInt8] { } } +@available(Configuration 1.0, *) extension ConfigValue { package static var magic: Self { ConfigValue(.bytes(.magic), isSecret: false) @@ -34,6 +35,7 @@ extension ConfigValue { } } +@available(Configuration 1.0, *) extension ConfigValue { /// Creates a new string configuration value. diff --git a/Sources/ConfigurationTestingInternal/InMemoryFileSystem.swift b/Sources/ConfigurationTestingInternal/InMemoryFileSystem.swift index 562f918..d02a840 100644 --- a/Sources/ConfigurationTestingInternal/InMemoryFileSystem.swift +++ b/Sources/ConfigurationTestingInternal/InMemoryFileSystem.swift @@ -22,6 +22,7 @@ package import SystemPackage import Synchronization /// A simple in-memory file system used for testing. +@available(Configuration 1.0, *) package final class InMemoryFileSystem: Sendable { /// Represents the type of data stored in the in-memory file system. @@ -97,6 +98,7 @@ package final class InMemoryFileSystem: Sendable { } } +@available(Configuration 1.0, *) extension InMemoryFileSystem: CommonProviderFileSystem { func listFileNames(atPath directoryPath: FilePath) async throws -> [String] { let prefixComponents = directoryPath.components diff --git a/Sources/ConfigurationTestingInternal/TestFuture.swift b/Sources/ConfigurationTestingInternal/TestFuture.swift index 367849e..f1e7dd0 100644 --- a/Sources/ConfigurationTestingInternal/TestFuture.swift +++ b/Sources/ConfigurationTestingInternal/TestFuture.swift @@ -37,6 +37,7 @@ import Foundation /// // In test code /// let result = await future.value /// ``` +@available(Configuration 1.0, *) package final class TestFuture: @unchecked Sendable /* lock + locked_state */ { /// The internal state of the future. diff --git a/Sources/ConfigurationTestingInternal/TestProvider.swift b/Sources/ConfigurationTestingInternal/TestProvider.swift index a2ea08a..0b8f25e 100644 --- a/Sources/ConfigurationTestingInternal/TestProvider.swift +++ b/Sources/ConfigurationTestingInternal/TestProvider.swift @@ -32,6 +32,7 @@ import Testing /// "error.key": .failure(TestProvider.TestError()) /// ]) /// ``` +@available(Configuration 1.0, *) package struct TestProvider: Sendable { /// A generic error type for testing error scenarios. @@ -53,6 +54,7 @@ package struct TestProvider: Sendable { } } +@available(Configuration 1.0, *) extension TestProvider { /// Creates a new test provider with string-based key mappings. @@ -80,6 +82,7 @@ extension TestProvider { } } +@available(Configuration 1.0, *) extension TestProvider: ConfigProvider, ConfigSnapshotProtocol { package var providerName: String { "TestProvider" diff --git a/Sources/ConfigurationTestingInternal/withService.swift b/Sources/ConfigurationTestingInternal/withService.swift index e3651b9..f07efb3 100644 --- a/Sources/ConfigurationTestingInternal/withService.swift +++ b/Sources/ConfigurationTestingInternal/withService.swift @@ -40,6 +40,7 @@ package import ServiceLifecycle /// - work: The test work to perform with the running service. /// - Returns: The result produced by the work closure. /// - Throws: Rethrows errors from service creation, service execution, or test work. +@available(Configuration 1.0, *) package func withService(createService: () async throws -> S, work: (S) async throws -> R) async throws -> R { diff --git a/Tests/ConfigurationTests/AccessLoggerTests.swift b/Tests/ConfigurationTests/AccessLoggerTests.swift index f156220..68def8c 100644 --- a/Tests/ConfigurationTests/AccessLoggerTests.swift +++ b/Tests/ConfigurationTests/AccessLoggerTests.swift @@ -21,6 +21,7 @@ import Synchronization import ConfigurationTestingInternal struct AccessLoggerTests { + @available(Configuration 1.0, *) @Test func test() throws { let collectingLogHandler = CollectingLogHandler() let logger = Logger(label: "Test", factory: { _ in collectingLogHandler }) diff --git a/Tests/ConfigurationTests/AccessReporterTests.swift b/Tests/ConfigurationTests/AccessReporterTests.swift index ea9812b..206c1b5 100644 --- a/Tests/ConfigurationTests/AccessReporterTests.swift +++ b/Tests/ConfigurationTests/AccessReporterTests.swift @@ -22,6 +22,7 @@ struct AccessReporterTests { case info } + @available(Configuration 1.0, *) @Test func get() async throws { let accessReporter = TestAccessReporter() let provider = InMemoryProvider( @@ -198,6 +199,7 @@ struct AccessReporterTests { ) } + @available(Configuration 1.0, *) @Test func fetch() async throws { let accessReporter = TestAccessReporter() let provider = InMemoryProvider( @@ -393,6 +395,7 @@ struct AccessReporterTests { ) } + @available(Configuration 1.0, *) @Test func watch() async throws { let accessReporter = TestAccessReporter() let provider = InMemoryProvider( diff --git a/Tests/ConfigurationTests/AsyncSequencesTests.swift b/Tests/ConfigurationTests/AsyncSequencesTests.swift index 613d7e2..04f563f 100644 --- a/Tests/ConfigurationTests/AsyncSequencesTests.swift +++ b/Tests/ConfigurationTests/AsyncSequencesTests.swift @@ -26,6 +26,7 @@ struct AsyncSequencesTests { // MARK: - ConfigUpdatesAsyncSequence tests + @available(Configuration 1.0, *) @Test func updatesAsyncSequenceWrapsExistentialSequence() async throws { let values = [1, 2, 3, 4, 5] let updatesSequence = ConfigUpdatesAsyncSequence(values.async) @@ -33,12 +34,14 @@ struct AsyncSequencesTests { #expect(results == values) } + @available(Configuration 1.0, *) @Test func updatesAsyncSequenceWithEmptySequence() async throws { let updatesSequence = ConfigUpdatesAsyncSequence(([] as [Int]).async) let results = await updatesSequence.collect() #expect(results.isEmpty) } + @available(Configuration 1.0, *) @Test func updatesAsyncSequencePropagatesErrors() async throws { let throwingSequence = AsyncThrowingStream { continuation in continuation.yield(1) @@ -59,6 +62,7 @@ struct AsyncSequencesTests { // MARK: - mapThrowing Tests + @available(Configuration 1.0, *) @Test func mapThrowingSuccessfulTransformation() async throws { let values = [1, 2, 3] let asyncSequence = values.async @@ -71,6 +75,7 @@ struct AsyncSequencesTests { #expect(results == expected) } + @available(Configuration 1.0, *) @Test func mapThrowingWithEmptySequence() async throws { let emptySequence = ([] as [Int]).async let mappedSequence = emptySequence.mapThrowing { value -> String in @@ -81,6 +86,7 @@ struct AsyncSequencesTests { #expect(results.isEmpty) } + @available(Configuration 1.0, *) @Test func mapThrowingPropagatesTransformErrors() async throws { let asyncSequence = [1, 2, 3, 4, 5].async let mappedSequence = asyncSequence.mapThrowing { value -> String in @@ -103,6 +109,7 @@ struct AsyncSequencesTests { // MARK: - Test Utilities +@available(Configuration 1.0, *) extension AsyncSequence where Failure == Never { /// Collects all elements from the async sequence into an array. /// @@ -121,6 +128,7 @@ extension AsyncSequence where Failure == Never { } } +@available(Configuration 1.0, *) extension AsyncSequence { /// Collects all elements from the async sequence into an array. /// diff --git a/Tests/ConfigurationTests/CLIArgumentParserTests.swift b/Tests/ConfigurationTests/CLIArgumentParserTests.swift index 3d138ee..cf6c484 100644 --- a/Tests/ConfigurationTests/CLIArgumentParserTests.swift +++ b/Tests/ConfigurationTests/CLIArgumentParserTests.swift @@ -19,8 +19,12 @@ import Testing struct CLIArgumentParserTests { - let parser = CLIArgumentParser() + @available(Configuration 1.0, *) + var parser: CLIArgumentParser { + .init() + } + @available(Configuration 1.0, *) @Test func parsing() { #expect(parser.parse([]).isEmpty) #expect(parser.parse(["program"]).isEmpty) diff --git a/Tests/ConfigurationTests/CLIKeyEncoderTests.swift b/Tests/ConfigurationTests/CLIKeyEncoderTests.swift index a6707d0..36cbcb6 100644 --- a/Tests/ConfigurationTests/CLIKeyEncoderTests.swift +++ b/Tests/ConfigurationTests/CLIKeyEncoderTests.swift @@ -18,9 +18,9 @@ import Foundation struct CLIKeyEncoderTests { - let encoder = CLIKeyEncoder() - + @available(Configuration 1.0, *) @Test func encoding() { + let encoder = CLIKeyEncoder() #expect(encoder.encode(["host"]) == "--host") #expect(encoder.encode(["app", "database", "host"]) == "--app-database-host") #expect(encoder.encode(["maxRetryCount"]) == "--max-retry-count") diff --git a/Tests/ConfigurationTests/CommandLineArgumentsProviderTests.swift b/Tests/ConfigurationTests/CommandLineArgumentsProviderTests.swift index ed66b17..4fdecaa 100644 --- a/Tests/ConfigurationTests/CommandLineArgumentsProviderTests.swift +++ b/Tests/ConfigurationTests/CommandLineArgumentsProviderTests.swift @@ -21,14 +21,15 @@ import Foundation import ConfigurationTesting struct CommandLineArgumentsProviderTests { - let provider: CommandLineArgumentsProvider - init() { + + @available(Configuration 1.0, *) + var provider: CommandLineArgumentsProvider { // Convert magic byte arrays to base64 let magicBase64 = "bWFnaWM=" let magic2Base64 = "bWFnaWMy" // Create a provider with the expected test data format for ProviderCompatTest - provider = CommandLineArgumentsProvider(arguments: [ + return CommandLineArgumentsProvider(arguments: [ "program", "--string", "Hello", "--other-string", "Other Hello", @@ -53,6 +54,7 @@ struct CommandLineArgumentsProviderTests { ]) } + @available(Configuration 1.0, *) @Test func printingDescription() throws { let expectedDescription = #""" CommandLineArgumentsProvider[20 values] @@ -60,6 +62,7 @@ struct CommandLineArgumentsProviderTests { #expect(provider.description == expectedDescription) } + @available(Configuration 1.0, *) @Test func printingDebugDescription() throws { let expectedDebugDescription = #""" CommandLineArgumentsProvider[20 values: --bool=true, --booly-array=true,false, --byte-chunky-array=bWFnaWM=,bWFnaWMy, --bytes=bWFnaWM=, --double=3.14, --doubly-array=3.14,2.72, --int=42, --inty-array=42,24, --other-bool=false, --other-booly-array=false,true,true, --other-byte-chunky-array=bWFnaWM=,bWFnaWMy,bWFnaWM=, --other-bytes=bWFnaWMy, --other-double=2.72, --other-doubly-array=0.9,1.8, --other-int=24, --other-inty-array=16,32, --other-string=Other Hello, --other-stringy-array=Hello,Swift, --string=Hello, --stringy-array=Hello,World] @@ -67,10 +70,12 @@ struct CommandLineArgumentsProviderTests { #expect(provider.debugDescription == expectedDebugDescription) } + @available(Configuration 1.0, *) @Test func compat() async throws { try await ProviderCompatTest(provider: provider).run() } + @available(Configuration 1.0, *) @Test func secretSpecifier() throws { let provider = CommandLineArgumentsProvider( arguments: ["program", "--api-token", "s3cret", "--hostname", "localhost"], diff --git a/Tests/ConfigurationTests/ConfigProvider+OperatorTests.swift b/Tests/ConfigurationTests/ConfigProvider+OperatorTests.swift index c03e2cc..8e5c223 100644 --- a/Tests/ConfigurationTests/ConfigProvider+OperatorTests.swift +++ b/Tests/ConfigurationTests/ConfigProvider+OperatorTests.swift @@ -17,6 +17,7 @@ import ConfigurationTestingInternal @testable import Configuration struct ConfigProviderOperatorTests { + @available(Configuration 1.0, *) @Test func prefixWithConfigKey() throws { let prefixed = InMemoryProvider(values: [["app", "foo"]: "bar"]).prefixKeys(with: ["app"]) let result = try prefixed.value(forKey: ["foo"], type: .string) @@ -24,6 +25,7 @@ struct ConfigProviderOperatorTests { #expect(result.encodedKey == "app.foo") } + @available(Configuration 1.0, *) @Test func prefixWithString() throws { let prefixed = InMemoryProvider(values: [["app", "prod", "foo"]: "bar"]).prefixKeys(with: "app.prod") let result = try prefixed.value(forKey: ["foo"], type: .string) @@ -31,6 +33,7 @@ struct ConfigProviderOperatorTests { #expect(result.encodedKey == "app.prod.foo") } + @available(Configuration 1.0, *) @Test func mapKeys() throws { let mapped = InMemoryProvider(values: [["foo"]: "bar"]) .mapKeys { key in diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsFetch1.swift b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsFetch1.swift index 6299f6c..ba6a19c 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsFetch1.swift +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsFetch1.swift @@ -28,6 +28,7 @@ struct ConfigReaderMethodTestsFetch1 { typealias TestEnum = ConfigReaderTests.TestEnum typealias TestStringConvertible = ConfigReaderTests.TestStringConvertible + @available(Configuration 1.0, *) @Test func fetch() async throws { let config = ConfigReaderTests.config diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsFetch1.swift.gyb b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsFetch1.swift.gyb index 53ac6fc..2a94889 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsFetch1.swift.gyb +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsFetch1.swift.gyb @@ -26,6 +26,7 @@ struct ConfigReaderMethodTestsFetch1 { typealias TestEnum = ConfigReaderTests.TestEnum typealias TestStringConvertible = ConfigReaderTests.TestStringConvertible + @available(Configuration 1.0, *) @Test func fetch() async throws { let config = ConfigReaderTests.config diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsFetch2.swift b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsFetch2.swift index 8186500..771eed2 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsFetch2.swift +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsFetch2.swift @@ -28,6 +28,7 @@ struct ConfigReaderMethodTestsFetch2 { typealias TestEnum = ConfigReaderTests.TestEnum typealias TestStringConvertible = ConfigReaderTests.TestStringConvertible + @available(Configuration 1.0, *) @Test func fetch() async throws { let config = ConfigReaderTests.config diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsFetch2.swift.gyb b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsFetch2.swift.gyb index 8736c53..2fd0b07 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsFetch2.swift.gyb +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsFetch2.swift.gyb @@ -26,6 +26,7 @@ struct ConfigReaderMethodTestsFetch2 { typealias TestEnum = ConfigReaderTests.TestEnum typealias TestStringConvertible = ConfigReaderTests.TestStringConvertible + @available(Configuration 1.0, *) @Test func fetch() async throws { let config = ConfigReaderTests.config diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsFetch3.swift b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsFetch3.swift index 7da8001..e87014f 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsFetch3.swift +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsFetch3.swift @@ -28,6 +28,7 @@ struct ConfigReaderMethodTestsFetch3 { typealias TestEnum = ConfigReaderTests.TestEnum typealias TestStringConvertible = ConfigReaderTests.TestStringConvertible + @available(Configuration 1.0, *) @Test func fetch() async throws { let config = ConfigReaderTests.config diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsFetch3.swift.gyb b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsFetch3.swift.gyb index 9219e7d..0223ad6 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsFetch3.swift.gyb +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsFetch3.swift.gyb @@ -26,6 +26,7 @@ struct ConfigReaderMethodTestsFetch3 { typealias TestEnum = ConfigReaderTests.TestEnum typealias TestStringConvertible = ConfigReaderTests.TestStringConvertible + @available(Configuration 1.0, *) @Test func fetch() async throws { let config = ConfigReaderTests.config diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsGet1.swift b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsGet1.swift index 6acdcef..eb7bdbb 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsGet1.swift +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsGet1.swift @@ -28,6 +28,7 @@ struct ConfigReaderMethodTestsGet1 { typealias TestEnum = ConfigReaderTests.TestEnum typealias TestStringConvertible = ConfigReaderTests.TestStringConvertible + @available(Configuration 1.0, *) @Test func get() async throws { let config = ConfigReaderTests.config diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsGet1.swift.gyb b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsGet1.swift.gyb index 89bc156..97c0818 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsGet1.swift.gyb +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsGet1.swift.gyb @@ -26,6 +26,7 @@ struct ConfigReaderMethodTestsGet1 { typealias TestEnum = ConfigReaderTests.TestEnum typealias TestStringConvertible = ConfigReaderTests.TestStringConvertible + @available(Configuration 1.0, *) @Test func get() async throws { let config = ConfigReaderTests.config diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsGet2.swift b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsGet2.swift index 4be1d8a..0c4186e 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsGet2.swift +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsGet2.swift @@ -28,6 +28,7 @@ struct ConfigReaderMethodTestsGet2 { typealias TestEnum = ConfigReaderTests.TestEnum typealias TestStringConvertible = ConfigReaderTests.TestStringConvertible + @available(Configuration 1.0, *) @Test func get() async throws { let config = ConfigReaderTests.config diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsGet2.swift.gyb b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsGet2.swift.gyb index 48e35c2..befe699 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsGet2.swift.gyb +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsGet2.swift.gyb @@ -26,6 +26,7 @@ struct ConfigReaderMethodTestsGet2 { typealias TestEnum = ConfigReaderTests.TestEnum typealias TestStringConvertible = ConfigReaderTests.TestStringConvertible + @available(Configuration 1.0, *) @Test func get() async throws { let config = ConfigReaderTests.config diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsGet3.swift b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsGet3.swift index 0b537c3..a4b256a 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsGet3.swift +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsGet3.swift @@ -28,6 +28,7 @@ struct ConfigReaderMethodTestsGet3 { typealias TestEnum = ConfigReaderTests.TestEnum typealias TestStringConvertible = ConfigReaderTests.TestStringConvertible + @available(Configuration 1.0, *) @Test func get() async throws { let config = ConfigReaderTests.config diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsGet3.swift.gyb b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsGet3.swift.gyb index 035aec9..3562580 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsGet3.swift.gyb +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsGet3.swift.gyb @@ -26,6 +26,7 @@ struct ConfigReaderMethodTestsGet3 { typealias TestEnum = ConfigReaderTests.TestEnum typealias TestStringConvertible = ConfigReaderTests.TestStringConvertible + @available(Configuration 1.0, *) @Test func get() async throws { let config = ConfigReaderTests.config diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsWatch1.swift b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsWatch1.swift index 7edccaa..7f51f08 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsWatch1.swift +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsWatch1.swift @@ -30,6 +30,7 @@ struct ConfigReaderMethodTestsWatch1 { typealias TestEnum = ConfigReaderTests.TestEnum typealias TestStringConvertible = ConfigReaderTests.TestStringConvertible + @available(Configuration 1.0, *) @Test func watch() async throws { let config = ConfigReaderTests.config diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsWatch1.swift.gyb b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsWatch1.swift.gyb index 72a7bf6..451cec9 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsWatch1.swift.gyb +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsWatch1.swift.gyb @@ -27,6 +27,7 @@ struct ConfigReaderMethodTestsWatch1 { typealias TestEnum = ConfigReaderTests.TestEnum typealias TestStringConvertible = ConfigReaderTests.TestStringConvertible + @available(Configuration 1.0, *) @Test func watch() async throws { let config = ConfigReaderTests.config diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsWatch2.swift b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsWatch2.swift index 000f762..b0d9f67 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsWatch2.swift +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsWatch2.swift @@ -30,6 +30,7 @@ struct ConfigReaderMethodTestsWatch2 { typealias TestEnum = ConfigReaderTests.TestEnum typealias TestStringConvertible = ConfigReaderTests.TestStringConvertible + @available(Configuration 1.0, *) @Test func watch() async throws { let config = ConfigReaderTests.config diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsWatch2.swift.gyb b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsWatch2.swift.gyb index 3b2f5dd..0a8b188 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsWatch2.swift.gyb +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsWatch2.swift.gyb @@ -27,6 +27,7 @@ struct ConfigReaderMethodTestsWatch2 { typealias TestEnum = ConfigReaderTests.TestEnum typealias TestStringConvertible = ConfigReaderTests.TestStringConvertible + @available(Configuration 1.0, *) @Test func watch() async throws { let config = ConfigReaderTests.config diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsWatch3.swift b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsWatch3.swift index 9086f64..b493e55 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsWatch3.swift +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsWatch3.swift @@ -30,6 +30,7 @@ struct ConfigReaderMethodTestsWatch3 { typealias TestEnum = ConfigReaderTests.TestEnum typealias TestStringConvertible = ConfigReaderTests.TestStringConvertible + @available(Configuration 1.0, *) @Test func watch() async throws { let config = ConfigReaderTests.config diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsWatch3.swift.gyb b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsWatch3.swift.gyb index 8cc38bf..098b92b 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsWatch3.swift.gyb +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderMethodTestsWatch3.swift.gyb @@ -27,6 +27,7 @@ struct ConfigReaderMethodTestsWatch3 { typealias TestEnum = ConfigReaderTests.TestEnum typealias TestStringConvertible = ConfigReaderTests.TestStringConvertible + @available(Configuration 1.0, *) @Test func watch() async throws { let config = ConfigReaderTests.config diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderTests.swift b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderTests.swift index 9cdc32f..793fc88 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderTests.swift +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigReaderTests.swift @@ -17,12 +17,14 @@ import Testing import ConfigurationTestingInternal struct ConfigReaderTests { + @available(Configuration 1.0, *) @Test func create() throws { let config = ConfigReader(provider: InMemoryProvider(values: [:])).scoped(to: "foo") // This config has no providers, so every returned value will match the default. try #require(config.string(forKey: "bar", default: "test") == "test") } + @available(Configuration 1.0, *) @Test func scoping() throws { let provider = InMemoryProvider( name: "test", @@ -36,6 +38,7 @@ struct ConfigReaderTests { #expect(scoped.string(forKey: "user-agent") == "Config/1.0 (Test)") } + @available(Configuration 1.0, *) @Test func scopingCustomDecoder() throws { let provider = InMemoryProvider( name: "test", @@ -48,6 +51,7 @@ struct ConfigReaderTests { #expect(scoped.string(forKey: "client:user-agent") == "Config/1.0 (Test)") } + @available(Configuration 1.0, *) @Test func context() throws { let provider = InMemoryProvider(values: [ AbsoluteConfigKey(["http", "client", "timeout"], context: ["upstream": "example1.org"]): 15.0, @@ -116,6 +120,7 @@ struct ConfigReaderTests { static var otherStringConvertibleArray: [TestStringConvertible] { [.hello, .world, .hello] } } + @available(Configuration 1.0, *) static var provider: TestProvider { TestProvider(values: [ "string": .success(ConfigValue(Defaults.string, isSecret: false)), @@ -140,6 +145,7 @@ struct ConfigReaderTests { ]) } + @available(Configuration 1.0, *) static var config: ConfigReader { ConfigReader(provider: provider) } diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigSnapshotReaderMethodTestsGet1.swift b/Tests/ConfigurationTests/ConfigReaderTests/ConfigSnapshotReaderMethodTestsGet1.swift index fdb072f..a2cb8ec 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigSnapshotReaderMethodTestsGet1.swift +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigSnapshotReaderMethodTestsGet1.swift @@ -28,6 +28,7 @@ struct ConfigSnapshotReaderMethodTestsGet1 { typealias TestEnum = ConfigReaderTests.TestEnum typealias TestStringConvertible = ConfigReaderTests.TestStringConvertible + @available(Configuration 1.0, *) @Test func get() async throws { let config = ConfigReaderTests.config diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigSnapshotReaderMethodTestsGet1.swift.gyb b/Tests/ConfigurationTests/ConfigReaderTests/ConfigSnapshotReaderMethodTestsGet1.swift.gyb index b407142..f2aa635 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigSnapshotReaderMethodTestsGet1.swift.gyb +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigSnapshotReaderMethodTestsGet1.swift.gyb @@ -27,6 +27,7 @@ struct ConfigSnapshotReaderMethodTestsGet1 { typealias TestEnum = ConfigReaderTests.TestEnum typealias TestStringConvertible = ConfigReaderTests.TestStringConvertible + @available(Configuration 1.0, *) @Test func get() async throws { let config = ConfigReaderTests.config diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigSnapshotReaderMethodTestsGet2.swift b/Tests/ConfigurationTests/ConfigReaderTests/ConfigSnapshotReaderMethodTestsGet2.swift index 890dfee..0bfd04b 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigSnapshotReaderMethodTestsGet2.swift +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigSnapshotReaderMethodTestsGet2.swift @@ -28,6 +28,7 @@ struct ConfigSnapshotReaderMethodTestsGet2 { typealias TestEnum = ConfigReaderTests.TestEnum typealias TestStringConvertible = ConfigReaderTests.TestStringConvertible + @available(Configuration 1.0, *) @Test func get() async throws { let config = ConfigReaderTests.config diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigSnapshotReaderMethodTestsGet2.swift.gyb b/Tests/ConfigurationTests/ConfigReaderTests/ConfigSnapshotReaderMethodTestsGet2.swift.gyb index ea9a160..006c34d 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigSnapshotReaderMethodTestsGet2.swift.gyb +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigSnapshotReaderMethodTestsGet2.swift.gyb @@ -27,6 +27,7 @@ struct ConfigSnapshotReaderMethodTestsGet2 { typealias TestEnum = ConfigReaderTests.TestEnum typealias TestStringConvertible = ConfigReaderTests.TestStringConvertible + @available(Configuration 1.0, *) @Test func get() async throws { let config = ConfigReaderTests.config diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigSnapshotReaderMethodTestsGet3.swift b/Tests/ConfigurationTests/ConfigReaderTests/ConfigSnapshotReaderMethodTestsGet3.swift index dfb3a38..b0db196 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigSnapshotReaderMethodTestsGet3.swift +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigSnapshotReaderMethodTestsGet3.swift @@ -28,6 +28,7 @@ struct ConfigSnapshotReaderMethodTestsGet3 { typealias TestEnum = ConfigReaderTests.TestEnum typealias TestStringConvertible = ConfigReaderTests.TestStringConvertible + @available(Configuration 1.0, *) @Test func get() async throws { let config = ConfigReaderTests.config diff --git a/Tests/ConfigurationTests/ConfigReaderTests/ConfigSnapshotReaderMethodTestsGet3.swift.gyb b/Tests/ConfigurationTests/ConfigReaderTests/ConfigSnapshotReaderMethodTestsGet3.swift.gyb index 9044b34..2005661 100644 --- a/Tests/ConfigurationTests/ConfigReaderTests/ConfigSnapshotReaderMethodTestsGet3.swift.gyb +++ b/Tests/ConfigurationTests/ConfigReaderTests/ConfigSnapshotReaderMethodTestsGet3.swift.gyb @@ -27,6 +27,7 @@ struct ConfigSnapshotReaderMethodTestsGet3 { typealias TestEnum = ConfigReaderTests.TestEnum typealias TestStringConvertible = ConfigReaderTests.TestStringConvertible + @available(Configuration 1.0, *) @Test func get() async throws { let config = ConfigReaderTests.config diff --git a/Tests/ConfigurationTests/ConfigSnapshotReaderTests.swift b/Tests/ConfigurationTests/ConfigSnapshotReaderTests.swift index e43161b..e4e30c8 100644 --- a/Tests/ConfigurationTests/ConfigSnapshotReaderTests.swift +++ b/Tests/ConfigurationTests/ConfigSnapshotReaderTests.swift @@ -18,6 +18,7 @@ import ConfigurationTestingInternal struct ConfigSnapshotReaderTests { + @available(Configuration 1.0, *) @Test func get() throws { let provider = InMemoryProvider( name: "test", @@ -32,6 +33,7 @@ struct ConfigSnapshotReaderTests { } } + @available(Configuration 1.0, *) @Test func watch() async throws { let provider = InMemoryProvider( name: "test", @@ -49,6 +51,7 @@ struct ConfigSnapshotReaderTests { } } + @available(Configuration 1.0, *) @Test func scoping() throws { let provider = InMemoryProvider( name: "test", @@ -64,6 +67,7 @@ struct ConfigSnapshotReaderTests { } } + @available(Configuration 1.0, *) @Test func scopingCustomDecoder() throws { let provider = InMemoryProvider( name: "test", diff --git a/Tests/ConfigurationTests/DirectoryFilesProviderTests.swift b/Tests/ConfigurationTests/DirectoryFilesProviderTests.swift index 87df7b1..7ba2270 100644 --- a/Tests/ConfigurationTests/DirectoryFilesProviderTests.swift +++ b/Tests/ConfigurationTests/DirectoryFilesProviderTests.swift @@ -22,6 +22,7 @@ import SystemPackage struct DirectoryFilesProviderTests { /// Creates test files for the provider. + @available(Configuration 1.0, *) static var testFiles: [FilePath: InMemoryFileSystem.FileInfo] { let stringValues: [String: String] = [ "string": "Hello", @@ -59,6 +60,7 @@ struct DirectoryFilesProviderTests { return Dictionary(uniqueKeysWithValues: tuples) } + @available(Configuration 1.0, *) @Test func printingDescription() async throws { let fileSystem = InMemoryFileSystem(files: Self.testFiles) let provider = try await DirectoryFilesProvider( @@ -69,6 +71,7 @@ struct DirectoryFilesProviderTests { #expect(provider.description == "DirectoryFilesProvider[21 files]") } + @available(Configuration 1.0, *) @Test func printingDebugDescription() async throws { let fileSystem = InMemoryFileSystem(files: Self.testFiles) let provider = try await DirectoryFilesProvider( @@ -83,6 +86,7 @@ struct DirectoryFilesProviderTests { #expect(provider.debugDescription == expectedDebugDescription) } + @available(Configuration 1.0, *) @Test func compat() async throws { let fileSystem = InMemoryFileSystem(files: Self.testFiles) let provider = try await DirectoryFilesProvider( diff --git a/Tests/ConfigurationTests/EnvironmentVariablesProviderTests.swift b/Tests/ConfigurationTests/EnvironmentVariablesProviderTests.swift index f24ada0..e5b08c1 100644 --- a/Tests/ConfigurationTests/EnvironmentVariablesProviderTests.swift +++ b/Tests/ConfigurationTests/EnvironmentVariablesProviderTests.swift @@ -20,9 +20,10 @@ import ConfigurationTesting import SystemPackage struct EnvironmentVariablesProviderTests { - let provider: EnvironmentVariablesProvider - init() { - provider = EnvironmentVariablesProvider( + + @available(Configuration 1.0, *) + var provider: EnvironmentVariablesProvider { + EnvironmentVariablesProvider( environmentVariables: [ "STRING": "Hello", "OTHER_STRING": "Other Hello", @@ -51,6 +52,7 @@ struct EnvironmentVariablesProviderTests { ) } + @available(Configuration 1.0, *) @Test func printingDescription() throws { let expectedDescription = #""" EnvironmentVariablesProvider[20 values] @@ -58,6 +60,7 @@ struct EnvironmentVariablesProviderTests { #expect(provider.description == expectedDescription) } + @available(Configuration 1.0, *) @Test func printingDebugDescription() throws { let expectedDebugDescription = #""" EnvironmentVariablesProvider[20 values: BOOL=true, BOOLY_ARRAY=true,false, BYTES=bWFnaWM=, BYTE_CHUNKY_ARRAY=bWFnaWM=,bWFnaWMy, DOUBLE=3.14, DOUBLY_ARRAY=3.14,2.72, INT=42, INTY_ARRAY=42,24, OTHER_BOOL=false, OTHER_BOOLY_ARRAY=false,true,true, OTHER_BYTES=bWFnaWMy, OTHER_BYTE_CHUNKY_ARRAY=bWFnaWM=,bWFnaWMy,bWFnaWM=, OTHER_DOUBLE=2.72, OTHER_DOUBLY_ARRAY=0.9,1.8, OTHER_INT=24, OTHER_INTY_ARRAY=16,32, OTHER_STRING=Other Hello, OTHER_STRINGY_ARRAY=Hello,Swift, STRING=, STRINGY_ARRAY=Hello,World] @@ -65,15 +68,18 @@ struct EnvironmentVariablesProviderTests { #expect(provider.debugDescription == expectedDebugDescription) } + @available(Configuration 1.0, *) @Test func compat() async throws { try await ProviderCompatTest(provider: provider).run() } + @available(Configuration 1.0, *) @Test func secretSpecifier() throws { #expect(try provider.value(forKey: ["string"], type: .string).value?.isSecret == true) #expect(try provider.value(forKey: ["other.string"], type: .string).value?.isSecret == false) } + @available(Configuration 1.0, *) @Test func parseEnvironmentFile() throws { let values = EnvironmentFileParser.parsed( #""" @@ -102,6 +108,7 @@ struct EnvironmentVariablesProviderTests { #expect(values == expected) } + @available(Configuration 1.0, *) @Test func loadEnvironmentFile() async throws { let envFilePath = try #require(Bundle.module.path(forResource: "Resources", ofType: nil)?.appending("/.env")) let provider = try await EnvironmentVariablesProvider( @@ -115,6 +122,7 @@ struct EnvironmentVariablesProviderTests { #expect(config.string(forKey: "http.secret") == "s3cret") } + @available(Configuration 1.0, *) @Test func loadEnvironmentFileError() async throws { let envFilePath: FilePath = "/tmp/definitelyNotAnEnvFile" do { @@ -137,6 +145,7 @@ struct EnvironmentVariablesProviderTests { struct EnvironmentKeyEncoderTests { + @available(Configuration 1.0, *) @Test func test() { let encoder = EnvironmentKeyEncoder() diff --git a/Tests/ConfigurationTests/FileAccessLoggerTests.swift b/Tests/ConfigurationTests/FileAccessLoggerTests.swift index c9b479c..b3e6828 100644 --- a/Tests/ConfigurationTests/FileAccessLoggerTests.swift +++ b/Tests/ConfigurationTests/FileAccessLoggerTests.swift @@ -19,6 +19,7 @@ import SystemPackage import ConfigurationTestingInternal struct FileAccessLoggerTests { + @available(Configuration 1.0, *) @Test func test() throws { let readString: String diff --git a/Tests/ConfigurationTests/InMemoryProviderTests.swift b/Tests/ConfigurationTests/InMemoryProviderTests.swift index 345d54a..8c6524a 100644 --- a/Tests/ConfigurationTests/InMemoryProviderTests.swift +++ b/Tests/ConfigurationTests/InMemoryProviderTests.swift @@ -19,9 +19,10 @@ import Foundation import ConfigurationTesting struct InMemoryProviderTests { - let provider: InMemoryProvider - init() { - provider = InMemoryProvider( + + @available(Configuration 1.0, *) + var provider: InMemoryProvider { + InMemoryProvider( name: "test", values: [ "string": .init("Hello", isSecret: false), @@ -48,6 +49,7 @@ struct InMemoryProviderTests { ) } + @available(Configuration 1.0, *) @Test func printingDescription() throws { let expectedDescription = #""" InMemoryProvider[test, 20 values] @@ -55,6 +57,7 @@ struct InMemoryProviderTests { #expect(provider.description == expectedDescription) } + @available(Configuration 1.0, *) @Test func printingDebugDescription() throws { let expectedDebugDescription = #""" InMemoryProvider[test, 20 values: bool=[bool: true], booly.array=[boolArray: true, false], byteChunky.array=[byteChunkArray: 5 bytes, prefix: 6d61676963, 6 bytes, prefix: 6d6167696332], bytes=[bytes: 5 bytes, prefix: 6d61676963], double=[double: 3.14], doubly.array=[doubleArray: 3.14, 2.72], int=[int: 42], inty.array=[intArray: 42, 24], other.bool=[bool: false], other.booly.array=[boolArray: false, true, true], other.byteChunky.array=[byteChunkArray: 5 bytes, prefix: 6d61676963, 6 bytes, prefix: 6d6167696332, 5 bytes, prefix: 6d61676963], other.bytes=[bytes: 6 bytes, prefix: 6d6167696332], other.double=[double: 2.72], other.doubly.array=[doubleArray: 0.9, 1.8], other.int=[int: 24], other.inty.array=[intArray: 16, 32], other.string=[string: Other Hello], other.stringy.array=[stringArray: Hello, Swift], string=[string: Hello], stringy.array=[stringArray: Hello, World]] @@ -62,6 +65,7 @@ struct InMemoryProviderTests { #expect(provider.debugDescription == expectedDebugDescription) } + @available(Configuration 1.0, *) @Test func compat() async throws { try await ProviderCompatTest(provider: provider).run() } diff --git a/Tests/ConfigurationTests/JSONProviderTests.swift b/Tests/ConfigurationTests/JSONProviderTests.swift index 539265e..211b301 100644 --- a/Tests/ConfigurationTests/JSONProviderTests.swift +++ b/Tests/ConfigurationTests/JSONProviderTests.swift @@ -23,25 +23,31 @@ private let resourcesPath = FilePath(try! #require(Bundle.module.path(forResourc let jsonConfigFile = resourcesPath.appending("/config.json") struct JSONProviderTests { - let provider: JSONProvider - init() async throws { - provider = try await JSONProvider(filePath: jsonConfigFile) + + @available(Configuration 1.0, *) + var provider: JSONProvider { + get async throws { + try await JSONProvider(filePath: jsonConfigFile) + } } - @Test func printingDescription() throws { + @available(Configuration 1.0, *) + @Test func printingDescription() async throws { let expectedDescription = #""" JSONProvider[20 values] """# - #expect(provider.description == expectedDescription) + try await #expect(provider.description == expectedDescription) } - @Test func printingDebugDescription() throws { + @available(Configuration 1.0, *) + @Test func printingDebugDescription() async throws { let expectedDebugDescription = #""" JSONProvider[20 values: bool=1, booly.array=1,0, byteChunky.array=bWFnaWM=,bWFnaWMy, bytes=bWFnaWM=, double=3.14, doubly.array=3.14,2.72, int=42, inty.array=42,24, other.bool=0, other.booly.array=0,1,1, other.byteChunky.array=bWFnaWM=,bWFnaWMy,bWFnaWM=, other.bytes=bWFnaWMy, other.double=2.72, other.doubly.array=0.9,1.8, other.int=24, other.inty.array=16,32, other.string=Other Hello, other.stringy.array=Hello,Swift, string=Hello, stringy.array=Hello,World] """# - #expect(provider.debugDescription == expectedDebugDescription) + try await #expect(provider.debugDescription == expectedDebugDescription) } + @available(Configuration 1.0, *) @Test func compat() async throws { try await ProviderCompatTest(provider: provider).run() } diff --git a/Tests/ConfigurationTests/KeyMappingProviderTests.swift b/Tests/ConfigurationTests/KeyMappingProviderTests.swift index 4e1837f..d721497 100644 --- a/Tests/ConfigurationTests/KeyMappingProviderTests.swift +++ b/Tests/ConfigurationTests/KeyMappingProviderTests.swift @@ -20,6 +20,7 @@ import ConfigurationTesting struct KeyMappingProviderTests { + @available(Configuration 1.0, *) @Test func getValueWithMappedKey() throws { let upstream = InMemoryProvider(values: ["app.foo": "bar", "app.bar": "baz"]) let mapper = KeyMappingProvider(upstream: upstream) { key in @@ -40,6 +41,7 @@ struct KeyMappingProviderTests { #expect(barResult.encodedKey == "app.bar") } + @available(Configuration 1.0, *) @Test func fetchValueWithMappedKey() async throws { let upstream = InMemoryProvider(values: ["app.foo": "bar", "app.bar": "baz"]) let mapper = KeyMappingProvider(upstream: upstream) { key in @@ -56,6 +58,7 @@ struct KeyMappingProviderTests { #expect(fooResult.encodedKey == "app.foo") } + @available(Configuration 1.0, *) @Test func watchValueWithMappedKey() async throws { let upstream = InMemoryProvider(values: ["app.foo": "bar", "app.bar": "baz"]) let mapper = KeyMappingProvider(upstream: upstream) { key in @@ -80,6 +83,7 @@ struct KeyMappingProviderTests { #expect(result.encodedKey == "app.foo") } + @available(Configuration 1.0, *) @Test func snapshotWithMappedKey() throws { let upstream = InMemoryProvider(values: ["app.foo": "bar", "app.bar": "baz"]) let mapper = KeyMappingProvider(upstream: upstream) { key in @@ -101,6 +105,7 @@ struct KeyMappingProviderTests { #expect(otherResult.encodedKey == "other") } + @available(Configuration 1.0, *) @Test func watchSnapshotWithMappedPrefix() async throws { let upstream = InMemoryProvider(values: ["app.foo": "bar", "app.bar": "baz"]) let mapper = KeyMappingProvider(upstream: upstream) { key in @@ -126,6 +131,7 @@ struct KeyMappingProviderTests { #expect(result.encodedKey == "app.foo") } + @available(Configuration 1.0, *) @Test func providerName() { let upstream = InMemoryProvider(name: "test-upstream", values: [:]) let mapper = KeyMappingProvider(upstream: upstream) { key in key } @@ -133,6 +139,7 @@ struct KeyMappingProviderTests { #expect(mapper.providerName == expectedName) } + @available(Configuration 1.0, *) @Test func description() { let upstream = InMemoryProvider(name: "test-upstream", values: [:]) let mapper = KeyMappingProvider(upstream: upstream) { key in key } @@ -141,6 +148,7 @@ struct KeyMappingProviderTests { #expect(mapper.description == expectedDescription) } + @available(Configuration 1.0, *) @Test func compat() async throws { let upstream = InMemoryProvider( name: "test", diff --git a/Tests/ConfigurationTests/MultiProviderTests.swift b/Tests/ConfigurationTests/MultiProviderTests.swift index 505711f..3e4344c 100644 --- a/Tests/ConfigurationTests/MultiProviderTests.swift +++ b/Tests/ConfigurationTests/MultiProviderTests.swift @@ -19,8 +19,9 @@ import ConfigurationTestingInternal import ConfigurationTesting struct MultiProviderTests { - let providers: [any ConfigProvider] - init() { + + @available(Configuration 1.0, *) + var providers: [any ConfigProvider] { let first = InMemoryProvider( name: "first", values: [ @@ -51,7 +52,7 @@ struct MultiProviderTests { "other.byteChunky.array": .init([.magic, .magic2, .magic], isSecret: false), ] ) - providers = [ + return [ first, second, ] @@ -62,6 +63,7 @@ struct MultiProviderTests { /// This is not a generally useful wrapper - the multi provider is an internal implementation detail. /// /// Here in tests, it's just helpful to be able to run ProviderCompatTests on it. + @available(Configuration 1.0, *) struct MultiProviderTestShims: ConfigProvider { /// The underlying multi provider. @@ -123,11 +125,13 @@ struct MultiProviderTests { } } + @available(Configuration 1.0, *) @Test func compat() async throws { let multiProvider = MultiProvider(providers: providers) try await ProviderCompatTest(provider: MultiProviderTestShims(multiProvider: multiProvider)).run() } + @available(Configuration 1.0, *) @Test func watchingTwoUpstreams() async throws { let first = MutableInMemoryProvider( name: "first", @@ -172,6 +176,7 @@ struct MultiProviderTests { } } +@available(Configuration 1.0, *) extension MultiSnapshot: ConfigSnapshotProtocol { var providerName: String { "MultiProvider" diff --git a/Tests/ConfigurationTests/MutableInMemoryProviderTests.swift b/Tests/ConfigurationTests/MutableInMemoryProviderTests.swift index 6a84485..7a40955 100644 --- a/Tests/ConfigurationTests/MutableInMemoryProviderTests.swift +++ b/Tests/ConfigurationTests/MutableInMemoryProviderTests.swift @@ -18,9 +18,10 @@ import ConfigurationTestingInternal import ConfigurationTesting struct MutableInMemoryProviderTests { - let provider: MutableInMemoryProvider - init() { - provider = MutableInMemoryProvider( + + @available(Configuration 1.0, *) + func makeProvider() -> MutableInMemoryProvider { + MutableInMemoryProvider( name: "test", initialValues: [ "string": .init("Hello", isSecret: false), @@ -47,25 +48,33 @@ struct MutableInMemoryProviderTests { ) } + @available(Configuration 1.0, *) @Test func printingDescription() throws { let expectedDescription = #""" MutableInMemoryProvider[test, 0 watchers, 20 values] """# + let provider = makeProvider() #expect(provider.description == expectedDescription) } + @available(Configuration 1.0, *) @Test func printingDebugDescription() throws { let expectedDebugDescription = #""" MutableInMemoryProvider[test, 0 watchers, 20 values: bool=[bool: true], booly.array=[boolArray: true, false], byteChunky.array=[byteChunkArray: 5 bytes, prefix: 6d61676963, 6 bytes, prefix: 6d6167696332], bytes=[bytes: 5 bytes, prefix: 6d61676963], double=[double: 3.14], doubly.array=[doubleArray: 3.14, 2.72], int=[int: 42], inty.array=[intArray: 42, 24], other.bool=[bool: false], other.booly.array=[boolArray: false, true, true], other.byteChunky.array=[byteChunkArray: 5 bytes, prefix: 6d61676963, 6 bytes, prefix: 6d6167696332, 5 bytes, prefix: 6d61676963], other.bytes=[bytes: 6 bytes, prefix: 6d6167696332], other.double=[double: 2.72], other.doubly.array=[doubleArray: 0.9, 1.8], other.int=[int: 24], other.inty.array=[intArray: 16, 32], other.string=[string: Other Hello], other.stringy.array=[stringArray: Hello, Swift], string=[string: Hello], stringy.array=[stringArray: Hello, World]] """# + let provider = makeProvider() #expect(provider.debugDescription == expectedDebugDescription) } + @available(Configuration 1.0, *) @Test func compat() async throws { + let provider = makeProvider() try await ProviderCompatTest(provider: provider).run() } + @available(Configuration 1.0, *) @Test func mutatingGet() throws { + let provider = makeProvider() let config = ConfigReader(provider: provider) #expect(config.bool(forKey: "bool") == true) @@ -73,7 +82,9 @@ struct MutableInMemoryProviderTests { #expect(config.bool(forKey: "bool") == false) } + @available(Configuration 1.0, *) @Test func mutatingFetch() async throws { + let provider = makeProvider() let config = ConfigReader(provider: provider) try await #expect(config.fetchBool(forKey: "bool") == true) @@ -81,7 +92,9 @@ struct MutableInMemoryProviderTests { try await #expect(config.fetchBool(forKey: "bool") == false) } + @available(Configuration 1.0, *) @Test func mutatingWatch() async throws { + let provider = makeProvider() let config = ConfigReader(provider: provider) #expect( @@ -114,7 +127,9 @@ struct MutableInMemoryProviderTests { } } + @available(Configuration 1.0, *) @Test func mutatingGetSnapshot() throws { + let provider = makeProvider() let config = ConfigReader(provider: provider) config.withSnapshot { snapshot in @@ -125,7 +140,9 @@ struct MutableInMemoryProviderTests { #expect(config.bool(forKey: "bool") == false) } + @available(Configuration 1.0, *) @Test func mutatingWatchSnapshot() async throws { + let provider = makeProvider() let config = ConfigReader(provider: provider) let firstValueFuture = TestFuture(name: "firstValue") diff --git a/Tests/ConfigurationTests/ReloadingFileProviderCoreTests.swift b/Tests/ConfigurationTests/ReloadingFileProviderCoreTests.swift index bc547ab..3348b10 100644 --- a/Tests/ConfigurationTests/ReloadingFileProviderCoreTests.swift +++ b/Tests/ConfigurationTests/ReloadingFileProviderCoreTests.swift @@ -24,6 +24,7 @@ import ServiceLifecycle import Synchronization import SystemPackage +@available(Configuration 1.0, *) private struct TestSnapshot: ConfigSnapshotProtocol { var values: [String: ConfigValue] @@ -54,54 +55,58 @@ private struct TestSnapshot: ConfigSnapshotProtocol { } } +@available(Configuration 1.0, *) extension InMemoryFileSystem.FileData { static func file(contents: String) -> Self { .file(Data(contents.utf8)) } } +@available(Configuration 1.0, *) extension InMemoryFileSystem.FileInfo { static func file(timestamp: Date, contents: String) -> Self { .init(lastModifiedTimestamp: timestamp, data: .file(contents: contents)) } } -struct ReloadingFileProviderCoreTests { - private func withTestProvider( - body: ( - ReloadingFileProviderCore, - InMemoryFileSystem, - FilePath, - Date - ) async throws -> R - ) async throws -> R { - let filePath = FilePath("/test/config.txt") - let originalTimestamp = Date(timeIntervalSince1970: 1_750_688_537) - let fileSystem = InMemoryFileSystem( - files: [ - filePath: .file( - timestamp: originalTimestamp, - contents: """ - key1=value1 - key2=value2 - """ - ) - ] - ) - let core = try await ReloadingFileProviderCore( - filePath: filePath, - pollInterval: .seconds(1), - providerName: "TestProvider", - fileSystem: fileSystem, - logger: .noop, - metrics: nil, - createSnapshot: { data in - try TestSnapshot(contents: String(decoding: data, as: UTF8.self)) - } - ) - return try await body(core, fileSystem, filePath, originalTimestamp) - } +@available(Configuration 1.0, *) +private func withTestProvider( + body: ( + ReloadingFileProviderCore, + InMemoryFileSystem, + FilePath, + Date + ) async throws -> R +) async throws -> R { + let filePath = FilePath("/test/config.txt") + let originalTimestamp = Date(timeIntervalSince1970: 1_750_688_537) + let fileSystem = InMemoryFileSystem( + files: [ + filePath: .file( + timestamp: originalTimestamp, + contents: """ + key1=value1 + key2=value2 + """ + ) + ] + ) + let core = try await ReloadingFileProviderCore( + filePath: filePath, + pollInterval: .seconds(1), + providerName: "TestProvider", + fileSystem: fileSystem, + logger: .noop, + metrics: nil, + createSnapshot: { data in + try TestSnapshot(contents: String(decoding: data, as: UTF8.self)) + } + ) + return try await body(core, fileSystem, filePath, originalTimestamp) +} +struct CoreTests { + @available(Configuration 1.0, *) @Test func testBasicManualReload() async throws { try await withTestProvider { core, fileSystem, filePath, originalTimestamp in // Check initial values @@ -129,6 +134,7 @@ struct ReloadingFileProviderCoreTests { } } + @available(Configuration 1.0, *) @Test func testBasicTimedReload() async throws { let filePath = FilePath("/test/config.txt") let originalTimestamp = Date(timeIntervalSince1970: 1_750_688_537) @@ -190,6 +196,7 @@ struct ReloadingFileProviderCoreTests { } } + @available(Configuration 1.0, *) @Test func testSymlink_targetPathChanged() async throws { try await withTestProvider { core, fileSystem, filePath, originalTimestamp in let targetPath1 = FilePath("/test/config1.txt") @@ -244,6 +251,7 @@ struct ReloadingFileProviderCoreTests { } } + @available(Configuration 1.0, *) @Test func testSymlink_timestampChanged() async throws { try await withTestProvider { core, fileSystem, filePath, originalTimestamp in let targetPath = FilePath("/test/config1.txt") @@ -292,6 +300,7 @@ struct ReloadingFileProviderCoreTests { } } + @available(Configuration 1.0, *) @Test func testWatchValue() async throws { try await withTestProvider { core, fileSystem, filePath, originalTimestamp in let firstValueConsumed = TestFuture(name: "First value consumed") diff --git a/Tests/ConfigurationTests/ReloadingJSONProviderTests.swift b/Tests/ConfigurationTests/ReloadingJSONProviderTests.swift index 801abe8..0674c4d 100644 --- a/Tests/ConfigurationTests/ReloadingJSONProviderTests.swift +++ b/Tests/ConfigurationTests/ReloadingJSONProviderTests.swift @@ -23,6 +23,7 @@ import Logging import SystemPackage struct ReloadingJSONProviderTests { + @available(Configuration 1.0, *) @Test func printingDescription() async throws { let provider = try await ReloadingJSONProvider(filePath: jsonConfigFile) let expectedDescription = #""" @@ -31,6 +32,7 @@ struct ReloadingJSONProviderTests { #expect(provider.description == expectedDescription) } + @available(Configuration 1.0, *) @Test func printingDebugDescription() async throws { let provider = try await ReloadingJSONProvider(filePath: jsonConfigFile) let expectedDebugDescription = #""" @@ -39,11 +41,13 @@ struct ReloadingJSONProviderTests { #expect(provider.debugDescription == expectedDebugDescription) } + @available(Configuration 1.0, *) @Test func compat() async throws { let provider = try await ReloadingJSONProvider(filePath: jsonConfigFile) try await ProviderCompatTest(provider: provider).run() } + @available(Configuration 1.0, *) @Test func initializationWithConfig() async throws { // Test initialization using config reader let envProvider = InMemoryProvider(values: [ diff --git a/Tests/ConfigurationTests/ReloadingYAMLProviderTests.swift b/Tests/ConfigurationTests/ReloadingYAMLProviderTests.swift index 70b4cb7..6371541 100644 --- a/Tests/ConfigurationTests/ReloadingYAMLProviderTests.swift +++ b/Tests/ConfigurationTests/ReloadingYAMLProviderTests.swift @@ -23,6 +23,7 @@ import Logging import SystemPackage struct ReloadingYAMLProviderTests { + @available(Configuration 1.0, *) @Test func printingDescription() async throws { let provider = try await ReloadingYAMLProvider(filePath: yamlConfigFile) let expectedDescription = #""" @@ -31,6 +32,7 @@ struct ReloadingYAMLProviderTests { #expect(provider.description == expectedDescription) } + @available(Configuration 1.0, *) @Test func printingDebugDescription() async throws { let provider = try await ReloadingYAMLProvider(filePath: yamlConfigFile) let expectedDebugDescription = #""" @@ -39,11 +41,13 @@ struct ReloadingYAMLProviderTests { #expect(provider.debugDescription == expectedDebugDescription) } + @available(Configuration 1.0, *) @Test func compat() async throws { let provider = try await ReloadingYAMLProvider(filePath: yamlConfigFile) try await ProviderCompatTest(provider: provider).run() } + @available(Configuration 1.0, *) @Test func initializationWithConfig() async throws { // Test initialization using config reader let envProvider = InMemoryProvider(values: [ diff --git a/Tests/ConfigurationTests/SecretMarkingTests.swift b/Tests/ConfigurationTests/SecretMarkingTests.swift index cf3f9e2..1668552 100644 --- a/Tests/ConfigurationTests/SecretMarkingTests.swift +++ b/Tests/ConfigurationTests/SecretMarkingTests.swift @@ -18,6 +18,7 @@ import ConfigurationTestingInternal struct SecretMarkingTests { + @available(Configuration 1.0, *) @Test func secretHandling() throws { let provider = InMemoryProvider(values: [ "public.key": ConfigValue("public-value", isSecret: false), @@ -37,6 +38,7 @@ struct SecretMarkingTests { #expect(try events[1].result.get()?.isSecret == true) } + @available(Configuration 1.0, *) @Test func get() throws { let accessReporter = TestAccessReporter() let provider = InMemoryProvider( @@ -81,6 +83,7 @@ struct SecretMarkingTests { try #expect(events[3].result.get() == ConfigValue("s3cret", isSecret: true)) } + @available(Configuration 1.0, *) @Test func fetch() async throws { let accessReporter = TestAccessReporter() let provider = InMemoryProvider( @@ -126,6 +129,7 @@ struct SecretMarkingTests { try #expect(events[3].result.get() == ConfigValue("s3cret", isSecret: true)) } + @available(Configuration 1.0, *) @Test func watch() async throws { let accessReporter = TestAccessReporter() let provider = InMemoryProvider( diff --git a/Tests/ConfigurationTests/SeparatorKeyEncoderTests.swift b/Tests/ConfigurationTests/SeparatorKeyEncoderTests.swift index 08b6a63..95ad240 100644 --- a/Tests/ConfigurationTests/SeparatorKeyEncoderTests.swift +++ b/Tests/ConfigurationTests/SeparatorKeyEncoderTests.swift @@ -16,6 +16,7 @@ import Configuration import Testing struct SeparatorKeyEncoderTests { + @available(Configuration 1.0, *) @Test func dotEncoding() { let encoder: any ConfigKeyEncoder = .dotSeparated #expect(encoder.encode(.init(["foo"])) == "foo") @@ -24,6 +25,7 @@ struct SeparatorKeyEncoderTests { #expect(encoder.encode(.init(["foo.bar"])) == "foo.bar") } + @available(Configuration 1.0, *) @Test func dashEncoding() { let encoder: any ConfigKeyEncoder = .dashSeparated #expect(encoder.encode(.init(["foo"])) == "foo") diff --git a/Tests/ConfigurationTests/YAMLProviderTests.swift b/Tests/ConfigurationTests/YAMLProviderTests.swift index dc0f9a9..7bc1abd 100644 --- a/Tests/ConfigurationTests/YAMLProviderTests.swift +++ b/Tests/ConfigurationTests/YAMLProviderTests.swift @@ -25,25 +25,31 @@ private let resourcesPath = FilePath(try! #require(Bundle.module.path(forResourc let yamlConfigFile = resourcesPath.appending("/config.yaml") struct YAMLProviderTests { - let provider: YAMLProvider - init() async throws { - provider = try await YAMLProvider(filePath: yamlConfigFile) + + @available(Configuration 1.0, *) + var provider: YAMLProvider { + get async throws { + try await YAMLProvider(filePath: yamlConfigFile) + } } - @Test func printingDescription() throws { + @available(Configuration 1.0, *) + @Test func printingDescription() async throws { let expectedDescription = #""" YAMLProvider[20 values] """# - #expect(provider.description == expectedDescription) + try await #expect(provider.description == expectedDescription) } - @Test func printingDebugDescription() throws { + @available(Configuration 1.0, *) + @Test func printingDebugDescription() async throws { let expectedDebugDescription = #""" YAMLProvider[20 values: bool=true, booly.array=true,false, byteChunky.array=bWFnaWM=,bWFnaWMy, bytes=bWFnaWM=, double=3.14, doubly.array=3.14,2.72, int=42, inty.array=42,24, other.bool=false, other.booly.array=false,true,true, other.byteChunky.array=bWFnaWM=,bWFnaWMy,bWFnaWM=, other.bytes=bWFnaWMy, other.double=2.72, other.doubly.array=0.9,1.8, other.int=24, other.inty.array=16,32, other.string=Other Hello, other.stringy.array=Hello,Swift, string=Hello, stringy.array=Hello,World] """# - #expect(provider.debugDescription == expectedDebugDescription) + try await #expect(provider.debugDescription == expectedDebugDescription) } + @available(Configuration 1.0, *) @Test func compat() async throws { try await ProviderCompatTest(provider: provider).run() }