diff --git a/Sources/Configuration/ConfigProvider.swift b/Sources/Configuration/ConfigProvider.swift index ae2d23f..caea6c6 100644 --- a/Sources/Configuration/ConfigProvider.swift +++ b/Sources/Configuration/ConfigProvider.swift @@ -115,7 +115,7 @@ public protocol ConfigProvider: Sendable { /// significant performance impact. /// /// - Returns: An immutable snapshot that represents the current provider state. - func snapshot() -> any ConfigSnapshotProtocol + func snapshot() -> any ConfigSnapshot /// Monitors the provider's state for changes by emitting snapshots. /// @@ -129,7 +129,7 @@ public protocol ConfigProvider: Sendable { /// - Throws: Provider-specific errors or errors thrown by the handler closure. /// - Returns: The value returned by the closure. func watchSnapshot( - updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Return + updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Return ) async throws -> Return } @@ -139,7 +139,7 @@ public protocol ConfigProvider: Sendable { /// 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 { +public protocol ConfigSnapshot: Sendable { /// The human-readable name of the configuration provider that created this snapshot. /// diff --git a/Sources/Configuration/ConfigProviderHelpers.swift b/Sources/Configuration/ConfigProviderHelpers.swift index 95cb83c..8db6c27 100644 --- a/Sources/Configuration/ConfigProviderHelpers.swift +++ b/Sources/Configuration/ConfigProviderHelpers.swift @@ -76,7 +76,7 @@ extension ConfigProvider { /// /// ```swift /// func watchSnapshot( - /// updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Void + /// updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Void /// ) async throws { /// try await watchSnapshotFromSnapshot(updatesHandler) /// } @@ -85,12 +85,10 @@ extension ConfigProvider { /// - Parameter updatesHandler: The closure that processes the async sequence of snapshot updates. /// - Returns: The value returned by the handler closure. /// - Throws: Provider-specific errors or errors thrown by the handler. - nonisolated(nonsending) - public func watchSnapshotFromSnapshot( - updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Return - ) async throws -> Return - { - let (stream, continuation) = AsyncStream + nonisolated(nonsending) public func watchSnapshotFromSnapshot( + updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Return + ) async throws -> Return { + let (stream, continuation) = AsyncStream .makeStream(bufferingPolicy: .bufferingNewest(1)) let initialValue = snapshot() continuation.yield(initialValue) diff --git a/Sources/Configuration/Deprecations.swift b/Sources/Configuration/Deprecations.swift index 0de81e6..f51902e 100644 --- a/Sources/Configuration/Deprecations.swift +++ b/Sources/Configuration/Deprecations.swift @@ -43,3 +43,8 @@ public typealias ReloadingYAMLProvider = ReloadingFileProvider #endif #endif + +/// An immutable snapshot of a configuration provider's state. +@available(Configuration 1.0, *) +@available(*, deprecated, renamed: "ConfigSnapshot") +public typealias ConfigSnapshotProtocol = ConfigSnapshot diff --git a/Sources/Configuration/Documentation.docc/Documentation.md b/Sources/Configuration/Documentation.docc/Documentation.md index 7649110..273f10a 100644 --- a/Sources/Configuration/Documentation.docc/Documentation.md +++ b/Sources/Configuration/Documentation.docc/Documentation.md @@ -426,7 +426,7 @@ Any package can implement a ``ConfigProvider``, making the ecosystem extensible - ``KeyMappingProvider`` ### Creating a custom provider -- ``ConfigSnapshotProtocol`` +- ``ConfigSnapshot`` - ``FileParsingOptions`` - ``ConfigProvider`` - ``ConfigContent`` diff --git a/Sources/Configuration/Documentation.docc/Reference/ConfigSnapshot.md b/Sources/Configuration/Documentation.docc/Reference/ConfigSnapshot.md new file mode 100644 index 0000000..1f60076 --- /dev/null +++ b/Sources/Configuration/Documentation.docc/Reference/ConfigSnapshot.md @@ -0,0 +1,8 @@ +# ``Configuration/ConfigSnapshot`` + +## Topics + +### Required methods + +- ``ConfigSnapshot/providerName`` +- ``ConfigSnapshot/value(forKey:type:)`` diff --git a/Sources/Configuration/Documentation.docc/Reference/ConfigSnapshotProtocol.md b/Sources/Configuration/Documentation.docc/Reference/ConfigSnapshotProtocol.md deleted file mode 100644 index 3052a70..0000000 --- a/Sources/Configuration/Documentation.docc/Reference/ConfigSnapshotProtocol.md +++ /dev/null @@ -1,8 +0,0 @@ -# ``Configuration/ConfigSnapshotProtocol`` - -## Topics - -### Required methods - -- ``ConfigSnapshotProtocol/providerName`` -- ``ConfigSnapshotProtocol/value(forKey:type:)`` diff --git a/Sources/Configuration/Documentation.docc/Reference/FileConfigSnapshot.md b/Sources/Configuration/Documentation.docc/Reference/FileConfigSnapshot.md index 5f5ebe8..f88efab 100644 --- a/Sources/Configuration/Documentation.docc/Reference/FileConfigSnapshot.md +++ b/Sources/Configuration/Documentation.docc/Reference/FileConfigSnapshot.md @@ -9,4 +9,4 @@ ### Protocol requirements -- ``ConfigSnapshotProtocol`` +- ``ConfigSnapshot`` diff --git a/Sources/Configuration/Documentation.docc/Reference/JSONSnapshot.md b/Sources/Configuration/Documentation.docc/Reference/JSONSnapshot.md index fd6ff92..c2901cc 100644 --- a/Sources/Configuration/Documentation.docc/Reference/JSONSnapshot.md +++ b/Sources/Configuration/Documentation.docc/Reference/JSONSnapshot.md @@ -10,4 +10,4 @@ ### Snapshot configuration - ``FileConfigSnapshot`` -- ``ConfigSnapshotProtocol`` +- ``ConfigSnapshot`` diff --git a/Sources/Configuration/Documentation.docc/Reference/YAMLSnapshot.md b/Sources/Configuration/Documentation.docc/Reference/YAMLSnapshot.md index 8e9d03b..d0c8365 100644 --- a/Sources/Configuration/Documentation.docc/Reference/YAMLSnapshot.md +++ b/Sources/Configuration/Documentation.docc/Reference/YAMLSnapshot.md @@ -10,4 +10,4 @@ ### Snapshot configuration - ``FileConfigSnapshot`` -- ``ConfigSnapshotProtocol`` +- ``ConfigSnapshot`` diff --git a/Sources/Configuration/MultiProvider.swift b/Sources/Configuration/MultiProvider.swift index 23bcd0c..d73dfaf 100644 --- a/Sources/Configuration/MultiProvider.swift +++ b/Sources/Configuration/MultiProvider.swift @@ -89,7 +89,7 @@ extension MultiProvider: CustomStringConvertible { struct MultiSnapshot { /// The individual snapshots from each nested provider, maintained in precedence order. - var snapshots: [any ConfigSnapshotProtocol] + var snapshots: [any ConfigSnapshot] /// Resolves a configuration value by querying nested provider snapshots in precedence order. /// - Parameters: @@ -201,7 +201,7 @@ extension MultiProvider { ) async throws -> Return { let providers = storage.providers - typealias UpdatesSequence = any (AsyncSequence & Sendable) + typealias UpdatesSequence = any (AsyncSequence & Sendable) var updateSequences: [UpdatesSequence] = [] updateSequences.reserveCapacity(providers.count) return try await withProvidersWatchingSnapshot( diff --git a/Sources/Configuration/Providers/CLI/CLISnapshot.swift b/Sources/Configuration/Providers/CLI/CLISnapshot.swift index 0a2e321..85bcd65 100644 --- a/Sources/Configuration/Providers/CLI/CLISnapshot.swift +++ b/Sources/Configuration/Providers/CLI/CLISnapshot.swift @@ -155,7 +155,7 @@ internal struct CLISnapshot { } @available(Configuration 1.0, *) -extension CLISnapshot: ConfigSnapshotProtocol { +extension CLISnapshot: ConfigSnapshot { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation func value(forKey key: AbsoluteConfigKey, type: ConfigType) throws -> LookupResult { let encodedKey = keyEncoder.encode(key) diff --git a/Sources/Configuration/Providers/CLI/CommandLineArgumentsProvider.swift b/Sources/Configuration/Providers/CLI/CommandLineArgumentsProvider.swift index 08186bd..515c7d8 100644 --- a/Sources/Configuration/Providers/CLI/CommandLineArgumentsProvider.swift +++ b/Sources/Configuration/Providers/CLI/CommandLineArgumentsProvider.swift @@ -159,13 +159,13 @@ extension CommandLineArgumentsProvider: ConfigProvider { } // swift-format-ignore: AllPublicDeclarationsHaveDocumentation - public func snapshot() -> any ConfigSnapshotProtocol { + public func snapshot() -> any ConfigSnapshot { _snapshot } // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public func watchSnapshot( - updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Return + updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Return ) async throws -> Return { try await watchSnapshotFromSnapshot(updatesHandler: updatesHandler) } diff --git a/Sources/Configuration/Providers/EnvironmentVariables/EnvironmentVariablesProvider.swift b/Sources/Configuration/Providers/EnvironmentVariables/EnvironmentVariablesProvider.swift index aeabb03..de71a22 100644 --- a/Sources/Configuration/Providers/EnvironmentVariables/EnvironmentVariablesProvider.swift +++ b/Sources/Configuration/Providers/EnvironmentVariables/EnvironmentVariablesProvider.swift @@ -442,7 +442,7 @@ extension EnvironmentVariablesProvider.Snapshot { } @available(Configuration 1.0, *) -extension EnvironmentVariablesProvider.Snapshot: ConfigSnapshotProtocol { +extension EnvironmentVariablesProvider.Snapshot: ConfigSnapshot { func value( forKey key: AbsoluteConfigKey, type: ConfigType @@ -495,13 +495,13 @@ extension EnvironmentVariablesProvider: ConfigProvider { } // swift-format-ignore: AllPublicDeclarationsHaveDocumentation - public func snapshot() -> any ConfigSnapshotProtocol { + public func snapshot() -> any ConfigSnapshot { _snapshot } // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public func watchSnapshot( - updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Return + updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Return ) async throws -> Return { try await watchSnapshotFromSnapshot(updatesHandler: updatesHandler) } diff --git a/Sources/Configuration/Providers/Files/DirectoryFilesProvider.swift b/Sources/Configuration/Providers/Files/DirectoryFilesProvider.swift index b5b0ff5..367fe94 100644 --- a/Sources/Configuration/Providers/Files/DirectoryFilesProvider.swift +++ b/Sources/Configuration/Providers/Files/DirectoryFilesProvider.swift @@ -381,7 +381,7 @@ extension DirectoryFilesProvider.Snapshot { } @available(Configuration 1.0, *) -extension DirectoryFilesProvider.Snapshot: ConfigSnapshotProtocol { +extension DirectoryFilesProvider.Snapshot: ConfigSnapshot { func value( forKey key: AbsoluteConfigKey, type: ConfigType @@ -433,13 +433,13 @@ extension DirectoryFilesProvider: ConfigProvider { } // swift-format-ignore: AllPublicDeclarationsHaveDocumentation - public func snapshot() -> any ConfigSnapshotProtocol { + public func snapshot() -> any ConfigSnapshot { _snapshot } // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public func watchSnapshot( - updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Return + updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Return ) async throws -> Return { try await watchSnapshotFromSnapshot(updatesHandler: updatesHandler) } diff --git a/Sources/Configuration/Providers/Files/FileProvider.swift b/Sources/Configuration/Providers/Files/FileProvider.swift index 189eb38..eafaafb 100644 --- a/Sources/Configuration/Providers/Files/FileProvider.swift +++ b/Sources/Configuration/Providers/Files/FileProvider.swift @@ -178,7 +178,7 @@ extension FileProvider: ConfigProvider { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public func watchSnapshot( - updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Return + updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Return ) async throws -> Return { try await watchSnapshotFromSnapshot(updatesHandler: updatesHandler) } @@ -195,7 +195,7 @@ extension FileProvider: ConfigProvider { } // swift-format-ignore: AllPublicDeclarationsHaveDocumentation - public func snapshot() -> any ConfigSnapshotProtocol { + public func snapshot() -> any ConfigSnapshot { _snapshot } } diff --git a/Sources/Configuration/Providers/Files/FileProviderSnapshot.swift b/Sources/Configuration/Providers/Files/FileProviderSnapshot.swift index b4bcc25..4ac421c 100644 --- a/Sources/Configuration/Providers/Files/FileProviderSnapshot.swift +++ b/Sources/Configuration/Providers/Files/FileProviderSnapshot.swift @@ -47,7 +47,7 @@ public protocol FileParsingOptions: Sendable { /// A protocol for configuration snapshots created from file data. /// -/// This protocol extends ``ConfigSnapshotProtocol`` to provide file-specific functionality +/// This protocol extends ``ConfigSnapshot`` to provide file-specific functionality /// for creating configuration snapshots from raw file data. Types conforming to this protocol /// can parse various file formats (such as JSON and YAML) and convert them into configuration values. /// @@ -75,7 +75,7 @@ public protocol FileParsingOptions: Sendable { /// The snapshot is responsible for parsing the file data and converting it into a /// representation of configuration values that can be queried by the configuration system. @available(Configuration 1.0, *) -public protocol FileConfigSnapshot: ConfigSnapshotProtocol, CustomStringConvertible, +public protocol FileConfigSnapshot: ConfigSnapshot, CustomStringConvertible, CustomDebugStringConvertible { /// The parsing options type used for parsing this snapshot. diff --git a/Sources/Configuration/Providers/Files/JSONSnapshot.swift b/Sources/Configuration/Providers/Files/JSONSnapshot.swift index 7b8a2fb..688e8ab 100644 --- a/Sources/Configuration/Providers/Files/JSONSnapshot.swift +++ b/Sources/Configuration/Providers/Files/JSONSnapshot.swift @@ -313,7 +313,7 @@ extension JSONSnapshot: FileConfigSnapshot { } @available(Configuration 1.0, *) -extension JSONSnapshot: ConfigSnapshotProtocol { +extension JSONSnapshot: ConfigSnapshot { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public func value(forKey key: AbsoluteConfigKey, type: ConfigType) throws -> LookupResult { let encodedKey = Self.keyEncoder.encode(key) diff --git a/Sources/Configuration/Providers/Files/ReloadingFileProvider.swift b/Sources/Configuration/Providers/Files/ReloadingFileProvider.swift index 9b779e6..e0da725 100644 --- a/Sources/Configuration/Providers/Files/ReloadingFileProvider.swift +++ b/Sources/Configuration/Providers/Files/ReloadingFileProvider.swift @@ -489,13 +489,13 @@ extension ReloadingFileProvider: ConfigProvider { } // swift-format-ignore: AllPublicDeclarationsHaveDocumentation - public func snapshot() -> any ConfigSnapshotProtocol { + public func snapshot() -> any ConfigSnapshot { storage.withLock { $0.snapshot } } // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public func watchSnapshot( - updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Return + updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Return ) async throws -> Return { let (stream, continuation) = AsyncStream.makeStream(bufferingPolicy: .bufferingNewest(1)) let id = UUID() diff --git a/Sources/Configuration/Providers/Files/YAMLSnapshot.swift b/Sources/Configuration/Providers/Files/YAMLSnapshot.swift index 84ffc75..6a9fc44 100644 --- a/Sources/Configuration/Providers/Files/YAMLSnapshot.swift +++ b/Sources/Configuration/Providers/Files/YAMLSnapshot.swift @@ -264,7 +264,7 @@ extension YAMLSnapshot: FileConfigSnapshot { } @available(Configuration 1.0, *) -extension YAMLSnapshot: ConfigSnapshotProtocol { +extension YAMLSnapshot: ConfigSnapshot { // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public func value(forKey key: AbsoluteConfigKey, type: ConfigType) throws -> LookupResult { let encodedKey = Self.keyEncoder.encode(key) diff --git a/Sources/Configuration/Providers/InMemory/InMemoryProvider.swift b/Sources/Configuration/Providers/InMemory/InMemoryProvider.swift index b5c53ba..8c7aaee 100644 --- a/Sources/Configuration/Providers/InMemory/InMemoryProvider.swift +++ b/Sources/Configuration/Providers/InMemory/InMemoryProvider.swift @@ -174,7 +174,7 @@ extension InMemoryProvider: CustomDebugStringConvertible { } @available(Configuration 1.0, *) -extension InMemoryProvider.Snapshot: ConfigSnapshotProtocol { +extension InMemoryProvider.Snapshot: ConfigSnapshot { func value( forKey key: AbsoluteConfigKey, type: ConfigType @@ -226,13 +226,13 @@ extension InMemoryProvider: ConfigProvider { } // swift-format-ignore: AllPublicDeclarationsHaveDocumentation - public func snapshot() -> any ConfigSnapshotProtocol { + public func snapshot() -> any ConfigSnapshot { _snapshot } // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public func watchSnapshot( - updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Return + updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Return ) async throws -> Return { try await watchSnapshotFromSnapshot(updatesHandler: updatesHandler) } diff --git a/Sources/Configuration/Providers/InMemory/MutableInMemoryProvider.swift b/Sources/Configuration/Providers/InMemory/MutableInMemoryProvider.swift index 0173a88..2335659 100644 --- a/Sources/Configuration/Providers/InMemory/MutableInMemoryProvider.swift +++ b/Sources/Configuration/Providers/InMemory/MutableInMemoryProvider.swift @@ -373,7 +373,7 @@ extension MutableInMemoryProvider { } @available(Configuration 1.0, *) -extension MutableInMemoryProvider.Snapshot: ConfigSnapshotProtocol { +extension MutableInMemoryProvider.Snapshot: ConfigSnapshot { func value(forKey key: AbsoluteConfigKey, type: ConfigType) throws -> LookupResult { try MutableInMemoryProvider.parseValue( values[key], @@ -450,13 +450,13 @@ extension MutableInMemoryProvider: ConfigProvider { } // swift-format-ignore: AllPublicDeclarationsHaveDocumentation - public func snapshot() -> any ConfigSnapshotProtocol { + public func snapshot() -> any ConfigSnapshot { storage.withLock { $0.snapshot } } // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public func watchSnapshot( - updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Return + updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Return ) async throws -> Return { let (stream, continuation) = AsyncStream.makeStream(bufferingPolicy: .bufferingNewest(1)) let id = UUID() diff --git a/Sources/Configuration/Providers/Wrappers/KeyMappingProvider.swift b/Sources/Configuration/Providers/Wrappers/KeyMappingProvider.swift index a149d3b..6e0adf1 100644 --- a/Sources/Configuration/Providers/Wrappers/KeyMappingProvider.swift +++ b/Sources/Configuration/Providers/Wrappers/KeyMappingProvider.swift @@ -112,13 +112,13 @@ extension KeyMappingProvider: ConfigProvider { } // swift-format-ignore: AllPublicDeclarationsHaveDocumentation - public func snapshot() -> any ConfigSnapshotProtocol { + public func snapshot() -> any ConfigSnapshot { MappedKeySnapshot(mapKey: self.mapKey, upstream: self.upstream.snapshot()) } // swift-format-ignore: AllPublicDeclarationsHaveDocumentation public func watchSnapshot( - updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Return + updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Return ) async throws -> Return { try await upstream.watchSnapshot { sequence in try await updatesHandler( @@ -135,13 +135,13 @@ extension KeyMappingProvider: ConfigProvider { /// A configuration snapshot that maps all keys before delegating to an upstream snapshot. @available(Configuration 1.0, *) -private struct MappedKeySnapshot: ConfigSnapshotProtocol { +private struct MappedKeySnapshot: ConfigSnapshot { /// The prefix key to prepend to all configuration keys. let mapKey: @Sendable (AbsoluteConfigKey) -> AbsoluteConfigKey /// The upstream configuration snapshot to delegate to after prefixing keys. - var upstream: any ConfigSnapshotProtocol + var upstream: any ConfigSnapshot var providerName: String { "KeyMappingProvider[upstream: \(self.upstream.providerName)]" diff --git a/Sources/ConfigurationTestingInternal/TestProvider.swift b/Sources/ConfigurationTestingInternal/TestProvider.swift index 0b8f25e..0f70c6a 100644 --- a/Sources/ConfigurationTestingInternal/TestProvider.swift +++ b/Sources/ConfigurationTestingInternal/TestProvider.swift @@ -83,7 +83,7 @@ extension TestProvider { } @available(Configuration 1.0, *) -extension TestProvider: ConfigProvider, ConfigSnapshotProtocol { +extension TestProvider: ConfigProvider, ConfigSnapshot { package var providerName: String { "TestProvider" } @@ -103,12 +103,12 @@ extension TestProvider: ConfigProvider, ConfigSnapshotProtocol { } } - package func snapshot() -> any ConfigSnapshotProtocol { + package func snapshot() -> any ConfigSnapshot { self } package func watchSnapshot( - updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Return + updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Return ) async throws -> Return { diff --git a/Tests/ConfigurationTests/KeyMappingProviderTests.swift b/Tests/ConfigurationTests/KeyMappingProviderTests.swift index 0f28bdc..7047ab0 100644 --- a/Tests/ConfigurationTests/KeyMappingProviderTests.swift +++ b/Tests/ConfigurationTests/KeyMappingProviderTests.swift @@ -117,7 +117,7 @@ struct KeyMappingProviderTests { } } - var receivedSnapshots: [any ConfigSnapshotProtocol] = [] + var receivedSnapshots: [any ConfigSnapshot] = [] try await mapper.watchSnapshot { sequence in for try await snapshot in sequence { receivedSnapshots.append(snapshot) diff --git a/Tests/ConfigurationTests/MultiProviderTests.swift b/Tests/ConfigurationTests/MultiProviderTests.swift index ed42d21..ef4d020 100644 --- a/Tests/ConfigurationTests/MultiProviderTests.swift +++ b/Tests/ConfigurationTests/MultiProviderTests.swift @@ -106,12 +106,12 @@ struct MultiProviderTests { } } - func snapshot() -> any ConfigSnapshotProtocol { + func snapshot() -> any ConfigSnapshot { multiProvider.snapshot() } func watchSnapshot( - updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Return + updatesHandler: (ConfigUpdatesAsyncSequence) async throws -> Return ) async throws -> Return { @@ -235,7 +235,7 @@ struct MultiProviderTests { } @available(Configuration 1.0, *) -extension MultiSnapshot: ConfigSnapshotProtocol { +extension MultiSnapshot: ConfigSnapshot { var providerName: String { "MultiProvider" }