From a7a6f40d022005a555a63982b26fa6c2ed1587ac Mon Sep 17 00:00:00 2001 From: Corey Date: Wed, 28 Apr 2021 15:52:22 -0400 Subject: [PATCH] New Feature: Health Check (#134) * New Feature: Health Check * Fix test for linux comparison * Simplify error check for linux * Remove debugDescription in ParseHealth --- CHANGELOG.md | 8 +- .../Contents.swift | 3 + ParseSwift.podspec | 2 +- ParseSwift.xcodeproj/project.pbxproj | 52 ++++++-- Scripts/jazzy.sh | 2 +- Sources/ParseSwift/API/API.swift | 3 + Sources/ParseSwift/API/Responses.swift | 5 + Sources/ParseSwift/Objects/ParseUser.swift | 2 +- Sources/ParseSwift/ParseConstants.swift | 2 +- .../ParseSwift/Types/ParseCloud+combine.swift | 2 +- Sources/ParseSwift/Types/ParseCloud.swift | 8 +- .../Types/ParseConfig+combine.swift | 2 +- Sources/ParseSwift/Types/ParseConfig.swift | 4 +- .../Types/ParseHealth+Combine.swift | 31 +++++ Sources/ParseSwift/Types/ParseHealth.swift | 50 ++++++++ .../ParseHealthCombineTests.swift | 74 +++++++++++ Tests/ParseSwiftTests/ParseHealthTests.swift | 121 ++++++++++++++++++ 17 files changed, 350 insertions(+), 21 deletions(-) create mode 100644 Sources/ParseSwift/Types/ParseHealth+Combine.swift create mode 100644 Sources/ParseSwift/Types/ParseHealth.swift create mode 100644 Tests/ParseSwiftTests/ParseHealthCombineTests.swift create mode 100644 Tests/ParseSwiftTests/ParseHealthTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b610baa8..4bfc1583a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,15 @@ # Parse-Swift Changelog ### main -[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/1.7.0...main) +[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/1.7.1...main) * _Contributing to this repo? Add info about your change here to be included in the next release_ +### 1.7.1 +[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/1.7.0...1.7.1) + +__New features__ +- Can now check the health of a Parse Server using ParseHealth. ([#134](https://github.com/parse-community/Parse-Swift/pull/134)), thanks to [Corey Baker](https://github.com/cbaker6). + ### 1.7.0 [Full Changelog](https://github.com/parse-community/Parse-Swift/compare/1.6.0...1.7.0) diff --git a/ParseSwift.playground/Pages/1 - Your first Object.xcplaygroundpage/Contents.swift b/ParseSwift.playground/Pages/1 - Your first Object.xcplaygroundpage/Contents.swift index 87949c2a7..3c1fd5b95 100644 --- a/ParseSwift.playground/Pages/1 - Your first Object.xcplaygroundpage/Contents.swift +++ b/ParseSwift.playground/Pages/1 - Your first Object.xcplaygroundpage/Contents.swift @@ -18,6 +18,9 @@ npm start -- --appId applicationId --clientKey clientKey --masterKey masterKey - initializeParse() +//: Check the health of your Parse Server. +print(try ParseHealth.check()) + //: Create your own value typed `ParseObject`. struct GameScore: ParseObject { //: Those are required for Object diff --git a/ParseSwift.podspec b/ParseSwift.podspec index e0b716c61..a008059ae 100644 --- a/ParseSwift.podspec +++ b/ParseSwift.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "ParseSwift" - s.version = "1.7.0" + s.version = "1.7.1" s.summary = "Parse Pure Swift SDK" s.homepage = "https://github.com/parse-community/Parse-Swift" s.authors = { diff --git a/ParseSwift.xcodeproj/project.pbxproj b/ParseSwift.xcodeproj/project.pbxproj index c90092d6f..e861890ea 100644 --- a/ParseSwift.xcodeproj/project.pbxproj +++ b/ParseSwift.xcodeproj/project.pbxproj @@ -321,6 +321,20 @@ 70F2E2C0254F283000B2EA5C /* MockURLResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 911DB12B24C3F7720027F3C7 /* MockURLResponse.swift */; }; 70F2E2C1254F283000B2EA5C /* AnyCodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FFF552C2217E729007C3B4E /* AnyCodableTests.swift */; }; 70F2E2C2254F283000B2EA5C /* APICommandTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 911DB12D24C4837E0027F3C7 /* APICommandTests.swift */; }; + 70F79A192639CE6F00731C46 /* ParseHealth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70F79A182639CE6F00731C46 /* ParseHealth.swift */; }; + 70F79A1A2639CE6F00731C46 /* ParseHealth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70F79A182639CE6F00731C46 /* ParseHealth.swift */; }; + 70F79A1B2639CE6F00731C46 /* ParseHealth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70F79A182639CE6F00731C46 /* ParseHealth.swift */; }; + 70F79A1C2639CE6F00731C46 /* ParseHealth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70F79A182639CE6F00731C46 /* ParseHealth.swift */; }; + 70F79A272639D84600731C46 /* ParseHealth+Combine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70F79A262639D84600731C46 /* ParseHealth+Combine.swift */; }; + 70F79A282639D84600731C46 /* ParseHealth+Combine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70F79A262639D84600731C46 /* ParseHealth+Combine.swift */; }; + 70F79A292639D84600731C46 /* ParseHealth+Combine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70F79A262639D84600731C46 /* ParseHealth+Combine.swift */; }; + 70F79A2A2639D84600731C46 /* ParseHealth+Combine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70F79A262639D84600731C46 /* ParseHealth+Combine.swift */; }; + 70F79A672639DE9700731C46 /* ParseHealthCombineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70F79A662639DE9700731C46 /* ParseHealthCombineTests.swift */; }; + 70F79A682639DE9700731C46 /* ParseHealthCombineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70F79A662639DE9700731C46 /* ParseHealthCombineTests.swift */; }; + 70F79A692639DE9700731C46 /* ParseHealthCombineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70F79A662639DE9700731C46 /* ParseHealthCombineTests.swift */; }; + 70F79A732639DEA000731C46 /* ParseHealthTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70F79A4F2639DE6900731C46 /* ParseHealthTests.swift */; }; + 70F79A7D2639DEA100731C46 /* ParseHealthTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70F79A4F2639DE6900731C46 /* ParseHealthTests.swift */; }; + 70F79A872639DEA200731C46 /* ParseHealthTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70F79A4F2639DE6900731C46 /* ParseHealthTests.swift */; }; 7FFF552E2217E72A007C3B4E /* AnyEncodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FFF552B2217E729007C3B4E /* AnyEncodableTests.swift */; }; 7FFF552F2217E72A007C3B4E /* AnyCodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FFF552C2217E729007C3B4E /* AnyCodableTests.swift */; }; 7FFF55302217E72A007C3B4E /* AnyDecodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FFF552D2217E729007C3B4E /* AnyDecodableTests.swift */; }; @@ -647,6 +661,10 @@ 70F2E23E254F246000B2EA5C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 70F2E250254F247000B2EA5C /* ParseSwiftTestsmacOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ParseSwiftTestsmacOS.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 70F2E254254F247000B2EA5C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 70F79A182639CE6F00731C46 /* ParseHealth.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseHealth.swift; sourceTree = ""; }; + 70F79A262639D84600731C46 /* ParseHealth+Combine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ParseHealth+Combine.swift"; sourceTree = ""; }; + 70F79A4F2639DE6900731C46 /* ParseHealthTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseHealthTests.swift; sourceTree = ""; }; + 70F79A662639DE9700731C46 /* ParseHealthCombineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseHealthCombineTests.swift; sourceTree = ""; }; 7FFF552B2217E729007C3B4E /* AnyEncodableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnyEncodableTests.swift; sourceTree = ""; }; 7FFF552C2217E729007C3B4E /* AnyCodableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnyCodableTests.swift; sourceTree = ""; }; 7FFF552D2217E729007C3B4E /* AnyDecodableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnyDecodableTests.swift; sourceTree = ""; }; @@ -839,6 +857,8 @@ 705A99F8259807F900B3547F /* ParseFileManagerTests.swift */, 705727882593FF8000F0ADD5 /* ParseFileTests.swift */, 70BC0B32251903D1001556DB /* ParseGeoPointTests.swift */, + 70F79A662639DE9700731C46 /* ParseHealthCombineTests.swift */, + 70F79A4F2639DE6900731C46 /* ParseHealthTests.swift */, 7044C1BA25C52E410011F6E7 /* ParseInstallationCombineTests.swift */, 70110D5B2506ED0E0091CC1D /* ParseInstallationTests.swift */, 70386A5B25D9A4010048EC1B /* ParseLDAPCombineTests.swift */, @@ -1127,6 +1147,8 @@ children = ( F97B45C024D9C6F200F4A88B /* ParseACL.swift */, 916786E1259B7DDA00BB5B4E /* ParseCloud.swift */, + 70F79A182639CE6F00731C46 /* ParseHealth.swift */, + 70F79A262639D84600731C46 /* ParseHealth+Combine.swift */, 7044C17425C4ECFF0011F6E7 /* ParseCloud+combine.swift */, 70D1BDB925BB17A600A42E7C /* ParseConfig.swift */, 7044C18225C4EFC10011F6E7 /* ParseConfig+combine.swift */, @@ -1609,12 +1631,14 @@ 70D1BDBA25BB17A600A42E7C /* ParseConfig.swift in Sources */, F97B465224D9C78C00F4A88B /* AddUnique.swift in Sources */, F97B45D624D9C6F200F4A88B /* ParseEncoder.swift in Sources */, + 70F79A272639D84600731C46 /* ParseHealth+Combine.swift in Sources */, 700395A325A119430052CB31 /* Operations.swift in Sources */, 70386A3825D998D90048EC1B /* ParseLDAP.swift in Sources */, 700395F225A171320052CB31 /* LiveQueryable.swift in Sources */, F97B45F224D9C6F200F4A88B /* Pointer.swift in Sources */, 70510AAC259EE25E00FEA700 /* LiveQuerySocket.swift in Sources */, 7044C19125C4F5B60011F6E7 /* ParseFile+combine.swift in Sources */, + 70F79A192639CE6F00731C46 /* ParseHealth.swift in Sources */, 7044C19F25C4FA870011F6E7 /* ParseOperation+combine.swift in Sources */, F97B461E24D9C6F200F4A88B /* ParseStorage.swift in Sources */, 7044C1AD25C4FC080011F6E7 /* Query+combine.swift in Sources */, @@ -1695,6 +1719,7 @@ 70DFEA8A2618E77800F8EB4B /* InitializeSDKTests.swift in Sources */, 7044C1DF25C5C70D0011F6E7 /* ParseObjectCombine.swift in Sources */, 89899D9F26045998002E2043 /* ParseTwitterCombineTests.swift in Sources */, + 70F79A672639DE9700731C46 /* ParseHealthCombineTests.swift in Sources */, 70C5504625B40D5200B5DBC2 /* ParseSessionTests.swift in Sources */, 70110D5C2506ED0E0091CC1D /* ParseInstallationTests.swift in Sources */, 7016ED4025C4A25A00038648 /* ParseUserCombineTests.swift in Sources */, @@ -1722,6 +1747,7 @@ 89899DB526045DC4002E2043 /* ParseFacebookCombineTests.swift in Sources */, F971F4F624DE381A006CB79B /* ParseEncoderExtraTests.swift in Sources */, 70C7DC2124D20F190050419B /* ParseQueryTests.swift in Sources */, + 70F79A732639DEA000731C46 /* ParseHealthTests.swift in Sources */, 7044C22D25C5E4E90011F6E7 /* ParseAnonymousCombineTests.swift in Sources */, 9194657824F16E330070296B /* ParseACLTests.swift in Sources */, 7044C21325C5DE490011F6E7 /* ParseCloudCombineTests.swift in Sources */, @@ -1754,12 +1780,14 @@ 70D1BDBB25BB17A600A42E7C /* ParseConfig.swift in Sources */, F97B465324D9C78C00F4A88B /* AddUnique.swift in Sources */, F97B45D724D9C6F200F4A88B /* ParseEncoder.swift in Sources */, + 70F79A282639D84600731C46 /* ParseHealth+Combine.swift in Sources */, 700395A425A119430052CB31 /* Operations.swift in Sources */, 70386A3925D998D90048EC1B /* ParseLDAP.swift in Sources */, 700395F325A171320052CB31 /* LiveQueryable.swift in Sources */, F97B45F324D9C6F200F4A88B /* Pointer.swift in Sources */, 70510AAD259EE25E00FEA700 /* LiveQuerySocket.swift in Sources */, 7044C19225C4F5B60011F6E7 /* ParseFile+combine.swift in Sources */, + 70F79A1A2639CE6F00731C46 /* ParseHealth.swift in Sources */, 7044C1A025C4FA870011F6E7 /* ParseOperation+combine.swift in Sources */, F97B461F24D9C6F200F4A88B /* ParseStorage.swift in Sources */, 7044C1AE25C4FC080011F6E7 /* Query+combine.swift in Sources */, @@ -1849,6 +1877,7 @@ 70DFEA8C2618E77800F8EB4B /* InitializeSDKTests.swift in Sources */, 7044C1E125C5C70D0011F6E7 /* ParseObjectCombine.swift in Sources */, 89899DA126045998002E2043 /* ParseTwitterCombineTests.swift in Sources */, + 70F79A692639DE9700731C46 /* ParseHealthCombineTests.swift in Sources */, 70C5504825B40D5200B5DBC2 /* ParseSessionTests.swift in Sources */, 709B98572556ECAA00507778 /* ParseACLTests.swift in Sources */, 7016ED4225C4A25A00038648 /* ParseUserCombineTests.swift in Sources */, @@ -1876,6 +1905,7 @@ 89899DB726045DC4002E2043 /* ParseFacebookCombineTests.swift in Sources */, 709B98502556ECAA00507778 /* KeychainStoreTests.swift in Sources */, 709B98562556ECAA00507778 /* ParseObjectTests.swift in Sources */, + 70F79A872639DEA200731C46 /* ParseHealthTests.swift in Sources */, 7044C22F25C5E4E90011F6E7 /* ParseAnonymousCombineTests.swift in Sources */, 709B985A2556ECAA00507778 /* ParseObjectBatchTests.swift in Sources */, 7044C21525C5DE490011F6E7 /* ParseCloudCombineTests.swift in Sources */, @@ -1906,6 +1936,7 @@ 70DFEA8B2618E77800F8EB4B /* InitializeSDKTests.swift in Sources */, 7044C1E025C5C70D0011F6E7 /* ParseObjectCombine.swift in Sources */, 89899DA026045998002E2043 /* ParseTwitterCombineTests.swift in Sources */, + 70F79A682639DE9700731C46 /* ParseHealthCombineTests.swift in Sources */, 70C5504725B40D5200B5DBC2 /* ParseSessionTests.swift in Sources */, 70F2E2BC254F283000B2EA5C /* ParseObjectTests.swift in Sources */, 7016ED4125C4A25A00038648 /* ParseUserCombineTests.swift in Sources */, @@ -1933,6 +1964,7 @@ 89899DB626045DC4002E2043 /* ParseFacebookCombineTests.swift in Sources */, 70F2E2BB254F283000B2EA5C /* ParseGeoPointTests.swift in Sources */, 70F2E2B8254F283000B2EA5C /* AnyEncodableTests.swift in Sources */, + 70F79A7D2639DEA100731C46 /* ParseHealthTests.swift in Sources */, 7044C22E25C5E4E90011F6E7 /* ParseAnonymousCombineTests.swift in Sources */, 70F2E2B4254F283000B2EA5C /* ParseQueryTests.swift in Sources */, 7044C21425C5DE490011F6E7 /* ParseCloudCombineTests.swift in Sources */, @@ -1965,12 +1997,14 @@ 70D1BDBD25BB17A600A42E7C /* ParseConfig.swift in Sources */, F97B45E524D9C6F200F4A88B /* AnyEncodable.swift in Sources */, F97B465D24D9C78C00F4A88B /* Increment.swift in Sources */, + 70F79A2A2639D84600731C46 /* ParseHealth+Combine.swift in Sources */, 700395A625A119430052CB31 /* Operations.swift in Sources */, 70386A3B25D998D90048EC1B /* ParseLDAP.swift in Sources */, 700395F525A171320052CB31 /* LiveQueryable.swift in Sources */, F97B45FD24D9C6F200F4A88B /* ParseACL.swift in Sources */, 70510AAF259EE25E00FEA700 /* LiveQuerySocket.swift in Sources */, 7044C19425C4F5B60011F6E7 /* ParseFile+combine.swift in Sources */, + 70F79A1C2639CE6F00731C46 /* ParseHealth.swift in Sources */, 7044C1A225C4FA870011F6E7 /* ParseOperation+combine.swift in Sources */, F97B465124D9C78C00F4A88B /* Add.swift in Sources */, 7044C1B025C4FC080011F6E7 /* Query+combine.swift in Sources */, @@ -2053,12 +2087,14 @@ 70D1BDBC25BB17A600A42E7C /* ParseConfig.swift in Sources */, F97B45E424D9C6F200F4A88B /* AnyEncodable.swift in Sources */, F97B465C24D9C78C00F4A88B /* Increment.swift in Sources */, + 70F79A292639D84600731C46 /* ParseHealth+Combine.swift in Sources */, 700395A525A119430052CB31 /* Operations.swift in Sources */, 70386A3A25D998D90048EC1B /* ParseLDAP.swift in Sources */, 700395F425A171320052CB31 /* LiveQueryable.swift in Sources */, F97B45FC24D9C6F200F4A88B /* ParseACL.swift in Sources */, 70510AAE259EE25E00FEA700 /* LiveQuerySocket.swift in Sources */, 7044C19325C4F5B60011F6E7 /* ParseFile+combine.swift in Sources */, + 70F79A1B2639CE6F00731C46 /* ParseHealth.swift in Sources */, 7044C1A125C4FA870011F6E7 /* ParseOperation+combine.swift in Sources */, F97B465024D9C78B00F4A88B /* Add.swift in Sources */, 7044C1AF25C4FC080011F6E7 /* Query+combine.swift in Sources */, @@ -2353,7 +2389,7 @@ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MARKETING_VERSION = 1.7.0; + MARKETING_VERSION = 1.7.1; PRODUCT_BUNDLE_IDENTIFIER = com.parse.ParseSwift; PRODUCT_NAME = ParseSwift; SKIP_INSTALL = YES; @@ -2377,7 +2413,7 @@ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MARKETING_VERSION = 1.7.0; + MARKETING_VERSION = 1.7.1; PRODUCT_BUNDLE_IDENTIFIER = com.parse.ParseSwift; PRODUCT_NAME = ParseSwift; SKIP_INSTALL = YES; @@ -2443,7 +2479,7 @@ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.13; - MARKETING_VERSION = 1.7.0; + MARKETING_VERSION = 1.7.1; PRODUCT_BUNDLE_IDENTIFIER = com.parse.ParseSwift; PRODUCT_NAME = ParseSwift; SDKROOT = macosx; @@ -2469,7 +2505,7 @@ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.13; - MARKETING_VERSION = 1.7.0; + MARKETING_VERSION = 1.7.1; PRODUCT_BUNDLE_IDENTIFIER = com.parse.ParseSwift; PRODUCT_NAME = ParseSwift; SDKROOT = macosx; @@ -2616,7 +2652,7 @@ INFOPLIST_FILE = "ParseSwift-watchOS/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MARKETING_VERSION = 1.7.0; + MARKETING_VERSION = 1.7.1; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "com.parse.ParseSwift-watchOS"; @@ -2645,7 +2681,7 @@ INFOPLIST_FILE = "ParseSwift-watchOS/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MARKETING_VERSION = 1.7.0; + MARKETING_VERSION = 1.7.1; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "com.parse.ParseSwift-watchOS"; PRODUCT_NAME = ParseSwift; @@ -2672,7 +2708,7 @@ INFOPLIST_FILE = "ParseSwift-tvOS/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MARKETING_VERSION = 1.7.0; + MARKETING_VERSION = 1.7.1; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "com.parse.ParseSwift-tvOS"; @@ -2700,7 +2736,7 @@ INFOPLIST_FILE = "ParseSwift-tvOS/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MARKETING_VERSION = 1.7.0; + MARKETING_VERSION = 1.7.1; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "com.parse.ParseSwift-tvOS"; PRODUCT_NAME = ParseSwift; diff --git a/Scripts/jazzy.sh b/Scripts/jazzy.sh index ee1d90d99..463185f2d 100755 --- a/Scripts/jazzy.sh +++ b/Scripts/jazzy.sh @@ -5,7 +5,7 @@ bundle exec jazzy \ --author_url http://parseplatform.org \ --github_url https://github.com/parse-community/Parse-Swift \ --root-url http://parseplatform.org/Parse-Swift/api/ \ - --module-version 1.7.0 \ + --module-version 1.7.1 \ --theme fullwidth \ --skip-undocumented \ --output ./docs/api \ diff --git a/Sources/ParseSwift/API/API.swift b/Sources/ParseSwift/API/API.swift index 030c2a539..370e88f09 100644 --- a/Sources/ParseSwift/API/API.swift +++ b/Sources/ParseSwift/API/API.swift @@ -36,6 +36,7 @@ public struct API { case jobs(name: String) case aggregate(className: String) case config + case health case any(String) var urlComponent: String { @@ -80,6 +81,8 @@ public struct API { return "/aggregate/\(className)" case .config: return "/config" + case .health: + return "/health" case .any(let path): return path } diff --git a/Sources/ParseSwift/API/Responses.swift b/Sources/ParseSwift/API/Responses.swift index a81c3fd1c..820571337 100644 --- a/Sources/ParseSwift/API/Responses.swift +++ b/Sources/ParseSwift/API/Responses.swift @@ -124,3 +124,8 @@ internal struct ConfigFetchResponse: Codable where T: ParseConfig { internal struct ConfigUpdateResponse: Codable { let result: Bool } + +// MARK: HealthResponse +internal struct HealthResponse: Codable { + let status: String +} diff --git a/Sources/ParseSwift/Objects/ParseUser.swift b/Sources/ParseSwift/Objects/ParseUser.swift index e7cc107ea..6457fc718 100644 --- a/Sources/ParseSwift/Objects/ParseUser.swift +++ b/Sources/ParseSwift/Objects/ParseUser.swift @@ -331,7 +331,7 @@ extension ParseUser { unless your code is already running from a background thread. - parameter options: A set of header options sent to the server. Defaults to an empty set. - parameter callbackQueue: The queue to return to after completion. Default value of .main. - - parameter completion: A block that will be called when logging out, completes or fails. + - parameter completion: A block that will be called when logging out completes or fails. */ public static func logout(options: API.Options = [], callbackQueue: DispatchQueue = .main, completion: @escaping (Result) -> Void) { diff --git a/Sources/ParseSwift/ParseConstants.swift b/Sources/ParseSwift/ParseConstants.swift index 6d14aa82a..0e630132b 100644 --- a/Sources/ParseSwift/ParseConstants.swift +++ b/Sources/ParseSwift/ParseConstants.swift @@ -9,7 +9,7 @@ import Foundation enum ParseConstants { - static let parseVersion = "1.7.0" + static let parseVersion = "1.7.1" static let hashingKey = "parseSwift" static let fileManagementDirectory = "parse/" static let fileManagementPrivateDocumentsDirectory = "Private Documents/" diff --git a/Sources/ParseSwift/Types/ParseCloud+combine.swift b/Sources/ParseSwift/Types/ParseCloud+combine.swift index 07f4b4402..528cb992a 100644 --- a/Sources/ParseSwift/Types/ParseCloud+combine.swift +++ b/Sources/ParseSwift/Types/ParseCloud+combine.swift @@ -32,7 +32,7 @@ public extension ParseCloud { // MARK: Jobs - Combine /** - Starts a Cloud Code job *asynchronously* and returns a result with the jobStatusId of the job. + Starts a Cloud Code Job *asynchronously* and returns a result with the jobStatusId of the job. Publishes when complete. - parameter options: A set of header options sent to the server. Defaults to an empty set. - returns: A publisher that eventually produces a single value and then finishes or fails. diff --git a/Sources/ParseSwift/Types/ParseCloud.swift b/Sources/ParseSwift/Types/ParseCloud.swift index 078057bd3..963472781 100644 --- a/Sources/ParseSwift/Types/ParseCloud.swift +++ b/Sources/ParseSwift/Types/ParseCloud.swift @@ -42,7 +42,7 @@ extension ParseCloud { Calls a Cloud Code function *asynchronously* and returns a result of it's execution. - parameter options: A set of header options sent to the server. Defaults to an empty set. - parameter callbackQueue: The queue to return to after completion. Default value of .main. - - parameter completion: A block that will be called when logging out, completes or fails. + - parameter completion: A block that will be called when the Cloud Code completes or fails. It should have the following argument signature: `(Result)`. */ public func runFunction(options: API.Options = [], @@ -70,7 +70,7 @@ extension ParseCloud { // MARK: Jobs extension ParseCloud { /** - Starts a Cloud Code job *synchronously* and returns a result with the jobStatusId of the job. + Starts a Cloud Code Job *synchronously* and returns a result with the jobStatusId of the job. - parameter options: A set of header options sent to the server. Defaults to an empty set. - returns: Returns a `Decodable` type. */ @@ -79,10 +79,10 @@ extension ParseCloud { } /** - Starts a Cloud Code job *asynchronously* and returns a result with the jobStatusId of the job. + Starts a Cloud Code Job *asynchronously* and returns a result with the jobStatusId of the job. - parameter options: A set of header options sent to the server. Defaults to an empty set. - parameter callbackQueue: The queue to return to after completion. Default value of .main. - - parameter completion: A block that will be called when logging out, completes or fails. + - parameter completion: A block that will be called when the Cloud Code Job completes or fails. It should have the following argument signature: `(Result)`. */ public func startJob(options: API.Options = [], diff --git a/Sources/ParseSwift/Types/ParseConfig+combine.swift b/Sources/ParseSwift/Types/ParseConfig+combine.swift index 13ea16656..4cf219c8a 100644 --- a/Sources/ParseSwift/Types/ParseConfig+combine.swift +++ b/Sources/ParseSwift/Types/ParseConfig+combine.swift @@ -17,7 +17,7 @@ public extension ParseConfig { // MARK: Fetchable - Combine /** - Fetch the Config *asynchronously*. + Fetch the Config *asynchronously*. Publishes when complete. - parameter options: A set of header options sent to the server. Defaults to an empty set. - returns: A publisher that eventually produces a single value and then finishes or fails. */ diff --git a/Sources/ParseSwift/Types/ParseConfig.swift b/Sources/ParseSwift/Types/ParseConfig.swift index cd687ac3b..128efa51c 100644 --- a/Sources/ParseSwift/Types/ParseConfig.swift +++ b/Sources/ParseSwift/Types/ParseConfig.swift @@ -32,7 +32,7 @@ extension ParseConfig { Fetch the Config *asynchronously*. - parameter options: A set of header options sent to the server. Defaults to an empty set. - parameter callbackQueue: The queue to return to after completion. Default value of .main. - - parameter completion: A block that will be called when logging out, completes or fails. + - parameter completion: A block that will be called when retrieving the config completes or fails. It should have the following argument signature: `(Result)`. */ public func fetch(options: API.Options = [], @@ -73,7 +73,7 @@ extension ParseConfig { Update the Config *asynchronously*. - parameter options: A set of header options sent to the server. Defaults to an empty set. - parameter callbackQueue: The queue to return to after completion. Default value of .main. - - parameter completion: A block that will be called when logging out, completes or fails. + - parameter completion: A block that will be called when retrieving the config completes or fails. It should have the following argument signature: `(Result)`. */ public func save(options: API.Options = [], diff --git a/Sources/ParseSwift/Types/ParseHealth+Combine.swift b/Sources/ParseSwift/Types/ParseHealth+Combine.swift new file mode 100644 index 000000000..6017efe2b --- /dev/null +++ b/Sources/ParseSwift/Types/ParseHealth+Combine.swift @@ -0,0 +1,31 @@ +// +// ParseHealth+Combine.swift +// ParseSwift +// +// Created by Corey Baker on 4/28/21. +// Copyright © 2021 Parse Community. All rights reserved. +// + +#if canImport(Combine) +import Foundation +import Combine + +// MARK: Combine +@available(macOS 10.15, iOS 13.0, macCatalyst 13.0, watchOS 6.0, tvOS 13.0, *) +public extension ParseHealth { + + // MARK: Check - Combine + + /** + Calls the health check function *asynchronously*. Publishes when complete. + - parameter options: A set of header options sent to the server. Defaults to an empty set. + - returns: A publisher that eventually produces a single value and then finishes or fails. + */ + static func checkPublisher(options: API.Options = []) -> Future { + Future { promise in + Self.check(options: options, + completion: promise) + } + } +} +#endif diff --git a/Sources/ParseSwift/Types/ParseHealth.swift b/Sources/ParseSwift/Types/ParseHealth.swift new file mode 100644 index 000000000..5ac3c2dd4 --- /dev/null +++ b/Sources/ParseSwift/Types/ParseHealth.swift @@ -0,0 +1,50 @@ +// +// ParseHealth.swift +// ParseSwift +// +// Created by Corey Baker on 4/28/21. +// Copyright © 2021 Parse Community. All rights reserved. +// + +import Foundation + +/** + `ParseHealth` allows you to check the health of a Parse Server. + */ +public struct ParseHealth: ParseType, Decodable { + + /** + Calls the health check function *synchronously* and returns a result of it's execution. + - parameter options: A set of header options sent to the server. Defaults to an empty set. + - returns: Returns the status of the server. + - throws: An error of type `ParseError`. + */ + static public func check(options: API.Options = []) throws -> String { + try healthCommand().execute(options: options) + } + + /** + Calls the health check function *asynchronously* and returns a result of it's execution. + - parameter options: A set of header options sent to the server. Defaults to an empty set. + - parameter callbackQueue: The queue to return to after completion. Default value of .main. + - parameter completion: A block that will be called when the health check completes or fails. + It should have the following argument signature: `(Result)`. + */ + static public func check(options: API.Options = [], + callbackQueue: DispatchQueue = .main, + completion: @escaping (Result) -> Void) { + healthCommand() + .executeAsync(options: options) { result in + callbackQueue.async { + completion(result) + } + } + } + + internal static func healthCommand() -> API.NonParseBodyCommand { + return API.NonParseBodyCommand(method: .POST, + path: .health) { (data) -> String in + return try ParseCoding.jsonDecoder().decode(HealthResponse.self, from: data).status + } + } +} diff --git a/Tests/ParseSwiftTests/ParseHealthCombineTests.swift b/Tests/ParseSwiftTests/ParseHealthCombineTests.swift new file mode 100644 index 000000000..1d3a5ca0e --- /dev/null +++ b/Tests/ParseSwiftTests/ParseHealthCombineTests.swift @@ -0,0 +1,74 @@ +// +// ParseHealthCombineTests.swift +// ParseSwift +// +// Created by Corey Baker on 4/28/21. +// Copyright © 2021 Parse Community. All rights reserved. +// + +#if canImport(Combine) + +import Foundation +import XCTest +import Combine +@testable import ParseSwift + +@available(macOS 10.15, iOS 13.0, macCatalyst 13.0, watchOS 6.0, tvOS 13.0, *) +class ParseHealthCombineTests: XCTestCase { + override func setUpWithError() throws { + try super.setUpWithError() + guard let url = URL(string: "http://localhost:1337/1") else { + XCTFail("Should create valid URL") + return + } + ParseSwift.initialize(applicationId: "applicationId", + clientKey: "clientKey", + masterKey: "masterKey", + serverURL: url, + testing: true) + } + + override func tearDownWithError() throws { + try super.tearDownWithError() + MockURLProtocol.removeAll() + #if !os(Linux) && !os(Android) + try KeychainStore.shared.deleteAll() + #endif + try ParseStorage.shared.deleteAll() + } + + func testCheck() { + var subscriptions = Set() + let expectation1 = XCTestExpectation(description: "Save") + + let healthOfServer = "ok" + let serverResponse = HealthResponse(status: healthOfServer) + let encoded: Data! + do { + encoded = try ParseCoding.jsonEncoder().encode(serverResponse) + } catch { + XCTFail("Should encode/decode. Error \(error)") + return + } + + MockURLProtocol.mockRequests { _ in + return MockURLResponse(data: encoded, statusCode: 200, delay: 0.0) + } + + let publisher = ParseHealth.checkPublisher() + .sink(receiveCompletion: { result in + + if case let .failure(error) = result { + XCTFail(error.localizedDescription) + } + expectation1.fulfill() + + }, receiveValue: { health in + XCTAssertEqual(health, healthOfServer) + }) + publisher.store(in: &subscriptions) + + wait(for: [expectation1], timeout: 20.0) + } +} +#endif diff --git a/Tests/ParseSwiftTests/ParseHealthTests.swift b/Tests/ParseSwiftTests/ParseHealthTests.swift new file mode 100644 index 000000000..2aa6cd99a --- /dev/null +++ b/Tests/ParseSwiftTests/ParseHealthTests.swift @@ -0,0 +1,121 @@ +// +// ParseHealthTests.swift +// ParseSwift +// +// Created by Corey Baker on 4/28/21. +// Copyright © 2021 Parse Community. All rights reserved. +// + +import Foundation +import XCTest +@testable import ParseSwift + +class ParseHealthTests: XCTestCase { + + override func setUpWithError() throws { + try super.setUpWithError() + guard let url = URL(string: "http://localhost:1337/1") else { + XCTFail("Should create valid URL") + return + } + ParseSwift.initialize(applicationId: "applicationId", + clientKey: "clientKey", + masterKey: "masterKey", + serverURL: url, + testing: true) + } + + override func tearDownWithError() throws { + try super.tearDownWithError() + MockURLProtocol.removeAll() + #if !os(Linux) && !os(Android) + try KeychainStore.shared.deleteAll() + #endif + try ParseStorage.shared.deleteAll() + } + + func testCheckCommand() throws { + let command = ParseHealth.healthCommand() + XCTAssertEqual(command.path.urlComponent, "/health") + XCTAssertEqual(command.method, API.Method.POST) + XCTAssertNil(command.body) + } + + func testCheck() { + + let healthOfServer = "ok" + let serverResponse = HealthResponse(status: healthOfServer) + let encoded: Data! + do { + encoded = try ParseCoding.jsonEncoder().encode(serverResponse) + } catch { + XCTFail("Should encode/decode. Error \(error)") + return + } + + MockURLProtocol.mockRequests { _ in + return MockURLResponse(data: encoded, statusCode: 200, delay: 0.0) + } + do { + let health = try ParseHealth.check() + XCTAssertEqual(health, healthOfServer) + + } catch { + XCTFail(error.localizedDescription) + } + } + + func testCheckAsync() { + let healthOfServer = "ok" + let serverResponse = HealthResponse(status: healthOfServer) + let encoded: Data! + do { + encoded = try ParseCoding.jsonEncoder().encode(serverResponse) + } catch { + XCTFail("Should encode/decode. Error \(error)") + return + } + + MockURLProtocol.mockRequests { _ in + return MockURLResponse(data: encoded, statusCode: 200, delay: 0.0) + } + + let expectation = XCTestExpectation(description: "Health check") + ParseHealth.check { result in + switch result { + + case .success(let health): + XCTAssertEqual(health, healthOfServer) + + case .failure(let error): + XCTFail(error.localizedDescription) + } + expectation.fulfill() + } + wait(for: [expectation], timeout: 10.0) + } + + func testCheckErrorAsync() { + let healthOfServer = "Should throw error" + let encoded: Data! + do { + encoded = try ParseCoding.jsonEncoder().encode(healthOfServer) + } catch { + XCTFail("Should encode/decode. Error \(error)") + return + } + + MockURLProtocol.mockRequests { _ in + return MockURLResponse(data: encoded, statusCode: 200, delay: 0.0) + } + + let expectation = XCTestExpectation(description: "Health check") + ParseHealth.check { result in + if case .success = result { + XCTFail("Should have thrown error") + } + expectation.fulfill() + } + wait(for: [expectation], timeout: 10.0) + } +}