Skip to content

Commit 618d19d

Browse files
authored
Move from platform versions to symbol availability (#48)
### Motivation Packages such as valkey-swift and async-http-client don't use platform versions in their Package.swift, so they can't depend on this package unless we drop it too. ### Modifications Switched from Package.swift platform versions to per-symbol availability. ### Result This does NOT actually make the code work on older versions than before, just changes how we express availability. It's still macOS 15.0+. ### Test Plan All tests passed locally.
1 parent 1f7cd0d commit 618d19d

File tree

93 files changed

+387
-81
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+387
-81
lines changed

Package.swift

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,6 @@ traits.insert(
7070

7171
let package = Package(
7272
name: "swift-configuration",
73-
platforms: [
74-
.macOS(.v15), .iOS(.v18), .macCatalyst(.v18), .tvOS(.v18), .watchOS(.v11), .visionOS(.v2),
75-
],
7673
products: [
7774
.library(name: "Configuration", targets: ["Configuration"]),
7875
.library(name: "ConfigurationTesting", targets: ["ConfigurationTesting"]),
@@ -170,21 +167,21 @@ let package = Package(
170167
)
171168

172169
for target in package.targets {
173-
if target.type != .plugin {
174-
var settings = target.swiftSettings ?? []
170+
var settings = target.swiftSettings ?? []
171+
172+
// https://github.com/apple/swift-evolution/blob/main/proposals/0335-existential-any.md
173+
// Require `any` for existential types.
174+
settings.append(.enableUpcomingFeature("ExistentialAny"))
175175

176-
// https://github.com/apple/swift-evolution/blob/main/proposals/0335-existential-any.md
177-
// Require `any` for existential types.
178-
settings.append(.enableUpcomingFeature("ExistentialAny"))
176+
// https://github.com/swiftlang/swift-evolution/blob/main/proposals/0444-member-import-visibility.md
177+
settings.append(.enableUpcomingFeature("MemberImportVisibility"))
179178

180-
// https://github.com/swiftlang/swift-evolution/blob/main/proposals/0444-member-import-visibility.md
181-
settings.append(.enableUpcomingFeature("MemberImportVisibility"))
179+
// https://github.com/swiftlang/swift-evolution/blob/main/proposals/0409-access-level-on-imports.md
180+
settings.append(.enableUpcomingFeature("InternalImportsByDefault"))
182181

183-
// https://github.com/swiftlang/swift-evolution/blob/main/proposals/0409-access-level-on-imports.md
184-
settings.append(.enableUpcomingFeature("InternalImportsByDefault"))
182+
settings.append(.enableExperimentalFeature("AvailabilityMacro=Configuration 1.0:macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0"))
185183

186-
target.swiftSettings = settings
187-
}
184+
target.swiftSettings = settings
188185
}
189186

190187
if addDoccPlugin {

Sources/Configuration/AccessReporter.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import Synchronization
2424
/// Access reporters track when configuration values are read, fetched, or watched,
2525
/// to provide visibility into configuration usage patterns. This is useful for
2626
/// debugging, auditing, and understanding configuration dependencies.
27+
@available(Configuration 1.0, *)
2728
public protocol AccessReporter: Sendable {
2829

2930
/// Processes a configuration access event.
@@ -41,6 +42,7 @@ public protocol AccessReporter: Sendable {
4142
/// Access events are generated whenever configuration values are accessed through
4243
/// ``ConfigReader`` and ``ConfigSnapshotReader`` methods. They contain metadata about
4344
/// the access, results from individual providers, and the final outcome of the operation.
45+
@available(Configuration 1.0, *)
4446
public struct AccessEvent: Sendable {
4547

4648
/// Metadata describing the configuration access operation.
@@ -184,6 +186,7 @@ public struct AccessEvent: Sendable {
184186
/// Use this reporter to send configuration access events to multiple destinations
185187
/// simultaneously. Each upstream reporter receives a copy of every event in the
186188
/// order they were provided during initialization.
189+
@available(Configuration 1.0, *)
187190
public struct BroadcastingAccessReporter: Sendable {
188191

189192
/// The reporters that receive forwarded events.
@@ -198,6 +201,7 @@ public struct BroadcastingAccessReporter: Sendable {
198201
}
199202
}
200203

204+
@available(Configuration 1.0, *)
201205
extension BroadcastingAccessReporter: AccessReporter {
202206
// swift-format-ignore: AllPublicDeclarationsHaveDocumentation
203207
public func report(_ event: AccessEvent) {

Sources/Configuration/AccessReporters/AccessLogger.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import Synchronization
5353
/// - `value`: The resolved configuration value (redacted for secrets)
5454
/// - `counter`: An incrementing counter for tracking access frequency
5555
/// - Provider-specific information for each provider in the hierarchy
56+
@available(Configuration 1.0, *)
5657
public final class AccessLogger: Sendable {
5758

5859
/// The logger used to emit configuration access events.
@@ -94,6 +95,7 @@ public final class AccessLogger: Sendable {
9495
}
9596
}
9697

98+
@available(Configuration 1.0, *)
9799
extension AccessLogger: AccessReporter {
98100
// swift-format-ignore: AllPublicDeclarationsHaveDocumentation
99101
public func report(_ event: AccessEvent) {
@@ -109,6 +111,7 @@ extension AccessLogger: AccessReporter {
109111
}
110112
}
111113

114+
@available(Configuration 1.0, *)
112115
extension AccessEvent.Metadata {
113116
/// Add log metadata.
114117
/// - Parameter metadata: The metadata to which to add values.
@@ -119,6 +122,7 @@ extension AccessEvent.Metadata {
119122
}
120123
}
121124

125+
@available(Configuration 1.0, *)
122126
extension AccessEvent.ProviderResult {
123127
/// Add log metadata.
124128
/// - Parameters:
@@ -136,6 +140,7 @@ extension AccessEvent.ProviderResult {
136140
}
137141
}
138142

143+
@available(Configuration 1.0, *)
139144
extension AccessEvent {
140145
/// Add log metadata.
141146
/// - Parameter metadata: The metadata to which to add values.
@@ -151,6 +156,7 @@ extension AccessEvent {
151156
}
152157
}
153158

159+
@available(Configuration 1.0, *)
154160
extension Result<ConfigValue?, any Error> {
155161
/// Add log metadata.
156162
/// - Parameter metadata: The metadata to which to add values.

Sources/Configuration/AccessReporters/FileAccessLogger.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ import Synchronization
6464
/// - Resolved value (redacted for secrets)
6565
/// - Provider that supplied the value or error information
6666
/// - Access metadata (operation type, value type, source location, timestamp)
67+
@available(Configuration 1.0, *)
6768
public final class FileAccessLogger: Sendable {
6869

6970
/// The file descriptor used for writing access events to the log file.
@@ -199,6 +200,7 @@ public final class FileAccessLogger: Sendable {
199200
}
200201
}
201202

203+
@available(Configuration 1.0, *)
202204
extension FileAccessLogger: AccessReporter {
203205
// swift-format-ignore: AllPublicDeclarationsHaveDocumentation
204206
public func report(_ event: AccessEvent) {
@@ -213,6 +215,7 @@ extension FileAccessLogger: AccessReporter {
213215
}
214216
}
215217

218+
@available(Configuration 1.0, *)
216219
extension FileAccessLogger {
217220
/// Renders a string summary for the event.
218221
/// - Parameter event: The event to render.
@@ -222,6 +225,7 @@ extension FileAccessLogger {
222225
}
223226
}
224227

228+
@available(Configuration 1.0, *)
225229
extension AccessEvent {
226230
/// Returns a human-readable single line string summarizing the access event.
227231
/// - Parameter dateFormatStyle: The format style used for rendering dates.
@@ -280,6 +284,7 @@ extension AccessEvent {
280284
}
281285
}
282286

287+
@available(Configuration 1.0, *)
283288
extension ConfigContent {
284289
/// Returns a string representation of the config value, formatting complex types appropriately.
285290
///

Sources/Configuration/ConfigProvider.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
///
4646
/// **Dynamic providers**: Implement `watch` methods to emit real-time updates from
4747
/// polling, file system monitoring, or other change detection mechanisms.
48+
@available(Configuration 1.0, *)
4849
public protocol ConfigProvider: Sendable {
4950

5051
/// The human-readable name of the configuration provider.
@@ -137,6 +138,7 @@ public protocol ConfigProvider: Sendable {
137138
/// Snapshots enable consistent reads of multiple related configuration keys by
138139
/// capturing the provider's state at a specific moment. This prevents the underlying
139140
/// data from changing between individual key lookups.
141+
@available(Configuration 1.0, *)
140142
public protocol ConfigSnapshotProtocol: Sendable {
141143

142144
/// The human-readable name of the configuration provider that created this snapshot.
@@ -159,6 +161,7 @@ public protocol ConfigSnapshotProtocol: Sendable {
159161
}
160162

161163
/// The result of looking up a configuration value in a provider.
164+
@available(Configuration 1.0, *)
162165
public struct LookupResult: Sendable, Equatable, Hashable {
163166

164167
/// The provider-specific encoding of the configuration key.
@@ -181,6 +184,7 @@ public struct LookupResult: Sendable, Equatable, Hashable {
181184
}
182185

183186
/// The supported configuration value types.
187+
@available(Configuration 1.0, *)
184188
@frozen public enum ConfigType: String, Sendable, Equatable, Hashable {
185189

186190
/// A string value.
@@ -215,6 +219,7 @@ public struct LookupResult: Sendable, Equatable, Hashable {
215219
}
216220

217221
/// The raw content of a configuration value.
222+
@available(Configuration 1.0, *)
218223
@frozen public enum ConfigContent: Sendable, Equatable, Hashable {
219224

220225
/// A string value.
@@ -433,6 +438,7 @@ public struct LookupResult: Sendable, Equatable, Hashable {
433438
/// Configuration values include the actual content and a flag indicating whether
434439
/// the value contains sensitive information. Secret values are protected from
435440
/// accidental disclosure in logs and debug output.
441+
@available(Configuration 1.0, *)
436442
public struct ConfigValue: Sendable, Equatable, Hashable {
437443

438444
/// The configuration content.
@@ -451,6 +457,7 @@ public struct ConfigValue: Sendable, Equatable, Hashable {
451457
}
452458
}
453459

460+
@available(Configuration 1.0, *)
454461
extension ConfigValue: CustomStringConvertible {
455462
// swift-format-ignore: AllPublicDeclarationsHaveDocumentation
456463
public var description: String {
@@ -462,55 +469,63 @@ extension ConfigValue: CustomStringConvertible {
462469
}
463470
}
464471

472+
@available(Configuration 1.0, *)
465473
extension ConfigValue: ExpressibleByStringLiteral {
466474
// swift-format-ignore: AllPublicDeclarationsHaveDocumentation
467475
public init(stringLiteral value: String) {
468476
self = .init(.string(value), isSecret: false)
469477
}
470478
}
471479

480+
@available(Configuration 1.0, *)
472481
extension ConfigContent: ExpressibleByStringLiteral {
473482
// swift-format-ignore: AllPublicDeclarationsHaveDocumentation
474483
public init(stringLiteral value: String) {
475484
self = .string(value)
476485
}
477486
}
478487

488+
@available(Configuration 1.0, *)
479489
extension ConfigValue: ExpressibleByIntegerLiteral {
480490
// swift-format-ignore: AllPublicDeclarationsHaveDocumentation
481491
public init(integerLiteral value: Int) {
482492
self = .init(.int(value), isSecret: false)
483493
}
484494
}
485495

496+
@available(Configuration 1.0, *)
486497
extension ConfigContent: ExpressibleByIntegerLiteral {
487498
// swift-format-ignore: AllPublicDeclarationsHaveDocumentation
488499
public init(integerLiteral value: Int) {
489500
self = .int(value)
490501
}
491502
}
492503

504+
@available(Configuration 1.0, *)
493505
extension ConfigValue: ExpressibleByFloatLiteral {
494506
// swift-format-ignore: AllPublicDeclarationsHaveDocumentation
495507
public init(floatLiteral value: Double) {
496508
self = .init(.double(value), isSecret: false)
497509
}
498510
}
499511

512+
@available(Configuration 1.0, *)
500513
extension ConfigContent: ExpressibleByFloatLiteral {
501514
// swift-format-ignore: AllPublicDeclarationsHaveDocumentation
502515
public init(floatLiteral value: Double) {
503516
self = .double(value)
504517
}
505518
}
506519

520+
@available(Configuration 1.0, *)
507521
extension ConfigValue: ExpressibleByBooleanLiteral {
508522
// swift-format-ignore: AllPublicDeclarationsHaveDocumentation
509523
public init(booleanLiteral value: Bool) {
510524
self = .init(.bool(value), isSecret: false)
511525
}
512526
}
513527

528+
@available(Configuration 1.0, *)
514529
extension ConfigContent: ExpressibleByBooleanLiteral {
515530
// swift-format-ignore: AllPublicDeclarationsHaveDocumentation
516531
public init(booleanLiteral value: Bool) {

Sources/Configuration/ConfigProviderHelpers.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
//
1313
//===----------------------------------------------------------------------===//
1414

15+
@available(Configuration 1.0, *)
1516
extension ConfigProvider {
1617

1718
/// Implements `watchValue` by getting the current value and emitting it immediately.
@@ -116,6 +117,7 @@ extension ConfigProvider {
116117
/// - work: A closure that performs the value lookup and returns the result.
117118
/// - Returns: A lookup result containing the encoded key and the value from the closure.
118119
/// - Throws: Rethrows any errors thrown by the provided closure.
120+
@available(Configuration 1.0, *)
119121
package func withConfigValueLookup<Failure: Error>(
120122
encodedKey: String,
121123
work: () throws(Failure) -> ConfigValue?
@@ -147,6 +149,7 @@ package func withConfigValueLookup<Failure: Error>(
147149
/// - work: An async closure that performs the value lookup and returns the result.
148150
/// - Returns: A lookup result containing the encoded key and the value from the closure.
149151
/// - Throws: Rethrows any errors thrown by the provided closure.
152+
@available(Configuration 1.0, *)
150153
package func withConfigValueLookup<Failure: Error>(
151154
encodedKey: String,
152155
work: () async throws(Failure) -> ConfigValue?

Sources/Configuration/ConfigReader+internalHelpers.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import FoundationEssentials
1818
import Foundation
1919
#endif
2020

21+
@available(Configuration 1.0, *)
2122
extension ConfigValue {
2223
/// Returns a copy of the config value marked as secret.
2324
///
@@ -29,6 +30,7 @@ extension ConfigValue {
2930
}
3031
}
3132

33+
@available(Configuration 1.0, *)
3234
extension Result<ConfigValue?, any Error> {
3335
/// Returns a copy of the result with the value marked as secret.
3436
///
@@ -38,6 +40,7 @@ extension Result<ConfigValue?, any Error> {
3840
}
3941
}
4042

43+
@available(Configuration 1.0, *)
4144
extension LookupResult {
4245
/// Returns a copy of the config value marked as secret.
4346
///
@@ -49,6 +52,7 @@ extension LookupResult {
4952
}
5053
}
5154

55+
@available(Configuration 1.0, *)
5256
extension Result<LookupResult, any Error> {
5357
/// Returns a copy of the result with the value marked as secret.
5458
///
@@ -58,6 +62,7 @@ extension Result<LookupResult, any Error> {
5862
}
5963
}
6064

65+
@available(Configuration 1.0, *)
6166
extension AccessEvent.ProviderResult {
6267
/// Returns a copy of the result marked as secret.
6368
///
@@ -80,6 +85,7 @@ extension AccessEvent.ProviderResult {
8085
/// - isSecret: Whether to mark the values as secret.
8186
/// - tuple: A tuple containing provider results and a configuration value result.
8287
/// - Returns: The tuple with values marked as secret if the flag is true, otherwise unchanged.
88+
@available(Configuration 1.0, *)
8389
private func mergingIsSecret(
8490
_ isSecret: Bool,
8591
_ tuple: ([AccessEvent.ProviderResult], Result<ConfigValue?, any Error>)
@@ -121,6 +127,7 @@ private func mergingIsSecret(
121127
/// - fileID: Source file identifier for access event metadata.
122128
/// - line: Source line number for access event metadata.
123129
/// - Returns: The converted configuration value, or `nil` if not found or conversion fails.
130+
@available(Configuration 1.0, *)
124131
internal func valueFromReader<Value>(
125132
forKey key: ConfigKey,
126133
type: ConfigType,
@@ -193,6 +200,7 @@ internal func valueFromReader<Value>(
193200
/// - fileID: Source file identifier used for event reporting.
194201
/// - line: Source line number used for event reporting.
195202
/// - Returns: The configuration value converted to the requested type.
203+
@available(Configuration 1.0, *)
196204
internal func valueFromReader<Value>(
197205
forKey key: ConfigKey,
198206
type: ConfigType,
@@ -269,6 +277,7 @@ internal func valueFromReader<Value>(
269277
/// - Throws: `ConfigError.missingRequiredConfigValue` if the configuration value is not found, or any error thrown
270278
/// by the `unwrap` closure if conversion fails.
271279
/// - Returns: The configuration value converted to the requested type.
280+
@available(Configuration 1.0, *)
272281
internal func requiredValueFromReader<Value>(
273282
forKey key: ConfigKey,
274283
type: ConfigType,
@@ -324,6 +333,7 @@ internal func requiredValueFromReader<Value>(
324333
return try finalResult.get().0
325334
}
326335

336+
@available(Configuration 1.0, *)
327337
extension ConfigReader {
328338

329339
/// Gets a config value synchronously.

Sources/Configuration/ConfigReader+methods.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
// # #
1919
// #############################################################################
2020

21+
@available(Configuration 1.0, *)
2122
extension ConfigReader {
2223

2324
// MARK: - Get

0 commit comments

Comments
 (0)