diff --git a/README.md b/README.md index 2b9b44e..51cbea0 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,15 @@ # YMFF: Feature management made easy -YMFF is a nice little library that makes managing features with feature flags—and managing feature flags themselves—a bliss, thanks to Swift’s [macros](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/macros) and [property wrappers](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/properties/#Property-Wrappers). +YMFF is a nice little library that makes managing features with feature flags—and managing feature flags themselves—a bliss, thanks to Swift’s [property wrappers](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/properties/#Property-Wrappers) and (in the future) [macros](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/macros).
Why & How -Every company I worked for needed a way to manage availability of features in the apps already shipped to users. Surprisingly enough, [*feature flags*](https://en.wikipedia.org/wiki/Feature_toggle) (a.k.a. *feature toggles* a.k.a. *feature switches*) tend to cause a lot of struggle. +Every company I worked for needed a way to manage availability of features in the apps already shipped to the users. Surprisingly, [*feature flags*](https://en.wikipedia.org/wiki/Feature_toggle) (a.k.a. *feature toggles* a.k.a. *feature switches*) tend to cause a lot of struggle. **I aspire to change that.** -YMFF ships completely ready-to-use, right out of the box: you get everything you need to get started in just a few minutes. But you can also replace nearly any component of the system with your own, customized implementation. The supplied implementation and the protocols are kept in two separate targets (YMFF and YMFFProtocols, respectively). +YMFF ships completely ready-to-use, right out of the box: you get everything you need to get started in just a few lines of code.
@@ -21,35 +21,39 @@ I’m sure you know how to install dependencies. YMFF supports both SPM and Coco Need Help? ### Swift Package Manager (SPM) -To add YMFF to your project, use Xcode’s built-in support for Swift packages. Click File → Swift Packages → Add Package Dependency, and paste the following URL into the search field: + +To add YMFF to your project, use Xcode’s built-in support for Swift packages. Click File → Add Package Dependencies, and paste the following URL into the search field: ``` https://github.com/yakovmanshin/YMFF ``` -You’re then prompted to select the version to install and indicate the desired update policy. I recommend starting with the latest version (it’s selected automatically), and choosing “up to next major” as the preferred update rule. Once you click Next, the package is fetched. Then select the target you’re going to use YMFF in. Click Finish, and you’re ready to go. +You’re then prompted to select the version to install and indicate the desired update policy. I recommend starting with the latest version (it’s selected automatically), and choosing “up to next major” as the update rule. Then select the target you want to link YMFF to. Click Finish—and you’re ready to go! If you need to use YMFF in another Swift package, add it to the `Package.swift` file as a dependency: ```swift -.package(url: "https://github.com/yakovmanshin/YMFF", .upToNextMajor(from: "3.1.0")) +.package(url: "https://github.com/yakovmanshin/YMFF", from: "4.0.0") ``` ### CocoaPods -YMFF alternatively supports installation via [CocoaPods](https://youtu.be/iEAjvNRdZa0). + +YMFF supports installation via [CocoaPods](https://youtu.be/iEAjvNRdZa0), but please keep in mind this support is provided on the best-effort basis. Add the following to your Podfile: ```ruby -pod 'YMFF', '~> 3.1' +pod 'YMFF', '~> 4.0' ``` ## Setup + YMFF relies on the concept of *feature-flag stores*—“sources of truth” for feature-flag values. ### Firebase Remote Config + Firebase Remote Config is one of the most popular tools to control feature flags remotely. YMFF integrates with Remote Config seamlessly, although with some manual action.
@@ -59,47 +63,55 @@ Firebase Remote Config is one of the most popular tools to control feature flags import FirebaseRemoteConfig import YMFFProtocols -extension RemoteConfig: FeatureFlagStoreProtocol { +extension RemoteConfig: SynchronousFeatureFlagStore { - public func containsValue(forKey key: String) -> Bool { - self.allKeys(from: .remote).contains(key) - } - - public func value(forKey key: String) -> Value? { + public func valueSync(for key: FeatureFlagKey) -> Result { // Remote Config returns a default value if the requested key doesn’t exist, // so you need to check the key for existence explicitly. - guard containsValue(forKey: key) else { return nil } + guard allKeys(from: .remote).contains(key) else { + return .failure(.valueNotFound) + } let remoteConfigValue = self[key] + let value: Value? // You need to use different `RemoteConfigValue` methods, depending on the return type. // I know, it doesn’t look fancy. switch Value.self { case is Bool.Type: - return remoteConfigValue.boolValue as? Value + value = remoteConfigValue.boolValue as? Value case is Data.Type: - return remoteConfigValue.dataValue as? Value + value = remoteConfigValue.dataValue as? Value case is Double.Type: - return remoteConfigValue.numberValue.doubleValue as? Value + value = remoteConfigValue.numberValue.doubleValue as? Value case is Int.Type: - return remoteConfigValue.numberValue.intValue as? Value + value = remoteConfigValue.numberValue.intValue as? Value case is String.Type: - return remoteConfigValue.stringValue as? Value + value = remoteConfigValue.stringValue as? Value default: - return nil + value = nil + } + + if let value { + return .success(value) + } else { + return .failure(.typeMismatch) } } } ``` -Now, `RemoteConfig` is a valid *feature-flag store*. +`RemoteConfig` is now a valid *feature-flag store*. -Alternatively, you can create a custom wrapper object. That’s what I tend to do in my projects to achieve greater flexibility and avoid tight coupling. +Alternatively, you can create a custom wrapper object. That’s what I do in my projects to avoid tight coupling.
## Usage + +### Declaring Feature Flags + Here’s how you declare feature flags with YMFF: ```swift @@ -108,22 +120,16 @@ import YMFF // For convenience, organize feature flags in a separate namespace using an enum. enum FeatureFlags { - // `resolver` references one or more feature flag stores. - private static var resolver = FeatureFlagResolver(configuration: .init(stores: [ - // If you want to change feature flag values from within your app, you’ll need at least one mutable store. - // `RuntimeOverridesStore` is a YMFF-supplied object. It stores modified values until the app restarts. - .mutable(RuntimeOverridesStore()), - // `MyFeatureFlagStore.shared` is your object, conforming to `FeatureFlagStoreProtocol`. - .immutable(MyFeatureFlagStore.shared), - ])) + // `resolver` references one or more feature-flag stores. + private static let resolver = FeatureFlagResolver(stores: [MyFeatureFlagStore.shared]) // Feature flags are initialized with three pieces of data: // a key string, the default (fallback) value, and the resolver. - @FeatureFlag("promo_enabled", default: false, resolver: resolver) - static var promoEnabled + @FeatureFlag("ads_enabled", default: false, resolver: Self.resolver) + static var adsEnabled // Feature flags aren’t limited to booleans. You can use any type of value! - @FeatureFlag("number_of_banners", default: 3, resolver: resolver) + @FeatureFlag("number_of_banners", default: 3, resolver: Self.resolver) static var numberOfBanners // Advanced: Sometimes you want to map raw values from the store @@ -131,86 +137,86 @@ enum FeatureFlags { // stores values as strings, while the app uses an enum. // To switch between them, you use a `FeatureFlagValueTransformer`. @FeatureFlag( - "promo_unit_kind", - FeatureFlagValueTransformer { string in - PromoUnitKind(rawValue: string) - } rawValueFromValue: { kind in - kind.rawValue + "ad_unit_kind", + transformer: FeatureFlagValueTransformer { rawValue in + AdUnitKind(rawValue: rawValue) + } rawValueFromValue: { value in + value.rawValue }, default: .image, - resolver: resolver + resolver: Self.resolver ) - static var promoUnitKind + static var adUnitKind } // You can use custom types for feature-flag values. -enum PromoUnitKind: String { +enum AdUnitKind: String { case text case image case video } ``` +### Reading Values + To the code that makes use of a feature flag, the flag acts just like the type of its value: ```swift -if FeatureFlags.promoEnabled { - switch FeatureFlags.promoUnitKind { +if FeatureFlags.adsEnabled { + switch FeatureFlags.adUnitKind { case .text: - displayPromoText() + displayAdText() case .image: - displayPromoBanners(count: FeatureFlags.numberOfBanners) + displayAdBanners(count: FeatureFlags.numberOfBanners) case .video: - playPromoVideo() + playAdVideo() } } ``` -### Overriding Values - -YMFF lets you override feature flag values in mutable stores from within your app. When you do, the new value is set to the first mutable store found in resolver configuration. +### Writing Values -Overriding a feature flag value is as simple as assigning a new value to the flag. +YMFF lets you write feature-flag values to mutable stores. It’s as simple as assigning a new value to the flag: ```swift -FeatureFlags.promoEnabled = true +FeatureFlags.adsEnabled = true ``` -If you can set a value, you should also be able to remove it. And you can, indeed. Calling `removeValueFromMutableStore()` on `FeatureFlag`’s *projected value* (i.e. the `FeatureFlag` instance itself, as opposed to its *wrapped value*) removes the value from the first mutable feature flag store which contains one. +To remove the value, you call `removeValueFromMutableStores()` on `FeatureFlag`’s *projected value* (i.e. the `FeatureFlag` instance itself, as opposed to its *wrapped value*): ```swift -// Here `FeatureFlags.$promoEnabled` has the type `FeatureFlag`, -// while `FeatureFlags.promoEnabled` is of type `Bool`. -FeatureFlags.$promoEnabled.removeValueFromMutableStore() +// Here `FeatureFlags.$adsEnabled` has the type `FeatureFlag`, +// while `FeatureFlags.adsEnabled` is of type `Bool`. +FeatureFlags.$adsEnabled.removeValueFromMutableStore() ``` ### `UserDefaults` -You can use `UserDefaults` to read and write feature flag values. Your changes will persist when the app is restarted. +You can use `UserDefaults` to read and write feature-flag values. Your changes will persist when the app restarts. ```swift import YMFF -private static var resolver = FeatureFlagResolver(configuration: .init(stores: [.mutable(UserDefaultsStore())])) +private static let resolver = FeatureFlagResolver(stores: [UserDefaultsStore()]) ``` That’s it! ### More -Feel free to browse the source files to learn more about the available options! +You can browse the source files to learn more about the available options. + +## What’s in Store -## v4 Roadmap -* [[#96](https://github.com/yakovmanshin/YMFF/issues/96)] Support for asynchronous feature-flag stores +### [Next-Version Roadmap](https://github.com/yakovmanshin/YMFF/milestone/11) * [[#124](https://github.com/yakovmanshin/YMFF/issues/124)] Swift macros for easier setup * [[#113](https://github.com/yakovmanshin/YMFF/issues/113)] Thread-safety improvements -* ✅ ~~[[#104](https://github.com/yakovmanshin/YMFF/issues/104)] Minimum compiler version: Swift 5.5 (Xcode 13)~~ -* ✅ ~~[[#106](https://github.com/yakovmanshin/YMFF/issues/106)] Minimum deployment target: iOS 13, macOS 10.15~~ +* [[#150](https://github.com/yakovmanshin/YMFF/issues/150)] Support for optional values in `UserDefaultsStore` +* [[#144](https://github.com/yakovmanshin/YMFF/issues/144)] Minimum compiler version: Swift 5.9 (Xcode 15) -YMFF v4 is expected to be released in 2024. +This version is expected in late 2024, after Swift 6 is released. -## License and Copyright -YMFF is licensed under the Apache License. See the [LICENSE file](https://github.com/yakovmanshin/YMFF/blob/main/LICENSE) for details. +### Ideas & Bug Reports -© 2020–2024 Yakov Manshin +Feel free to open a new issue if something’s not working—or if you have a suggestion. diff --git a/Sources/YMFF/FeatureFlag/FeatureFlag.swift b/Sources/YMFF/FeatureFlag/FeatureFlag.swift index d521e8e..805982e 100644 --- a/Sources/YMFF/FeatureFlag/FeatureFlag.swift +++ b/Sources/YMFF/FeatureFlag/FeatureFlag.swift @@ -10,18 +10,18 @@ import YMFFProtocols #endif -/// An object that facilitates access to feature flag values. +/// The object which provides easy access to feature-flag values. @propertyWrapper final public class FeatureFlag { // MARK: Properties - /// The key used to retrieve feature flag values. + /// The key used to retrieve feature-flag values. public let key: FeatureFlagKey private let transformer: FeatureFlagValueTransformer - /// The fallback value returned when no store is able to provide the real one. + /// The fallback value returned when the actual one cannot be retrieved. public let defaultValue: Value private let resolver: any SynchronousFeatureFlagResolverProtocol @@ -29,11 +29,11 @@ final public class FeatureFlag { // MARK: Initializers /// Creates a new `FeatureFlag`. - /// + /// /// - Parameters: - /// - key: *Required.* The key used to address feature flag values in stores. - /// - transformer: *Required.* The object that transforms raw values into values, and vice versa. - /// - defaultValue: *Required.* The value returned in case all stores fail to provide a value. + /// - key: *Required.* The key used to address feature-flag values in stores. + /// - transformer: *Required.* The object that transforms raw values into client-type values, and vice versa. + /// - defaultValue: *Required.* The value returned in case no feature-flag store is able provide a value. /// - resolver: *Required.* The resolver object used to retrieve values from stores. public init( _ key: FeatureFlagKey, @@ -47,11 +47,11 @@ final public class FeatureFlag { self.resolver = resolver } - /// Creates a new `FeatureFlag` with value and raw value of the same type. + /// Creates a new `FeatureFlag` whose value and raw value are of the same type. /// /// - Parameters: - /// - key: *Required.* The key used to address feature flag values in stores. - /// - defaultValue: *Required.* The value returned in case all stores fail to provide a value. + /// - key: *Required.* The key used to address feature-flag values in stores. + /// - defaultValue: *Required.* The value returned in case no feature-flag store is able provide a value. /// - resolver: *Required.* The resolver object used to retrieve values from stores. public convenience init( _ key: FeatureFlagKey, @@ -79,12 +79,12 @@ final public class FeatureFlag { // MARK: Projected Value - /// The object returned when referencing the feature flag with a dollar sign (`$`). + /// The feature-flag object itself, returned when the feature flag is referenced with a dollar sign (`$`). public var projectedValue: FeatureFlag { self } // MARK: Mutable Value Removal - /// Removes the value from the first mutable feature flag store which contains one for `key`. + /// Removes the value from all *synchronous* mutable feature-flag stores. /// /// + Errors thrown by `resolver` are ignored. public func removeValueFromMutableStores() { diff --git a/Sources/YMFF/FeatureFlag/FeatureFlagValueTransformer.swift b/Sources/YMFF/FeatureFlag/FeatureFlagValueTransformer.swift index 36413b7..a9d3988 100644 --- a/Sources/YMFF/FeatureFlag/FeatureFlagValueTransformer.swift +++ b/Sources/YMFF/FeatureFlag/FeatureFlagValueTransformer.swift @@ -8,7 +8,7 @@ // MARK: - Transformer -/// An object used by `FeatureFlag` to transform raw values into native values, and vice versa. +/// The object used to transform raw values into client-type values, and vice versa. public struct FeatureFlagValueTransformer { let valueFromRawValue: (RawValue) -> Value? diff --git a/Sources/YMFF/FeatureFlagResolver/FeatureFlagResolver.swift b/Sources/YMFF/FeatureFlagResolver/FeatureFlagResolver.swift index 18218be..65baf4f 100644 --- a/Sources/YMFF/FeatureFlagResolver/FeatureFlagResolver.swift +++ b/Sources/YMFF/FeatureFlagResolver/FeatureFlagResolver.swift @@ -12,7 +12,7 @@ import YMFFProtocols // MARK: - FeatureFlagResolver -/// A concrete, YMFF-supplied implementation of the feature flag resolver. +/// The concrete, YMFF-supplied implementation of the *synchronous* feature-flag resolver. final public class FeatureFlagResolver { // MARK: Properties @@ -21,18 +21,18 @@ final public class FeatureFlagResolver { // MARK: Initializers - /// Initializes the resolver with an object that conforms to `FeatureFlagResolverConfiguration`. + /// Initializes the resolver with an object which conforms to `FeatureFlagResolverConfiguration`. /// - /// - Parameter configuration: *Required.* The configuration used to read and write feature flag values. + /// - Parameter configuration: *Required.* The configuration used to read and write feature-flag values. public init(configuration: any FeatureFlagResolverConfiguration) { self.configuration = configuration } - /// Initializes the resolver with the list of feature flag stores. + /// Initializes the resolver with an array of feature-flag stores. /// - /// + Passing in an empty array will produce the `noStoreAvailable` error on next read attempt. + /// + Passing an empty array will result in a `noStoreAvailable` error on the next read attempt. /// - /// - Parameter stores: *Required.* The array of feature flag stores. + /// - Parameter stores: *Required.* The array of feature-flag stores. public convenience init(stores: [any FeatureFlagStore]) { let configuration = Configuration(stores: stores) self.init(configuration: configuration) diff --git a/Sources/YMFF/FeatureFlagResolver/Store/RuntimeOverridesStore.swift b/Sources/YMFF/FeatureFlagResolver/Store/RuntimeOverridesStore.swift index 0590324..564dc39 100644 --- a/Sources/YMFF/FeatureFlagResolver/Store/RuntimeOverridesStore.swift +++ b/Sources/YMFF/FeatureFlagResolver/Store/RuntimeOverridesStore.swift @@ -12,7 +12,7 @@ import YMFFProtocols // MARK: - RuntimeOverridesStore -/// A YMFF-supplied implementation of the object that stores feature flag values used in runtime. +/// A YMFF-supplied implementation of an object which stores feature-flag values with no persistence. final public class RuntimeOverridesStore { var store: TransparentFeatureFlagStore diff --git a/Sources/YMFF/FeatureFlagResolver/Store/TransparentFeatureFlagStore.swift b/Sources/YMFF/FeatureFlagResolver/Store/TransparentFeatureFlagStore.swift index 38bbc71..b33aba5 100644 --- a/Sources/YMFF/FeatureFlagResolver/Store/TransparentFeatureFlagStore.swift +++ b/Sources/YMFF/FeatureFlagResolver/Store/TransparentFeatureFlagStore.swift @@ -12,7 +12,7 @@ import YMFFProtocols // MARK: - TransparentFeatureFlagStore -/// A simple dictionary used to store and retrieve feature flag values. +/// A simple dictionary used to store and retrieve feature-flag values. public typealias TransparentFeatureFlagStore = [String: Any] // MARK: - SynchronousFeatureFlagStore diff --git a/Sources/YMFF/FeatureFlagResolver/Store/UserDefaultsStore.swift b/Sources/YMFF/FeatureFlagResolver/Store/UserDefaultsStore.swift index 71e9bf3..896c677 100644 --- a/Sources/YMFF/FeatureFlagResolver/Store/UserDefaultsStore.swift +++ b/Sources/YMFF/FeatureFlagResolver/Store/UserDefaultsStore.swift @@ -15,7 +15,7 @@ import YMFFProtocols // MARK: - UserDefaultsStore -/// An object that provides read and write access to feature flag values store in `UserDefaults`. +/// The object which provides read and write access to feature-flag values stored in `UserDefaults`. final public class UserDefaultsStore { private let userDefaults: UserDefaults diff --git a/Sources/YMFFProtocols/FeatureFlagKey.swift b/Sources/YMFFProtocols/FeatureFlagKey.swift index b5b4cdb..0f542c1 100644 --- a/Sources/YMFFProtocols/FeatureFlagKey.swift +++ b/Sources/YMFFProtocols/FeatureFlagKey.swift @@ -6,5 +6,5 @@ // Copyright © 2020 Yakov Manshin. See the LICENSE file for license info. // -/// The identifier used to set and retrieve feature flag values. +/// The identifier used to set and retrieve feature-flag values. public typealias FeatureFlagKey = String diff --git a/Sources/YMFFProtocols/FeatureFlagResolver/Configuration/FeatureFlagResolverConfiguration.swift b/Sources/YMFFProtocols/FeatureFlagResolver/Configuration/FeatureFlagResolverConfiguration.swift index 7ed90d2..5601a25 100644 --- a/Sources/YMFFProtocols/FeatureFlagResolver/Configuration/FeatureFlagResolverConfiguration.swift +++ b/Sources/YMFFProtocols/FeatureFlagResolver/Configuration/FeatureFlagResolverConfiguration.swift @@ -6,7 +6,7 @@ // Copyright © 2020 Yakov Manshin. See the LICENSE file for license info. // -/// The object which provides the key resources to the resolver. +/// The object which provides the resources crucial to the functioning of the resolver. public protocol FeatureFlagResolverConfiguration: AnyObject { /// An array of stores which contain feature-flag values. diff --git a/Sources/YMFFProtocols/FeatureFlagResolver/Resolver/FeatureFlagResolverProtocol.swift b/Sources/YMFFProtocols/FeatureFlagResolver/Resolver/FeatureFlagResolverProtocol.swift index cbfb8ac..62563cd 100644 --- a/Sources/YMFFProtocols/FeatureFlagResolver/Resolver/FeatureFlagResolverProtocol.swift +++ b/Sources/YMFFProtocols/FeatureFlagResolver/Resolver/FeatureFlagResolverProtocol.swift @@ -6,24 +6,24 @@ // Copyright © 2020 Yakov Manshin. See the LICENSE file for license info. // -/// A service that resolves feature flag values with their keys. +/// The object which resolves feature-flag values. public protocol FeatureFlagResolverProtocol { - /// Returns a value for the specified key. + /// Returns the value from the first feature-flag store which contains one. /// - /// - Parameter key: *Required.* The feature flag key. + /// - Parameter key: *Required.* The feature-flag key. func value(for key: FeatureFlagKey) async throws -> Value - /// Sets a new feature flag value to the first mutable store found in `configuration.stores`. + /// Sets the feature-flag value to all mutable stores. /// /// - Parameters: - /// - newValue: *Required.* The override value. - /// - key: *Required.* The feature flag key. + /// - value: *Required.* The value. + /// - key: *Required.* The feature-flag key. func setValue(_ value: Value, for key: FeatureFlagKey) async throws - /// Removes the value from the first mutable feature flag store which has one for the specified key. + /// Removes the feature-flag value from all mutable stores. /// - /// - Parameter key: *Required.* The feature flag key. + /// - Parameter key: *Required.* The feature-flag key. func removeValue(for key: FeatureFlagKey) async throws } diff --git a/Sources/YMFFProtocols/FeatureFlagResolver/Resolver/SynchronousFeatureFlagResolverProtocol.swift b/Sources/YMFFProtocols/FeatureFlagResolver/Resolver/SynchronousFeatureFlagResolverProtocol.swift index 30f2bb1..b7886ab 100644 --- a/Sources/YMFFProtocols/FeatureFlagResolver/Resolver/SynchronousFeatureFlagResolverProtocol.swift +++ b/Sources/YMFFProtocols/FeatureFlagResolver/Resolver/SynchronousFeatureFlagResolverProtocol.swift @@ -6,23 +6,30 @@ // Copyright © 2024 Yakov Manshin. See the LICENSE file for license info. // +/// The synchronous version of `FeatureFlagResolverProtocol`. public protocol SynchronousFeatureFlagResolverProtocol: FeatureFlagResolverProtocol { - /// Returns a value for the specified key. + /// Synchronously returns the value from the first *synchronous* feature-flag store which contains one. /// - /// - Parameter key: *Required.* The feature flag key. + /// + Asynchronous feature-flag stores are ignored. + /// + /// - Parameter key: *Required.* The feature-flag key. func valueSync(for key: FeatureFlagKey) throws -> Value - /// Sets a new feature flag value to the first mutable store found in `configuration.stores`. + /// Synchronously sets the feature-flag value to all *synchronous* mutable stores. + /// + /// + Asynchronous feature-flag stores are ignored. /// /// - Parameters: - /// - newValue: *Required.* The override value. - /// - key: *Required.* The feature flag key. + /// - value: *Required.* The value. + /// - key: *Required.* The feature-flag key. func setValueSync(_ value: Value, for key: FeatureFlagKey) throws - /// Removes the value from the first mutable feature flag store which has one for the specified key. + /// Synchronously removes the feature-flag value from all *synchronous* mutable stores. + /// + /// + Asynchronous feature-flag stores are ignored. /// - /// - Parameter key: *Required.* The feature flag key. + /// - Parameter key: *Required.* The feature-flag key. func removeValueSync(for key: FeatureFlagKey) throws } diff --git a/Sources/YMFFProtocols/FeatureFlagResolver/Store/FeatureFlagStore.swift b/Sources/YMFFProtocols/FeatureFlagResolver/Store/FeatureFlagStore.swift index 07695a6..e0548b3 100644 --- a/Sources/YMFFProtocols/FeatureFlagResolver/Store/FeatureFlagStore.swift +++ b/Sources/YMFFProtocols/FeatureFlagResolver/Store/FeatureFlagStore.swift @@ -6,12 +6,12 @@ // Copyright © 2020 Yakov Manshin. See the LICENSE file for license info. // -/// An object that stores feature flag values, and provides them at the resolver's request. +/// The object which stores and provides feature-flag values. public protocol FeatureFlagStore { - /// Retrieves a feature flag value by its key. + /// Retrieves a feature-flag value by its key. /// - /// - Parameter key: *Required.* The key that points to a feature flag value in the store. + /// - Parameter key: *Required.* The key that points to a feature-flag value in the store. func value(for key: FeatureFlagKey) async -> Result } diff --git a/Sources/YMFFProtocols/FeatureFlagResolver/Store/MutableFeatureFlagStore.swift b/Sources/YMFFProtocols/FeatureFlagResolver/Store/MutableFeatureFlagStore.swift index 61189dc..38ca2fc 100644 --- a/Sources/YMFFProtocols/FeatureFlagResolver/Store/MutableFeatureFlagStore.swift +++ b/Sources/YMFFProtocols/FeatureFlagResolver/Store/MutableFeatureFlagStore.swift @@ -6,14 +6,14 @@ // Copyright © 2020 Yakov Manshin. See the LICENSE file for license info. // -/// An object that stores feature flag values that can be added and removed in runtime. +/// The object which stores and provides mutable feature-flag values. public protocol MutableFeatureFlagStore: AnyObject, FeatureFlagStore { /// Adds the value to the store so it can be retrieved with the key later. /// /// - Parameters: - /// - value: *Required.* The value to record. - /// - key: *Required.* The key used to address the value. + /// - value: *Required.* The value to add. + /// - key: *Required.* The feature-flag key. func setValue(_ value: Value, for key: FeatureFlagKey) async throws /// Removes the value from the store. diff --git a/Sources/YMFFProtocols/FeatureFlagResolver/Store/SynchronousFeatureFlagStore.swift b/Sources/YMFFProtocols/FeatureFlagResolver/Store/SynchronousFeatureFlagStore.swift index aebf428..1746261 100644 --- a/Sources/YMFFProtocols/FeatureFlagResolver/Store/SynchronousFeatureFlagStore.swift +++ b/Sources/YMFFProtocols/FeatureFlagResolver/Store/SynchronousFeatureFlagStore.swift @@ -6,11 +6,12 @@ // Copyright © 2022 Yakov Manshin. See the LICENSE file for license info. // +/// The synchronous version of `FeatureFlagStore`. public protocol SynchronousFeatureFlagStore: FeatureFlagStore { - /// Retrieves a feature flag value by its key. + /// Synchronously retrieves a feature-flag value by its key. /// - /// - Parameter key: *Required.* The key that points to a feature flag value in the store. + /// - Parameter key: *Required.* The key that points to a feature-flag value in the store. func valueSync(for key: FeatureFlagKey) -> Result } diff --git a/Sources/YMFFProtocols/FeatureFlagResolver/Store/SynchronousMutableFeatureFlagStore.swift b/Sources/YMFFProtocols/FeatureFlagResolver/Store/SynchronousMutableFeatureFlagStore.swift index 75a7c9b..570b70b 100644 --- a/Sources/YMFFProtocols/FeatureFlagResolver/Store/SynchronousMutableFeatureFlagStore.swift +++ b/Sources/YMFFProtocols/FeatureFlagResolver/Store/SynchronousMutableFeatureFlagStore.swift @@ -6,16 +6,17 @@ // Copyright © 2022 Yakov Manshin. See the LICENSE file for license info. // +/// The synchronous version of `MutableFeatureFlagStore`. public protocol SynchronousMutableFeatureFlagStore: SynchronousFeatureFlagStore, MutableFeatureFlagStore { - /// Adds the value to the store so it can be retrieved with the key later. + /// Synchronously adds the value to the store so it can be retrieved with the key later. /// /// - Parameters: - /// - value: *Required.* The value to record. - /// - key: *Required.* The key used to address the value. + /// - value: *Required.* The value to add. + /// - key: *Required.* The feature-flag key. func setValueSync(_ value: Value, for key: FeatureFlagKey) throws - /// Removes the value from the store. + /// Synchronously removes the value from the store. /// /// - Parameter key: *Required.* The key used to address the value. func removeValueSync(for key: FeatureFlagKey) throws diff --git a/YMFF.podspec b/YMFF.podspec index 6c85f73..840ca7a 100644 --- a/YMFF.podspec +++ b/YMFF.podspec @@ -3,10 +3,9 @@ Pod::Spec.new do |s| # Root s.name = "YMFF" - s.version = "3.1.0" + s.version = "4.0.0" s.swift_version = "5.8" - s.authors = { "Yakov Manshin" => "git@yakovmanshin.com" } - s.social_media_url = "https://twitter.com/yakovmanshin" + s.authors = { "Yakov Manshin" => "git@yakovmanshin.com" } s.license = { :type => "Apache License, version 2.0", :file => "LICENSE" } s.homepage = "https://github.com/yakovmanshin/YMFF" s.readme = "https://github.com/yakovmanshin/YMFF/blob/main/README.md"