diff --git a/.github/workflows/plugin-cd.yml b/.github/workflows/plugin-cd.yml index 9a5b41c..c06a0ed 100644 --- a/.github/workflows/plugin-cd.yml +++ b/.github/workflows/plugin-cd.yml @@ -6,6 +6,9 @@ on: tags: - 'v*' +env: + VCPKG_COMMIT_HASH: "59852bb5bd0779788e5fc95e50d2048ae6c9399d" + jobs: build-win64: runs-on: windows-latest @@ -16,6 +19,7 @@ jobs: - name: Install via vcpkg run: | git clone https://github.com/microsoft/vcpkg build/vcpkg + git -C build/vcpkg checkout ${{ env.VCPKG_COMMIT_HASH }} ./build/vcpkg/bootstrap-vcpkg.bat ./build/vcpkg/vcpkg install configcat[core] --triplet x64-windows @@ -35,6 +39,7 @@ jobs: - name: Install via vcpkg run: | git clone https://github.com/microsoft/vcpkg build/vcpkg + git -C build/vcpkg checkout ${{ env.VCPKG_COMMIT_HASH }} ./build/vcpkg/bootstrap-vcpkg.bat ./build/vcpkg/vcpkg install configcat[core] --triplet arm64-android @@ -54,6 +59,7 @@ jobs: - name: Install via vcpkg run: | git clone https://github.com/microsoft/vcpkg build/vcpkg + git -C build/vcpkg checkout ${{ env.VCPKG_COMMIT_HASH }} ./build/vcpkg/bootstrap-vcpkg.sh ./build/vcpkg/vcpkg install configcat[core] --triplet universal-osx-unreal --overlay-triplets "$GITHUB_WORKSPACE/Extras/triplets" @@ -73,6 +79,7 @@ jobs: - name: Install via vcpkg run: | git clone https://github.com/microsoft/vcpkg build/vcpkg + git -C build/vcpkg checkout ${{ env.VCPKG_COMMIT_HASH }} ./build/vcpkg/bootstrap-vcpkg.sh ./build/vcpkg/vcpkg install configcat[core] --triplet arm64-ios-unreal --overlay-triplets "$GITHUB_WORKSPACE/Extras/triplets" @@ -92,6 +99,7 @@ jobs: - name: Install via vcpkg run: | git clone https://github.com/microsoft/vcpkg build/vcpkg + git -C build/vcpkg checkout ${{ env.VCPKG_COMMIT_HASH }} ./build/vcpkg/bootstrap-vcpkg.sh # Extra steps for Unreal Engine integration diff --git a/.github/workflows/plugin-ci.yml b/.github/workflows/plugin-ci.yml index 1418120..959580a 100644 --- a/.github/workflows/plugin-ci.yml +++ b/.github/workflows/plugin-ci.yml @@ -8,6 +8,9 @@ on: branches: - main +env: + VCPKG_COMMIT_HASH: "59852bb5bd0779788e5fc95e50d2048ae6c9399d" + jobs: build-linux: runs-on: ubuntu-latest @@ -18,6 +21,7 @@ jobs: - name: Install via vcpkg run: | git clone https://github.com/microsoft/vcpkg build/vcpkg + git -C build/vcpkg checkout ${{ env.VCPKG_COMMIT_HASH }} ./build/vcpkg/bootstrap-vcpkg.sh # Extra steps for Unreal Engine integration diff --git a/ConfigCat.uplugin b/ConfigCat.uplugin index a361928..dfce2b2 100644 --- a/ConfigCat.uplugin +++ b/ConfigCat.uplugin @@ -19,6 +19,12 @@ "LoadingPhase": "PreDefault", "PlatformAllowList": [ "Win64", "Mac", "Linux", "Android", "iOS" ] }, + { + "Name": "ConfigCatWrappers", + "Type": "Runtime", + "LoadingPhase": "PreDefault", + "PlatformAllowList": [ "Win64", "Mac", "Linux", "Android", "iOS" ] + }, { "Name": "ConfigCatEditor", "Type": "Editor", diff --git a/Source/ConfigCat/ConfigCat.Build.cs b/Source/ConfigCat/ConfigCat.Build.cs index 22c307d..7ebcf59 100644 --- a/Source/ConfigCat/ConfigCat.Build.cs +++ b/Source/ConfigCat/ConfigCat.Build.cs @@ -18,6 +18,7 @@ public ConfigCat(ReadOnlyTargetRules Target) : base(Target) PrivateDependencyModuleNames.AddRange(new[] { + "ConfigCatWrappers", "ConfigCatCppSdk" }); @@ -31,5 +32,7 @@ public ConfigCat(ReadOnlyTargetRules Target) : base(Target) PrivateDefinitions.Add("CONFIGCAT_HTTPTHREAD_WORKAROUND"); } + + bEnableExceptions = true; } } \ No newline at end of file diff --git a/Source/ConfigCat/Private/ConfigCatLogger.cpp b/Source/ConfigCat/Private/ConfigCatLogger.cpp index 8260c21..98ca061 100644 --- a/Source/ConfigCat/Private/ConfigCatLogger.cpp +++ b/Source/ConfigCat/Private/ConfigCatLogger.cpp @@ -10,7 +10,7 @@ FConfigCatLogger::FConfigCatLogger() : ILogger(LOG_LEVEL_DEBUG) { } -void FConfigCatLogger::log(configcat::LogLevel level, const std::string& message) +void FConfigCatLogger::log(configcat::LogLevel level, const std::string& message, const std::exception_ptr& exception) { const FString& LogMessage = UTF8_TO_TCHAR(message.c_str()); @@ -32,4 +32,10 @@ void FConfigCatLogger::log(configcat::LogLevel level, const std::string& message UE_LOG(LogConfigCat, Log, TEXT("[CPP-SDK] %s"), *LogMessage); break; } + + if (exception) + { + const FString ExceptionMessage = UTF8_TO_TCHAR(unwrap_exception_message(exception).c_str()); + UE_LOG(LogConfigCat, Error, TEXT("[CPP-SDK] Exception: %s"), *ExceptionMessage); + } } diff --git a/Source/ConfigCat/Private/ConfigCatNetworkAdapter.cpp b/Source/ConfigCat/Private/ConfigCatNetworkAdapter.cpp index 00662a0..4ec97f9 100644 --- a/Source/ConfigCat/Private/ConfigCatNetworkAdapter.cpp +++ b/Source/ConfigCat/Private/ConfigCatNetworkAdapter.cpp @@ -40,7 +40,10 @@ bool ConfigCatNetworkAdapter::init(uint32_t connectTimeoutMs, uint32_t readTimeo } Response ConfigCatNetworkAdapter::get( - const std::string& url, const std::map& header, const std::map& proxies, const std::map& proxyAuthentications + const std::string& url, + const std::map& header, + const std::map& proxies, + const std::map& proxyAuthentications ) { UE_LOG(LogConfigCat, Verbose, TEXT("Network Adapter performing GET request.")); @@ -57,10 +60,10 @@ Response ConfigCatNetworkAdapter::get( const float Timeout = (ConnectionTimeout + ReadTimeout) / 1000.0f; GetRequest->SetTimeout(Timeout); - for (const auto& it : header) + for (const std::pair& It : header) { - const FString HeaderKey = UTF8_TO_TCHAR(it.first.c_str()); - const FString HeaderValue = UTF8_TO_TCHAR(it.second.c_str()); + const FString HeaderKey = UTF8_TO_TCHAR(It.first.c_str()); + const FString HeaderValue = UTF8_TO_TCHAR(It.second.c_str()); GetRequest->SetHeader(HeaderKey, HeaderValue); } @@ -101,7 +104,7 @@ Response ConfigCatNetworkAdapter::get( if (!GetResponse) { Response.error = "Unreal Engine Network Adapter failed to launch request. Check logs"; - Response.operationTimedOut = GetRequest->GetElapsedTime() > Timeout; + Response.errorCode = ResponseErrorCode::InternalError; return Response; } @@ -131,4 +134,4 @@ void ConfigCatNetworkAdapter::close() { GetRequest->CancelRequest(); } -} +} \ No newline at end of file diff --git a/Source/ConfigCat/Private/ConfigCatSubsystem.cpp b/Source/ConfigCat/Private/ConfigCatSubsystem.cpp index 956d3e9..71930c4 100644 --- a/Source/ConfigCat/Private/ConfigCatSubsystem.cpp +++ b/Source/ConfigCat/Private/ConfigCatSubsystem.cpp @@ -18,68 +18,77 @@ #include "ConfigCatLogger.h" #include "ConfigCatNetworkAdapter.h" #include "ConfigCatSettings.h" -#include "Wrapper/ConfigCatEvaluationDetails.h" -#include "Wrapper/ConfigCatUser.h" -#include "Wrapper/ConfigCatValue.h" +#include "ConfigCatSettingsWrapper.h" +#include "ConfigCatEvaluationWrapper.h" +#include "ConfigCatUserWrapper.h" +#include "ConfigCatValueWrapper.h" using namespace configcat; namespace { + bool EnsureConfigCatClient(const std::shared_ptr& Client) + { + if (ensure(Client)) + { + return true; + } + + UE_LOG(LogConfigCat, Warning, TEXT("Trying to access the ConfigCatClient before initialization or after shutdown.")); + return false; + } + template - T GetValue(ConfigCatClient* Client, FString Key, T DefaultValue, const FConfigCatUser& User) + T GetValue(const std::shared_ptr& Client, FString Key, T DefaultValue, const UConfigCatUserWrapper* User) { - if (!ensure(Client)) + if(!EnsureConfigCatClient(Client)) { - UE_LOG(LogConfigCat, Warning, TEXT("Trying to access the ConfigCatClient before initialization or after shutdown.")); return DefaultValue; } - const ConfigCatUser* TargetUser = User.User.get(); const std::string& FlagKey = TCHAR_TO_UTF8(*Key); - return Client->getValue(FlagKey, DefaultValue, TargetUser); + return Client->getValue(FlagKey, DefaultValue, User ? User->User : nullptr); } template - EvaluationDetails GetEvaluationDetails(ConfigCatClient* Client, FString Key, T DefaultValue, const FConfigCatUser& User) + UConfigCatEvaluationWrapper* GetEvaluationDetails(const std::shared_ptr& Client, FString Key, T DefaultValue, const UConfigCatUserWrapper* User) { - if (!ensure(Client)) + if(!EnsureConfigCatClient(Client)) { - UE_LOG(LogConfigCat, Warning, TEXT("Trying to access the ConfigCatClient before initialization or after shutdown.")); return {}; } - const ConfigCatUser* TargetUser = User.User.get(); const std::string& FlagKey = TCHAR_TO_UTF8(*Key); - return Client->getValueDetails(FlagKey, DefaultValue, TargetUser); + return UConfigCatEvaluationWrapper::CreateEvaluation(Client->getValueDetails(FlagKey, DefaultValue, User ? User->User : nullptr)); } -} // namespace +} // namespace + UConfigCatSubsystem* UConfigCatSubsystem::Get(const UObject* WorldContext) { const UGameInstance* GameInstance = UGameplayStatics::GetGameInstance(WorldContext); return GameInstance->GetSubsystem(); } -bool UConfigCatSubsystem::GetBoolValue(const FString& Key, bool bDefaultValue, const FConfigCatUser& User) const +bool UConfigCatSubsystem::GetBoolValue(const FString& Key, bool bDefaultValue, const UConfigCatUserWrapper* User) const { return GetValue(ConfigCatClient, Key, bDefaultValue, User); } -int32 UConfigCatSubsystem::GetIntValue(const FString& Key, int32 DefaultValue, const FConfigCatUser& User) const +int32 UConfigCatSubsystem::GetIntValue(const FString& Key, int32 DefaultValue, const UConfigCatUserWrapper* User) const { return GetValue(ConfigCatClient, Key, DefaultValue, User); } -double UConfigCatSubsystem::GetDoubleValue(const FString& Key, double DefaultValue, const FConfigCatUser& User) const +double UConfigCatSubsystem::GetDoubleValue(const FString& Key, double DefaultValue, const UConfigCatUserWrapper* User) const { return GetValue(ConfigCatClient, Key, DefaultValue, User); } -FString UConfigCatSubsystem::GetStringValue(const FString& Key, const FString& DefaultValue, const FConfigCatUser& User) const +FString UConfigCatSubsystem::GetStringValue(const FString& Key, const FString& DefaultValue, const UConfigCatUserWrapper* User) const { UE_LOG(LogConfigCat, Display, TEXT("Request %s feature flag from configcat cpp-sdk"), *Key); const std::string& StringDefaultValue = TCHAR_TO_UTF8(*DefaultValue); @@ -87,37 +96,35 @@ FString UConfigCatSubsystem::GetStringValue(const FString& Key, const FString& D return UTF8_TO_TCHAR(StringResult.c_str()); } -FConfigCatValue UConfigCatSubsystem::GetConfigValue(const FString& Key, const FConfigCatUser& User) const +UConfigCatValueWrapper* UConfigCatSubsystem::GetConfigValue(const FString& Key, const UConfigCatUserWrapper* User) const { - if (!ensure(ConfigCatClient)) + if(!EnsureConfigCatClient(ConfigCatClient)) { - UE_LOG(LogConfigCat, Warning, TEXT("Trying to access the ConfigCatClient before initialization or after shutdown.")); return {}; } - const ConfigCatUser* TargetUser = User.User.get(); const std::string& FlagKey = TCHAR_TO_UTF8(*Key); + const std::optional FeatureFlagValue = ConfigCatClient->getValue(FlagKey, User ? User->User : nullptr); - const std::shared_ptr FeatureFlagValue = ConfigCatClient->getValue(FlagKey, TargetUser); - return FConfigCatValue(FeatureFlagValue); + return UConfigCatValueWrapper::CreateValue(FeatureFlagValue); } -FConfigCatEvaluationDetails UConfigCatSubsystem::GetBoolValueDetails(const FString& Key, bool DefaultValue, const FConfigCatUser& User) const +UConfigCatEvaluationWrapper* UConfigCatSubsystem::GetBoolValueDetails(const FString& Key, bool DefaultValue, const UConfigCatUserWrapper* User) const { return GetEvaluationDetails(ConfigCatClient, Key, DefaultValue, User); } -FConfigCatEvaluationDetails UConfigCatSubsystem::GetIntValueDetails(const FString& Key, int DefaultValue, const FConfigCatUser& User) const +UConfigCatEvaluationWrapper* UConfigCatSubsystem::GetIntValueDetails(const FString& Key, int DefaultValue, const UConfigCatUserWrapper* User) const { return GetEvaluationDetails(ConfigCatClient, Key, DefaultValue, User); } -FConfigCatEvaluationDetails UConfigCatSubsystem::GetDoubleValueDetails(const FString& Key, double DefaultValue, const FConfigCatUser& User) const +UConfigCatEvaluationWrapper* UConfigCatSubsystem::GetDoubleValueDetails(const FString& Key, double DefaultValue, const UConfigCatUserWrapper* User) const { return GetEvaluationDetails(ConfigCatClient, Key, DefaultValue, User); } -FConfigCatEvaluationDetails UConfigCatSubsystem::GetStringValueDetails(const FString& Key, const FString& DefaultValue, const FConfigCatUser& User) const +UConfigCatEvaluationWrapper* UConfigCatSubsystem::GetStringValueDetails(const FString& Key, const FString& DefaultValue, const UConfigCatUserWrapper* User) const { const std::string& StringDefaultValue = TCHAR_TO_UTF8(*DefaultValue); return GetEvaluationDetails(ConfigCatClient, Key, StringDefaultValue, User); @@ -125,9 +132,8 @@ FConfigCatEvaluationDetails UConfigCatSubsystem::GetStringValueDetails(const FSt TArray UConfigCatSubsystem::GetAllKeys() const { - if (!ensure(ConfigCatClient)) + if(!EnsureConfigCatClient(ConfigCatClient)) { - UE_LOG(LogConfigCat, Warning, TEXT("Trying to access the ConfigCatClient before initialization or after shutdown.")); return {}; } @@ -142,17 +148,16 @@ TArray UConfigCatSubsystem::GetAllKeys() const return Result; } -bool UConfigCatSubsystem::GetKeyAndValue(const FString& VariationId, FString& OutKey, FConfigCatValue& OutValue) const +bool UConfigCatSubsystem::GetKeyAndValue(const FString& VariationId, FString& OutKey, UConfigCatValueWrapper*& OutValue) const { - if (!ensure(ConfigCatClient)) + if(!EnsureConfigCatClient(ConfigCatClient)) { - UE_LOG(LogConfigCat, Warning, TEXT("Trying to access the ConfigCatClient before initialization or after shutdown.")); return false; } const std::string& VariationIdString = TCHAR_TO_UTF8(*VariationId); - std::shared_ptr KeyValue = ConfigCatClient->getKeyAndValue(VariationIdString); + std::optional KeyValue = ConfigCatClient->getKeyAndValue(VariationIdString); if (!KeyValue) { @@ -160,47 +165,41 @@ bool UConfigCatSubsystem::GetKeyAndValue(const FString& VariationId, FString& Ou } OutKey = UTF8_TO_TCHAR(KeyValue->key.c_str()); - OutValue = KeyValue->value; + OutValue = UConfigCatValueWrapper::CreateValue(KeyValue->value); return true; } -TMap UConfigCatSubsystem::GetAllValues(const FConfigCatUser& User) const +TMap UConfigCatSubsystem::GetAllValues(const UConfigCatUserWrapper* User) const { - if (!ensure(ConfigCatClient)) + if(!EnsureConfigCatClient(ConfigCatClient)) { - UE_LOG(LogConfigCat, Warning, TEXT("Trying to access the ConfigCatClient before initialization or after shutdown.")); return {}; } - const ConfigCatUser* TargetUser = User.User.get(); - - const std::unordered_map Values = ConfigCatClient->getAllValues(TargetUser); + const std::unordered_map Values = ConfigCatClient->getAllValues(User ? User->User : nullptr); - TMap Result; + TMap Result; for (const std::pair& Value : Values) { - Result.Emplace(UTF8_TO_TCHAR(Value.first.c_str()), Value.second); + Result.Emplace(UTF8_TO_TCHAR(Value.first.c_str()), UConfigCatValueWrapper::CreateValue(Value.second)); } return Result; } -TArray UConfigCatSubsystem::GetAllValueDetails(const FConfigCatUser& User) const +TArray UConfigCatSubsystem::GetAllValueDetails(const UConfigCatUserWrapper* User) const { - if (!ensure(ConfigCatClient)) + if(!EnsureConfigCatClient(ConfigCatClient)) { - UE_LOG(LogConfigCat, Warning, TEXT("Trying to access the ConfigCatClient before initialization or after shutdown.")); return {}; } - const ConfigCatUser* TargetUser = User.User.get(); - - const std::vector ValueDetails = ConfigCatClient->getAllValueDetails(TargetUser); + const std::vector> ValueDetails = ConfigCatClient->getAllValueDetails(User ? User->User : nullptr); - TArray Result; - for (const EvaluationDetails& ValueDetail : ValueDetails) + TArray Result; + for (const EvaluationDetails& ValueDetail : ValueDetails) { - Result.Emplace(ValueDetail); + Result.Emplace(UConfigCatEvaluationWrapper::CreateEvaluation(ValueDetail)); } return Result; @@ -208,36 +207,33 @@ TArray UConfigCatSubsystem::GetAllValueDetails(cons void UConfigCatSubsystem::ForceRefresh() { - if (!ensure(ConfigCatClient)) + if(!EnsureConfigCatClient(ConfigCatClient)) { - UE_LOG(LogConfigCat, Warning, TEXT("Trying to access the ConfigCatClient before initialization or after shutdown.")); return; } ConfigCatClient->forceRefresh(); } -void UConfigCatSubsystem::SetDefaultUser(const FConfigCatUser& User) +void UConfigCatSubsystem::SetDefaultUser(const UConfigCatUserWrapper* User) { - if (!ensure(ConfigCatClient)) + if(!EnsureConfigCatClient(ConfigCatClient)) { - UE_LOG(LogConfigCat, Warning, TEXT("Trying to access the ConfigCatClient before initialization or after shutdown.")); return; } - if (!User.User) + if (!User || !User->User) { UE_LOG(LogConfigCat, Warning, TEXT("Trying to set Default User with invalid pointer.")); return; } - ConfigCatClient->setDefaultUser(User.User); + ConfigCatClient->setDefaultUser(User->User); } void UConfigCatSubsystem::ClearDefaultUser() { - if (!ensure(ConfigCatClient)) + if(!EnsureConfigCatClient(ConfigCatClient)) { - UE_LOG(LogConfigCat, Warning, TEXT("Trying to access the ConfigCatClient before initialization or after shutdown.")); return; } @@ -246,9 +242,8 @@ void UConfigCatSubsystem::ClearDefaultUser() void UConfigCatSubsystem::SetOnline() { - if (!ensure(ConfigCatClient)) + if(!EnsureConfigCatClient(ConfigCatClient)) { - UE_LOG(LogConfigCat, Warning, TEXT("Trying to access the ConfigCatClient before initialization or after shutdown.")); return; } @@ -257,9 +252,8 @@ void UConfigCatSubsystem::SetOnline() void UConfigCatSubsystem::SetOffline() { - if (!ensure(ConfigCatClient)) + if(!EnsureConfigCatClient(ConfigCatClient)) { - UE_LOG(LogConfigCat, Warning, TEXT("Trying to access the ConfigCatClient before initialization or after shutdown.")); return; } @@ -268,9 +262,8 @@ void UConfigCatSubsystem::SetOffline() bool UConfigCatSubsystem::IsOffline() const { - if (!ensure(ConfigCatClient)) + if(!EnsureConfigCatClient(ConfigCatClient)) { - UE_LOG(LogConfigCat, Warning, TEXT("Trying to access the ConfigCatClient before initialization or after shutdown.")); return true; } @@ -284,7 +277,7 @@ void UConfigCatSubsystem::Initialize(FSubsystemCollectionBase& Collection) #endif const UConfigCatSettings* ConfigCatSettings = GetDefault(); - if(!ConfigCatSettings || ConfigCatSettings->SdkKey.IsEmpty()) + if (!ConfigCatSettings || ConfigCatSettings->SdkKey.IsEmpty()) { UE_LOG(LogConfigCat, Warning, TEXT("Empty SdkKey detected. Please set your SdkKey in the Project Settings.")); return; @@ -371,16 +364,17 @@ void UConfigCatSubsystem::SetupClientHooks(ConfigCatOptions& Options) TWeakObjectPtr WeakThis(this); Options.hooks->addOnError( - [WeakThis](const std::string& Error) + [WeakThis](const std::string& Error, const std::exception_ptr& Exception) { if (WeakThis.IsValid()) { const FString& StringError = UTF8_TO_TCHAR(Error.c_str()); + const FString& StringException = UTF8_TO_TCHAR(unwrap_exception_message(Exception).c_str()); - UE_LOG(LogConfigCat, Error, TEXT("ConfigCatClient Error: %s"), *StringError); + UE_LOG(LogConfigCat, Error, TEXT("ConfigCatClient Error: %s Exception: %s"), *StringError, *StringException); - WeakThis->OnError.Broadcast(StringError); - WeakThis->OnErrorBp.Broadcast(StringError); + WeakThis->OnError.Broadcast(StringError, StringException); + WeakThis->OnErrorBp.Broadcast(StringError, StringException); } } ); @@ -395,29 +389,24 @@ void UConfigCatSubsystem::SetupClientHooks(ConfigCatOptions& Options) } ); Options.hooks->addOnConfigChanged( - [WeakThis](const std::shared_ptr& Config) + [WeakThis](const std::shared_ptr& InConfig) { if (WeakThis.IsValid()) { - FConfigCatConfig NewConfig; - if (Config) - { - for (const std::pair& Setting : *Config) - { - NewConfig.Settings.Emplace(UTF8_TO_TCHAR(Setting.first.c_str()), Setting.second); - } - } - - WeakThis->OnConfigChanged.Broadcast(NewConfig); - WeakThis->OnConfigChangedBp.Broadcast(NewConfig); + UConfigCatSettingsWrapper* Config = UConfigCatSettingsWrapper::CreateSettings(InConfig); + + WeakThis->OnConfigChanged.Broadcast(Config); + WeakThis->OnConfigChangedBp.Broadcast(Config); } } ); Options.hooks->addOnFlagEvaluated( - [WeakThis](const EvaluationDetails& EvaluationDetails) + [WeakThis](const EvaluationDetailsBase& InEvaluationDetails) { if (WeakThis.IsValid()) { + UConfigCatEvaluationWrapper* EvaluationDetails = UConfigCatEvaluationWrapper::CreateEvaluation(InEvaluationDetails); + WeakThis->OnFlagEvaluated.Broadcast(EvaluationDetails); WeakThis->OnFlagEvaluatedBp.Broadcast(EvaluationDetails); } @@ -457,4 +446,4 @@ void UConfigCatSubsystem::SetupClientOverrides(ConfigCatOptions& Options) // std::unordered_map OverrideFlags; // Options.flagOverrides = std::make_shared(OverrideFlags, Behaviour); } -} +} \ No newline at end of file diff --git a/Source/ConfigCat/Private/Wrapper/ConfigCatEvaluationDetails.cpp b/Source/ConfigCat/Private/Wrapper/ConfigCatEvaluationDetails.cpp deleted file mode 100644 index e51feac..0000000 --- a/Source/ConfigCat/Private/Wrapper/ConfigCatEvaluationDetails.cpp +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (c) ConfigCat 2024. All Rights Reserved. - -#include "Wrapper/ConfigCatEvaluationDetails.h" - -#include - -#include "Wrapper/ConfigCatRolloutPercentageItem.h" -#include "Wrapper/ConfigCatRolloutRule.h" -#include "Wrapper/ConfigCatUser.h" -#include "Wrapper/ConfigCatValue.h" - -using namespace configcat; - -FConfigCatEvaluationDetails::FConfigCatEvaluationDetails(configcat::EvaluationDetails InDetails) -{ - EvaluationDetails = std::make_shared(InDetails); -} - -FString FConfigCatEvaluationDetails::GetKey() const -{ - if (EvaluationDetails) - { - return UTF8_TO_TCHAR(EvaluationDetails->key.c_str()); - } - - return {}; -} - -FConfigCatValue FConfigCatEvaluationDetails::GetValue() const -{ - if (EvaluationDetails) - { - return FConfigCatValue(EvaluationDetails->value); - } - - return {}; -} - -FString FConfigCatEvaluationDetails::GetVariationId() const -{ - if (EvaluationDetails) - { - return UTF8_TO_TCHAR(EvaluationDetails->variationId.c_str()); - } - - return {}; -} - -FDateTime FConfigCatEvaluationDetails::GetFetchTime() const -{ - if (EvaluationDetails) - { - const auto TimeSinceEpoch = EvaluationDetails->fetchTime.time_since_epoch().count(); - return FDateTime::FromUnixTimestamp(TimeSinceEpoch); - } - - return {}; -} - -FConfigCatUser FConfigCatEvaluationDetails::GetUser() const -{ - if (EvaluationDetails) - { - // TODO: Discuss if we can make everything const? ideally the configcat client should not need the non-const version for SetUser - return FConfigCatUser(const_cast(EvaluationDetails->user)); - } - - return {}; -} - -bool FConfigCatEvaluationDetails::IsDefaultValue() const -{ - if (EvaluationDetails) - { - return EvaluationDetails->isDefaultValue; - } - - return {}; -} - -FString FConfigCatEvaluationDetails::GetError() const -{ - if (EvaluationDetails) - { - return UTF8_TO_TCHAR(EvaluationDetails->error.c_str()); - } - - return {}; -} - -FConfigCatRolloutRule FConfigCatEvaluationDetails::GetRolloutRule() const -{ - if (EvaluationDetails && EvaluationDetails->matchedEvaluationRule.has_value()) - { - return EvaluationDetails->matchedEvaluationRule.value(); - } - - return {}; -} - -FConfigCatRolloutPercentageItem FConfigCatEvaluationDetails::GetRolloutPercentageItem() const -{ - if (EvaluationDetails && EvaluationDetails->matchedEvaluationPercentageRule.has_value()) - { - return EvaluationDetails->matchedEvaluationPercentageRule.value(); - } - - return {}; -} - -FString UConfigCatEvaluationDetailsAccessorsBPLibrary::GetKey(const FConfigCatEvaluationDetails& Struct) -{ - return Struct.GetKey(); -} - -FConfigCatValue UConfigCatEvaluationDetailsAccessorsBPLibrary::GetValue(const FConfigCatEvaluationDetails& Struct) -{ - return Struct.GetValue(); -} - -FString UConfigCatEvaluationDetailsAccessorsBPLibrary::GetVariationId(const FConfigCatEvaluationDetails& Struct) -{ - return Struct.GetVariationId(); -} - -FDateTime UConfigCatEvaluationDetailsAccessorsBPLibrary::GetFetchTime(const FConfigCatEvaluationDetails& Struct) -{ - return Struct.GetFetchTime(); -} - -FConfigCatUser UConfigCatEvaluationDetailsAccessorsBPLibrary::GetUser(const FConfigCatEvaluationDetails& Struct) -{ - return Struct.GetUser(); -} - -bool UConfigCatEvaluationDetailsAccessorsBPLibrary::IsDefaultValue(const FConfigCatEvaluationDetails& Struct) -{ - return Struct.IsDefaultValue(); -} - -FString UConfigCatEvaluationDetailsAccessorsBPLibrary::GetError(const FConfigCatEvaluationDetails& Struct) -{ - return Struct.GetError(); -} - -FConfigCatRolloutRule UConfigCatEvaluationDetailsAccessorsBPLibrary::GetRolloutRule(const FConfigCatEvaluationDetails& Struct) -{ - return Struct.GetRolloutRule(); -} - -FConfigCatRolloutPercentageItem UConfigCatEvaluationDetailsAccessorsBPLibrary::GetRolloutPercentageItem(const FConfigCatEvaluationDetails& Struct) -{ - return Struct.GetRolloutPercentageItem(); -} diff --git a/Source/ConfigCat/Private/Wrapper/ConfigCatRolloutPercentageItem.cpp b/Source/ConfigCat/Private/Wrapper/ConfigCatRolloutPercentageItem.cpp deleted file mode 100644 index 000d689..0000000 --- a/Source/ConfigCat/Private/Wrapper/ConfigCatRolloutPercentageItem.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) ConfigCat 2024. All Rights Reserved. - -#include "Wrapper/ConfigCatRolloutPercentageItem.h" - -#include - -#include "Wrapper/ConfigCatValue.h" - -FConfigCatRolloutPercentageItem::FConfigCatRolloutPercentageItem(const configcat::RolloutPercentageItem& InPercentageItem) -{ - PercentageItem = std::make_shared(InPercentageItem); -} - -bool FConfigCatRolloutPercentageItem::IsValid() const -{ - return PercentageItem.get() != nullptr; -} - -FConfigCatValue FConfigCatRolloutPercentageItem::GetPercentageValue() const -{ - if (IsValid()) - { - return PercentageItem->value; - } - - return {}; -} - -double FConfigCatRolloutPercentageItem::GetPercentagePercentage() const -{ - if (IsValid()) - { - return PercentageItem->percentage; - } - - return {}; -} - -FString FConfigCatRolloutPercentageItem::GetPercentageVariationId() const -{ - if (IsValid()) - { - return UTF8_TO_TCHAR(PercentageItem->variationId.c_str()); - } - - return {}; -} - -bool UConfigCatPercentageItemAccessorsBPLibrary::IsValid(const FConfigCatRolloutPercentageItem& Struct) -{ - return Struct.IsValid(); -} - -FConfigCatValue UConfigCatPercentageItemAccessorsBPLibrary::GetPercentageValue(const FConfigCatRolloutPercentageItem& Struct) -{ - return Struct.GetPercentageValue(); -} - -double UConfigCatPercentageItemAccessorsBPLibrary::GetPercentagePercentage(const FConfigCatRolloutPercentageItem& Struct) -{ - return Struct.GetPercentagePercentage(); -} - -FString UConfigCatPercentageItemAccessorsBPLibrary::GetPercentageVariationId(const FConfigCatRolloutPercentageItem& Struct) -{ - return Struct.GetPercentageVariationId(); -} diff --git a/Source/ConfigCat/Private/Wrapper/ConfigCatRolloutRule.cpp b/Source/ConfigCat/Private/Wrapper/ConfigCatRolloutRule.cpp deleted file mode 100644 index dbb4984..0000000 --- a/Source/ConfigCat/Private/Wrapper/ConfigCatRolloutRule.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) ConfigCat 2024. All Rights Reserved. - -#include "Wrapper/ConfigCatRolloutRule.h" - -#include - -#include "Wrapper/ConfigCatValue.h" - -FConfigCatRolloutRule::FConfigCatRolloutRule(const configcat::RolloutRule& InRule) -{ - Rule = std::make_shared(InRule); -} - -bool FConfigCatRolloutRule::IsValid() const -{ - return Rule.get() != nullptr; -} - -FConfigCatValue FConfigCatRolloutRule::GetRuleValue() const -{ - if (IsValid()) - { - return Rule->value; - } - - return {}; -} - -FString FConfigCatRolloutRule::GetRuleComparisonAttribute() const -{ - if (IsValid()) - { - return UTF8_TO_TCHAR(Rule->comparisonAttribute.c_str()); - } - - return {}; -} - -FString FConfigCatRolloutRule::GetRuleComparator() const -{ - if (IsValid()) - { - return UTF8_TO_TCHAR(configcat::comparatorToString(Rule->comparator)); - } - - return {}; -} - -FString FConfigCatRolloutRule::GetRuleComparisonValue() const -{ - if (IsValid()) - { - return UTF8_TO_TCHAR(Rule->comparisonValue.c_str()); - } - - return {}; -} - -FString FConfigCatRolloutRule::GetRuleVariationId() const -{ - if (IsValid()) - { - return UTF8_TO_TCHAR(Rule->variationId.c_str()); - } - - return {}; -} - -bool UConfigCatRuleAccessorsBPLibrary::IsValid(const FConfigCatRolloutRule& Struct) -{ - return Struct.IsValid(); -} - -FConfigCatValue UConfigCatRuleAccessorsBPLibrary::GetRuleValue(const FConfigCatRolloutRule& Struct) -{ - return Struct.GetRuleValue(); -} - -FString UConfigCatRuleAccessorsBPLibrary::GetRuleComparisonAttribute(const FConfigCatRolloutRule& Struct) -{ - return Struct.GetRuleComparisonAttribute(); -} - -FString UConfigCatRuleAccessorsBPLibrary::GetRuleComparator(const FConfigCatRolloutRule& Struct) -{ - return Struct.GetRuleComparator(); -} - -FString UConfigCatRuleAccessorsBPLibrary::GetRuleComparisonValue(const FConfigCatRolloutRule& Struct) -{ - return Struct.GetRuleComparisonValue(); -} - -FString UConfigCatRuleAccessorsBPLibrary::GetRuleVariationId(const FConfigCatRolloutRule& Struct) -{ - return Struct.GetRuleVariationId(); -} diff --git a/Source/ConfigCat/Private/Wrapper/ConfigCatSetting.cpp b/Source/ConfigCat/Private/Wrapper/ConfigCatSetting.cpp deleted file mode 100644 index 9131a45..0000000 --- a/Source/ConfigCat/Private/Wrapper/ConfigCatSetting.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) ConfigCat 2024. All Rights Reserved. - -#include "Wrapper/ConfigCatSetting.h" - -#include - -#include "Wrapper/ConfigCatRolloutPercentageItem.h" -#include "Wrapper/ConfigCatRolloutRule.h" -#include "Wrapper/ConfigCatValue.h" - -FConfigCatSetting::FConfigCatSetting(const configcat::Setting& InSetting) -{ - Setting = std::make_shared(InSetting); -} - -FConfigCatValue FConfigCatSetting::GetSettingValue() const -{ - if (Setting) - { - return Setting->value; - } - - return {}; -} - -TArray FConfigCatSetting::GetSettingRolloutRules() const -{ - TArray Result; - - if (Setting) - { - for (const auto& Rule : Setting->rolloutRules) - { - Result.Emplace(Rule); - } - } - - return Result; -} - -TArray FConfigCatSetting::GetSettingRolloutPercentageItem() const -{ - TArray Result; - - if (Setting) - { - for (const auto& PercentageItem : Setting->percentageItems) - { - Result.Emplace(PercentageItem); - } - } - - return Result; -} - -FString FConfigCatSetting::GetSettingVariationId() const -{ - if (Setting) - { - return UTF8_TO_TCHAR(Setting->variationId.c_str()); - } - - return {}; -} - -FConfigCatValue UConfigCatSettingAccessorsBPLibrary::GetSettingValue(const FConfigCatSetting& Struct) -{ - return Struct.GetSettingValue(); -} - -TArray UConfigCatSettingAccessorsBPLibrary::GetSettingRolloutRules(const FConfigCatSetting& Struct) -{ - return Struct.GetSettingRolloutRules(); -} - -TArray UConfigCatSettingAccessorsBPLibrary::GetSettingRolloutPercentageItem(const FConfigCatSetting& Struct) -{ - return Struct.GetSettingRolloutPercentageItem(); -} - -FString UConfigCatSettingAccessorsBPLibrary::GetSettingVariationId(const FConfigCatSetting& Struct) -{ - return Struct.GetSettingVariationId(); -} \ No newline at end of file diff --git a/Source/ConfigCat/Private/Wrapper/ConfigCatUser.cpp b/Source/ConfigCat/Private/Wrapper/ConfigCatUser.cpp deleted file mode 100644 index e25b5ea..0000000 --- a/Source/ConfigCat/Private/Wrapper/ConfigCatUser.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) ConfigCat 2024. All Rights Reserved. - -#include "Wrapper/ConfigCatUser.h" - -#include - -using namespace configcat; - -FConfigCatUser::FConfigCatUser(ConfigCatUser* InUser) -{ - if (InUser) - { - User = std::make_shared(*InUser); - } -} - -FConfigCatUser::FConfigCatUser(const FString& Id, const FString& Email, const FString& Country, const TMap& Attributes) -{ - const std::string& UserId = TCHAR_TO_UTF8(*Id); - const std::string& UserEmail = TCHAR_TO_UTF8(*Email); - const std::string& UserCountry = TCHAR_TO_UTF8(*Country); - - std::unordered_map UserAttributes; - for (const TTuple& Attribute : Attributes) - { - const std::string& AttributeKey = TCHAR_TO_UTF8(*Attribute.Key); - const std::string& AttributeValue = TCHAR_TO_UTF8(*Attribute.Value); - - UserAttributes.emplace(AttributeKey, AttributeValue); - } - - User = std::make_shared(UserId, UserEmail, UserCountry, UserAttributes); -} - -FString FConfigCatUser::GetIdentifier() const -{ - if (User) - { - return UTF8_TO_TCHAR(User->identifier.c_str()); - } - - return {}; -} - -FString FConfigCatUser::GetAttribute(const FString& Key) const -{ - const std::string* Result = nullptr; - if (User) - { - const std::string AttributeKey = TCHAR_TO_UTF8(*Key); - Result = User->getAttribute(AttributeKey); - } - - return Result ? UTF8_TO_TCHAR(Result->c_str()) : TEXT(""); -} - -FConfigCatUser UConfigCatUserAccessorsBPLibrary::CreateUser(const FString& Id, const FString& Email, const FString& Country, const TMap& Attributes) -{ - return FConfigCatUser(Id, Email, Country, Attributes); -} - -FString UConfigCatUserAccessorsBPLibrary::GetIdentifier(const FConfigCatUser& Struct) -{ - return Struct.GetIdentifier(); -} - -FString UConfigCatUserAccessorsBPLibrary::GetAttribute(const FConfigCatUser& Struct, const FString& Key) -{ - return Struct.GetAttribute(Key); -} \ No newline at end of file diff --git a/Source/ConfigCat/Private/Wrapper/ConfigCatValue.cpp b/Source/ConfigCat/Private/Wrapper/ConfigCatValue.cpp deleted file mode 100644 index 673e0fa..0000000 --- a/Source/ConfigCat/Private/Wrapper/ConfigCatValue.cpp +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright (c) ConfigCat 2024. All Rights Reserved. - -#include "Wrapper/ConfigCatValue.h" - -#include - -FConfigCatValue::FConfigCatValue(const configcat::Value& InValue) -{ - Value = std::make_shared(InValue); -} - -FConfigCatValue::FConfigCatValue(std::shared_ptr InValue) -{ - Value = InValue; -} - -bool FConfigCatValue::HasAnyValue() const -{ - return HasBooleanValue() || HasStringValue() || HasIntegerValue() || HasDecimalValue(); -} - -bool FConfigCatValue::HasBooleanValue() const -{ - return Value && std::holds_alternative(*Value); -} - -bool FConfigCatValue::HasStringValue() const -{ - return Value && std::holds_alternative(*Value); -} - -bool FConfigCatValue::HasIntegerValue() const -{ - return Value && std::holds_alternative(*Value); -} - -bool FConfigCatValue::HasDecimalValue() const -{ - return Value && std::holds_alternative(*Value); -} - -bool FConfigCatValue::GetBooleanValue() const -{ - if (HasBooleanValue()) - { - return std::get(*Value); - } - - return {}; -} - -FString FConfigCatValue::GetStringValue() const -{ - if (HasStringValue()) - { - return UTF8_TO_TCHAR(std::get(*Value).c_str()); - } - - return {}; -} - -int FConfigCatValue::GetIntegerValue() const -{ - if (HasIntegerValue()) - { - return std::get(*Value); - } - - return {}; -} - -double FConfigCatValue::GetDecimalValue() const -{ - if (HasDecimalValue()) - { - return std::get(*Value); - } - - return {}; -} - -bool UConfigCatValueAccessorsBPLibrary::HasAnyValue(const FConfigCatValue& Struct) -{ - return Struct.HasAnyValue(); -} - -bool UConfigCatValueAccessorsBPLibrary::HasBooleanValue(const FConfigCatValue& Struct) -{ - return Struct.HasBooleanValue(); -} - -bool UConfigCatValueAccessorsBPLibrary::HasStringValue(const FConfigCatValue& Struct) -{ - return Struct.HasStringValue(); -} - -bool UConfigCatValueAccessorsBPLibrary::HasIntegerValue(const FConfigCatValue& Struct) -{ - return Struct.HasIntegerValue(); -} - -bool UConfigCatValueAccessorsBPLibrary::HasDecimalValue(const FConfigCatValue& Struct) -{ - return Struct.HasDecimalValue(); -} - -bool UConfigCatValueAccessorsBPLibrary::GetBooleanValue(const FConfigCatValue& Struct) -{ - return Struct.GetBooleanValue(); -} - -FString UConfigCatValueAccessorsBPLibrary::GetStringValue(const FConfigCatValue& Struct) -{ - return Struct.GetStringValue(); -} - -int UConfigCatValueAccessorsBPLibrary::GetIntegerValue(const FConfigCatValue& Struct) -{ - return Struct.GetIntegerValue(); -} - -double UConfigCatValueAccessorsBPLibrary::GetDecimalValue(const FConfigCatValue& Struct) -{ - return Struct.GetDecimalValue(); -} - -FConfigCatValue UConfigCatValueAccessorsBPLibrary::CreteBooleanValue(bool Value) -{ - return FConfigCatValue(configcat::Value(Value)); -} - -FConfigCatValue UConfigCatValueAccessorsBPLibrary::CreateStringValue(const FString& Value) -{ - const std::string StringValue = TCHAR_TO_UTF8(*Value); - return FConfigCatValue(configcat::Value(StringValue)); -} - -FConfigCatValue UConfigCatValueAccessorsBPLibrary::CreateIntegerValue(int Value) -{ - return FConfigCatValue(configcat::Value(Value)); -} - -FConfigCatValue UConfigCatValueAccessorsBPLibrary::CreateDecimalValue(double Value) -{ - return FConfigCatValue(configcat::Value(Value)); -} diff --git a/Source/ConfigCat/Public/ConfigCatLogger.h b/Source/ConfigCat/Public/ConfigCatLogger.h index 176c76d..35bf712 100644 --- a/Source/ConfigCat/Public/ConfigCatLogger.h +++ b/Source/ConfigCat/Public/ConfigCatLogger.h @@ -15,6 +15,6 @@ class FConfigCatLogger : public configcat::ILogger private: // Begin configcat::ILogger interface - virtual void log(configcat::LogLevel level, const std::string& message) override; + virtual void log(configcat::LogLevel level, const std::string& message, const std::exception_ptr& exception = nullptr) override; // End configcat::ILogger interface }; diff --git a/Source/ConfigCat/Public/ConfigCatNetworkAdapter.h b/Source/ConfigCat/Public/ConfigCatNetworkAdapter.h index 9266e4f..4edadba 100644 --- a/Source/ConfigCat/Public/ConfigCatNetworkAdapter.h +++ b/Source/ConfigCat/Public/ConfigCatNetworkAdapter.h @@ -24,9 +24,9 @@ class ConfigCatNetworkAdapter : public configcat::HttpSessionAdapter virtual bool init(uint32_t connectTimeoutMs, uint32_t readTimeoutMs) override; virtual configcat::Response get(const std::string& url, - const std::map& header, - const std::map& proxies, - const std::map& proxyAuthentications) override; + const std::map& header, + const std::map& proxies, + const std::map& proxyAuthentications) override; virtual void close() override; // End configcat::HttpSessionAdapter interface /* @@ -45,4 +45,4 @@ class ConfigCatNetworkAdapter : public configcat::HttpSessionAdapter * Value used for the HTTP request header field X-ConfigCat-UserAgent */ FString UserAgentVersion; -}; +}; \ No newline at end of file diff --git a/Source/ConfigCat/Public/ConfigCatSubsystem.h b/Source/ConfigCat/Public/ConfigCatSubsystem.h index 0a71647..63dc3b1 100644 --- a/Source/ConfigCat/Public/ConfigCatSubsystem.h +++ b/Source/ConfigCat/Public/ConfigCatSubsystem.h @@ -4,29 +4,29 @@ #include #include - -#include "Wrapper/ConfigCatSetting.h" -#include "Wrapper/ConfigCatUser.h" +#include #include "ConfigCatSubsystem.generated.h" -struct FConfigCatEvaluationDetails; +class UConfigCatSettingsWrapper; +class UConfigCatEvaluationWrapper; +class UConfigCatValueWrapper; + namespace configcat { struct ConfigCatOptions; class ConfigCatClient; - class ConfigCatUser; } // namespace configcat using FOnClientReady = FSimpleMulticastDelegate; -using FOnConfigChanged = TMulticastDelegate; -using FOnFlagEvaluated = TMulticastDelegate; -using FOnError = TMulticastDelegate; +using FOnConfigChanged = TMulticastDelegate; +using FOnFlagEvaluated = TMulticastDelegate; +using FOnError = TMulticastDelegate; DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnClientReadyBP); -DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnConfigChangedBp, const FConfigCatConfig&, Config); -DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnFlagEvaluatedBp, const FConfigCatEvaluationDetails&, Details); -DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnErrorBp, const FString&, Error); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnConfigChangedBp, UConfigCatSettingsWrapper*, Config); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnFlagEvaluatedBp, UConfigCatEvaluationWrapper*, Details); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnErrorBp, const FString&, Error, const FString&, Exception); /** * Wrapper for accessing the configcat client. This subsystem is responsible for initializing and managing the client's lifecycle. @@ -46,47 +46,47 @@ class CONFIGCAT_API UConfigCatSubsystem : public UGameInstanceSubsystem * Gets a feature flag of boolean value for a specific key. Optionally takes in a target user. */ UFUNCTION(BlueprintPure, DisplayName = "Get Value (Boolean)", Category = "ConfigCat", meta = (AdvancedDisplay = "bDefaultValue, User", AutoCreateRefTerm = "User")) - bool GetBoolValue(const FString& Key, bool bDefaultValue, const FConfigCatUser& User = FConfigCatUser()) const; + bool GetBoolValue(const FString& Key, bool bDefaultValue, const UConfigCatUserWrapper* User = nullptr) const; /** * Gets a feature flag of integer value for a specific key. Optionally takes in a target user. */ UFUNCTION(BlueprintPure, DisplayName = "Get Value (Integer)", Category = "ConfigCat", meta = (AdvancedDisplay = "DefaultValue, User", AutoCreateRefTerm = "User")) - int32 GetIntValue(const FString& Key, int32 DefaultValue, const FConfigCatUser& User = FConfigCatUser()) const; + int32 GetIntValue(const FString& Key, int32 DefaultValue, const UConfigCatUserWrapper* User = nullptr) const; /** * Gets a feature flag of decimal (double) value for a specific key. Optionally takes in a target user. */ UFUNCTION(BlueprintPure, DisplayName = "Get Value (Double)", Category = "ConfigCat", meta = (AdvancedDisplay = "DefaultValue, User", AutoCreateRefTerm = "User")) - double GetDoubleValue(const FString& Key, double DefaultValue, const FConfigCatUser& User = FConfigCatUser()) const; + double GetDoubleValue(const FString& Key, double DefaultValue, const UConfigCatUserWrapper* User = nullptr) const; /** * Gets a feature flag of string value for a specific key. Optionally takes in a target user. */ UFUNCTION(BlueprintPure, DisplayName = "Get Value (String)", Category = "ConfigCat", meta = (AdvancedDisplay = "DefaultValue, User", AutoCreateRefTerm = "User")) - FString GetStringValue(const FString& Key, const FString& DefaultValue, const FConfigCatUser& User = FConfigCatUser()) const; + FString GetStringValue(const FString& Key, const FString& DefaultValue, const UConfigCatUserWrapper* User = nullptr) const; /** * Gets a feature flag of variant value for a specific key. Optionally takes in a target user. */ UFUNCTION(BlueprintPure, DisplayName = "Get Config Value", Category = "ConfigCat", meta = (AdvancedDisplay = "User", AutoCreateRefTerm = "User")) - FConfigCatValue GetConfigValue(const FString& Key, const FConfigCatUser& User = FConfigCatUser()) const; + UConfigCatValueWrapper* GetConfigValue(const FString& Key, const UConfigCatUserWrapper* User = nullptr) const; /** * Gets the evaluation details of a feature flag of bool value for a specific key. Optionally takes in a target user. */ UFUNCTION(BlueprintPure, DisplayName = "Get Value Details(Boolean)", Category = "ConfigCat", meta = (AdvancedDisplay = "DefaultValue, User", AutoCreateRefTerm = "User")) - FConfigCatEvaluationDetails GetBoolValueDetails(const FString& Key, bool DefaultValue, const FConfigCatUser& User = FConfigCatUser()) const; + UConfigCatEvaluationWrapper* GetBoolValueDetails(const FString& Key, bool DefaultValue, const UConfigCatUserWrapper* User = nullptr) const; /** * Gets the evaluation details of a feature flag of integer value for a specific key. Optionally takes in a target user. */ UFUNCTION(BlueprintPure, DisplayName = "Get Value Details(Integer)", Category = "ConfigCat", meta = (AdvancedDisplay = "DefaultValue, User", AutoCreateRefTerm = "User")) - FConfigCatEvaluationDetails GetIntValueDetails(const FString& Key, int DefaultValue, const FConfigCatUser& User = FConfigCatUser()) const; + UConfigCatEvaluationWrapper* GetIntValueDetails(const FString& Key, int DefaultValue, const UConfigCatUserWrapper* User = nullptr) const; /** * Gets the evaluation details of a feature flag of decimal (double) value for a specific key. Optionally takes in a target user. */ UFUNCTION(BlueprintPure, DisplayName = "Get Value Details(Double)", Category = "ConfigCat", meta = (AdvancedDisplay = "DefaultValue, User", AutoCreateRefTerm = "User")) - FConfigCatEvaluationDetails GetDoubleValueDetails(const FString& Key, double DefaultValue, const FConfigCatUser& User = FConfigCatUser()) const; + UConfigCatEvaluationWrapper* GetDoubleValueDetails(const FString& Key, double DefaultValue, const UConfigCatUserWrapper* User = nullptr) const; /** * Gets the evaluation details of a feature flag of string value for a specific key. Optionally takes in a target user. */ UFUNCTION(BlueprintPure, DisplayName = "Get Value Details(String)", Category = "ConfigCat", meta = (AdvancedDisplay = "DefaultValue, User", AutoCreateRefTerm = "User")) - FConfigCatEvaluationDetails GetStringValueDetails(const FString& Key, const FString& DefaultValue, const FConfigCatUser& User = FConfigCatUser()) const; + UConfigCatEvaluationWrapper* GetStringValueDetails(const FString& Key, const FString& DefaultValue, const UConfigCatUserWrapper* User = nullptr) const; /** * Gets all the setting keys. */ @@ -96,17 +96,17 @@ class CONFIGCAT_API UConfigCatSubsystem : public UGameInstanceSubsystem * Gets the key of a setting and it's value identified by the given Variation ID (analytics) */ UFUNCTION(BlueprintPure, Category = "ConfigCat") - bool GetKeyAndValue(const FString& VariationId, FString& OutKey, FConfigCatValue& OutValue) const; + bool GetKeyAndValue(const FString& VariationId, FString& OutKey, UConfigCatValueWrapper*& OutValue) const; /** * Gets the values of all feature flags or settings. */ UFUNCTION(BlueprintPure, Category = "ConfigCat", meta = (AdvancedDisplay = "User", AutoCreateRefTerm = "User")) - TMap GetAllValues(const FConfigCatUser& User = FConfigCatUser()) const; + TMap GetAllValues(const UConfigCatUserWrapper* User = nullptr) const; /** * Gets the values along with evaluation details of all feature flags and settings. */ UFUNCTION(BlueprintPure, Category = "ConfigCat", meta = (AdvancedDisplay = "User", AutoCreateRefTerm = "User")) - TArray GetAllValueDetails(const FConfigCatUser& User = FConfigCatUser()) const; + TArray GetAllValueDetails(const UConfigCatUserWrapper* User = nullptr) const; /** * Initiates a force refresh synchronously on the cached configuration. */ @@ -116,7 +116,7 @@ class CONFIGCAT_API UConfigCatSubsystem : public UGameInstanceSubsystem * Sets the default user. */ UFUNCTION(BlueprintCallable, Category = "ConfigCat") - void SetDefaultUser(const FConfigCatUser& User = FConfigCatUser()); + void SetDefaultUser(const UConfigCatUserWrapper* User = nullptr); /** * Sets the default user to nullptr. */ @@ -190,5 +190,5 @@ class CONFIGCAT_API UConfigCatSubsystem : public UGameInstanceSubsystem /** * Internal pointer to the configcat client singleton. */ - configcat::ConfigCatClient* ConfigCatClient; + std::shared_ptr ConfigCatClient; }; diff --git a/Source/ConfigCat/Public/Wrapper/ConfigCatEvaluationDetails.h b/Source/ConfigCat/Public/Wrapper/ConfigCatEvaluationDetails.h deleted file mode 100644 index 65e12cf..0000000 --- a/Source/ConfigCat/Public/Wrapper/ConfigCatEvaluationDetails.h +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) ConfigCat 2024. All Rights Reserved. - -#pragma once - -#include - -#include - -#include "ConfigCatEvaluationDetails.generated.h" - -struct FConfigCatRolloutPercentageItem; -struct FConfigCatRolloutRule; -struct FConfigCatUser; -struct FConfigCatValue; - -namespace configcat -{ - struct EvaluationDetails; -} - -/** - * Wrapper class for configcat::EvaluationDetails - */ -USTRUCT(BlueprintType) -struct CONFIGCAT_API FConfigCatEvaluationDetails -{ - GENERATED_BODY() - - FConfigCatEvaluationDetails() = default; - FConfigCatEvaluationDetails(configcat::EvaluationDetails InDetails); - - FString GetKey() const; - FConfigCatValue GetValue() const; - FString GetVariationId() const; - FDateTime GetFetchTime() const; - FConfigCatUser GetUser() const; - bool IsDefaultValue() const; - FString GetError() const; - FConfigCatRolloutRule GetRolloutRule() const; - FConfigCatRolloutPercentageItem GetRolloutPercentageItem() const; - - /** - * Internal evaluation details we want to expose in blueprints - */ - std::shared_ptr EvaluationDetails; -}; - -/** - * Getters for all the properties of the configcat::EvaluationDetails stored inside a FConfigCatEvaluationDetails wrapper - */ -UCLASS() -class CONFIGCAT_API UConfigCatEvaluationDetailsAccessorsBPLibrary : public UBlueprintFunctionLibrary -{ - GENERATED_BODY() - - /** - * Gets the identifier Key of the evaluated feature flag - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|EvaluationDetails") - static FString GetKey(const FConfigCatEvaluationDetails& Struct); - /** - * Gets the value of the evaluated feature flag - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|EvaluationDetails") - static FConfigCatValue GetValue(const FConfigCatEvaluationDetails& Struct); - /** - * Gets the variation identifier of the evaluated feature flag - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|EvaluationDetails") - static FString GetVariationId(const FConfigCatEvaluationDetails& Struct); - /** - * Gets the timestamp of the last fetch at the time of evaluation - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|EvaluationDetails") - static FDateTime GetFetchTime(const FConfigCatEvaluationDetails& Struct); - /** - * Gets the user the evaluation was performed against - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|EvaluationDetails") - static FConfigCatUser GetUser(const FConfigCatEvaluationDetails& Struct); - /** - * Gets if the value returned is the default value of the feature flag - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|EvaluationDetails") - static bool IsDefaultValue(const FConfigCatEvaluationDetails& Struct); - /** - * Gets the error associated with the evaluation (if any) - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|EvaluationDetails") - static FString GetError(const FConfigCatEvaluationDetails& Struct); - /** - * Gets the matched rollout rule (if any) - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|EvaluationDetails") - static FConfigCatRolloutRule GetRolloutRule(const FConfigCatEvaluationDetails& Struct); - /** - * Gets the matched rollout percentage item (if any) - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|EvaluationDetails") - static FConfigCatRolloutPercentageItem GetRolloutPercentageItem(const FConfigCatEvaluationDetails& Struct); -}; diff --git a/Source/ConfigCat/Public/Wrapper/ConfigCatRolloutPercentageItem.h b/Source/ConfigCat/Public/Wrapper/ConfigCatRolloutPercentageItem.h deleted file mode 100644 index f766b6c..0000000 --- a/Source/ConfigCat/Public/Wrapper/ConfigCatRolloutPercentageItem.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) ConfigCat 2024. All Rights Reserved. - -#pragma once - -#include - -#include - -#include "ConfigCatRolloutPercentageItem.generated.h" - -namespace configcat -{ - struct RolloutPercentageItem; -} // namespace configcat - -/** - * Wrapper class for configcat::RolloutPercentageItem - */ -USTRUCT(BlueprintType) -struct FConfigCatRolloutPercentageItem -{ - GENERATED_BODY() - - FConfigCatRolloutPercentageItem() = default; - FConfigCatRolloutPercentageItem(const configcat::RolloutPercentageItem& InPercentageItem); - - bool IsValid() const; - FConfigCatValue GetPercentageValue() const; - double GetPercentagePercentage() const; - FString GetPercentageVariationId() const; - - /** - * Internal percentage item we want to expose in blueprints - */ - std::shared_ptr PercentageItem; -}; - -/** - * Getters for all the properties of the configcat::RolloutPercentageItem stored inside a FConfigCatRolloutPercentageItem wrapper - */ -UCLASS() -class CONFIGCAT_API UConfigCatPercentageItemAccessorsBPLibrary : public UBlueprintFunctionLibrary -{ - GENERATED_BODY() - - /** - * Checks if the underlying percentage item is valid - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Percentage") - static bool IsValid(const FConfigCatRolloutPercentageItem& Struct); - /** - * Gets the value of the percentage item - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Percentage") - static FConfigCatValue GetPercentageValue(const FConfigCatRolloutPercentageItem& Struct); - /** - * Gets the percentage of the percentage item - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Percentage") - static double GetPercentagePercentage(const FConfigCatRolloutPercentageItem& Struct); - /** - * Gets the variation identifier of the percentage item - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Percentage") - static FString GetPercentageVariationId(const FConfigCatRolloutPercentageItem& Struct); -}; \ No newline at end of file diff --git a/Source/ConfigCat/Public/Wrapper/ConfigCatRolloutRule.h b/Source/ConfigCat/Public/Wrapper/ConfigCatRolloutRule.h deleted file mode 100644 index b8e9fce..0000000 --- a/Source/ConfigCat/Public/Wrapper/ConfigCatRolloutRule.h +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) ConfigCat 2024. All Rights Reserved. - -#pragma once - -#include - -#include - -#include "ConfigCatRolloutRule.generated.h" - -namespace configcat -{ - struct RolloutRule; -} // namespace configcat - -/** - * Wrapper class for configcat::RolloutRule - */ -USTRUCT(BlueprintType) -struct FConfigCatRolloutRule -{ - GENERATED_BODY() - - FConfigCatRolloutRule() = default; - FConfigCatRolloutRule(const configcat::RolloutRule& InRule); - - bool IsValid() const; - FConfigCatValue GetRuleValue() const; - FString GetRuleComparisonAttribute() const; - FString GetRuleComparator() const; - FString GetRuleComparisonValue() const; - FString GetRuleVariationId() const; - - /** - * Internal rule we want to expose in blueprints - */ - std::shared_ptr Rule; -}; - -/** - * Getters for all the properties of the configcat::RolloutRule stored inside a FConfigCatRolloutRule wrapper - */ -UCLASS() -class CONFIGCAT_API UConfigCatRuleAccessorsBPLibrary : public UBlueprintFunctionLibrary -{ - GENERATED_BODY() - - /** - * Checks if the underlying rule is valid - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Rule") - static bool IsValid(const FConfigCatRolloutRule& Struct); - /** - * Gets the value of the rollout rule - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Rule") - static FConfigCatValue GetRuleValue(const FConfigCatRolloutRule& Struct); - /** - * Gets the comparison attribute of the rollout rule - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Rule") - static FString GetRuleComparisonAttribute(const FConfigCatRolloutRule& Struct); - /** - * Gets the comparator of the rollout rule - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Rule") - static FString GetRuleComparator(const FConfigCatRolloutRule& Struct); - /** - * Gets the comparison value of the rollout rule - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Rule") - static FString GetRuleComparisonValue(const FConfigCatRolloutRule& Struct); - /** - * Gets the variation identifier of the rollout rule - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Rule") - static FString GetRuleVariationId(const FConfigCatRolloutRule& Struct); -}; diff --git a/Source/ConfigCat/Public/Wrapper/ConfigCatSetting.h b/Source/ConfigCat/Public/Wrapper/ConfigCatSetting.h deleted file mode 100644 index 1964396..0000000 --- a/Source/ConfigCat/Public/Wrapper/ConfigCatSetting.h +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) ConfigCat 2024. All Rights Reserved. - -#pragma once - -#include - -#include - -#include "ConfigCatSetting.generated.h" - -struct FConfigCatValue; - -namespace configcat -{ - struct Setting; -} - -/** - * Wrapper class for configcat::Setting - */ -USTRUCT(BlueprintType) -struct CONFIGCAT_API FConfigCatSetting -{ - GENERATED_BODY() - - FConfigCatSetting() = default; - FConfigCatSetting(const configcat::Setting& InSetting); - - FConfigCatValue GetSettingValue() const; - TArray GetSettingRolloutRules() const; - TArray GetSettingRolloutPercentageItem() const; - FString GetSettingVariationId() const; - - /** - * Internal Setting we want to expose in blueprints - */ - std::shared_ptr Setting; -}; - -/** - * Getters for all the properties of the configcat::Setting stored inside a FConfigCatSetting wrapper - */ -UCLASS() -class CONFIGCAT_API UConfigCatSettingAccessorsBPLibrary : public UBlueprintFunctionLibrary -{ - GENERATED_BODY() - - /** - * Gets the value of the feature flag / setting - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Setting") - static FConfigCatValue GetSettingValue(const FConfigCatSetting& Struct); - /** - * Gets the rollout rules of the feature flag / setting - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Setting") - static TArray GetSettingRolloutRules(const FConfigCatSetting& Struct); - /** - * Gets the rollout percentage items of the feature flag / setting - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Setting") - static TArray GetSettingRolloutPercentageItem(const FConfigCatSetting& Struct); - /** - * Gets the variation identifier of the feature flag / setting - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Setting") - static FString GetSettingVariationId(const FConfigCatSetting& Struct); -}; - -/** - * Wrapper to replicate configcat::Settings (using Settings = std::unordered_map) to blueprints - */ -USTRUCT(BlueprintType) -struct CONFIGCAT_API FConfigCatConfig -{ - GENERATED_BODY() - - UPROPERTY(BlueprintReadOnly, Category = "ConfigCat|Config") - TMap Settings; -}; \ No newline at end of file diff --git a/Source/ConfigCat/Public/Wrapper/ConfigCatUser.h b/Source/ConfigCat/Public/Wrapper/ConfigCatUser.h deleted file mode 100644 index 3bf58fc..0000000 --- a/Source/ConfigCat/Public/Wrapper/ConfigCatUser.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) ConfigCat 2024. All Rights Reserved. - -#pragma once - -#include - -#include - -#include "ConfigCatUser.generated.h" - -namespace configcat -{ - class ConfigCatUser; -} - -/** - * Wrapper class for configcat::ConfigCatUser - */ -USTRUCT(BlueprintType) -struct CONFIGCAT_API FConfigCatUser -{ - GENERATED_BODY() - - FConfigCatUser() = default; - FConfigCatUser(configcat::ConfigCatUser* InUser); - FConfigCatUser(const FString& Id, const FString& Email = TEXT(""), const FString& Country = TEXT(""), const TMap& Attributes = {}); - - FString GetIdentifier() const; - FString GetAttribute(const FString& Key) const; - - /** - * Internal user we want to expose in blueprints - */ - std::shared_ptr User; -}; - -/** - * Getters for all the properties of the configcat::ConfigCatUser stored inside a FConfigCatUser wrapper - */ -UCLASS() -class CONFIGCAT_API UConfigCatUserAccessorsBPLibrary : public UBlueprintFunctionLibrary -{ - GENERATED_BODY() - - /** - * Creates an instance of a ConfigCatUser struct based on the input - * @param Id Unique identifier of the user - * @param Email Email of the user (note: will be converted into Attribute internally) - * @param Country Country of the user (note: will be converted into Attribute internally) - * @param Attributes Additional Key-Value pairs associated with the user - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|User", meta = (AutoCreateRefTerm = "Attributes")) - static FConfigCatUser CreateUser(const FString& Id, const FString& Email, const FString& Country, const TMap& Attributes); - /** - * Gets the Id of a ConfigCatUser - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|User") - static FString GetIdentifier(const FConfigCatUser& Struct); - /** - * Gets an Attribute of a ConfigCatUser based on a Key - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|User") - static FString GetAttribute(const FConfigCatUser& Struct, const FString& Key); -}; \ No newline at end of file diff --git a/Source/ConfigCat/Public/Wrapper/ConfigCatValue.h b/Source/ConfigCat/Public/Wrapper/ConfigCatValue.h deleted file mode 100644 index 4a45a29..0000000 --- a/Source/ConfigCat/Public/Wrapper/ConfigCatValue.h +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) ConfigCat 2024. All Rights Reserved. - -#pragma once - -#include - -#include - -#include "ConfigCatValue.generated.h" - -namespace configcat -{ - struct Value; -} - -/** - * Wrapper class for configcat::Value - */ -USTRUCT(BlueprintType) -struct CONFIGCAT_API FConfigCatValue -{ - GENERATED_BODY() - - FConfigCatValue() = default; - FConfigCatValue(const configcat::Value& InValue); - FConfigCatValue(std::shared_ptr InValue); - - bool HasAnyValue() const; - bool HasBooleanValue() const; - bool HasStringValue() const; - bool HasIntegerValue() const; - bool HasDecimalValue() const; - - bool GetBooleanValue() const; - FString GetStringValue() const; - int GetIntegerValue() const; - double GetDecimalValue() const; - - /** - * Internal feature flag value we want to expose in blueprints - */ - std::shared_ptr Value; -}; - -/** - * Getters for all the properties of the configcat::Value stored inside a FConfigCatValue wrapper - */ -UCLASS() -class CONFIGCAT_API UConfigCatValueAccessorsBPLibrary : public UBlueprintFunctionLibrary -{ - GENERATED_BODY() - - /** - * Checks if the struct holds any type value - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Value") - static bool HasAnyValue(const FConfigCatValue& Struct); - /** - * Checks if the struct holds a boolean value - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Value") - static bool HasBooleanValue(const FConfigCatValue& Struct); - /** - * Checks if the struct holds a string value - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Value") - static bool HasStringValue(const FConfigCatValue& Struct); - /** - * Checks if the struct holds an integer value - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Value") - static bool HasIntegerValue(const FConfigCatValue& Struct); - /** - * Checks if the struct holds a decimal (double) value - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Value") - static bool HasDecimalValue(const FConfigCatValue& Struct); - - /** - * Returns the boolean value stored in the struct, if it holds one - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Value") - static bool GetBooleanValue(const FConfigCatValue& Struct); - /** - * Returns the string value stored in the struct, if it holds one - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Value") - static FString GetStringValue(const FConfigCatValue& Struct); - /** - * Returns the integer value stored in the struct, if it holds one - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Value") - static int GetIntegerValue(const FConfigCatValue& Struct); - /** - * Returns the decimal (double) value stored in the struct, if it holds one - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Value") - static double GetDecimalValue(const FConfigCatValue& Struct); - - /** - * Create a ConfigValue holding a boolean value - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Value") - static FConfigCatValue CreteBooleanValue(bool Value); - /** - * Create a ConfigValue holding a string value - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Value") - static FConfigCatValue CreateStringValue(const FString& Value); - /** - * Create a ConfigValue holding a integer value - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Value") - static FConfigCatValue CreateIntegerValue(int Value); - /** - * Create a ConfigValue holding a decimal (double) value - */ - UFUNCTION(BlueprintPure, Category = "ConfigCat|Value") - static FConfigCatValue CreateDecimalValue(double Value); -}; diff --git a/Source/ConfigCatWrappers/ConfigCatWrappers.Build.cs b/Source/ConfigCatWrappers/ConfigCatWrappers.Build.cs new file mode 100644 index 0000000..09126d8 --- /dev/null +++ b/Source/ConfigCatWrappers/ConfigCatWrappers.Build.cs @@ -0,0 +1,28 @@ +// Copyright (c) ConfigCat 2024. All Rights Reserved. + +using UnrealBuildTool; + +public class ConfigCatWrappers : ModuleRules +{ + public ConfigCatWrappers(ReadOnlyTargetRules Target) : base(Target) + { + PublicDependencyModuleNames.AddRange(new[] + { + "Core", + "CoreUObject", + "DeveloperSettings", + "Projects", + "Engine", + "HTTP" + }); + + PrivateDependencyModuleNames.AddRange(new[] + { + "ConfigCatCppSdk" + }); + + PrivateIncludePaths.Add("ThirdParty"); + + bEnableExceptions = true; + } +} \ No newline at end of file diff --git a/Source/ConfigCatWrappers/Private/ConfigCatEvaluationWrapper.cpp b/Source/ConfigCatWrappers/Private/ConfigCatEvaluationWrapper.cpp new file mode 100644 index 0000000..3f9a300 --- /dev/null +++ b/Source/ConfigCatWrappers/Private/ConfigCatEvaluationWrapper.cpp @@ -0,0 +1,117 @@ +// Copyright (c) ConfigCat 2024. All Rights Reserved. + +#include "ConfigCatEvaluationWrapper.h" + +#include "ConfigCatCppSDK/Include/log.h" + +#include "ConfigCatPercentageOptionWrapper.h" +#include "ConfigCatTargetingRuleWrapper.h" +#include "ConfigCatUserWrapper.h" +#include "ConfigCatValueWrapper.h" + +UConfigCatEvaluationWrapper* UConfigCatEvaluationWrapper::CreateEvaluation(const configcat::EvaluationDetailsBase& InEvaluationDetails) +{ + UConfigCatEvaluationWrapper* Result = NewObject(); + Result->EvaluationDetails = std::make_shared>(to_concrete(InEvaluationDetails)); + return Result; +} + +FString UConfigCatEvaluationWrapper::GetKey() const +{ + if (EvaluationDetails) + { + return UTF8_TO_TCHAR(EvaluationDetails->key.c_str()); + } + + return {}; +} + +UConfigCatValueWrapper* UConfigCatEvaluationWrapper::GetValue() const +{ + if (EvaluationDetails) + { + return UConfigCatValueWrapper::CreateValue(EvaluationDetails->value); + } + + return {}; +} + +FString UConfigCatEvaluationWrapper::GetVariationId() const +{ + if (EvaluationDetails && EvaluationDetails->variationId.has_value()) + { + return UTF8_TO_TCHAR(EvaluationDetails->variationId.value().c_str()); + } + + return {}; +} + +FDateTime UConfigCatEvaluationWrapper::GetFetchTime() const +{ + if (EvaluationDetails) + { + const auto TimeSinceEpoch = EvaluationDetails->fetchTime.time_since_epoch().count(); + return FDateTime::FromUnixTimestamp(TimeSinceEpoch); + } + + return {}; +} + +UConfigCatUserWrapper* UConfigCatEvaluationWrapper::GetUser() const +{ + if (EvaluationDetails && EvaluationDetails->user) + { + return UConfigCatUserWrapper::CreateUser(EvaluationDetails->user); + } + + return {}; +} + +bool UConfigCatEvaluationWrapper::IsDefaultValue() const +{ + if (EvaluationDetails) + { + return EvaluationDetails->isDefaultValue; + } + + return {}; +} + +FString UConfigCatEvaluationWrapper::GetError() const +{ + if (EvaluationDetails && EvaluationDetails->errorMessage.has_value()) + { + return UTF8_TO_TCHAR(EvaluationDetails->errorMessage.value().c_str()); + } + + return {}; +} + +FString UConfigCatEvaluationWrapper::GetException() const +{ + if (EvaluationDetails && EvaluationDetails->errorException) + { + return UTF8_TO_TCHAR(unwrap_exception_message(EvaluationDetails->errorException).c_str()); + } + return {}; +} + +UConfigCatTargetingRuleWrapper* UConfigCatEvaluationWrapper::GetMatchedTargetingRule() const +{ + if (EvaluationDetails && EvaluationDetails->matchedTargetingRule) + { + return UConfigCatTargetingRuleWrapper::CreateTargetingRule(EvaluationDetails->matchedTargetingRule.value()); + } + + return {}; +} + +UConfigCatPercentageOptionWrapper* UConfigCatEvaluationWrapper::GetMatchedPercentageOption() const +{ + if (EvaluationDetails && EvaluationDetails->matchedPercentageOption) + { + return UConfigCatPercentageOptionWrapper::CreatePercentageOption(EvaluationDetails->matchedPercentageOption.value()); + } + + return {}; +} diff --git a/Source/ConfigCatWrappers/Private/ConfigCatPercentageOptionWrapper.cpp b/Source/ConfigCatWrappers/Private/ConfigCatPercentageOptionWrapper.cpp new file mode 100644 index 0000000..b249fcf --- /dev/null +++ b/Source/ConfigCatWrappers/Private/ConfigCatPercentageOptionWrapper.cpp @@ -0,0 +1,33 @@ +// Copyright (c) ConfigCat 2024. All Rights Reserved. + +#include "ConfigCatPercentageOptionWrapper.h" + +#include "ConfigCatValueWrapper.h" + +UConfigCatPercentageOptionWrapper* UConfigCatPercentageOptionWrapper::CreatePercentageOption(const configcat::PercentageOption& InPercentageOption) +{ + UConfigCatPercentageOptionWrapper* Result = NewObject(); + Result->PercentageOption = InPercentageOption; + return Result; +} + +uint8 UConfigCatPercentageOptionWrapper::GetPercentage() const +{ + return PercentageOption.percentage; +} + +FString UConfigCatPercentageOptionWrapper::GetVariationId() const +{ + if (PercentageOption.variationId) + { + return UTF8_TO_TCHAR(PercentageOption.variationId.value().c_str()); + } + + return {}; +} + +UConfigCatValueWrapper* UConfigCatPercentageOptionWrapper::GetValue() const +{ + return UConfigCatValueWrapper::CreateValue(PercentageOption.value); + +} \ No newline at end of file diff --git a/Source/ConfigCatWrappers/Private/ConfigCatSettingValueContainerWrapper.cpp b/Source/ConfigCatWrappers/Private/ConfigCatSettingValueContainerWrapper.cpp new file mode 100644 index 0000000..44cd74d --- /dev/null +++ b/Source/ConfigCatWrappers/Private/ConfigCatSettingValueContainerWrapper.cpp @@ -0,0 +1,27 @@ +// Copyright (c) ConfigCat 2024. All Rights Reserved. + +#include "ConfigCatSettingValueContainerWrapper.h" + +#include "ConfigCatValueWrapper.h" + +UConfigCatSettingValueContainerWrapper* UConfigCatSettingValueContainerWrapper::CreateSettingValue(const configcat::SettingValueContainer& SettingValueContainer) +{ + UConfigCatSettingValueContainerWrapper* Result = NewObject(); + Result->SettingValueContainer = SettingValueContainer; + return Result; +} + +FString UConfigCatSettingValueContainerWrapper::GetVariationId() const +{ + if (SettingValueContainer.variationId.has_value()) + { + return UTF8_TO_TCHAR(SettingValueContainer.variationId.value().c_str()); + } + + return {}; +} + +UConfigCatValueWrapper* UConfigCatSettingValueContainerWrapper::GetValue() const +{ + return UConfigCatValueWrapper::CreateValue(SettingValueContainer.value); +} \ No newline at end of file diff --git a/Source/ConfigCatWrappers/Private/ConfigCatSettingsWrapper.cpp b/Source/ConfigCatWrappers/Private/ConfigCatSettingsWrapper.cpp new file mode 100644 index 0000000..454760d --- /dev/null +++ b/Source/ConfigCatWrappers/Private/ConfigCatSettingsWrapper.cpp @@ -0,0 +1,97 @@ +// Copyright (c) ConfigCat 2024. All Rights Reserved. + +#include "ConfigCatSettingsWrapper.h" + +#include "ConfigCatPercentageOptionWrapper.h" +#include "ConfigCatTargetingRuleWrapper.h" +#include "ConfigCatValueWrapper.h" + +using namespace configcat; + +UConfigCatSettingWrapper* UConfigCatSettingWrapper::CreateSetting(const configcat::Setting& InSetting) +{ + UConfigCatSettingWrapper* Result = NewObject(); + Result->Setting = InSetting; + return Result; +} + +bool UConfigCatSettingWrapper::HasInvalidType() const +{ + return Setting.hasInvalidType(); +} + +EConfigCatSettingTypeWrapper UConfigCatSettingWrapper::GetType() const +{ + return static_cast(Setting.type); +} + +FString UConfigCatSettingWrapper::GetPercentageOptionsAttribute() const +{ + if (Setting.percentageOptionsAttribute) + { + return UTF8_TO_TCHAR(Setting.percentageOptionsAttribute.value().c_str()); + } + + return {}; +} + +FString UConfigCatSettingWrapper::GetVariationId() const +{ + if (Setting.variationId) + { + return UTF8_TO_TCHAR(Setting.variationId.value().c_str()); + } + + return {}; +} + +UConfigCatValueWrapper* UConfigCatSettingWrapper::GetValue() const +{ + return UConfigCatValueWrapper::CreateValue(Setting.value); +} + +TArray UConfigCatSettingWrapper::GetTargetingRules() const +{ + TArray Result; + for (const auto& Rule : Setting.targetingRules) + { + Result.Add(UConfigCatTargetingRuleWrapper::CreateTargetingRule(Rule)); + } + + return Result; +} + +TArray UConfigCatSettingWrapper::GetPercentageOptions() const +{ + TArray Result; + for (const auto& Option : Setting.percentageOptions) + { + Result.Add(UConfigCatPercentageOptionWrapper::CreatePercentageOption(Option)); + } + + return Result; +} + +UConfigCatSettingsWrapper* UConfigCatSettingsWrapper::CreateSettings(const std::shared_ptr& InSettings) +{ + UConfigCatSettingsWrapper* Result = NewObject(); + Result->Settings = InSettings; + return Result; +} + +TMap UConfigCatSettingsWrapper::GetSettings() const +{ + TMap Result; + + if (Settings) + { + for (const std::pair& Setting : *Settings) + { + const FString Key = UTF8_TO_TCHAR(Setting.first.c_str()); + UConfigCatSettingWrapper* Value = UConfigCatSettingWrapper::CreateSetting(Setting.second); + Result.Emplace(Key, Value); + } + } + + return Result; +} \ No newline at end of file diff --git a/Source/ConfigCatWrappers/Private/ConfigCatTargetingRuleWrapper.cpp b/Source/ConfigCatWrappers/Private/ConfigCatTargetingRuleWrapper.cpp new file mode 100644 index 0000000..3421743 --- /dev/null +++ b/Source/ConfigCatWrappers/Private/ConfigCatTargetingRuleWrapper.cpp @@ -0,0 +1,192 @@ +// Copyright (c) ConfigCat 2024. All Rights Reserved. + +#include "ConfigCatTargetingRuleWrapper.h" + +#include "ConfigCatSettingValueContainerWrapper.h" +#include "ConfigCatPercentageOptionWrapper.h" +#include "ConfigCatValueWrapper.h" + +UConfigCatUserConditionWrapper* UConfigCatUserConditionWrapper::CreateUserCondition(const configcat::UserCondition& InUserCondition) +{ + UConfigCatUserConditionWrapper* Result = NewObject(); + Result->UserCondition = InUserCondition; + return Result; +} + +FString UConfigCatUserConditionWrapper::GetComparisonAttribute() const +{ + return UTF8_TO_TCHAR(UserCondition.comparisonAttribute.c_str()); +} + +EConfigCatUserComparator UConfigCatUserConditionWrapper::GetComparator() const +{ + if (static_cast(UserCondition.comparator) < 0) + { + return EConfigCatUserComparator::Invalid; + } + + return static_cast(UserCondition.comparator); +} + +bool UConfigCatUserConditionWrapper::HasAnyComparisonValue() +{ + return HasStringComparisonValue() || HasNumberComparisonValue() || HasStringArrayComparisonValue(); +} + +bool UConfigCatUserConditionWrapper::HasStringComparisonValue() const +{ + return std::holds_alternative(UserCondition.comparisonValue); +} + +bool UConfigCatUserConditionWrapper::HasNumberComparisonValue() const +{ + return std::holds_alternative(UserCondition.comparisonValue); +} + +bool UConfigCatUserConditionWrapper::HasStringArrayComparisonValue() const +{ + return std::holds_alternative>(UserCondition.comparisonValue); +} + +FString UConfigCatUserConditionWrapper::GetStringComparisonValue() const +{ + if (HasStringComparisonValue()) + { + return UTF8_TO_TCHAR(std::get(UserCondition.comparisonValue).c_str()); + } + + return {}; +} + +double UConfigCatUserConditionWrapper::GetNumberComparisonValue() const +{ + if (HasNumberComparisonValue()) + { + return std::get(UserCondition.comparisonValue); + } + + return {}; +} + +TArray UConfigCatUserConditionWrapper::GetStringArrayComparisonValue() const +{ + if (HasStringArrayComparisonValue()) + { + TArray Result; + const std::vector ArrayAttribute = std::get>(UserCondition.comparisonValue); + for (const std::string& ArrayIt : ArrayAttribute) + { + Result.Emplace(UTF8_TO_TCHAR(ArrayIt.c_str())); + } + return Result; + } + + return {}; +} + +UConfigCatPrerequisiteFlagConditionWrapper* UConfigCatPrerequisiteFlagConditionWrapper::CreatePrerequisiteFlagCondition(const configcat::PrerequisiteFlagCondition& InPrerequisiteFlagCondition) +{ + UConfigCatPrerequisiteFlagConditionWrapper* Result = NewObject(); + Result->PrerequisiteFlagCondition = InPrerequisiteFlagCondition; + return Result; +} + +FString UConfigCatPrerequisiteFlagConditionWrapper::GetPrerequisiteFlagKey() const +{ + return UTF8_TO_TCHAR(PrerequisiteFlagCondition.prerequisiteFlagKey.c_str()); +} + +EConfigCatPrerequisiteFlagComparator UConfigCatPrerequisiteFlagConditionWrapper::GetComparator() const +{ + if (static_cast(PrerequisiteFlagCondition.comparator) < 0) + { + return EConfigCatPrerequisiteFlagComparator::Invalid; + } + + return static_cast(PrerequisiteFlagCondition.comparator); +} + +UConfigCatValueWrapper* UConfigCatPrerequisiteFlagConditionWrapper::GetComparisonValue() const +{ + return UConfigCatValueWrapper::CreateValue(PrerequisiteFlagCondition.comparisonValue); +} + +UConfigCatSegmentConditionWrapper* UConfigCatSegmentConditionWrapper::CreateSegmentCondition(const configcat::SegmentCondition& InSegmentCondition) +{ + UConfigCatSegmentConditionWrapper* Result = NewObject(); + Result->SegmentCondition = InSegmentCondition; + return Result; +} + +int32 UConfigCatSegmentConditionWrapper::GetSegmentIndex() const +{ + return SegmentCondition.segmentIndex; +} + +EConfigCatSegmentComparator UConfigCatSegmentConditionWrapper::GetComparator() const +{ + if (static_cast(SegmentCondition.comparator) < 0) + { + return EConfigCatSegmentComparator::Invalid; + } + + return static_cast(SegmentCondition.comparator); +} + +UConfigCatTargetingRuleWrapper* UConfigCatTargetingRuleWrapper::CreateTargetingRule(const configcat::TargetingRule& InTargetingRule) +{ + UConfigCatTargetingRuleWrapper* Result = NewObject(); + Result->TargetingRule = InTargetingRule; + return Result; +} + +TArray UConfigCatTargetingRuleWrapper::GetConditions() const +{ + TArray Result; + + for (const configcat::ConditionContainer& ConditionContainer : TargetingRule.conditions) + { + FConfigCatConditionContainer NewCondition; + const auto& Condition = ConditionContainer.condition; + if (std::holds_alternative(Condition)) + { + const configcat::UserCondition& UserCondition = std::get(Condition); + NewCondition.UserCondition = nullptr; + Result.Add(NewCondition); + } + else if (std::holds_alternative(Condition)) + { + const configcat::PrerequisiteFlagCondition& PrerequisiteFlagCondition = std::get(Condition); + NewCondition.PrerequisiteFlagCondition = nullptr; + Result.Add(NewCondition); + } + else if (std::holds_alternative(Condition)) + { + const configcat::SegmentCondition& SegmentCondition = std::get(Condition); + NewCondition.SegmentCondition = nullptr; + Result.Add(NewCondition); + } + } + + return Result; +} + +FConfigCatThenContainer UConfigCatTargetingRuleWrapper::GetThen() const +{ + FConfigCatThenContainer Result; + if (std::holds_alternative(TargetingRule.then)) + { + const configcat::SettingValueContainer& SettingValueContainer = std::get(TargetingRule.then); + Result.SettingValueContainer = UConfigCatSettingValueContainerWrapper::CreateSettingValue(SettingValueContainer); + } + else if (std::holds_alternative(TargetingRule.then)) + { + const auto& PercentageOptions = std::get(TargetingRule.then); + for (const auto& PercentageOption : PercentageOptions) + { + Result.PercentageOptions.Add(UConfigCatPercentageOptionWrapper::CreatePercentageOption(PercentageOption)); + } + } + + return Result; +} \ No newline at end of file diff --git a/Source/ConfigCatWrappers/Private/ConfigCatUserWrapper.cpp b/Source/ConfigCatWrappers/Private/ConfigCatUserWrapper.cpp new file mode 100644 index 0000000..475e9c7 --- /dev/null +++ b/Source/ConfigCatWrappers/Private/ConfigCatUserWrapper.cpp @@ -0,0 +1,133 @@ +// Copyright (c) ConfigCat 2024. All Rights Reserved. + +#include "ConfigCatUserWrapper.h" + +#include + +using namespace configcat; + +UConfigCatUserWrapper* UConfigCatUserWrapper::CreateUser(const FString& Id, const FString& Email, const FString& Country, const TMap& Attributes) +{ + const std::string& UserId = TCHAR_TO_UTF8(*Id); + const std::string& UserEmail = TCHAR_TO_UTF8(*Email); + const std::string& UserCountry = TCHAR_TO_UTF8(*Country); + + std::unordered_map UserAttributes; + for (const TTuple& Attribute : Attributes) + { + const std::string& AttributeKey = TCHAR_TO_UTF8(*Attribute.Key); + const std::string& AttributeValue = TCHAR_TO_UTF8(*Attribute.Value); + + UserAttributes.emplace(AttributeKey, AttributeValue); + } + + return CreateUser(ConfigCatUser::create(UserId, UserEmail, UserCountry, UserAttributes)); +} + +UConfigCatUserWrapper* UConfigCatUserWrapper::CreateUser(const std::shared_ptr& InUser) +{ + UConfigCatUserWrapper* Result = NewObject(); + Result->User = InUser; + return Result; +} + +FString UConfigCatUserWrapper::GetIdentifier() const +{ + if (User) + { + return UTF8_TO_TCHAR(User->getIdentifier().c_str()); + } + + return {}; +} + +FString UConfigCatUserWrapper::GetStringAttribute(const FString& Key) const +{ + if (HasStringAttribute(Key)) + { + const ConfigCatUser::AttributeValue* Attribute = GetUserAttributeForKey(Key); + return UTF8_TO_TCHAR(std::get(*Attribute).c_str()); + } + + return {}; +} + +double UConfigCatUserWrapper::GetNumberAttribute(const FString& Key) const +{ + if (HasNumberAttribute(Key)) + { + const ConfigCatUser::AttributeValue* Attribute = GetUserAttributeForKey(Key); + return std::get(*Attribute); + } + + return {}; +} + +FDateTime UConfigCatUserWrapper::GetTimeAttribute(const FString& Key) const +{ + if (HasTimeAttribute(Key)) + { + const ConfigCatUser::AttributeValue* Attribute = GetUserAttributeForKey(Key); + const auto TimeSinceEpoch = std::get(*Attribute).time_since_epoch().count(); + return FDateTime::FromUnixTimestamp(TimeSinceEpoch); + } + + return {}; +} + +TArray UConfigCatUserWrapper::GetStringArrayAttribute(const FString& Key) const +{ + if (HasStringArrayAttribute(Key)) + { + const ConfigCatUser::AttributeValue* Attribute = GetUserAttributeForKey(Key); + TArray Result; + const std::vector ArrayAttribute = std::get>(*Attribute); + for (const std::string& ArrayIt : ArrayAttribute) + { + Result.Emplace(UTF8_TO_TCHAR(ArrayIt.c_str())); + } + return Result; + } + + return {}; +} + +bool UConfigCatUserWrapper::HasAnyAttribute(const FString& Key) const +{ + return HasStringAttribute(Key) || HasNumberAttribute(Key) || HasTimeAttribute(Key) || HasStringArrayAttribute(Key); +} + +bool UConfigCatUserWrapper::HasStringAttribute(const FString& Key) const +{ + const ConfigCatUser::AttributeValue* Attribute = GetUserAttributeForKey(Key); + return Attribute && std::holds_alternative(*Attribute); +} + +bool UConfigCatUserWrapper::HasNumberAttribute(const FString& Key) const +{ + const ConfigCatUser::AttributeValue* Attribute = GetUserAttributeForKey(Key); + return Attribute && std::holds_alternative(*Attribute); +} + +bool UConfigCatUserWrapper::HasTimeAttribute(const FString& Key) const +{ + const ConfigCatUser::AttributeValue* Attribute = GetUserAttributeForKey(Key); + return Attribute && std::holds_alternative(*Attribute); +} + +bool UConfigCatUserWrapper::HasStringArrayAttribute(const FString& Key) const +{ + const ConfigCatUser::AttributeValue* Attribute = GetUserAttributeForKey(Key); + return Attribute && std::holds_alternative>(*Attribute); +} + +const ConfigCatUser::AttributeValue* UConfigCatUserWrapper::GetUserAttributeForKey(const FString& Key) const +{ + if (!User) + { + return {}; + } + + const std::string AttributeKey = TCHAR_TO_UTF8(*Key); + return User->getAttribute(AttributeKey); +} \ No newline at end of file diff --git a/Source/ConfigCatWrappers/Private/ConfigCatValueWrapper.cpp b/Source/ConfigCatWrappers/Private/ConfigCatValueWrapper.cpp new file mode 100644 index 0000000..0e7bbca --- /dev/null +++ b/Source/ConfigCatWrappers/Private/ConfigCatValueWrapper.cpp @@ -0,0 +1,86 @@ +// Copyright (c) ConfigCat 2024. All Rights Reserved. + +#include "ConfigCatValueWrapper.h" + +UConfigCatValueWrapper* UConfigCatValueWrapper::CreateValue(const configcat::SettingValue& InValue) +{ + // This leverages the operator std::optional from configcat::SettingValue + return CreateValue(std::optional(InValue)); +} + +UConfigCatValueWrapper* UConfigCatValueWrapper::CreateValue(const configcat::Value& InValue) +{ + return CreateValue(std::make_optional(InValue)); +} + +UConfigCatValueWrapper* UConfigCatValueWrapper::CreateValue(const std::optional& InValue) +{ + UConfigCatValueWrapper* Result = NewObject(); + Result->Value = InValue; + return Result; +} + +bool UConfigCatValueWrapper::HasAnyValue() const +{ + return HasBooleanValue() || HasStringValue() || HasIntegerValue() || HasDecimalValue(); +} + +bool UConfigCatValueWrapper::HasBooleanValue() const +{ + return Value && std::holds_alternative(*Value); +} + +bool UConfigCatValueWrapper::HasStringValue() const +{ + return Value && std::holds_alternative(*Value); +} + +bool UConfigCatValueWrapper::HasIntegerValue() const +{ + return Value && std::holds_alternative(*Value); +} + +bool UConfigCatValueWrapper::HasDecimalValue() const +{ + return Value && std::holds_alternative(*Value); +} + +bool UConfigCatValueWrapper::GetBooleanValue() const +{ + if (HasBooleanValue()) + { + return std::get(*Value); + } + + return {}; +} + +FString UConfigCatValueWrapper::GetStringValue() const +{ + if (HasStringValue()) + { + return UTF8_TO_TCHAR(std::get(*Value).c_str()); + } + + return {}; +} + +int UConfigCatValueWrapper::GetIntegerValue() const +{ + if (HasIntegerValue()) + { + return std::get(*Value); + } + + return {}; +} + +double UConfigCatValueWrapper::GetDecimalValue() const +{ + if (HasDecimalValue()) + { + return std::get(*Value); + } + + return {}; +} \ No newline at end of file diff --git a/Source/ConfigCatWrappers/Private/ConfigCatWrappers.cpp b/Source/ConfigCatWrappers/Private/ConfigCatWrappers.cpp new file mode 100644 index 0000000..2a704b6 --- /dev/null +++ b/Source/ConfigCatWrappers/Private/ConfigCatWrappers.cpp @@ -0,0 +1,5 @@ +// Copyright (c) ConfigCat 2024. All Rights Reserved. + +#include "ConfigCatWrappers.h" + +IMPLEMENT_MODULE(FConfigCatWrappersModule, ConfigCatWrappers) \ No newline at end of file diff --git a/Source/ConfigCatWrappers/Public/ConfigCatEvaluationWrapper.h b/Source/ConfigCatWrappers/Public/ConfigCatEvaluationWrapper.h new file mode 100644 index 0000000..26dbaf2 --- /dev/null +++ b/Source/ConfigCatWrappers/Public/ConfigCatEvaluationWrapper.h @@ -0,0 +1,47 @@ +// Copyright (c) ConfigCat 2024. All Rights Reserved. + +#pragma once + +#include + +#include "Misc/DateTime.h" +#include + +#include "ConfigCatEvaluationWrapper.generated.h" + +class UConfigCatPercentageOptionWrapper; +class UConfigCatTargetingRuleWrapper; +class UConfigCatUserWrapper; +class UConfigCatValueWrapper; + +UCLASS(DisplayName="Config Cat Evaluation") +class CONFIGCATWRAPPERS_API UConfigCatEvaluationWrapper : public UObject +{ + GENERATED_BODY() + +public: + static UConfigCatEvaluationWrapper* CreateEvaluation(const configcat::EvaluationDetailsBase& InEvaluationDetails); + + UFUNCTION(BlueprintPure, Category = "ConfigCat|EvaluationDetails") + FString GetKey() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|EvaluationDetails") + FString GetVariationId() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|EvaluationDetails") + FDateTime GetFetchTime() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|EvaluationDetails") + UConfigCatUserWrapper* GetUser() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|EvaluationDetails") + bool IsDefaultValue() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|EvaluationDetails") + FString GetError() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|EvaluationDetails") + FString GetException() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|EvaluationDetails") + UConfigCatTargetingRuleWrapper* GetMatchedTargetingRule() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|EvaluationDetails") + UConfigCatPercentageOptionWrapper* GetMatchedPercentageOption() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|EvaluationDetails") + UConfigCatValueWrapper* GetValue() const; + + std::shared_ptr> EvaluationDetails; +}; \ No newline at end of file diff --git a/Source/ConfigCatWrappers/Public/ConfigCatPercentageOptionWrapper.h b/Source/ConfigCatWrappers/Public/ConfigCatPercentageOptionWrapper.h new file mode 100644 index 0000000..8024b91 --- /dev/null +++ b/Source/ConfigCatWrappers/Public/ConfigCatPercentageOptionWrapper.h @@ -0,0 +1,29 @@ +// Copyright (c) ConfigCat 2024. All Rights Reserved. + +#pragma once + +#include "ConfigCatCppSDK/Include/config.h" + +#include "ConfigCatPercentageOptionWrapper.generated.h" + +class UConfigCatValueWrapper; + +UCLASS(DisplayName="Config Cat Percentage Option") +class CONFIGCATWRAPPERS_API UConfigCatPercentageOptionWrapper : public UObject +{ + GENERATED_BODY() + +public: + static UConfigCatPercentageOptionWrapper* CreatePercentageOption(const configcat::PercentageOption& InPercentageOption); + + UFUNCTION(BlueprintPure, Category = "ConfigCat|PercentageOption") + uint8 GetPercentage() const; + + UFUNCTION(BlueprintPure, Category = "ConfigCat|PercentageOption") + FString GetVariationId() const; + + UFUNCTION(BlueprintPure, Category = "ConfigCat|PercentageOption") + UConfigCatValueWrapper* GetValue() const; + + configcat::PercentageOption PercentageOption; +}; diff --git a/Source/ConfigCatWrappers/Public/ConfigCatSettingValueContainerWrapper.h b/Source/ConfigCatWrappers/Public/ConfigCatSettingValueContainerWrapper.h new file mode 100644 index 0000000..14b1292 --- /dev/null +++ b/Source/ConfigCatWrappers/Public/ConfigCatSettingValueContainerWrapper.h @@ -0,0 +1,26 @@ +// Copyright (c) ConfigCat 2024. All Rights Reserved. + +#pragma once + +#include + +#include "UObject/Object.h" + +#include "ConfigCatSettingValueContainerWrapper.generated.h" + +class UConfigCatValueWrapper; +UCLASS(DisplayName="Config Cat Setting Value Container") +class CONFIGCATWRAPPERS_API UConfigCatSettingValueContainerWrapper : public UObject +{ + GENERATED_BODY() + +public: + static UConfigCatSettingValueContainerWrapper* CreateSettingValue(const configcat::SettingValueContainer& SettingValueContainer); + + UFUNCTION(BlueprintPure, Category = "ConfigCat|SettingValueContainer") + FString GetVariationId() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|SettingValueContainer") + UConfigCatValueWrapper* GetValue() const; + + configcat::SettingValueContainer SettingValueContainer; +}; diff --git a/Source/ConfigCatWrappers/Public/ConfigCatSettingsWrapper.h b/Source/ConfigCatWrappers/Public/ConfigCatSettingsWrapper.h new file mode 100644 index 0000000..2907715 --- /dev/null +++ b/Source/ConfigCatWrappers/Public/ConfigCatSettingsWrapper.h @@ -0,0 +1,68 @@ +// Copyright (c) ConfigCat 2024. All Rights Reserved. + +#pragma once + +#include + +#include + +#include "ConfigCatSettingsWrapper.generated.h" + +class UConfigCatPercentageOptionWrapper; +class UConfigCatTargetingRuleWrapper; +class UConfigCatValueWrapper; + +UENUM(BlueprintType) +enum EConfigCatSettingTypeWrapper : uint8 +{ + Bool = 0, + String = 1, + Int = 2, + Double = 3, +}; + +UCLASS(DisplayName="Config Cat Setting") +class CONFIGCATWRAPPERS_API UConfigCatSettingWrapper : public UObject +{ + GENERATED_BODY() + +public: + static UConfigCatSettingWrapper* CreateSetting(const configcat::Setting& InSetting); + + UFUNCTION(BlueprintPure, Category = "ConfigCat|Setting") + FString GetVariationId() const; + + UFUNCTION(BlueprintPure, Category = "ConfigCat|Setting") + FString GetPercentageOptionsAttribute() const; + + UFUNCTION(BlueprintPure, Category = "ConfigCat|Setting") + bool HasInvalidType() const; + + UFUNCTION(BlueprintPure, Category = "ConfigCat|Setting") + EConfigCatSettingTypeWrapper GetType() const; + + UFUNCTION(BlueprintPure, Category = "ConfigCat|Setting") + UConfigCatValueWrapper* GetValue() const; + + UFUNCTION(BlueprintPure, Category = "ConfigCat|Setting") + TArray GetTargetingRules() const; + + UFUNCTION(BlueprintPure, Category = "ConfigCat|Setting") + TArray GetPercentageOptions() const; + + configcat::Setting Setting; +}; + +UCLASS(DisplayName="Config Cat Settings") +class CONFIGCATWRAPPERS_API UConfigCatSettingsWrapper : public UObject +{ + GENERATED_BODY() + +public: + static UConfigCatSettingsWrapper* CreateSettings(const std::shared_ptr& InSettings); + + UFUNCTION(BlueprintPure, Category = "ConfigCat|Settings") + TMap GetSettings() const; + + std::shared_ptr Settings; +}; diff --git a/Source/ConfigCatWrappers/Public/ConfigCatTargetingRuleWrapper.h b/Source/ConfigCatWrappers/Public/ConfigCatTargetingRuleWrapper.h new file mode 100644 index 0000000..9ec38fa --- /dev/null +++ b/Source/ConfigCatWrappers/Public/ConfigCatTargetingRuleWrapper.h @@ -0,0 +1,177 @@ +// Copyright (c) ConfigCat 2024. All Rights Reserved. + +#pragma once + +#include "ConfigCatCppSDK/Include/config.h" + +#include "ConfigCatTargetingRuleWrapper.generated.h" + +class UConfigCatSettingValueContainerWrapper; +class UConfigCatPercentageOptionWrapper; +class UConfigCatValueWrapper; + +UENUM(BlueprintType) +enum class EConfigCatUserComparator : uint8 +{ + TextIsOneOf = 0, + TextIsNotOneOf = 1, + TextContainsAnyOf = 2, + TextNotContainsAnyOf = 3, + SemVerIsOneOf = 4, + SemVerIsNotOneOf = 5, + SemVerLess = 6, + SemVerLessOrEquals = 7, + SemVerGreater = 8, + SemVerGreaterOrEquals = 9, + NumberEquals = 10, + NumberNotEquals = 11, + NumberLess = 12, + NumberLessOrEquals = 13, + NumberGreater = 14, + NumberGreaterOrEquals = 15, + SensitiveTextIsOneOf = 16, + SensitiveTextIsNotOneOf = 17, + DateTimeBefore = 18, + DateTimeAfter = 19, + SensitiveTextEquals = 20, + SensitiveTextNotEquals = 21, + SensitiveTextStartsWithAnyOf = 22, + SensitiveTextNotStartsWithAnyOf = 23, + SensitiveTextEndsWithAnyOf = 24, + SensitiveTextNotEndsWithAnyOf = 25, + SensitiveArrayContainsAnyOf = 26, + SensitiveArrayNotContainsAnyOf = 27, + TextEquals = 28, + TextNotEquals = 29, + TextStartsWithAnyOf = 30, + TextNotStartsWithAnyOf = 31, + TextEndsWithAnyOf = 32, + TextNotEndsWithAnyOf = 33, + ArrayContainsAnyOf = 34, + ArrayNotContainsAnyOf = 35, + + Invalid +}; + +UCLASS(DisplayName="Config Cat User Condition") +class CONFIGCATWRAPPERS_API UConfigCatUserConditionWrapper : public UObject +{ + GENERATED_BODY() + +public: + static UConfigCatUserConditionWrapper* CreateUserCondition(const configcat::UserCondition& InUserCondition); + + UFUNCTION(BlueprintPure, Category = "ConfigCat|UserCondition") + FString GetComparisonAttribute() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|UserCondition") + EConfigCatUserComparator GetComparator() const; + + UFUNCTION(BlueprintPure, Category = "ConfigCat|UserCondition") + bool HasAnyComparisonValue(); + UFUNCTION(BlueprintPure, Category = "ConfigCat|UserCondition") + bool HasStringComparisonValue() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|UserCondition") + bool HasNumberComparisonValue() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|UserCondition") + bool HasStringArrayComparisonValue() const; + + UFUNCTION(BlueprintPure, Category = "ConfigCat|UserCondition") + FString GetStringComparisonValue() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|UserCondition") + double GetNumberComparisonValue() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|UserCondition") + TArray GetStringArrayComparisonValue() const; + + configcat::UserCondition UserCondition; +}; + +UENUM(BlueprintType) +enum class EConfigCatPrerequisiteFlagComparator : uint8 +{ + Equals = 0, + NotEquals = 1, + Invalid +}; + +UCLASS(DisplayName="Config Cat Prerequisite Flag Condition") +class CONFIGCATWRAPPERS_API UConfigCatPrerequisiteFlagConditionWrapper : public UObject +{ + GENERATED_BODY() + +public: + static UConfigCatPrerequisiteFlagConditionWrapper* CreatePrerequisiteFlagCondition(const configcat::PrerequisiteFlagCondition& InPrerequisiteFlagCondition); + + UFUNCTION(BlueprintPure, Category = "ConfigCat|PrerequisiteFlagCondition") + FString GetPrerequisiteFlagKey() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|PrerequisiteFlagCondition") + EConfigCatPrerequisiteFlagComparator GetComparator() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|PrerequisiteFlagCondition") + UConfigCatValueWrapper* GetComparisonValue() const; + + configcat::PrerequisiteFlagCondition PrerequisiteFlagCondition; +}; + +UENUM(BlueprintType) +enum class EConfigCatSegmentComparator : uint8 +{ + IsIn = 0, + IsNotIn = 1, + Invalid +}; + +UCLASS(DisplayName="Config Cat Segment Condition") +class CONFIGCATWRAPPERS_API UConfigCatSegmentConditionWrapper : public UObject +{ + GENERATED_BODY() + +public: + static UConfigCatSegmentConditionWrapper* CreateSegmentCondition(const configcat::SegmentCondition& InSegmentCondition); + + UFUNCTION(BlueprintPure, Category = "ConfigCat|SegmentCondition") + int32 GetSegmentIndex() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|SegmentCondition") + EConfigCatSegmentComparator GetComparator() const; + + configcat::SegmentCondition SegmentCondition; +}; + +USTRUCT(BlueprintType) +struct CONFIGCATWRAPPERS_API FConfigCatConditionContainer +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadOnly, Category = "ConfigCat|ConditionContainer") + UConfigCatUserConditionWrapper* UserCondition; + UPROPERTY(BlueprintReadOnly, Category = "ConfigCat|ConditionContainer") + UConfigCatPrerequisiteFlagConditionWrapper* PrerequisiteFlagCondition; + UPROPERTY(BlueprintReadOnly, Category = "ConfigCat|ConditionContainer") + UConfigCatSegmentConditionWrapper* SegmentCondition; +}; + +USTRUCT(BlueprintType) +struct FConfigCatThenContainer +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadOnly, Category = "ConfigCat|ThenContainer") + UConfigCatSettingValueContainerWrapper* SettingValueContainer = nullptr; + + UPROPERTY(BlueprintReadOnly, Category = "ConfigCat|ThenContainer") + TArray PercentageOptions; +}; + +UCLASS(DisplayName="Config Cat Targeting Rule") +class CONFIGCATWRAPPERS_API UConfigCatTargetingRuleWrapper : public UObject +{ + GENERATED_BODY() + +public: + static UConfigCatTargetingRuleWrapper* CreateTargetingRule(const configcat::TargetingRule& InTargetingRule); + + UFUNCTION(BlueprintPure, Category = "ConfigCat|TargetingRule") + TArray GetConditions() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|TargetingRule") + FConfigCatThenContainer GetThen() const; + + configcat::TargetingRule TargetingRule; +}; \ No newline at end of file diff --git a/Source/ConfigCatWrappers/Public/ConfigCatUserWrapper.h b/Source/ConfigCatWrappers/Public/ConfigCatUserWrapper.h new file mode 100644 index 0000000..3fd8903 --- /dev/null +++ b/Source/ConfigCatWrappers/Public/ConfigCatUserWrapper.h @@ -0,0 +1,51 @@ +// Copyright (c) ConfigCat 2024. All Rights Reserved. + +#pragma once + +#include + +#include + +#include "ConfigCatUserWrapper.generated.h" + +UCLASS(DisplayName="Config Cat User") +class CONFIGCATWRAPPERS_API UConfigCatUserWrapper : public UObject +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintPure, Category = "ConfigCat|User") + static UConfigCatUserWrapper* CreateUser(const FString& Id, const FString& Email, const FString& Country, const TMap& Attributes); + static UConfigCatUserWrapper* CreateUser(const std::shared_ptr& InUser); + + /** + * Gets the Id of a ConfigCatUser + */ + UFUNCTION(BlueprintPure, Category = "ConfigCat|User") + FString GetIdentifier() const; + + UFUNCTION(BlueprintPure, Category = "ConfigCat|User") + FString GetStringAttribute(const FString& Key) const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|User") + double GetNumberAttribute(const FString& Key) const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|User") + FDateTime GetTimeAttribute(const FString& Key) const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|User") + TArray GetStringArrayAttribute(const FString& Key) const; + + UFUNCTION(BlueprintPure, Category = "ConfigCat|User") + bool HasAnyAttribute(const FString& Key) const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|User") + bool HasStringAttribute(const FString& Key) const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|User") + bool HasNumberAttribute(const FString& Key) const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|User") + bool HasTimeAttribute(const FString& Key) const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|User") + bool HasStringArrayAttribute(const FString& Key) const; + + std::shared_ptr User; + +private: + const configcat::ConfigCatUser::AttributeValue* GetUserAttributeForKey(const FString& Key) const; +}; \ No newline at end of file diff --git a/Source/ConfigCatWrappers/Public/ConfigCatValueWrapper.h b/Source/ConfigCatWrappers/Public/ConfigCatValueWrapper.h new file mode 100644 index 0000000..40e2fab --- /dev/null +++ b/Source/ConfigCatWrappers/Public/ConfigCatValueWrapper.h @@ -0,0 +1,42 @@ +// Copyright (c) ConfigCat 2024. All Rights Reserved. + +#pragma once + +#include + +#include + +#include "ConfigCatValueWrapper.generated.h" + +UCLASS(DisplayName="Config Cat SettingValue") +class CONFIGCATWRAPPERS_API UConfigCatValueWrapper : public UObject +{ + GENERATED_BODY() + +public: + static UConfigCatValueWrapper* CreateValue(const configcat::SettingValue& InValue); + static UConfigCatValueWrapper* CreateValue(const configcat::Value& InValue); + static UConfigCatValueWrapper* CreateValue(const std::optional& InValue); + + UFUNCTION(BlueprintPure, Category = "ConfigCat|Value") + bool HasAnyValue() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|Value") + bool HasBooleanValue() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|Value") + bool HasStringValue() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|Value") + bool HasIntegerValue() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|Value") + bool HasDecimalValue() const; + + UFUNCTION(BlueprintPure, Category = "ConfigCat|Value") + bool GetBooleanValue() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|Value") + FString GetStringValue() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|Value") + int GetIntegerValue() const; + UFUNCTION(BlueprintPure, Category = "ConfigCat|Value") + double GetDecimalValue() const; + + std::optional Value; +}; diff --git a/Source/ConfigCatWrappers/Public/ConfigCatWrappers.h b/Source/ConfigCatWrappers/Public/ConfigCatWrappers.h new file mode 100644 index 0000000..11c10b5 --- /dev/null +++ b/Source/ConfigCatWrappers/Public/ConfigCatWrappers.h @@ -0,0 +1,12 @@ +// Copyright (c) ConfigCat 2024. All Rights Reserved. + +#pragma once + +#include + +/** + * @brief ConfigCatWrappers module contains all the blueprint-friendly wrapper classes based on the cpp-sdk classes + */ +class FConfigCatWrappersModule : public IModuleInterface +{ +}; diff --git a/Source/ThirdParty/ConfigCatCppSDK/Include/config.h b/Source/ThirdParty/ConfigCatCppSDK/Include/config.h index 29a197c..5a29baf 100644 --- a/Source/ThirdParty/ConfigCatCppSDK/Include/config.h +++ b/Source/ThirdParty/ConfigCatCppSDK/Include/config.h @@ -1,211 +1,401 @@ #pragma once +#include +#include +#include +#include #include -#include #include +#include #include -#include -#include -#include namespace configcat { -using ValueType = std::variant; -// Disable implicit conversion from pointer types (const char*) to bool when constructing std::variant -// https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0608r3.html -struct Value : public ValueType { - Value() : ValueType() {} - Value(bool v) : ValueType(v) {} - Value(const char* v) : ValueType(std::string(v)) {} - Value(const std::string& v) : ValueType(v) {} - Value(int v) : ValueType(v) {} - Value(double v) : ValueType(v) {} +struct SettingValue; + +struct Value : public std::variant { +private: + using _Base = std::variant; +public: + Value(const char* v) : _Base(std::string(v)) {} + // Disable the implicit conversion from pointer to bool: https://stackoverflow.com/a/59372958/8656352 template Value(T*) = delete; + + using _Base::_Base; + using _Base::operator=; + + operator SettingValue() const; + + std::string toString() const; +}; + +inline std::ostream& operator<<(std::ostream& os, const Value& v) { + return os << v.toString(); +} + +inline std::ostream& operator<<(std::ostream& os, const std::optional& v) { + return os << (v ? v->toString() : ""); +} + +enum class RedirectMode : int { + No = 0, + Should = 1, + Force = 2 }; -std::string valueToString(const ValueType& value); +/** Setting type. */ +enum class SettingType : int { + /** On/off type (feature flag). */ + Boolean = 0, + /** Text type. */ + String = 1, + /** Whole number type. */ + Int = 2, + /** Decimal number type. */ + Double = 3, +}; -enum RedirectMode: int { - NoRedirect = 0, - ShouldRedirect = 1, - ForceRedirect = 2 +/** User Object attribute comparison operator used during the evaluation process. */ +enum class UserComparator { + /** IS ONE OF (cleartext) - Checks whether the comparison attribute is equal to any of the comparison values. */ + TextIsOneOf = 0, + /** IS NOT ONE OF (cleartext) - Checks whether the comparison attribute is not equal to any of the comparison values. */ + TextIsNotOneOf = 1, + /** CONTAINS ANY OF (cleartext) - Checks whether the comparison attribute contains any comparison values as a substring. */ + TextContainsAnyOf = 2, + /** NOT CONTAINS ANY OF (cleartext) - Checks whether the comparison attribute does not contain any comparison values as a substring. */ + TextNotContainsAnyOf = 3, + /** IS ONE OF (semver) - Checks whether the comparison attribute interpreted as a semantic version is equal to any of the comparison values. */ + SemVerIsOneOf = 4, + /** IS NOT ONE OF (semver) - Checks whether the comparison attribute interpreted as a semantic version is not equal to any of the comparison values. */ + SemVerIsNotOneOf = 5, + /** < (semver) - Checks whether the comparison attribute interpreted as a semantic version is less than the comparison value. */ + SemVerLess = 6, + /** <= (semver) - Checks whether the comparison attribute interpreted as a semantic version is less than or equal to the comparison value. */ + SemVerLessOrEquals = 7, + /** > (semver) - Checks whether the comparison attribute interpreted as a semantic version is greater than the comparison value. */ + SemVerGreater = 8, + /** >= (semver) - Checks whether the comparison attribute interpreted as a semantic version is greater than or equal to the comparison value. */ + SemVerGreaterOrEquals = 9, + /** = (number) - Checks whether the comparison attribute interpreted as a decimal number is equal to the comparison value. */ + NumberEquals = 10, + /** != (number) - Checks whether the comparison attribute interpreted as a decimal number is not equal to the comparison value. */ + NumberNotEquals = 11, + /** < (number) - Checks whether the comparison attribute interpreted as a decimal number is less than the comparison value. */ + NumberLess = 12, + /** <= (number) - Checks whether the comparison attribute interpreted as a decimal number is less than or equal to the comparison value. */ + NumberLessOrEquals = 13, + /** > (number) - Checks whether the comparison attribute interpreted as a decimal number is greater than the comparison value. */ + NumberGreater = 14, + /** >= (number) - Checks whether the comparison attribute interpreted as a decimal number is greater than or equal to the comparison value. */ + NumberGreaterOrEquals = 15, + /** IS ONE OF (hashed) - Checks whether the comparison attribute is equal to any of the comparison values (where the comparison is performed using the salted SHA256 hashes of the values). */ + SensitiveTextIsOneOf = 16, + /** IS NOT ONE OF (hashed) - Checks whether the comparison attribute is not equal to any of the comparison values (where the comparison is performed using the salted SHA256 hashes of the values). */ + SensitiveTextIsNotOneOf = 17, + /** BEFORE (UTC datetime) - Checks whether the comparison attribute interpreted as the seconds elapsed since Unix Epoch is less than the comparison value. */ + DateTimeBefore = 18, + /** AFTER (UTC datetime) - Checks whether the comparison attribute interpreted as the seconds elapsed since Unix Epoch is greater than the comparison value. */ + DateTimeAfter = 19, + /** EQUALS (hashed) - Checks whether the comparison attribute is equal to the comparison value (where the comparison is performed using the salted SHA256 hashes of the values). */ + SensitiveTextEquals = 20, + /** NOT EQUALS (hashed) - Checks whether the comparison attribute is not equal to the comparison value (where the comparison is performed using the salted SHA256 hashes of the values). */ + SensitiveTextNotEquals = 21, + /** STARTS WITH ANY OF (hashed) - Checks whether the comparison attribute starts with any of the comparison values (where the comparison is performed using the salted SHA256 hashes of the values). */ + SensitiveTextStartsWithAnyOf = 22, + /** NOT STARTS WITH ANY OF (hashed) - Checks whether the comparison attribute does not start with any of the comparison values (where the comparison is performed using the salted SHA256 hashes of the values). */ + SensitiveTextNotStartsWithAnyOf = 23, + /** ENDS WITH ANY OF (hashed) - Checks whether the comparison attribute ends with any of the comparison values (where the comparison is performed using the salted SHA256 hashes of the values). */ + SensitiveTextEndsWithAnyOf = 24, + /** NOT ENDS WITH ANY OF (hashed) - Checks whether the comparison attribute does not end with any of the comparison values (where the comparison is performed using the salted SHA256 hashes of the values). */ + SensitiveTextNotEndsWithAnyOf = 25, + /** ARRAY CONTAINS ANY OF (hashed) - Checks whether the comparison attribute interpreted as a comma-separated list contains any of the comparison values (where the comparison is performed using the salted SHA256 hashes of the values). */ + SensitiveArrayContainsAnyOf = 26, + /** ARRAY NOT CONTAINS ANY OF (hashed) - Checks whether the comparison attribute interpreted as a comma-separated list does not contain any of the comparison values (where the comparison is performed using the salted SHA256 hashes of the values). */ + SensitiveArrayNotContainsAnyOf = 27, + /** EQUALS (cleartext) - Checks whether the comparison attribute is equal to the comparison value. */ + TextEquals = 28, + /** NOT EQUALS (cleartext) - Checks whether the comparison attribute is not equal to the comparison value. */ + TextNotEquals = 29, + /** STARTS WITH ANY OF (cleartext) - Checks whether the comparison attribute starts with any of the comparison values. */ + TextStartsWithAnyOf = 30, + /** NOT STARTS WITH ANY OF (cleartext) - Checks whether the comparison attribute does not start with any of the comparison values. */ + TextNotStartsWithAnyOf = 31, + /** ENDS WITH ANY OF (cleartext) - Checks whether the comparison attribute ends with any of the comparison values. */ + TextEndsWithAnyOf = 32, + /** NOT ENDS WITH ANY OF (cleartext) - Checks whether the comparison attribute does not end with any of the comparison values. */ + TextNotEndsWithAnyOf = 33, + /** ARRAY CONTAINS ANY OF (cleartext) - Checks whether the comparison attribute interpreted as a comma-separated list contains any of the comparison values. */ + ArrayContainsAnyOf = 34, + /** ARRAY NOT CONTAINS ANY OF (cleartext) - Checks whether the comparison attribute interpreted as a comma-separated list does not contain any of the comparison values. */ + ArrayNotContainsAnyOf = 35, }; -struct Preferences { - std::string url; - RedirectMode redirect = NoRedirect; +/** Prerequisite flag comparison operator used during the evaluation process. */ +enum class PrerequisiteFlagComparator { + /** EQUALS - Checks whether the evaluated value of the specified prerequisite flag is equal to the comparison value. */ + Equals = 0, + /** NOT EQUALS - Checks whether the evaluated value of the specified prerequisite flag is not equal to the comparison value. */ + NotEquals = 1 }; -struct RolloutPercentageItem { - // Value served when the rule is selected during evaluation. - Value value = 0; +/** Segment comparison operator used during the evaluation process. */ +enum class SegmentComparator { + /** IS IN SEGMENT - Checks whether the conditions of the specified segment are evaluated to true. */ + IsIn = 0, + /** IS NOT IN SEGMENT - Checks whether the conditions of the specified segment are evaluated to false. */ + IsNotIn = 1, +}; - // The rule's percentage value. - double percentage = 0.0; +template +class one_of : public std::variant { + using _Base = std::variant; +public: + one_of() : _Base(std::nullopt) {} + using _Base::_Base; // inherit std::variant's ctors + using _Base::operator=; // inherit std::variant's assignment operators +}; - // The rule's variation ID (for analytical purposes). - std::string variationId; +std::ostream& operator<<(std::ostream& os, const Value& v); - bool operator==(const RolloutPercentageItem& other) const { - return value == other.value - && percentage == other.percentage - && variationId == other.variationId; +struct SettingValuePrivate; + +struct SettingValue : public one_of { + // Not for maintainers: the indices of variant alternatives must correspond to + // the SettingType enum's member values because we rely on this! (See also getSettingType) +private: + using _Base = one_of; +protected: + friend struct SettingValuePrivate; + + struct UnsupportedValue { + std::string type; + std::string value; + }; + + std::shared_ptr unsupportedValue; +public: + static constexpr char kBoolean[] = "b"; + static constexpr char kString[] = "s"; + static constexpr char kInt[] = "i"; + static constexpr char kDouble[] = "d"; + + SettingValue(const char* v) : _Base(std::string(v)) {} + + using _Base::_Base; + using _Base::operator=; + + operator std::optional() const; + std::optional toValueChecked(SettingType type, bool throwIfInvalid = true) const; + + inline SettingType getSettingType() const { + // For unsupported values this results in -1, which value is not present in the SettingType enum. + // However, we only use this value internally (will never expose it to the end user). + return static_cast(this->index() - 1); } }; -enum Comparator: int { - ONE_OF = 0, // IS ONE OF - NOT_ONE_OF = 1, // IS NOT ONE OF - CONTAINS = 2, // CONTAINS - NOT_CONTAINS = 3, // DOES NOT CONTAIN - ONE_OF_SEMVER = 4, // IS ONE OF (SemVer) - NOT_ONE_OF_SEMVER = 5, // IS NOT ONE OF (SemVer) - LT_SEMVER = 6, // < (SemVer) - LTE_SEMVER = 7, // <= (SemVer) - GT_SEMVER = 8, // > (SemVer) - GTE_SEMVER = 9, // >= (SemVer) - EQ_NUM = 10, // = (Number) - NOT_EQ_NUM = 11, // <> (Number) - LT_NUM = 12, // < (Number) - LTE_NUM = 13, // <= (Number) - GT_NUM = 14, // > (Number) - GTE_NUM = 15, // >= (Number) - ONE_OF_SENS = 16, // IS ONE OF (Sensitive) - NOT_ONE_OF_SENS = 17 // IS NOT ONE OF (Sensitive) -}; - -static constexpr char const* kComparatorTexts[] = { - "IS ONE OF", - "IS NOT ONE OF", - "CONTAINS", - "DOES NOT CONTAIN", - "IS ONE OF (SemVer)", - "IS NOT ONE OF (SemVer)", - "< (SemVer)", - "<= (SemVer)", - "> (SemVer)", - ">= (SemVer)", - "= (Number)", - "<> (Number)", - "< (Number)", - "<= (Number)", - "> (Number)", - ">= (Number)", - "IS ONE OF (Sensitive)", - "IS NOT ONE OF (Sensitive)" -}; - -inline const char* comparatorToString(Comparator comparator) { - return kComparatorTexts[comparator]; -} +struct SettingValueContainer { + static constexpr char kValue[] = "v"; + static constexpr char kVariationId[] = "i"; + + SettingValue value; + std::optional variationId; +}; + +struct PercentageOption : public SettingValueContainer { + static constexpr char kPercentage[] = "p"; + + uint8_t percentage = 0; +}; + +using PercentageOptions = std::vector; -struct RolloutRule { - // Value served when the rule is selected during evaluation. - Value value = 0; // optional +using UserConditionComparisonValue = one_of>; + +struct UserCondition { + static constexpr char kComparisonAttribute[] = "a"; + static constexpr char kComparator[] = "c"; + static constexpr char kStringComparisonValue[] = "s"; + static constexpr char kNumberComparisonValue[] = "d"; + static constexpr char kStringListComparisonValue[] = "l"; - // The user attribute used in the comparison during evaluation. std::string comparisonAttribute; + UserComparator comparator = static_cast(-1); + UserConditionComparisonValue comparisonValue; +}; - // The operator used in the comparison. - Comparator comparator = ONE_OF; +using UserConditions = std::vector; - // The comparison value compared to the given user attribute. - std::string comparisonValue; +struct PrerequisiteFlagCondition { + static constexpr char kPrerequisiteFlagKey[] = "f"; + static constexpr char kComparator[] = "c"; + static constexpr char kComparisonValue[] = "v"; - // The rule's variation ID (for analytical purposes). - std::string variationId; + std::string prerequisiteFlagKey; + PrerequisiteFlagComparator comparator = static_cast(-1); + SettingValue comparisonValue; +}; - bool operator==(const RolloutRule& other) const { - return value == other.value && - comparisonAttribute == other.comparisonAttribute && - comparator == other.comparator && - comparisonValue == other.comparisonValue && - variationId == other.variationId; - } +struct SegmentCondition { + static constexpr char kSegmentIndex[] = "s"; + static constexpr char kComparator[] = "c"; + + int32_t segmentIndex = -1; + SegmentComparator comparator = static_cast(-1); }; -struct Setting { - // Value of the feature flag / setting. - Value value = 0; +using Condition = one_of; + +struct ConditionContainer { + static constexpr char kUserCondition[] = "u"; + static constexpr char kPrerequisiteFlagCondition[] = "p"; + static constexpr char kSegmentCondition[] = "s"; - // Collection of percentage rules that belongs to the feature flag / setting. - std::vector percentageItems; + Condition condition; +}; - // Collection of targeting rules that belongs to the feature flag / setting. - std::vector rolloutRules; +using Conditions = std::vector; - // Variation ID (for analytical purposes). - std::string variationId; +using TargetingRuleThenPart = one_of; - bool operator==(const Setting& other) const { - return value == other.value - && percentageItems == other.percentageItems - && rolloutRules == other.rolloutRules - && variationId == other.variationId; - } +struct TargetingRule { + static constexpr char kConditions[] = "c"; + static constexpr char kSimpleValue[] = "s"; + static constexpr char kPercentageOptions[] = "p"; + + Conditions conditions; + TargetingRuleThenPart then; +}; + +using TargetingRules = std::vector; + +struct Segment { + static constexpr char kName[] = "n"; + static constexpr char kConditions[] = "r"; + + std::string name; + UserConditions conditions; +}; + +using Segments = std::vector; + +struct Config; +class RolloutEvaluator; + +struct Setting : public SettingValueContainer { + static constexpr char kType[] = "t"; + static constexpr char kPercentageOptionsAttribute[] = "a"; + static constexpr char kTargetingRules[] = "r"; + static constexpr char kPercentageOptions[] = "p"; + + static Setting fromValue(const SettingValue& value); + + SettingType type = static_cast(-1); + std::optional percentageOptionsAttribute; + TargetingRules targetingRules; + PercentageOptions percentageOptions; + + inline bool hasInvalidType() const { return type < SettingType::Boolean || SettingType::Double < type; } + SettingType getTypeChecked() const; + +protected: + friend struct Config; + friend class RolloutEvaluator; + std::shared_ptr configJsonSalt; + std::shared_ptr segments; }; using Settings = std::unordered_map; +struct Preferences { + /** + * The JSON key of the base url from where the config.json is intended to be downloaded. + */ + static constexpr char kBaseUrl[] = "u"; + /** + * The JSON key of the redirect mode that should be used in case the data governance mode is wrongly configured. + */ + static constexpr char kRedirectMode[] = "r"; + /** + * The JSON key of The salt that, combined with the feature flag key or segment name, is used to hash values for sensitive text comparisons. + */ + static constexpr char kSalt[] = "s"; + + std::optional baseUrl; + RedirectMode redirectMode = RedirectMode::No; + std::shared_ptr salt; + + Preferences() {} + + Preferences(const Preferences& other) : Preferences() { *this = other; } + + Preferences& operator=(const Preferences& other) { + baseUrl = other.baseUrl; + redirectMode = other.redirectMode; + salt = other.salt ? std::make_shared(*other.salt) : nullptr; + return *this; + } + + Preferences(Preferences&& other) noexcept = default; + + Preferences& operator=(Preferences&& other) noexcept = default; +}; + +/** + * Details of a ConfigCat config. + */ struct Config { - static constexpr char kValue[] = "v"; - static constexpr char kComparator[] = "t"; - static constexpr char kComparisonAttribute[] = "a"; - static constexpr char kComparisonValue[] = "c"; - static constexpr char kRolloutPercentageItems[] = "p"; - static constexpr char kPercentage[] = "p"; - static constexpr char kRolloutRules[] = "r"; - static constexpr char kVariationId[] = "i"; + /** + * The JSON key of preferences of the config.json, mostly for controlling the redirection behaviour of the SDK. + */ static constexpr char kPreferences[] = "p"; - static constexpr char kPreferencesUrl[] = "u"; - static constexpr char kPreferencesRedirect[] = "r"; - static constexpr char kEntries[] = "f"; + /** + * The JSON key of segment definitions for re-using segment rules in targeting rules. + */ + static constexpr char kSegments[] = "s"; + /** + * The JSON key of setting definitions. + */ + static constexpr char kSettings[] = "f"; - std::shared_ptr preferences; - std::shared_ptr entries; + static const std::shared_ptr empty; std::string toJson(); - static std::shared_ptr fromJson(const std::string& jsonString); - static std::shared_ptr fromFile(const std::string& filePath); - - static std::shared_ptr empty; + static std::shared_ptr fromJson(const std::string& jsonString, bool tolerant = false); + static std::shared_ptr fromFile(const std::string& filePath, bool tolerant = true); - Config() {}; - Config(const Config&) = delete; // Disable copy -}; + std::optional preferences; + std::shared_ptr segments; + std::shared_ptr settings; -// extra brackets to avoid numeric_limits::max()/min() not recognized error on windows -constexpr double kDistantFuture = (std::numeric_limits::max)(); -constexpr double kDistantPast = (std::numeric_limits::min)(); + std::shared_ptr getSegmentsOrEmpty() const { return segments ? segments : std::make_shared(); } + std::shared_ptr getSettingsOrEmpty() const { return settings ? settings : std::make_shared(); } -struct ConfigEntry { - static constexpr char kConfig[] = "config"; - static constexpr char kETag[] = "etag"; - static constexpr char kFetchTime[] = "fetch_time"; - static constexpr char kSerializationFormatVersion[] = "v2"; + Config() {} - static std::shared_ptr empty; + Config(const Config& other) + : preferences(other.preferences) + , segments(other.segments ? std::make_shared(*other.segments) : nullptr) + , settings(other.settings ? std::make_shared(*other.settings) : nullptr) { + fixupSaltAndSegments(); + } - ConfigEntry(std::shared_ptr config = Config::empty, - const std::string& eTag = "", - const std::string& configJsonString = "{}", - double fetchTime = kDistantPast): - config(config), - eTag(eTag), - configJsonString(configJsonString), - fetchTime(fetchTime) { + Config& operator=(const Config& other) { + preferences = other.preferences; + segments = other.segments ? std::make_shared(*other.segments) : nullptr; + settings = other.settings ? std::make_shared(*other.settings) : nullptr; + fixupSaltAndSegments(); + return *this; } - ConfigEntry(const ConfigEntry&) = delete; // Disable copy - static std::shared_ptr fromString(const std::string& text); - std::string serialize() const; + Config(Config&& other) noexcept = default; - std::shared_ptr config; - std::string eTag; - std::string configJsonString; - double fetchTime; + Config& operator=(Config&& other) noexcept = default; +private: + void fixupSaltAndSegments(); }; } // namespace configcat diff --git a/Source/ThirdParty/ConfigCatCppSDK/Include/configcatclient.h b/Source/ThirdParty/ConfigCatCppSDK/Include/configcatclient.h index 5591528..ffbf8ad 100644 --- a/Source/ThirdParty/ConfigCatCppSDK/Include/configcatclient.h +++ b/Source/ThirdParty/ConfigCatCppSDK/Include/configcatclient.h @@ -8,7 +8,6 @@ #include "keyvalue.h" #include "configcatoptions.h" #include "refreshresult.h" -#include "settingresult.h" #include "evaluationdetails.h" @@ -20,15 +19,21 @@ class ConfigFetcher; class RolloutEvaluator; class FlagOverrides; class ConfigService; - +struct SettingResult; class ConfigCatClient { public: + ConfigCatClient(const ConfigCatClient&) = delete; // Disable copy + ConfigCatClient& operator=(const ConfigCatClient&) = delete; + + ConfigCatClient(ConfigCatClient&&) = delete; // Disable move + ConfigCatClient& operator=(ConfigCatClient&&) = delete; + // Creates a new or gets an already existing [ConfigCatClient] for the given [sdkKey]. - static ConfigCatClient* get(const std::string& sdkKey, const ConfigCatOptions* options = nullptr); + static std::shared_ptr get(const std::string& sdkKey, const ConfigCatOptions* options = nullptr); // Closes an individual [ConfigCatClient] instance. - static void close(ConfigCatClient* client); + static void close(const std::shared_ptr& client); // Closes all [ConfigCatClient] instances. static void closeAll(); @@ -43,17 +48,17 @@ class ConfigCatClient { * Parameter [defaultValue]: in case of any failure, this value will be returned. * Parameter [user]: the user object to identify the caller. */ - bool getValue(const std::string& key, bool defaultValue, const ConfigCatUser* user = nullptr) const; - int getValue(const std::string& key, int defaultValue, const ConfigCatUser* user = nullptr) const; - double getValue(const std::string& key, double defaultValue, const ConfigCatUser* user = nullptr) const; - std::string getValue(const std::string& key, const char* defaultValue, const ConfigCatUser* user = nullptr) const; - std::string getValue(const std::string& key, const std::string& defaultValue, const ConfigCatUser* user = nullptr) const; + bool getValue(const std::string& key, bool defaultValue, const std::shared_ptr& user = nullptr) const; + int32_t getValue(const std::string& key, int32_t defaultValue, const std::shared_ptr& user = nullptr) const; + double getValue(const std::string& key, double defaultValue, const std::shared_ptr& user = nullptr) const; + std::string getValue(const std::string& key, const char* defaultValue, const std::shared_ptr& user = nullptr) const; + std::string getValue(const std::string& key, const std::string& defaultValue, const std::shared_ptr& user = nullptr) const; /** - * Gets the value of a feature flag or setting as std::shared_ptr identified by the given [key]. - * In case of any failure, nullptr will be returned. The [user] param identifies the caller. + * Gets the value of a feature flag or setting as std::optional identified by the given [key]. + * In case of any failure, std::nullopt will be returned. The [user] param identifies the caller. */ - std::shared_ptr getValue(const std::string& key, const ConfigCatUser* user = nullptr) const; + std::optional getValue(const std::string& key, const std::shared_ptr& user = nullptr) const; /** * Gets the value and evaluation details of a feature flag or setting identified by the given `key`. @@ -62,34 +67,40 @@ class ConfigCatClient { * Parameter [defaultValue]: in case of any failure, this value will be returned. * Parameter [user]: the user object to identify the caller. */ - EvaluationDetails getValueDetails(const std::string& key, bool defaultValue, const ConfigCatUser* user = nullptr) const; - EvaluationDetails getValueDetails(const std::string& key, int defaultValue, const ConfigCatUser* user = nullptr) const; - EvaluationDetails getValueDetails(const std::string& key, double defaultValue, const ConfigCatUser* user = nullptr) const; - EvaluationDetails getValueDetails(const std::string& key, const std::string& defaultValue, const ConfigCatUser* user = nullptr) const; - EvaluationDetails getValueDetails(const std::string& key, const char* defaultValue, const ConfigCatUser* user = nullptr) const; + EvaluationDetails getValueDetails(const std::string& key, bool defaultValue, const std::shared_ptr& user = nullptr) const; + EvaluationDetails getValueDetails(const std::string& key, int32_t defaultValue, const std::shared_ptr& user = nullptr) const; + EvaluationDetails getValueDetails(const std::string& key, double defaultValue, const std::shared_ptr& user = nullptr) const; + EvaluationDetails getValueDetails(const std::string& key, const std::string& defaultValue, const std::shared_ptr& user = nullptr) const; + EvaluationDetails getValueDetails(const std::string& key, const char* defaultValue, const std::shared_ptr& user = nullptr) const; + + /** + * Gets the value and evaluation details of a feature flag or setting identified by the given [key]. + * In case of any failure, the [value] field of the returned EvaluationDetails struct will be set to std::nullopt. The [user] param identifies the caller. + */ + EvaluationDetails> getValueDetails(const std::string& key, const std::shared_ptr& user = nullptr) const; // Gets all the setting keys. std::vector getAllKeys() const; // Gets the key of a setting and it's value identified by the given Variation ID (analytics) - std::shared_ptr getKeyAndValue(const std::string& variationId) const; + std::optional getKeyAndValue(const std::string& variationId) const; // Gets the values of all feature flags or settings. - std::unordered_map getAllValues(const ConfigCatUser* user = nullptr) const; + std::unordered_map getAllValues(const std::shared_ptr& user = nullptr) const; // Gets the values along with evaluation details of all feature flags and settings. - std::vector getAllValueDetails(const ConfigCatUser* user = nullptr) const; + std::vector> getAllValueDetails(const std::shared_ptr& user = nullptr) const; // Initiates a force refresh synchronously on the cached configuration. - void forceRefresh(); + RefreshResult forceRefresh(); // Sets the default user. - void setDefaultUser(std::shared_ptr user) { + inline void setDefaultUser(const std::shared_ptr& user) { defaultUser = user; } // Sets the default user to nullptr. - void clearDefaultUser() { + inline void clearDefaultUser() { defaultUser.reset(); } @@ -103,23 +114,30 @@ class ConfigCatClient { bool isOffline() const; // Gets the Hooks object for subscribing events. - std::shared_ptr getHooks() { return hooks; } + inline std::shared_ptr getHooks() { return hooks; } private: + struct MakeSharedEnabler; + ConfigCatClient(const std::string& sdkKey, const ConfigCatOptions& options); + void closeResources(); + template - ValueType _getValue(const std::string& key, const ValueType& defaultValue, const ConfigCatUser* user = nullptr) const; + ValueType _getValue(const std::string& key, const ValueType& defaultValue, const std::shared_ptr& user = nullptr) const; template - EvaluationDetails _getValueDetails(const std::string& key, ValueType defaultValue, const ConfigCatUser* user = nullptr) const; + EvaluationDetails _getValueDetails(const std::string& key, const ValueType& defaultValue, const std::shared_ptr& user = nullptr) const; SettingResult getSettings() const; - EvaluationDetails evaluate(const std::string& key, - const ConfigCatUser* user, - const Setting& setting, - double fetchTime) const; + template + EvaluationDetails evaluate(const std::string& key, + const std::optional& defaultValue, + const std::shared_ptr& effectiveUser, + const Setting& setting, + const std::shared_ptr& settings, + double fetchTime) const; std::shared_ptr hooks; std::shared_ptr logger; @@ -129,7 +147,7 @@ class ConfigCatClient { std::unique_ptr configService; static std::mutex instancesMutex; - static std::unordered_map> instances; + static std::unordered_map> instances; }; } // namespace configcat diff --git a/Source/ThirdParty/ConfigCatCppSDK/Include/configcatlogger.h b/Source/ThirdParty/ConfigCatCppSDK/Include/configcatlogger.h deleted file mode 100644 index daeb89e..0000000 --- a/Source/ThirdParty/ConfigCatCppSDK/Include/configcatlogger.h +++ /dev/null @@ -1,126 +0,0 @@ -#pragma once - -#include "log.h" -#include "configcatoptions.h" -#include "configcatuser.h" -#include "config.h" - -namespace configcat { - -class ConfigCatLogger { -public: - ConfigCatLogger(std::shared_ptr logger, std::shared_ptr hooks): - logger(logger), - hooks(hooks) { - } - - void log(LogLevel level, int eventId, const std::string& message) { - if (hooks && level == LOG_LEVEL_ERROR) { - hooks->invokeOnError(message); - } - - if (logger) { - logger->log(level, "[" + std::to_string(eventId) + "] " + message); - } - } - - void setLogLevel(LogLevel logLevel) { if (logger) logger->setLogLevel(logLevel); } - LogLevel getLogLevel() const { return logger ? logger->getLogLevel() : LOG_LEVEL_WARNING; } - -private: - std::shared_ptr logger; - std::shared_ptr hooks; -}; - -class LogEntry { -public: - LogEntry(std::shared_ptr logger, LogLevel level, int eventId) : logger(logger), level(level), eventId(eventId) {} - ~LogEntry() { - if (logger && level <= logger->getLogLevel()) - logger->log(level, eventId, message); - } - - LogEntry& operator<<(const char* str) { - if (str && logger && level <= logger->getLogLevel()) - message += str; - return *this; - } - - LogEntry& operator<<(char* str) { - if (str && logger && level <= logger->getLogLevel()) - message += str; - return *this; - } - - LogEntry& operator<<(const std::string& str) { - if (logger && level <= logger->getLogLevel()) - message += str; - return *this; - } - - LogEntry& operator<<(bool arg) { - if (logger && level <= logger->getLogLevel()) - message += arg ? "true" : "false"; - return *this; - } - - LogEntry& operator<<(const ConfigCatUser* user) { - return operator<<(*user); - } - - LogEntry& operator<<(const ConfigCatUser& user) { - if (logger && level <= logger->getLogLevel()) - message += user.toJson(); - return *this; - } - - LogEntry& operator<<(const Value& v) { - if (logger && level <= logger->getLogLevel()) - message += valueToString(v); - return *this; - } - - template - LogEntry& operator<<(Type arg) { - if (logger && level <= logger->getLogLevel()) - message += std::to_string(arg); - return *this; - } - - template - LogEntry& operator<<(const std::vector& v) { - if (logger && level <= logger->getLogLevel()) { - message += "["; - size_t last = v.size() - 1; - for (size_t i = 0; i < v.size(); ++i) { - operator<<(v[i]); - if (i != last) { - message += ", "; - } - } - message += "]"; - } - return *this; - } - - const std::string& getMessage() { return message; } - -private: - std::shared_ptr logger; - LogLevel level; - int eventId; - std::string message; -}; - -} // namespace configcat - -// Log macros (requires a shared_ptr logger object in the current scope) -#define LOG_ERROR(eventId) configcat::LogEntry(logger, configcat::LOG_LEVEL_ERROR, eventId) -#define LOG_WARN(eventId) configcat::LogEntry(logger, configcat::LOG_LEVEL_WARNING, eventId) -#define LOG_INFO(eventId) configcat::LogEntry(logger, configcat::LOG_LEVEL_INFO, eventId) -#define LOG_DEBUG configcat::LogEntry(logger, configcat::LOG_LEVEL_DEBUG, 0) - -#define LOG_ERROR_OBJECT(logger, eventId) configcat::LogEntry(logger, configcat::LOG_LEVEL_ERROR, eventId) -#define LOG_WARN_OBJECT(logger, eventId) configcat::LogEntry(logger, configcat::LOG_LEVEL_WARNING, eventId) -#define LOG_INFO_OBJECT(logger, eventId) configcat::LogEntry(logger, configcat::LOG_LEVEL_INFO, eventId) -#define LOG_DEBUG_OBJECT(logger) configcat::LogEntry(logger, configcat::LOG_LEVEL_DEBUG, 0) diff --git a/Source/ThirdParty/ConfigCatCppSDK/Include/configcatoptions.h b/Source/ThirdParty/ConfigCatCppSDK/Include/configcatoptions.h index 90a412d..9a8e2fd 100644 --- a/Source/ThirdParty/ConfigCatCppSDK/Include/configcatoptions.h +++ b/Source/ThirdParty/ConfigCatCppSDK/Include/configcatoptions.h @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include "datagovernance.h" #include "pollingmode.h" #include "configcache.h" @@ -21,9 +23,9 @@ namespace configcat { class Hooks { public: explicit Hooks(const std::function& onClientReady = nullptr, - const std::function)>& onConfigChanged = nullptr, - const std::function& onFlagEvaluated = nullptr, - const std::function& onError = nullptr) { + const std::function)>& onConfigChanged = nullptr, + const std::function& onFlagEvaluated = nullptr, + const std::function& onError = nullptr) { if (onClientReady) { onClientReadyCallbacks.push_back(onClientReady); } @@ -43,17 +45,17 @@ class Hooks { onClientReadyCallbacks.push_back(callback); } - void addOnConfigChanged(const std::function)>& callback) { + void addOnConfigChanged(const std::function)>& callback) { std::lock_guard lock(mutex); onConfigChangedCallbacks.push_back(callback); } - void addOnFlagEvaluated(const std::function& callback) { + void addOnFlagEvaluated(const std::function& callback) { std::lock_guard lock(mutex); onFlagEvaluatedCallbacks.push_back(callback); } - void addOnError(const std::function& callback) { + void addOnError(const std::function& callback) { std::lock_guard lock(mutex); onErrorCallbacks.push_back(callback); } @@ -65,24 +67,24 @@ class Hooks { } } - void invokeOnConfigChanged(std::shared_ptr config) { + void invokeOnConfigChanged(const std::shared_ptr& config) { std::lock_guard lock(mutex); for (auto& callback : onConfigChangedCallbacks) { callback(config); } } - void invokeOnFlagEvaluated(const EvaluationDetails& details) { + void invokeOnFlagEvaluated(const EvaluationDetailsBase& details) { std::lock_guard lock(mutex); for (auto& callback : onFlagEvaluatedCallbacks) { callback(details); } } - void invokeOnError(const std::string& error) { + void invokeOnError(const std::string& message, const std::exception_ptr& exception) { std::lock_guard lock(mutex); for (auto& callback : onErrorCallbacks) { - callback(error); + callback(message, exception); } } @@ -97,9 +99,9 @@ class Hooks { private: std::mutex mutex; std::vector> onClientReadyCallbacks; - std::vector)>> onConfigChangedCallbacks; - std::vector> onFlagEvaluatedCallbacks; - std::vector> onErrorCallbacks; + std::vector)>> onConfigChangedCallbacks; + std::vector> onFlagEvaluatedCallbacks; + std::vector> onErrorCallbacks; }; // Configuration options for ConfigCatClient. diff --git a/Source/ThirdParty/ConfigCatCppSDK/Include/configcatuser.h b/Source/ThirdParty/ConfigCatCppSDK/Include/configcatuser.h index 6da6b0b..92f15a1 100644 --- a/Source/ThirdParty/ConfigCatCppSDK/Include/configcatuser.h +++ b/Source/ThirdParty/ConfigCatCppSDK/Include/configcatuser.h @@ -1,26 +1,101 @@ #pragma once +#include +#include +#include #include #include +#include +#include +#include "timeutils.h" namespace configcat { // An object containing attributes to properly identify a given user for rollout evaluation. class ConfigCatUser { public: + struct AttributeValue : public std::variant> { + private: + using _Base = std::variant>; + public: + AttributeValue(const char* v) : _Base(std::string(v)) {} + // CLang number type conversion to variant fix + AttributeValue(double value) : _Base(value) {} + + // Disable the implicit conversion from pointer to bool: https://stackoverflow.com/a/59372958/8656352 + template + AttributeValue(T*) = delete; + + using _Base::_Base; + using _Base::operator=; + }; + + static constexpr char kIdentifierAttribute[] = "Identifier"; + static constexpr char kEmailAttribute[] = "Email"; + static constexpr char kCountryAttribute[] = "Country"; + + /** + * Creates a new instance of the [ConfigCatUser] class. + * + * Parameter [id]: the unique identifier of the user or session (e.g. email address, primary key, session ID, etc.) + * Parameter [email]: email address of the user. + * Parameter [country]: country of the user. + * Parameter [custom]: custom attributes of the user for advanced targeting rule definitions (e.g. user role, subscription type, etc.) + * + * All comparators support `std::string` values as User Object attribute (in some cases they need to be provided in a specific format though, see below), + * but some of them also support other types of values. It depends on the comparator how the values will be handled. The following rules apply: + * + * **Text-based comparators** (EQUALS, IS ONE OF, etc.) + * * accept `std::string` values, + * * all other values are automatically converted to `std::string` (a warning will be logged but evaluation will continue as normal). + * + * **SemVer-based comparators** (IS ONE OF, <, >=, etc.) + * * accept `std::string` values containing a properly formatted, valid semver value, + * * all other values are considered invalid (a warning will be logged and the currently evaluated targeting rule will be skipped). + * + * **Number-based comparators** (=, <, >=, etc.) + * * accept `double` values, + * * accept `std::string` values containing a properly formatted, valid `double` value, + * * all other values are considered invalid (a warning will be logged and the currently evaluated targeting rule will be skipped). + * + * **Date time-based comparators** (BEFORE / AFTER) + * * accept `configcat::date_time_t` (`std::chrono::system_clock::time_point`) values, + which are automatically converted to a second-based Unix timestamp, + * * accept `double` values representing a second-based Unix timestamp, + * * accept `std::string` values containing a properly formatted, valid `double` value, + * * all other values are considered invalid (a warning will be logged and the currently evaluated targeting rule will be skipped). + * + * **String array-based comparators** (ARRAY CONTAINS ANY OF / ARRAY NOT CONTAINS ANY OF) + * * accept lists of `std::string` (i.e. `std::vector`), + * * accept `std::string` values containing a valid JSON string which can be deserialized to a list of `std::string`, + * * all other values are considered invalid (a warning will be logged and the currently evaluated targeting rule will be skipped). + */ ConfigCatUser(const std::string& id, - const std::string& email = {}, - const std::string& country = {}, - const std::unordered_map& custom = {}); + const std::optional& email = std::nullopt, + const std::optional& country = std::nullopt, + const std::unordered_map& custom = {}) + : identifier(id) + , email(email) + , country(country) + , custom(custom) {} - const std::string* getAttribute(const std::string& key) const; + static inline std::shared_ptr create(const std::string& id, + const std::optional& email = std::nullopt, + const std::optional& country = std::nullopt, + const std::unordered_map& custom = {}) { + return std::make_shared(id, email, country, custom); + } + + inline const std::string& getIdentifier() const { return std::get(identifier); } + inline const ConfigCatUser::AttributeValue& getIdentifierAttribute() const { return identifier; } + const ConfigCatUser::AttributeValue* getAttribute(const std::string& key) const; std::string toJson() const; private: - std::unordered_map attributes; - -public: - const std::string& identifier; + ConfigCatUser::AttributeValue identifier; + std::optional email; + std::optional country; + std::unordered_map custom; }; } // namespace configcat diff --git a/Source/ThirdParty/ConfigCatCppSDK/Include/consolelogger.h b/Source/ThirdParty/ConfigCatCppSDK/Include/consolelogger.h index c779b90..da0f2a6 100644 --- a/Source/ThirdParty/ConfigCatCppSDK/Include/consolelogger.h +++ b/Source/ThirdParty/ConfigCatCppSDK/Include/consolelogger.h @@ -9,8 +9,9 @@ class ConsoleLogger : public ILogger { public: ConsoleLogger(LogLevel logLevel = LOG_LEVEL_WARNING): ILogger(logLevel) {} - void log(LogLevel level, const std::string& message) override { + void log(LogLevel level, const std::string& message, const std::exception_ptr& exception = nullptr) override { printf("[%s]: %s\n", logLevelAsString(level), message.c_str()); + if (exception) printf("Exception details: %s\n", unwrap_exception_message(exception).c_str()); } }; diff --git a/Source/ThirdParty/ConfigCatCppSDK/Include/evaluationdetails.h b/Source/ThirdParty/ConfigCatCppSDK/Include/evaluationdetails.h index bcbc99e..4b6d251 100644 --- a/Source/ThirdParty/ConfigCatCppSDK/Include/evaluationdetails.h +++ b/Source/ThirdParty/ConfigCatCppSDK/Include/evaluationdetails.h @@ -1,49 +1,98 @@ #pragma once -#include -#include #include +#include + #include "config.h" +#include "configcatuser.h" namespace configcat { -class ConfigCatUser; +using fetch_time_t = std::chrono::time_point>; -struct EvaluationDetails { -public: - EvaluationDetails(const std::string& key = "", - const Value& value = {}, - const std::string& variationId = "", - const std::chrono::time_point>& fetchTime = {}, - const ConfigCatUser* user = nullptr, - bool isDefaultValue = false, - const std::string& error = "", - const RolloutRule* matchedEvaluationRule = nullptr, - const RolloutPercentageItem* matchedEvaluationPercentageRule = nullptr) +struct EvaluationDetailsBase { + std::string key; + std::optional variationId; + configcat::fetch_time_t fetchTime; + std::shared_ptr user; + bool isDefaultValue; + std::optional errorMessage; + std::exception_ptr errorException; + std::optional matchedTargetingRule; + std::optional matchedPercentageOption; + + inline std::optional value() const { return getValue(); } + +protected: + EvaluationDetailsBase(const std::string& key = "", + const std::optional& variationId = "", + const configcat::fetch_time_t& fetchTime = {}, + const std::shared_ptr& user = nullptr, + bool isDefaultValue = false, + const std::optional& errorMessage = std::nullopt, + const std::exception_ptr& errorException = nullptr, + const TargetingRule* matchedTargetingRule = nullptr, + const PercentageOption* matchedPercentageOption = nullptr) : key(key) - , value(value) , variationId(variationId) , fetchTime(fetchTime) , user(user) , isDefaultValue(isDefaultValue) - , error(error) - , matchedEvaluationRule(matchedEvaluationRule ? std::optional{*matchedEvaluationRule} : std::nullopt) - , matchedEvaluationPercentageRule(matchedEvaluationPercentageRule ? std::optional{*matchedEvaluationPercentageRule} : std::nullopt) + , errorMessage(errorMessage) + , errorException(errorException) + // Unfortunately, std::optional is not possible (https://stackoverflow.com/a/26862721/8656352). + // We could use std::optional> as a workaround. However, that would take up more space + // than pointers, so we'd rather resort to pointers, as this is ctor is not meant for public use. + , matchedTargetingRule(matchedTargetingRule ? std::optional(*matchedTargetingRule) : std::nullopt) + , matchedPercentageOption(matchedPercentageOption ? std::optional(*matchedPercentageOption) : std::nullopt) {} - static EvaluationDetails fromError(const std::string& key, const Value& value, const std::string& error, const std::string& variationId = {}) { - return EvaluationDetails(key, value, variationId, {}, nullptr, true, error); + virtual ~EvaluationDetailsBase() = default; + + virtual std::optional getValue() const = 0; +}; + +template > +struct EvaluationDetails : public EvaluationDetailsBase { + EvaluationDetails(const std::string& key = "", + const ValueType& value = {}, + const std::optional& variationId = "", + const configcat::fetch_time_t& fetchTime = {}, + const std::shared_ptr& user = nullptr, + bool isDefaultValue = false, + const std::optional& errorMessage = std::nullopt, + const std::exception_ptr& errorException = nullptr, + const TargetingRule* matchedTargetingRule = nullptr, + const PercentageOption* matchedPercentageOption = nullptr) : + EvaluationDetailsBase(key, variationId, fetchTime, user, isDefaultValue, errorMessage, errorException, matchedTargetingRule, matchedPercentageOption), + value(value) { } - std::string key; - Value value; - std::string variationId; - std::chrono::time_point> fetchTime; - const ConfigCatUser* user; - bool isDefaultValue; - std::string error; - std::optional matchedEvaluationRule; - std::optional matchedEvaluationPercentageRule; + static EvaluationDetails fromError(const std::string& key, + const ValueType& defaultValue, + const std::string& errorMessage, + const std::exception_ptr& errorException = nullptr) { + return EvaluationDetails(key, defaultValue, std::nullopt, {}, nullptr, true, errorMessage, errorException); + } + + ValueType value; + +protected: + std::optional getValue() const override { + if constexpr (std::is_same_v>) { + return value; + } else { + return Value(value); + } + } }; +/** Helper function for creating copies of [EvaluationDetailsBase], which is not constructible, thus, not copyable. */ +inline EvaluationDetails<> to_concrete(const EvaluationDetailsBase& details) { + return EvaluationDetails<>(details.key, details.value(), details.variationId, details.fetchTime, + details.user, details.isDefaultValue, details.errorMessage, details.errorException, + details.matchedTargetingRule ? &*details.matchedTargetingRule : nullptr, + details.matchedPercentageOption ? &*details.matchedPercentageOption : nullptr); +} + } // namespace configcat diff --git a/Source/ThirdParty/ConfigCatCppSDK/Include/fileoverridedatasource.h b/Source/ThirdParty/ConfigCatCppSDK/Include/fileoverridedatasource.h index 067fcc1..debde25 100644 --- a/Source/ThirdParty/ConfigCatCppSDK/Include/fileoverridedatasource.h +++ b/Source/ThirdParty/ConfigCatCppSDK/Include/fileoverridedatasource.h @@ -10,7 +10,9 @@ namespace configcat { class FileFlagOverrides : public FlagOverrides { public: FileFlagOverrides(const std::string& filePath, OverrideBehaviour behaviour); - std::shared_ptr createDataSource(std::shared_ptr logger) override; + std::shared_ptr createDataSource(const std::shared_ptr& logger) override; + + inline OverrideBehaviour getBehavior() override { return behaviour; } private: const std::string filePath; @@ -20,10 +22,10 @@ class FileFlagOverrides : public FlagOverrides { class FileOverrideDataSource : public OverrideDataSource { public: - FileOverrideDataSource(const std::string& filePath, OverrideBehaviour behaviour, std::shared_ptr logger); + FileOverrideDataSource(const std::string& filePath, OverrideBehaviour behaviour, const std::shared_ptr& logger); // Gets all the overrides defined in the given source. - const std::shared_ptr getOverrides() override; + std::shared_ptr getOverrides() override; private: void reloadFileContent(); diff --git a/Source/ThirdParty/ConfigCatCppSDK/Include/flagoverrides.h b/Source/ThirdParty/ConfigCatCppSDK/Include/flagoverrides.h index 1265a15..5027780 100644 --- a/Source/ThirdParty/ConfigCatCppSDK/Include/flagoverrides.h +++ b/Source/ThirdParty/ConfigCatCppSDK/Include/flagoverrides.h @@ -25,8 +25,10 @@ enum OverrideBehaviour { // FlagOverrides abstract base class. class FlagOverrides { public: - virtual std::shared_ptr createDataSource(std::shared_ptr logger) = 0; + virtual std::shared_ptr createDataSource(const std::shared_ptr& logger) = 0; virtual ~FlagOverrides() = default; + + virtual OverrideBehaviour getBehavior() = 0; }; } // namespace configcat diff --git a/Source/ThirdParty/ConfigCatCppSDK/Include/httpsessionadapter.h b/Source/ThirdParty/ConfigCatCppSDK/Include/httpsessionadapter.h index 13d0937..1dc8b95 100644 --- a/Source/ThirdParty/ConfigCatCppSDK/Include/httpsessionadapter.h +++ b/Source/ThirdParty/ConfigCatCppSDK/Include/httpsessionadapter.h @@ -6,12 +6,19 @@ namespace configcat { +enum class ResponseErrorCode : int { + OK = 0, + TimedOut = 1, + RequestCancelled = 2, + InternalError = 3 +}; + struct Response { long statusCode = 0; std::string text; std::map header; - bool operationTimedOut = false; + ResponseErrorCode errorCode = ResponseErrorCode::OK; std::string error; }; diff --git a/Source/ThirdParty/ConfigCatCppSDK/Include/keyvalue.h b/Source/ThirdParty/ConfigCatCppSDK/Include/keyvalue.h index ca0231e..0fc0110 100644 --- a/Source/ThirdParty/ConfigCatCppSDK/Include/keyvalue.h +++ b/Source/ThirdParty/ConfigCatCppSDK/Include/keyvalue.h @@ -6,9 +6,14 @@ namespace configcat { struct KeyValue { - KeyValue(const std::string& key, const Value& value): - key(key), - value(value) { + KeyValue(const std::string& key, const Value& value) + : key(key) + , value(value) { + } + + KeyValue(const std::string& key, Value&& value) noexcept + : key(key) + , value(value) { } std::string key; diff --git a/Source/ThirdParty/ConfigCatCppSDK/Include/log.h b/Source/ThirdParty/ConfigCatCppSDK/Include/log.h index a292149..e531618 100644 --- a/Source/ThirdParty/ConfigCatCppSDK/Include/log.h +++ b/Source/ThirdParty/ConfigCatCppSDK/Include/log.h @@ -1,5 +1,7 @@ #pragma once +#include +#include #include #include #include @@ -7,7 +9,6 @@ namespace configcat { class ConfigCatUser; -struct Value; enum LogLevel { LOG_LEVEL_ERROR, @@ -18,10 +19,10 @@ enum LogLevel { inline const char* logLevelAsString(LogLevel level) { static const char* const names[] = { - "Error", - "Warning", - "Info", - "Debug" + "ERROR", + "WARNING", + "INFO", + "DEBUG" }; return (LOG_LEVEL_ERROR <= level && level <= LOG_LEVEL_DEBUG) ? names[level] : ""; } @@ -32,10 +33,22 @@ class ILogger { void setLogLevel(LogLevel logLevel) { maxLogLevel = logLevel; } LogLevel getLogLevel() const { return maxLogLevel; } - virtual void log(LogLevel level, const std::string& message) = 0; + virtual void log(LogLevel level, const std::string& message, const std::exception_ptr& exception = nullptr) = 0; protected: LogLevel maxLogLevel = LOG_LEVEL_WARNING; }; } // namespace configcat + +static inline std::string unwrap_exception_message(const std::exception_ptr& eptr) { + // Based on: https://stackoverflow.com/a/37222762/8656352 + if (eptr) { + try { std::rethrow_exception(eptr); } + catch (const std::exception& ex) { return ex.what(); } + catch (const std::string& ex) { return ex; } + catch (const char* ex) { return ex; } + catch (...) { return ""; } + } + return ""; +} diff --git a/Source/ThirdParty/ConfigCatCppSDK/Include/mapoverridedatasource.h b/Source/ThirdParty/ConfigCatCppSDK/Include/mapoverridedatasource.h index 1d2d5d5..6d55f63 100644 --- a/Source/ThirdParty/ConfigCatCppSDK/Include/mapoverridedatasource.h +++ b/Source/ThirdParty/ConfigCatCppSDK/Include/mapoverridedatasource.h @@ -8,7 +8,9 @@ namespace configcat { class MapFlagOverrides : public FlagOverrides { public: MapFlagOverrides(const std::unordered_map& source, OverrideBehaviour behaviour); - std::shared_ptr createDataSource(std::shared_ptr logger) override; + std::shared_ptr createDataSource(const std::shared_ptr& logger) override; + + inline OverrideBehaviour getBehavior() override { return behaviour; } private: const std::shared_ptr overrides; @@ -17,17 +19,17 @@ class MapFlagOverrides : public FlagOverrides { class MapOverrideDataSource : public OverrideDataSource { public: - MapOverrideDataSource(const std::shared_ptr overrides, + MapOverrideDataSource(const std::shared_ptr& overrides, OverrideBehaviour behaviour): OverrideDataSource(behaviour), overrides(overrides) { } // Gets all the overrides defined in the given source. - const std::shared_ptr getOverrides() override { return overrides; } + std::shared_ptr getOverrides() override { return overrides; } private: - const std::shared_ptr overrides; + std::shared_ptr overrides; }; } // namespace configcat diff --git a/Source/ThirdParty/ConfigCatCppSDK/Include/overridedatasource.h b/Source/ThirdParty/ConfigCatCppSDK/Include/overridedatasource.h index 7220e58..5d130ad 100644 --- a/Source/ThirdParty/ConfigCatCppSDK/Include/overridedatasource.h +++ b/Source/ThirdParty/ConfigCatCppSDK/Include/overridedatasource.h @@ -17,7 +17,7 @@ class OverrideDataSource { OverrideBehaviour getBehaviour() const { return behaviour; } // Gets all the overrides defined in the given source. - virtual const std::shared_ptr getOverrides() = 0; + virtual std::shared_ptr getOverrides() = 0; private: OverrideBehaviour behaviour; diff --git a/Source/ThirdParty/ConfigCatCppSDK/Include/pollingmode.h b/Source/ThirdParty/ConfigCatCppSDK/Include/pollingmode.h index f6f1fc0..a8663c0 100644 --- a/Source/ThirdParty/ConfigCatCppSDK/Include/pollingmode.h +++ b/Source/ThirdParty/ConfigCatCppSDK/Include/pollingmode.h @@ -7,9 +7,7 @@ namespace configcat { -class RefreshPolicy; class ConfigFetcher; -class ConfigJsonCache; // The base class of a polling mode configuration. class PollingMode { diff --git a/Source/ThirdParty/ConfigCatCppSDK/Include/refreshresult.h b/Source/ThirdParty/ConfigCatCppSDK/Include/refreshresult.h index f2809a5..2370e37 100644 --- a/Source/ThirdParty/ConfigCatCppSDK/Include/refreshresult.h +++ b/Source/ThirdParty/ConfigCatCppSDK/Include/refreshresult.h @@ -1,12 +1,15 @@ #pragma once +#include +#include #include namespace configcat { struct RefreshResult { - bool success = false; - std::string error; + inline bool success() { return !errorMessage; }; + std::optional errorMessage; + std::exception_ptr errorException; }; } // namespace configcat diff --git a/Source/ThirdParty/ConfigCatCppSDK/Include/settingresult.h b/Source/ThirdParty/ConfigCatCppSDK/Include/settingresult.h deleted file mode 100644 index 288c339..0000000 --- a/Source/ThirdParty/ConfigCatCppSDK/Include/settingresult.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include "config.h" - -namespace configcat { - -struct SettingResult { - const std::shared_ptr settings; - double fetchTime; -}; - -} // namespace configcat diff --git a/Source/ThirdParty/ConfigCatCppSDK/Include/timeutils.h b/Source/ThirdParty/ConfigCatCppSDK/Include/timeutils.h new file mode 100644 index 0000000..834662a --- /dev/null +++ b/Source/ThirdParty/ConfigCatCppSDK/Include/timeutils.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace configcat { + +using date_time_t = std::chrono::system_clock::time_point; + +std::string datetime_to_isostring(const date_time_t& tp); +date_time_t make_datetime(int year, int month, int day, int hour, int min, int sec, int millisec = 0); + +} // namespace configcat