From 63c207f087a18014425ba1bae62adad543a7084b Mon Sep 17 00:00:00 2001 From: Corey Baker Date: Tue, 30 Aug 2022 11:30:12 -0400 Subject: [PATCH 1/4] fix: Allow fully qualified ParseSwift types --- CHANGELOG.md | 8 +- Sources/ParseSwift/API/API+Command.swift | 20 +- .../API/API+NonParseBodyCommand.swift | 4 +- Sources/ParseSwift/API/API.swift | 6 +- Sources/ParseSwift/Coding/ParseEncoder.swift | 4 +- Sources/ParseSwift/Extensions/URLCache.swift | 12 +- .../ParseSwift/Extensions/URLSession.swift | 42 +- Sources/ParseSwift/LiveQuery/Messages.swift | 6 +- .../ParseSwift/LiveQuery/ParseLiveQuery.swift | 6 +- .../Objects/ParseInstallation+async.swift | 10 +- .../Objects/ParseInstallation+combine.swift | 10 +- .../Objects/ParseInstallation.swift | 20 +- .../Objects/ParseObject+async.swift | 10 +- .../Objects/ParseObject+combine.swift | 10 +- Sources/ParseSwift/Objects/ParseObject.swift | 16 +- .../ParseSwift/Objects/ParseUser+async.swift | 10 +- .../Objects/ParseUser+combine.swift | 10 +- Sources/ParseSwift/Objects/ParseUser.swift | 20 +- Sources/ParseSwift/Parse.swift | 730 +++++++++--------- Sources/ParseSwift/ParseConstants.swift | 2 +- Sources/ParseSwift/Protocols/Objectable.swift | 4 +- .../ParseSwift/Storage/KeychainStore.swift | 14 +- .../ParseSwift/Storage/ParseFileManager.swift | 2 +- .../Types/ParseKeychainAccessGroup.swift | 6 +- Sources/ParseSwift/Types/Query.swift | 36 +- .../ParseSwift/Types/QueryConstraint.swift | 4 +- Tests/ParseSwiftTests/ExtensionsTests.swift | 2 +- .../ParseSwiftTests/InitializeSDKTests.swift | 12 +- .../ParseSwiftTests/ParseFileAsyncTests.swift | 80 +- Tests/ParseSwiftTests/ParseFileTests.swift | 80 +- Tests/ParseSwiftTests/ParseRoleTests.swift | 8 +- Tests/ParseSwiftTests/ParseSessionTests.swift | 4 +- 32 files changed, 607 insertions(+), 601 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe0ed3973..7c1797953 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/4.9.1...main) +[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/4.9.2...main) * _Contributing to this repo? Add info about your change here to be included in the next release_ +### 4.9.2 +[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/4.9.1...4.9.2) + +__Fixes__ +- Allow fully qualified ParseSwift types to be used externally by fixing clash with module name ([#397](https://github.com/parse-community/Parse-Swift/pull/397)), thanks to [Corey Baker](https://github.com/cbaker6). + ### 4.9.1 [Full Changelog](https://github.com/parse-community/Parse-Swift/compare/4.9.0...4.9.1) diff --git a/Sources/ParseSwift/API/API+Command.swift b/Sources/ParseSwift/API/API+Command.swift index b1c14a748..82a271dd2 100644 --- a/Sources/ParseSwift/API/API+Command.swift +++ b/Sources/ParseSwift/API/API+Command.swift @@ -60,16 +60,16 @@ internal extension API { case .success(let urlRequest): if method == .POST || method == .PUT || method == .PATCH { let task = URLSession.parse.uploadTask(withStreamedRequest: urlRequest) - ParseSwift.sessionDelegate.streamDelegates[task] = stream + Parse.sessionDelegate.streamDelegates[task] = stream #if compiler(>=5.5.2) && canImport(_Concurrency) Task { - await ParseSwift.sessionDelegate.delegates.updateUpload(task, callback: uploadProgress) - await ParseSwift.sessionDelegate.delegates.updateTask(task, queue: callbackQueue) + await Parse.sessionDelegate.delegates.updateUpload(task, callback: uploadProgress) + await Parse.sessionDelegate.delegates.updateTask(task, queue: callbackQueue) task.resume() } #else - ParseSwift.sessionDelegate.uploadDelegates[task] = uploadProgress - ParseSwift.sessionDelegate.taskCallbackQueues[task] = callbackQueue + Parse.sessionDelegate.uploadDelegates[task] = uploadProgress + Parse.sessionDelegate.taskCallbackQueues[task] = callbackQueue task.resume() #endif return @@ -274,7 +274,7 @@ internal extension API { headers.removeValue(forKey: "X-Parse-Request-Id") } let url = parseURL == nil ? - ParseSwift.configuration.serverURL.appendingPathComponent(path.urlComponent) : parseURL! + Parse.configuration.serverURL.appendingPathComponent(path.urlComponent) : parseURL! guard var components = URLComponents(url: url, resolvingAgainstBaseURL: false) else { return .failure(ParseError(code: .unknownError, @@ -319,7 +319,7 @@ internal extension API { } static func requestCachePolicy(options: API.Options) -> URLRequest.CachePolicy { - var policy: URLRequest.CachePolicy = ParseSwift.configuration.requestCachePolicy + var policy: URLRequest.CachePolicy = Parse.configuration.requestCachePolicy options.forEach { option in if case .cachePolicy(let updatedPolicy) = option { policy = updatedPolicy @@ -395,7 +395,7 @@ internal extension API.Command { static func save(_ object: T, original data: Data?, ignoringCustomObjectIdConfig: Bool) throws -> API.Command where T: ParseObject { - if ParseSwift.configuration.isAllowingCustomObjectIds + if Parse.configuration.isAllowingCustomObjectIds && object.objectId == nil && !ignoringCustomObjectIdConfig { throw ParseError(code: .missingObjectId, message: "objectId must not be nil") } @@ -501,7 +501,7 @@ internal extension API.Command where T: ParseObject { static func batch(commands: [API.Command], transaction: Bool) -> RESTBatchCommandType { let batchCommands = commands.compactMap { (command) -> API.Command? in - let path = ParseSwift.configuration.mountPath + command.path.urlComponent + let path = Parse.configuration.mountPath + command.path.urlComponent guard let body = command.body else { return nil } @@ -553,7 +553,7 @@ internal extension API.Command where T: ParseObject { static func batch(commands: [API.NonParseBodyCommand], transaction: Bool) -> RESTBatchCommandNoBodyType { let commands = commands.compactMap { (command) -> API.NonParseBodyCommand? in - let path = ParseSwift.configuration.mountPath + command.path.urlComponent + let path = Parse.configuration.mountPath + command.path.urlComponent return API.NonParseBodyCommand( method: command.method, path: .any(path), mapper: command.mapper) diff --git a/Sources/ParseSwift/API/API+NonParseBodyCommand.swift b/Sources/ParseSwift/API/API+NonParseBodyCommand.swift index 8fe7a3d17..97225d177 100644 --- a/Sources/ParseSwift/API/API+NonParseBodyCommand.swift +++ b/Sources/ParseSwift/API/API+NonParseBodyCommand.swift @@ -90,7 +90,7 @@ internal extension API { if method == .GET || method == .DELETE { headers.removeValue(forKey: "X-Parse-Request-Id") } - let url = ParseSwift.configuration.serverURL.appendingPathComponent(path.urlComponent) + let url = Parse.configuration.serverURL.appendingPathComponent(path.urlComponent) guard var components = URLComponents(url: url, resolvingAgainstBaseURL: false) else { return .failure(ParseError(code: .unknownError, @@ -169,7 +169,7 @@ internal extension API.NonParseBodyCommand { return try objectable.toPointer() } - let path = ParseSwift.configuration.mountPath + objectable.endpoint.urlComponent + let path = Parse.configuration.mountPath + objectable.endpoint.urlComponent let encoded = try ParseCoding.parseEncoder().encode(object) let body = try ParseCoding.jsonDecoder().decode(AnyCodable.self, from: encoded) return API.BatchCommand(method: method, diff --git a/Sources/ParseSwift/API/API.swift b/Sources/ParseSwift/API/API.swift index cbd889208..86bf352a7 100644 --- a/Sources/ParseSwift/API/API.swift +++ b/Sources/ParseSwift/API/API.swift @@ -197,9 +197,9 @@ public struct API { // swiftlint:disable:next cyclomatic_complexity internal static func getHeaders(options: API.Options) -> [String: String] { - var headers: [String: String] = ["X-Parse-Application-Id": ParseSwift.configuration.applicationId, + var headers: [String: String] = ["X-Parse-Application-Id": Parse.configuration.applicationId, "Content-Type": "application/json"] - if let clientKey = ParseSwift.configuration.clientKey { + if let clientKey = Parse.configuration.clientKey { headers["X-Parse-Client-Key"] = clientKey } @@ -217,7 +217,7 @@ public struct API { options.forEach { (option) in switch option { case .useMasterKey: - headers["X-Parse-Master-Key"] = ParseSwift.configuration.masterKey + headers["X-Parse-Master-Key"] = Parse.configuration.masterKey case .sessionToken(let sessionToken): headers["X-Parse-Session-Token"] = sessionToken case .installationId(let installationId): diff --git a/Sources/ParseSwift/Coding/ParseEncoder.swift b/Sources/ParseSwift/Coding/ParseEncoder.swift index f241537b9..c6d763532 100644 --- a/Sources/ParseSwift/Coding/ParseEncoder.swift +++ b/Sources/ParseSwift/Coding/ParseEncoder.swift @@ -147,7 +147,7 @@ public struct ParseEncoder { unique: PointerType?, unsavedChildren: [Encodable]) { let keysToSkip: Set! - if !ParseSwift.configuration.isAllowingCustomObjectIds { + if !Parse.configuration.isAllowingCustomObjectIds { keysToSkip = SkipKeys.object.keys() } else { keysToSkip = SkipKeys.customObjectId.keys() @@ -172,7 +172,7 @@ public struct ParseEncoder { objectsSavedBeforeThisOne: [String: PointerType]?, filesSavedBeforeThisOne: [UUID: ParseFile]?) throws -> (encoded: Data, unique: PointerType?, unsavedChildren: [Encodable]) { let keysToSkip: Set! - if !ParseSwift.configuration.isAllowingCustomObjectIds { + if !Parse.configuration.isAllowingCustomObjectIds { keysToSkip = SkipKeys.object.keys() } else { keysToSkip = SkipKeys.customObjectId.keys() diff --git a/Sources/ParseSwift/Extensions/URLCache.swift b/Sources/ParseSwift/Extensions/URLCache.swift index 6a0afc914..8b9380c00 100644 --- a/Sources/ParseSwift/Extensions/URLCache.swift +++ b/Sources/ParseSwift/Extensions/URLCache.swift @@ -14,19 +14,19 @@ import FoundationNetworking internal extension URLCache { static let parse: URLCache = { guard let cacheURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first else { - return URLCache(memoryCapacity: ParseSwift.configuration.cacheMemoryCapacity, - diskCapacity: ParseSwift.configuration.cacheDiskCapacity, + return URLCache(memoryCapacity: Parse.configuration.cacheMemoryCapacity, + diskCapacity: Parse.configuration.cacheDiskCapacity, diskPath: nil) } let parseCacheDirectory = "ParseCache" let diskURL = cacheURL.appendingPathComponent(parseCacheDirectory, isDirectory: true) #if !os(Linux) && !os(Android) && !os(Windows) - return URLCache(memoryCapacity: ParseSwift.configuration.cacheMemoryCapacity, - diskCapacity: ParseSwift.configuration.cacheDiskCapacity, + return URLCache(memoryCapacity: Parse.configuration.cacheMemoryCapacity, + diskCapacity: Parse.configuration.cacheDiskCapacity, directory: diskURL) #else - return URLCache(memoryCapacity: ParseSwift.configuration.cacheMemoryCapacity, - diskCapacity: ParseSwift.configuration.cacheDiskCapacity, + return URLCache(memoryCapacity: Parse.configuration.cacheMemoryCapacity, + diskCapacity: Parse.configuration.cacheDiskCapacity, diskPath: diskURL.absoluteString) #endif }() diff --git a/Sources/ParseSwift/Extensions/URLSession.swift b/Sources/ParseSwift/Extensions/URLSession.swift index 730eca314..8aa177913 100644 --- a/Sources/ParseSwift/Extensions/URLSession.swift +++ b/Sources/ParseSwift/Extensions/URLSession.swift @@ -17,19 +17,19 @@ internal extension URLSession { static var parse = URLSession.shared #else static var parse: URLSession = /* URLSession.shared */ { - if !ParseSwift.configuration.isTestingSDK { + if !Parse.configuration.isTestingSDK { let configuration = URLSessionConfiguration.default configuration.urlCache = URLCache.parse - configuration.requestCachePolicy = ParseSwift.configuration.requestCachePolicy - configuration.httpAdditionalHeaders = ParseSwift.configuration.httpAdditionalHeaders + configuration.requestCachePolicy = Parse.configuration.requestCachePolicy + configuration.httpAdditionalHeaders = Parse.configuration.httpAdditionalHeaders return URLSession(configuration: configuration, - delegate: ParseSwift.sessionDelegate, + delegate: Parse.sessionDelegate, delegateQueue: nil) } else { let session = URLSession.shared session.configuration.urlCache = URLCache.parse - session.configuration.requestCachePolicy = ParseSwift.configuration.requestCachePolicy - session.configuration.httpAdditionalHeaders = ParseSwift.configuration.httpAdditionalHeaders + session.configuration.requestCachePolicy = Parse.configuration.requestCachePolicy + session.configuration.httpAdditionalHeaders = Parse.configuration.httpAdditionalHeaders return session } }() @@ -37,19 +37,19 @@ internal extension URLSession { static func updateParseURLSession() { #if !os(Linux) && !os(Android) && !os(Windows) - if !ParseSwift.configuration.isTestingSDK { + if !Parse.configuration.isTestingSDK { let configuration = URLSessionConfiguration.default configuration.urlCache = URLCache.parse - configuration.requestCachePolicy = ParseSwift.configuration.requestCachePolicy - configuration.httpAdditionalHeaders = ParseSwift.configuration.httpAdditionalHeaders + configuration.requestCachePolicy = Parse.configuration.requestCachePolicy + configuration.httpAdditionalHeaders = Parse.configuration.httpAdditionalHeaders Self.parse = URLSession(configuration: configuration, - delegate: ParseSwift.sessionDelegate, + delegate: Parse.sessionDelegate, delegateQueue: nil) } else { let session = URLSession.shared session.configuration.urlCache = URLCache.parse - session.configuration.requestCachePolicy = ParseSwift.configuration.requestCachePolicy - session.configuration.httpAdditionalHeaders = ParseSwift.configuration.httpAdditionalHeaders + session.configuration.requestCachePolicy = Parse.configuration.requestCachePolicy + session.configuration.httpAdditionalHeaders = Parse.configuration.httpAdditionalHeaders Self.parse = session } #endif @@ -186,7 +186,7 @@ internal extension URLSession { let statusCode = httpResponse.statusCode guard (200...299).contains(statusCode) else { guard statusCode >= 500, - attempts <= ParseSwift.configuration.maxConnectionAttempts + 1, + attempts <= Parse.configuration.maxConnectionAttempts + 1, responseData == nil else { completion(self.makeResult(request: request, responseData: responseData, @@ -248,13 +248,13 @@ internal extension URLSession { if let task = task { #if compiler(>=5.5.2) && canImport(_Concurrency) Task { - await ParseSwift.sessionDelegate.delegates.updateUpload(task, callback: progress) - await ParseSwift.sessionDelegate.delegates.updateTask(task, queue: notificationQueue) + await Parse.sessionDelegate.delegates.updateUpload(task, callback: progress) + await Parse.sessionDelegate.delegates.updateTask(task, queue: notificationQueue) task.resume() } #else - ParseSwift.sessionDelegate.uploadDelegates[task] = progress - ParseSwift.sessionDelegate.taskCallbackQueues[task] = notificationQueue + Parse.sessionDelegate.uploadDelegates[task] = progress + Parse.sessionDelegate.taskCallbackQueues[task] = notificationQueue task.resume() #endif } @@ -291,13 +291,13 @@ internal extension URLSession { } #if compiler(>=5.5.2) && canImport(_Concurrency) Task { - await ParseSwift.sessionDelegate.delegates.updateDownload(task, callback: progress) - await ParseSwift.sessionDelegate.delegates.updateTask(task, queue: notificationQueue) + await Parse.sessionDelegate.delegates.updateDownload(task, callback: progress) + await Parse.sessionDelegate.delegates.updateTask(task, queue: notificationQueue) task.resume() } #else - ParseSwift.sessionDelegate.downloadDelegates[task] = progress - ParseSwift.sessionDelegate.taskCallbackQueues[task] = notificationQueue + Parse.sessionDelegate.downloadDelegates[task] = progress + Parse.sessionDelegate.taskCallbackQueues[task] = notificationQueue task.resume() #endif } diff --git a/Sources/ParseSwift/LiveQuery/Messages.swift b/Sources/ParseSwift/LiveQuery/Messages.swift index d18159b3a..58d536453 100644 --- a/Sources/ParseSwift/LiveQuery/Messages.swift +++ b/Sources/ParseSwift/LiveQuery/Messages.swift @@ -21,9 +21,9 @@ struct StandardMessage: LiveQueryable, Codable { init(operation: ClientOperation, additionalProperties: Bool = false) { self.op = operation if additionalProperties { - self.applicationId = ParseSwift.configuration.applicationId - self.masterKey = ParseSwift.configuration.masterKey - self.clientKey = ParseSwift.configuration.clientKey + self.applicationId = Parse.configuration.applicationId + self.masterKey = Parse.configuration.masterKey + self.clientKey = Parse.configuration.clientKey self.sessionToken = BaseParseUser.currentContainer?.sessionToken self.installationId = BaseParseInstallation.currentContainer.installationId } diff --git a/Sources/ParseSwift/LiveQuery/ParseLiveQuery.swift b/Sources/ParseSwift/LiveQuery/ParseLiveQuery.swift index 459aff9f7..369953ae9 100644 --- a/Sources/ParseSwift/LiveQuery/ParseLiveQuery.swift +++ b/Sources/ParseSwift/LiveQuery/ParseLiveQuery.swift @@ -193,10 +193,10 @@ Not attempting to open ParseLiveQuery socket anymore if let userSuppliedURL = serverURL { url = userSuppliedURL - } else if let liveQueryConfigURL = ParseSwift.configuration.liveQuerysServerURL { + } else if let liveQueryConfigURL = Parse.configuration.liveQuerysServerURL { url = liveQueryConfigURL } else { - url = ParseSwift.configuration.serverURL + url = Parse.configuration.serverURL } guard var components = URLComponents(url: url, @@ -579,7 +579,7 @@ extension ParseLiveQuery: LiveQuerySocketDelegate { notificationQueue.async { if let delegate = self.authenticationDelegate { delegate.received(challenge, completionHandler: completionHandler) - } else if let parseAuthentication = ParseSwift.sessionDelegate.authentication { + } else if let parseAuthentication = Parse.sessionDelegate.authentication { parseAuthentication(challenge, completionHandler) } else { completionHandler(.performDefaultHandling, nil) diff --git a/Sources/ParseSwift/Objects/ParseInstallation+async.swift b/Sources/ParseSwift/Objects/ParseInstallation+async.swift index f0670ceee..9cefaa8ea 100644 --- a/Sources/ParseSwift/Objects/ParseInstallation+async.swift +++ b/Sources/ParseSwift/Objects/ParseInstallation+async.swift @@ -175,7 +175,7 @@ public extension Sequence where Element: ParseInstallation { desires a different policy, it should be inserted in `options`. */ @discardableResult func saveAll(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, ignoringCustomObjectIdConfig: Bool = false, options: API.Options = []) async throws -> [(Result)] { try await withCheckedThrowingContinuation { continuation in @@ -205,7 +205,7 @@ public extension Sequence where Element: ParseInstallation { desires a different policy, it should be inserted in `options`. */ @discardableResult func createAll(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) async throws -> [(Result)] { try await withCheckedThrowingContinuation { continuation in self.createAll(batchLimit: limit, @@ -234,7 +234,7 @@ public extension Sequence where Element: ParseInstallation { desires a different policy, it should be inserted in `options`. */ @discardableResult func replaceAll(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) async throws -> [(Result)] { try await withCheckedThrowingContinuation { continuation in self.replaceAll(batchLimit: limit, @@ -263,7 +263,7 @@ public extension Sequence where Element: ParseInstallation { desires a different policy, it should be inserted in `options`. */ internal func updateAll(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) async throws -> [(Result)] { try await withCheckedThrowingContinuation { continuation in self.updateAll(batchLimit: limit, @@ -289,7 +289,7 @@ public extension Sequence where Element: ParseInstallation { the transactions can fail. */ @discardableResult func deleteAll(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) async throws -> [(Result)] { try await withCheckedThrowingContinuation { continuation in self.deleteAll(batchLimit: limit, diff --git a/Sources/ParseSwift/Objects/ParseInstallation+combine.swift b/Sources/ParseSwift/Objects/ParseInstallation+combine.swift index 0e9d802f8..b7dae2d0d 100644 --- a/Sources/ParseSwift/Objects/ParseInstallation+combine.swift +++ b/Sources/ParseSwift/Objects/ParseInstallation+combine.swift @@ -170,7 +170,7 @@ public extension Sequence where Element: ParseInstallation { desires a different policy, it should be inserted in `options`. */ func saveAllPublisher(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, ignoringCustomObjectIdConfig: Bool = false, options: API.Options = []) -> Future<[(Result)], ParseError> { Future { promise in @@ -199,7 +199,7 @@ public extension Sequence where Element: ParseInstallation { desires a different policy, it should be inserted in `options`. */ func createAllPublisher(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) -> Future<[(Result)], ParseError> { Future { promise in self.createAll(batchLimit: limit, @@ -227,7 +227,7 @@ public extension Sequence where Element: ParseInstallation { desires a different policy, it should be inserted in `options`. */ func replaceAllPublisher(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) -> Future<[(Result)], ParseError> { Future { promise in self.replaceAll(batchLimit: limit, @@ -255,7 +255,7 @@ public extension Sequence where Element: ParseInstallation { desires a different policy, it should be inserted in `options`. */ internal func updateAllPublisher(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) -> Future<[(Result)], ParseError> { Future { promise in @@ -282,7 +282,7 @@ public extension Sequence where Element: ParseInstallation { the transactions can fail. */ func deleteAllPublisher(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) -> Future<[(Result)], ParseError> { Future { promise in self.deleteAll(batchLimit: limit, diff --git a/Sources/ParseSwift/Objects/ParseInstallation.swift b/Sources/ParseSwift/Objects/ParseInstallation.swift index bcdb8fb09..2dd5b59eb 100644 --- a/Sources/ParseSwift/Objects/ParseInstallation.swift +++ b/Sources/ParseSwift/Objects/ParseInstallation.swift @@ -169,7 +169,7 @@ extension ParseInstallation { } func endpoint(_ method: API.Method) -> API.Endpoint { - if !ParseSwift.configuration.isAllowingCustomObjectIds || method != .POST { + if !Parse.configuration.isAllowingCustomObjectIds || method != .POST { return endpoint } else { return .installations @@ -741,7 +741,7 @@ extension ParseInstallation { } func saveCommand(ignoringCustomObjectIdConfig: Bool = false) throws -> API.Command { - if ParseSwift.configuration.isAllowingCustomObjectIds && objectId == nil && !ignoringCustomObjectIdConfig { + if Parse.configuration.isAllowingCustomObjectIds && objectId == nil && !ignoringCustomObjectIdConfig { throw ParseError(code: .missingObjectId, message: "objectId must not be nil") } if isSaved { @@ -938,7 +938,7 @@ public extension Sequence where Element: ParseInstallation { desires a different policy, it should be inserted in `options`. */ func saveAll(batchLimit limit: Int? = nil, // swiftlint:disable:this function_body_length - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, ignoringCustomObjectIdConfig: Bool = false, options: API.Options = []) throws -> [(Result)] { var options = options @@ -1038,7 +1038,7 @@ public extension Sequence where Element: ParseInstallation { */ func saveAll( // swiftlint:disable:this function_body_length cyclomatic_complexity batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, ignoringCustomObjectIdConfig: Bool = false, options: API.Options = [], callbackQueue: DispatchQueue = .main, @@ -1072,7 +1072,7 @@ public extension Sequence where Element: ParseInstallation { */ func createAll( // swiftlint:disable:this function_body_length cyclomatic_complexity batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = [], callbackQueue: DispatchQueue = .main, completion: @escaping (Result<[(Result)], ParseError>) -> Void @@ -1105,7 +1105,7 @@ public extension Sequence where Element: ParseInstallation { */ func replaceAll( // swiftlint:disable:this function_body_length cyclomatic_complexity batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = [], callbackQueue: DispatchQueue = .main, completion: @escaping (Result<[(Result)], ParseError>) -> Void @@ -1138,7 +1138,7 @@ public extension Sequence where Element: ParseInstallation { */ internal func updateAll( // swiftlint:disable:this function_body_length cyclomatic_complexity batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = [], callbackQueue: DispatchQueue = .main, completion: @escaping (Result<[(Result)], ParseError>) -> Void @@ -1414,7 +1414,7 @@ public extension Sequence where Element: ParseInstallation { desires a different policy, it should be inserted in `options`. */ func deleteAll(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) throws -> [(Result)] { var options = options options.insert(.cachePolicy(.reloadIgnoringLocalCacheData)) @@ -1463,7 +1463,7 @@ public extension Sequence where Element: ParseInstallation { */ func deleteAll( batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = [], callbackQueue: DispatchQueue = .main, completion: @escaping (Result<[(Result)], ParseError>) -> Void @@ -1633,7 +1633,7 @@ public extension ParseInstallation { } currentInstallation.installationId = oldInstallationId do { - try ParseSwift.deleteObjectiveCKeychain() + try deleteObjectiveCKeychain() // Only delete the `ParseInstallation` on Parse Server if it is not current. guard Self.current?.installationId == oldInstallationId else { currentInstallation.delete(options: options, diff --git a/Sources/ParseSwift/Objects/ParseObject+async.swift b/Sources/ParseSwift/Objects/ParseObject+async.swift index 28b42a3b9..4fedae25c 100644 --- a/Sources/ParseSwift/Objects/ParseObject+async.swift +++ b/Sources/ParseSwift/Objects/ParseObject+async.swift @@ -157,7 +157,7 @@ public extension Sequence where Element: ParseObject { desires a different policy, it should be inserted in `options`. */ @discardableResult func saveAll(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, ignoringCustomObjectIdConfig: Bool = false, options: API.Options = []) async throws -> [(Result)] { try await withCheckedThrowingContinuation { continuation in @@ -187,7 +187,7 @@ public extension Sequence where Element: ParseObject { desires a different policy, it should be inserted in `options`. */ @discardableResult func createAll(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) async throws -> [(Result)] { try await withCheckedThrowingContinuation { continuation in self.createAll(batchLimit: limit, @@ -215,7 +215,7 @@ public extension Sequence where Element: ParseObject { desires a different policy, it should be inserted in `options`. */ @discardableResult func replaceAll(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) async throws -> [(Result)] { try await withCheckedThrowingContinuation { continuation in self.replaceAll(batchLimit: limit, @@ -243,7 +243,7 @@ public extension Sequence where Element: ParseObject { desires a different policy, it should be inserted in `options`. */ internal func updateAll(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) async throws -> [(Result)] { try await withCheckedThrowingContinuation { continuation in self.updateAll(batchLimit: limit, @@ -268,7 +268,7 @@ public extension Sequence where Element: ParseObject { the transactions can fail. */ @discardableResult func deleteAll(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) async throws -> [(Result)] { try await withCheckedThrowingContinuation { continuation in self.deleteAll(batchLimit: limit, diff --git a/Sources/ParseSwift/Objects/ParseObject+combine.swift b/Sources/ParseSwift/Objects/ParseObject+combine.swift index c320750e1..cb41326dc 100644 --- a/Sources/ParseSwift/Objects/ParseObject+combine.swift +++ b/Sources/ParseSwift/Objects/ParseObject+combine.swift @@ -160,7 +160,7 @@ public extension Sequence where Element: ParseObject { client-side checks are disabled. Developers are responsible for handling such cases. */ func saveAllPublisher(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, ignoringCustomObjectIdConfig: Bool = false, options: API.Options = []) -> Future<[(Result)], ParseError> { Future { promise in @@ -187,7 +187,7 @@ public extension Sequence where Element: ParseObject { the transactions can fail. */ func createAllPublisher(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) -> Future<[(Result)], ParseError> { Future { promise in self.createAll(batchLimit: limit, @@ -212,7 +212,7 @@ public extension Sequence where Element: ParseObject { the transactions can fail. */ func replaceAllPublisher(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) -> Future<[(Result)], ParseError> { Future { promise in self.replaceAll(batchLimit: limit, @@ -237,7 +237,7 @@ public extension Sequence where Element: ParseObject { the transactions can fail. */ internal func updateAllPublisher(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) -> Future<[(Result)], ParseError> { Future { promise in @@ -263,7 +263,7 @@ public extension Sequence where Element: ParseObject { the transactions can fail. */ func deleteAllPublisher(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) -> Future<[(Result)], ParseError> { Future { promise in self.deleteAll(batchLimit: limit, diff --git a/Sources/ParseSwift/Objects/ParseObject.swift b/Sources/ParseSwift/Objects/ParseObject.swift index 84ba91eb5..604f0b587 100644 --- a/Sources/ParseSwift/Objects/ParseObject.swift +++ b/Sources/ParseSwift/Objects/ParseObject.swift @@ -258,7 +258,7 @@ transactions for this call. desires a different policy, it should be inserted in `options`. */ func saveAll(batchLimit limit: Int? = nil, // swiftlint:disable:this function_body_length - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, ignoringCustomObjectIdConfig: Bool = false, options: API.Options = []) throws -> [(Result)] { var options = options @@ -356,7 +356,7 @@ transactions for this call. */ func saveAll( // swiftlint:disable:this function_body_length cyclomatic_complexity batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, ignoringCustomObjectIdConfig: Bool = false, options: API.Options = [], callbackQueue: DispatchQueue = .main, @@ -390,7 +390,7 @@ transactions for this call. */ func createAll( // swiftlint:disable:this function_body_length cyclomatic_complexity batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = [], callbackQueue: DispatchQueue = .main, completion: @escaping (Result<[(Result)], ParseError>) -> Void @@ -422,7 +422,7 @@ transactions for this call. */ func replaceAll( // swiftlint:disable:this function_body_length cyclomatic_complexity batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = [], callbackQueue: DispatchQueue = .main, completion: @escaping (Result<[(Result)], ParseError>) -> Void @@ -454,7 +454,7 @@ transactions for this call. */ internal func updateAll( // swiftlint:disable:this function_body_length cyclomatic_complexity batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = [], callbackQueue: DispatchQueue = .main, completion: @escaping (Result<[(Result)], ParseError>) -> Void @@ -716,7 +716,7 @@ transactions for this call. desires a different policy, it should be inserted in `options`. */ func deleteAll(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) throws -> [(Result)] { var options = options options.insert(.cachePolicy(.reloadIgnoringLocalCacheData)) @@ -762,7 +762,7 @@ transactions for this call. */ func deleteAll( batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = [], callbackQueue: DispatchQueue = .main, completion: @escaping (Result<[(Result)], ParseError>) -> Void @@ -1213,7 +1213,7 @@ extension ParseObject { // MARK: Savable Encodable Version internal extension ParseEncodable { func saveAll(objects: [ParseEncodable], - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) throws -> [(Result)] { try API.NonParseBodyCommand .batch(objects: objects, diff --git a/Sources/ParseSwift/Objects/ParseUser+async.swift b/Sources/ParseSwift/Objects/ParseUser+async.swift index 86a3fbea6..ca61c5fb8 100644 --- a/Sources/ParseSwift/Objects/ParseUser+async.swift +++ b/Sources/ParseSwift/Objects/ParseUser+async.swift @@ -376,7 +376,7 @@ public extension Sequence where Element: ParseUser { desires a different policy, it should be inserted in `options`. */ @discardableResult func saveAll(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, ignoringCustomObjectIdConfig: Bool = false, options: API.Options = []) async throws -> [(Result)] { try await withCheckedThrowingContinuation { continuation in @@ -406,7 +406,7 @@ public extension Sequence where Element: ParseUser { desires a different policy, it should be inserted in `options`. */ @discardableResult func createAll(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) async throws -> [(Result)] { try await withCheckedThrowingContinuation { continuation in self.createAll(batchLimit: limit, @@ -435,7 +435,7 @@ public extension Sequence where Element: ParseUser { desires a different policy, it should be inserted in `options`. */ @discardableResult func replaceAll(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) async throws -> [(Result)] { try await withCheckedThrowingContinuation { continuation in self.replaceAll(batchLimit: limit, @@ -464,7 +464,7 @@ public extension Sequence where Element: ParseUser { desires a different policy, it should be inserted in `options`. */ internal func updateAll(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) async throws -> [(Result)] { try await withCheckedThrowingContinuation { continuation in self.updateAll(batchLimit: limit, @@ -492,7 +492,7 @@ public extension Sequence where Element: ParseUser { desires a different policy, it should be inserted in `options`. */ @discardableResult func deleteAll(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) async throws -> [(Result)] { try await withCheckedThrowingContinuation { continuation in self.deleteAll(batchLimit: limit, diff --git a/Sources/ParseSwift/Objects/ParseUser+combine.swift b/Sources/ParseSwift/Objects/ParseUser+combine.swift index fc43a8e1c..2c40c32ed 100644 --- a/Sources/ParseSwift/Objects/ParseUser+combine.swift +++ b/Sources/ParseSwift/Objects/ParseUser+combine.swift @@ -360,7 +360,7 @@ public extension Sequence where Element: ParseUser { desires a different policy, it should be inserted in `options`. */ func saveAllPublisher(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, ignoringCustomObjectIdConfig: Bool = false, options: API.Options = []) -> Future<[(Result)], ParseError> { Future { promise in @@ -389,7 +389,7 @@ public extension Sequence where Element: ParseUser { desires a different policy, it should be inserted in `options`. */ func createAllPublisher(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) -> Future<[(Result)], ParseError> { Future { promise in self.createAll(batchLimit: limit, @@ -417,7 +417,7 @@ public extension Sequence where Element: ParseUser { desires a different policy, it should be inserted in `options`. */ func replaceAllPublisher(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) -> Future<[(Result)], ParseError> { Future { promise in @@ -446,7 +446,7 @@ public extension Sequence where Element: ParseUser { desires a different policy, it should be inserted in `options`. */ internal func updateAllPublisher(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) -> Future<[(Result)], ParseError> { Future { promise in @@ -475,7 +475,7 @@ public extension Sequence where Element: ParseUser { desires a different policy, it should be inserted in `options`. */ func deleteAllPublisher(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) -> Future<[(Result)], ParseError> { Future { promise in self.deleteAll(batchLimit: limit, diff --git a/Sources/ParseSwift/Objects/ParseUser.swift b/Sources/ParseSwift/Objects/ParseUser.swift index 5fd94c7b2..6b428a653 100644 --- a/Sources/ParseSwift/Objects/ParseUser.swift +++ b/Sources/ParseSwift/Objects/ParseUser.swift @@ -84,7 +84,7 @@ extension ParseUser { } func endpoint(_ method: API.Method) -> API.Endpoint { - if !ParseSwift.configuration.isAllowingCustomObjectIds || method != .POST { + if !Parse.configuration.isAllowingCustomObjectIds || method != .POST { return endpoint } else { return .users @@ -96,7 +96,7 @@ extension ParseUser { BaseParseInstallation.deleteCurrentContainerFromKeychain() ParseACL.deleteDefaultFromKeychain() BaseConfig.deleteCurrentContainerFromKeychain() - ParseSwift.clearCache() + clearCache() } } @@ -1224,7 +1224,7 @@ extension ParseUser { } func saveCommand(ignoringCustomObjectIdConfig: Bool = false) throws -> API.Command { - if ParseSwift.configuration.isAllowingCustomObjectIds && objectId == nil && !ignoringCustomObjectIdConfig { + if Parse.configuration.isAllowingCustomObjectIds && objectId == nil && !ignoringCustomObjectIdConfig { throw ParseError(code: .missingObjectId, message: "objectId must not be nil") } if isSaved { @@ -1442,7 +1442,7 @@ public extension Sequence where Element: ParseUser { desires a different policy, it should be inserted in `options`. */ func saveAll(batchLimit limit: Int? = nil, // swiftlint:disable:this function_body_length - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, ignoringCustomObjectIdConfig: Bool = false, options: API.Options = []) throws -> [(Result)] { var childObjects = [String: PointerType]() @@ -1542,7 +1542,7 @@ public extension Sequence where Element: ParseUser { */ func saveAll( // swiftlint:disable:this function_body_length cyclomatic_complexity batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, ignoringCustomObjectIdConfig: Bool = false, options: API.Options = [], callbackQueue: DispatchQueue = .main, @@ -1576,7 +1576,7 @@ public extension Sequence where Element: ParseUser { */ func createAll( // swiftlint:disable:this function_body_length cyclomatic_complexity batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = [], callbackQueue: DispatchQueue = .main, completion: @escaping (Result<[(Result)], ParseError>) -> Void @@ -1609,7 +1609,7 @@ public extension Sequence where Element: ParseUser { */ func replaceAll( // swiftlint:disable:this function_body_length cyclomatic_complexity batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = [], callbackQueue: DispatchQueue = .main, completion: @escaping (Result<[(Result)], ParseError>) -> Void @@ -1642,7 +1642,7 @@ public extension Sequence where Element: ParseUser { */ internal func updateAll( // swiftlint:disable:this function_body_length cyclomatic_complexity batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = [], callbackQueue: DispatchQueue = .main, completion: @escaping (Result<[(Result)], ParseError>) -> Void @@ -1910,7 +1910,7 @@ public extension Sequence where Element: ParseUser { desires a different policy, it should be inserted in `options`. */ func deleteAll(batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = []) throws -> [(Result)] { var options = options options.insert(.cachePolicy(.reloadIgnoringLocalCacheData)) @@ -1958,7 +1958,7 @@ public extension Sequence where Element: ParseUser { */ func deleteAll( batchLimit limit: Int? = nil, - transaction: Bool = ParseSwift.configuration.isUsingTransactions, + transaction: Bool = configuration.isUsingTransactions, options: API.Options = [], callbackQueue: DispatchQueue = .main, completion: @escaping (Result<[(Result)], ParseError>) -> Void diff --git a/Sources/ParseSwift/Parse.swift b/Sources/ParseSwift/Parse.swift index d61f012eb..890b4cf77 100644 --- a/Sources/ParseSwift/Parse.swift +++ b/Sources/ParseSwift/Parse.swift @@ -250,402 +250,402 @@ public struct ParseConfiguration { } } +public var configuration: ParseConfiguration { + Parse.configuration +} + +internal struct Parse { + static var configuration: ParseConfiguration! + static var sessionDelegate: ParseURLSessionDelegate! +} + /** - `ParseSwift` contains static methods to handle global configuration for the Parse framework. + Configure the Parse Swift client. This should only be used when starting your app. Typically in the + `application(... didFinishLaunchingWithOptions launchOptions...)`. + - parameter configuration: The Parse configuration. */ -public struct ParseSwift { +public func initialize(configuration: ParseConfiguration) { + Parse.configuration = configuration + Parse.sessionDelegate = ParseURLSessionDelegate(callbackQueue: .main, + authentication: configuration.authentication) + URLSession.updateParseURLSession() + deleteKeychainIfNeeded() - public internal(set) static var configuration: ParseConfiguration! - static var sessionDelegate: ParseURLSessionDelegate! + #if !os(Linux) && !os(Android) && !os(Windows) + if let keychainAccessGroup = ParseKeychainAccessGroup.current { + Parse.configuration.keychainAccessGroup = keychainAccessGroup + } else { + ParseKeychainAccessGroup.current = ParseKeychainAccessGroup() + } + #endif - /** - Configure the Parse Swift client. This should only be used when starting your app. Typically in the - `application(... didFinishLaunchingWithOptions launchOptions...)`. - - parameter configuration: The Parse configuration. - */ - static public func initialize(configuration: ParseConfiguration) { - Self.configuration = configuration - Self.sessionDelegate = ParseURLSessionDelegate(callbackQueue: .main, - authentication: configuration.authentication) - URLSession.updateParseURLSession() - deleteKeychainIfNeeded() + do { + let previousSDKVersion = try ParseVersion(ParseVersion.current) + let currentSDKVersion = try ParseVersion(ParseConstants.version) + let oneNineEightSDKVersion = try ParseVersion("1.9.8") + // All migrations from previous versions to current should occur here: #if !os(Linux) && !os(Android) && !os(Windows) - if let keychainAccessGroup = ParseKeychainAccessGroup.current { - ParseSwift.configuration.keychainAccessGroup = keychainAccessGroup - } else { - ParseKeychainAccessGroup.current = ParseKeychainAccessGroup() + if previousSDKVersion < oneNineEightSDKVersion { + // Old macOS Keychain cannot be used because it is global to all apps. + _ = KeychainStore.old + try? KeychainStore.shared.copy(KeychainStore.old, + oldAccessGroup: configuration.keychainAccessGroup, + newAccessGroup: configuration.keychainAccessGroup) + // Need to delete the old Keychain because a new one is created with bundleId. + try? KeychainStore.old.deleteAll() } #endif - - do { - let previousSDKVersion = try ParseVersion(ParseVersion.current) - let currentSDKVersion = try ParseVersion(ParseConstants.version) - let oneNineEightSDKVersion = try ParseVersion("1.9.8") - - // All migrations from previous versions to current should occur here: - #if !os(Linux) && !os(Android) && !os(Windows) - if previousSDKVersion < oneNineEightSDKVersion { - // Old macOS Keychain cannot be used because it is global to all apps. - _ = KeychainStore.old - try? KeychainStore.shared.copy(KeychainStore.old, - oldAccessGroup: configuration.keychainAccessGroup, - newAccessGroup: configuration.keychainAccessGroup) - // Need to delete the old Keychain because a new one is created with bundleId. - try? KeychainStore.old.deleteAll() - } - #endif - if currentSDKVersion > previousSDKVersion { - ParseVersion.current = currentSDKVersion.string - } - } catch { - // Migrate old installations made with ParseSwift < 1.3.0 - if let currentInstallation = BaseParseInstallation.current { - if currentInstallation.objectId == nil { - BaseParseInstallation.deleteCurrentContainerFromKeychain() - // Prepare installation - BaseParseInstallation.createNewInstallationIfNeeded() - } - } else { + if currentSDKVersion > previousSDKVersion { + ParseVersion.current = currentSDKVersion.string + } + } catch { + // Migrate old installations made with ParseSwift < 1.3.0 + if let currentInstallation = BaseParseInstallation.current { + if currentInstallation.objectId == nil { + BaseParseInstallation.deleteCurrentContainerFromKeychain() // Prepare installation BaseParseInstallation.createNewInstallationIfNeeded() } - ParseVersion.current = ParseConstants.version + } else { + // Prepare installation + BaseParseInstallation.createNewInstallationIfNeeded() } + ParseVersion.current = ParseConstants.version + } - // Migrate installations with installationId, but missing - // currentInstallation, ParseSwift < 1.9.10 - if let installationId = BaseParseInstallation.currentContainer.installationId, - BaseParseInstallation.currentContainer.currentInstallation == nil { - if let foundInstallation = try? BaseParseInstallation - .query("installationId" == installationId) - .first(options: [.cachePolicy(.reloadIgnoringLocalCacheData)]) { - let newContainer = CurrentInstallationContainer(currentInstallation: foundInstallation, - installationId: installationId) - BaseParseInstallation.currentContainer = newContainer - BaseParseInstallation.saveCurrentContainerToKeychain() - } + // Migrate installations with installationId, but missing + // currentInstallation, ParseSwift < 1.9.10 + if let installationId = BaseParseInstallation.currentContainer.installationId, + BaseParseInstallation.currentContainer.currentInstallation == nil { + if let foundInstallation = try? BaseParseInstallation + .query("installationId" == installationId) + .first(options: [.cachePolicy(.reloadIgnoringLocalCacheData)]) { + let newContainer = CurrentInstallationContainer(currentInstallation: foundInstallation, + installationId: installationId) + BaseParseInstallation.currentContainer = newContainer + BaseParseInstallation.saveCurrentContainerToKeychain() } - BaseParseInstallation.createNewInstallationIfNeeded() + } + BaseParseInstallation.createNewInstallationIfNeeded() - #if !os(Linux) && !os(Android) && !os(Windows) - if configuration.isMigratingFromObjcSDK { - if let objcParseKeychain = KeychainStore.objectiveC { - guard let installationId: String = objcParseKeychain.object(forKey: "installationId"), - BaseParseInstallation.current?.installationId != installationId else { - return - } - var updatedInstallation = BaseParseInstallation.current - updatedInstallation?.installationId = installationId - BaseParseInstallation.currentContainer.installationId = installationId - BaseParseInstallation.currentContainer.currentInstallation = updatedInstallation - BaseParseInstallation.saveCurrentContainerToKeychain() + #if !os(Linux) && !os(Android) && !os(Windows) + if configuration.isMigratingFromObjcSDK { + if let objcParseKeychain = KeychainStore.objectiveC { + guard let installationId: String = objcParseKeychain.object(forKey: "installationId"), + BaseParseInstallation.current?.installationId != installationId else { + return } + var updatedInstallation = BaseParseInstallation.current + updatedInstallation?.installationId = installationId + BaseParseInstallation.currentContainer.installationId = installationId + BaseParseInstallation.currentContainer.currentInstallation = updatedInstallation + BaseParseInstallation.saveCurrentContainerToKeychain() } - #endif } + #endif +} - /** - Configure the Parse Swift client. This should only be used when starting your app. Typically in the - `application(... didFinishLaunchingWithOptions launchOptions...)`. - - parameter applicationId: The application id for your Parse application. - - parameter clientKey: The client key for your Parse application. - - parameter masterKey: The master key for your Parse application. This key should only be - specified when using the SDK on a server. - - parameter serverURL: The server URL to connect to Parse Server. - - parameter liveQueryServerURL: The live query server URL to connect to Parse Server. - - parameter allowingCustomObjectIds: Allows objectIds to be created on the client. - side for each object. Must be enabled on the server to work. - - parameter usingTransactions: Use transactions when saving/updating multiple objects. - - parameter usingEqualQueryConstraint: Use the **$eq** query constraint when querying. - - parameter usingPostForQuery: Use **POST** instead of **GET** when making query calls. - Defaults to **false**. - - parameter keyValueStore: A key/value store that conforms to the `ParseKeyValueStore` - protocol. Defaults to `nil` in which one will be created an memory, but never persisted. For Linux, this - this is the only store available since there is no Keychain. Linux users should replace this store with an - encrypted one. - - parameter requestCachePolicy: The default caching policy for all http requests that determines - when to return a response from the cache. Defaults to `useProtocolCachePolicy`. See Apple's [documentation](https://developer.apple.com/documentation/foundation/url_loading_system/accessing_cached_data) - for more info. - - parameter cacheMemoryCapacity: The memory capacity of the cache, in bytes. Defaults to 512KB. - - parameter cacheDiskCapacity: The disk capacity of the cache, in bytes. Defaults to 10MB. - - parameter deletingKeychainIfNeeded: Deletes the Parse Keychain when the app is running for the first time. - Defaults to **false**. - - parameter httpAdditionalHeaders: A dictionary of additional headers to send with requests. See Apple's - [documentation](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1411532-httpadditionalheaders) - for more info. - - parameter authentication: A callback block that will be used to receive/accept/decline network challenges. - Defaults to `nil` in which the SDK will use the default OS authentication methods for challenges. - It should have the following argument signature: `(challenge: URLAuthenticationChallenge, - completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void`. - See Apple's [documentation](https://developer.apple.com/documentation/foundation/urlsessiontaskdelegate/1411595-urlsession) for more for details. - - warning: `usingTransactions` is experimental. - - warning: It is recomended to only specify `masterKey` when using the SDK on a server. Do not use this key on the client. - - warning: Setting `usingPostForQuery` to **true** will require all queries to access the server instead of following the `requestCachePolicy`. - */ - static public func initialize( - applicationId: String, - clientKey: String? = nil, - masterKey: String? = nil, - serverURL: URL, - liveQueryServerURL: URL? = nil, - allowingCustomObjectIds: Bool = false, - usingTransactions: Bool = false, - usingEqualQueryConstraint: Bool = false, - usingPostForQuery: Bool = false, - keyValueStore: ParseKeyValueStore? = nil, - requestCachePolicy: URLRequest.CachePolicy = .useProtocolCachePolicy, - cacheMemoryCapacity: Int = 512_000, - cacheDiskCapacity: Int = 10_000_000, - deletingKeychainIfNeeded: Bool = false, - httpAdditionalHeaders: [AnyHashable: Any]? = nil, - maxConnectionAttempts: Int = 5, - authentication: ((URLAuthenticationChallenge, - (URLSession.AuthChallengeDisposition, - URLCredential?) -> Void) -> Void)? = nil - ) { - let configuration = ParseConfiguration(applicationId: applicationId, - clientKey: clientKey, - masterKey: masterKey, - serverURL: serverURL, - liveQueryServerURL: liveQueryServerURL, - allowingCustomObjectIds: allowingCustomObjectIds, - usingTransactions: usingTransactions, - usingEqualQueryConstraint: usingEqualQueryConstraint, - usingPostForQuery: usingPostForQuery, - keyValueStore: keyValueStore, - requestCachePolicy: requestCachePolicy, - cacheMemoryCapacity: cacheMemoryCapacity, - cacheDiskCapacity: cacheDiskCapacity, - deletingKeychainIfNeeded: deletingKeychainIfNeeded, - httpAdditionalHeaders: httpAdditionalHeaders, - maxConnectionAttempts: maxConnectionAttempts, - authentication: authentication) - initialize(configuration: configuration) - } +/** + Configure the Parse Swift client. This should only be used when starting your app. Typically in the + `application(... didFinishLaunchingWithOptions launchOptions...)`. + - parameter applicationId: The application id for your Parse application. + - parameter clientKey: The client key for your Parse application. + - parameter masterKey: The master key for your Parse application. This key should only be + specified when using the SDK on a server. + - parameter serverURL: The server URL to connect to Parse Server. + - parameter liveQueryServerURL: The live query server URL to connect to Parse Server. + - parameter allowingCustomObjectIds: Allows objectIds to be created on the client. + side for each object. Must be enabled on the server to work. + - parameter usingTransactions: Use transactions when saving/updating multiple objects. + - parameter usingEqualQueryConstraint: Use the **$eq** query constraint when querying. + - parameter usingPostForQuery: Use **POST** instead of **GET** when making query calls. + Defaults to **false**. + - parameter keyValueStore: A key/value store that conforms to the `ParseKeyValueStore` + protocol. Defaults to `nil` in which one will be created an memory, but never persisted. For Linux, this + this is the only store available since there is no Keychain. Linux users should replace this store with an + encrypted one. + - parameter requestCachePolicy: The default caching policy for all http requests that determines + when to return a response from the cache. Defaults to `useProtocolCachePolicy`. See Apple's [documentation](https://developer.apple.com/documentation/foundation/url_loading_system/accessing_cached_data) + for more info. + - parameter cacheMemoryCapacity: The memory capacity of the cache, in bytes. Defaults to 512KB. + - parameter cacheDiskCapacity: The disk capacity of the cache, in bytes. Defaults to 10MB. + - parameter deletingKeychainIfNeeded: Deletes the Parse Keychain when the app is running for the first time. + Defaults to **false**. + - parameter httpAdditionalHeaders: A dictionary of additional headers to send with requests. See Apple's + [documentation](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1411532-httpadditionalheaders) + for more info. + - parameter authentication: A callback block that will be used to receive/accept/decline network challenges. + Defaults to `nil` in which the SDK will use the default OS authentication methods for challenges. + It should have the following argument signature: `(challenge: URLAuthenticationChallenge, + completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void`. + See Apple's [documentation](https://developer.apple.com/documentation/foundation/urlsessiontaskdelegate/1411595-urlsession) for more for details. + - warning: `usingTransactions` is experimental. + - warning: It is recomended to only specify `masterKey` when using the SDK on a server. Do not use this key on the client. + - warning: Setting `usingPostForQuery` to **true** will require all queries to access the server instead of following the `requestCachePolicy`. + */ +public func initialize( + applicationId: String, + clientKey: String? = nil, + masterKey: String? = nil, + serverURL: URL, + liveQueryServerURL: URL? = nil, + allowingCustomObjectIds: Bool = false, + usingTransactions: Bool = false, + usingEqualQueryConstraint: Bool = false, + usingPostForQuery: Bool = false, + keyValueStore: ParseKeyValueStore? = nil, + requestCachePolicy: URLRequest.CachePolicy = .useProtocolCachePolicy, + cacheMemoryCapacity: Int = 512_000, + cacheDiskCapacity: Int = 10_000_000, + deletingKeychainIfNeeded: Bool = false, + httpAdditionalHeaders: [AnyHashable: Any]? = nil, + maxConnectionAttempts: Int = 5, + authentication: ((URLAuthenticationChallenge, + (URLSession.AuthChallengeDisposition, + URLCredential?) -> Void) -> Void)? = nil +) { + let configuration = ParseConfiguration(applicationId: applicationId, + clientKey: clientKey, + masterKey: masterKey, + serverURL: serverURL, + liveQueryServerURL: liveQueryServerURL, + allowingCustomObjectIds: allowingCustomObjectIds, + usingTransactions: usingTransactions, + usingEqualQueryConstraint: usingEqualQueryConstraint, + usingPostForQuery: usingPostForQuery, + keyValueStore: keyValueStore, + requestCachePolicy: requestCachePolicy, + cacheMemoryCapacity: cacheMemoryCapacity, + cacheDiskCapacity: cacheDiskCapacity, + deletingKeychainIfNeeded: deletingKeychainIfNeeded, + httpAdditionalHeaders: httpAdditionalHeaders, + maxConnectionAttempts: maxConnectionAttempts, + authentication: authentication) + initialize(configuration: configuration) +} - /** - Configure the Parse Swift client. This should only be used when starting your app. Typically in the - `application(... didFinishLaunchingWithOptions launchOptions...)`. - - parameter applicationId: The application id for your Parse application. - - parameter clientKey: The client key for your Parse application. - - parameter masterKey: The master key for your Parse application. This key should only be - specified when using the SDK on a server. - - parameter serverURL: The server URL to connect to Parse Server. - - parameter liveQueryServerURL: The live query server URL to connect to Parse Server. - - parameter allowingCustomObjectIds: Allows objectIds to be created on the client. - side for each object. Must be enabled on the server to work. - - parameter usingTransactions: Use transactions when saving/updating multiple objects. - - parameter usingEqualQueryConstraint: Use the **$eq** query constraint when querying. - - parameter usingPostForQuery: Use **POST** instead of **GET** when making query calls. - Defaults to **false**. - - parameter keyValueStore: A key/value store that conforms to the `ParseKeyValueStore` - protocol. Defaults to `nil` in which one will be created an memory, but never persisted. For Linux, this - this is the only store available since there is no Keychain. Linux users should replace this store with an - encrypted one. - - parameter requestCachePolicy: The default caching policy for all http requests that determines - when to return a response from the cache. Defaults to `useProtocolCachePolicy`. See Apple's [documentation](https://developer.apple.com/documentation/foundation/url_loading_system/accessing_cached_data) - for more info. - - parameter cacheMemoryCapacity: The memory capacity of the cache, in bytes. Defaults to 512KB. - - parameter cacheDiskCapacity: The disk capacity of the cache, in bytes. Defaults to 10MB. - - parameter migratingFromObjcSDK: If your app previously used the iOS Objective-C SDK, setting this value - to **true** will attempt to migrate relevant data stored in the Keychain to ParseSwift. Defaults to **false**. - - parameter deletingKeychainIfNeeded: Deletes the Parse Keychain when the app is running for the first time. - Defaults to **false**. - - parameter httpAdditionalHeaders: A dictionary of additional headers to send with requests. See Apple's - [documentation](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1411532-httpadditionalheaders) - for more info. - - parameter authentication: A callback block that will be used to receive/accept/decline network challenges. - Defaults to `nil` in which the SDK will use the default OS authentication methods for challenges. - It should have the following argument signature: `(challenge: URLAuthenticationChallenge, - completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void`. - See Apple's [documentation](https://developer.apple.com/documentation/foundation/urlsessiontaskdelegate/1411595-urlsession) for more for details. - - warning: `usingTransactions` is experimental. - - warning: It is recomended to only specify `masterKey` when using the SDK on a server. Do not use this key on the client. - - warning: Setting `usingPostForQuery` to **true** will require all queries to access the server instead of following the `requestCachePolicy`. - */ - @available(*, deprecated, message: "Remove the migratingFromObjcSDK argument") - static public func initialize( - applicationId: String, - clientKey: String? = nil, - masterKey: String? = nil, - serverURL: URL, - liveQueryServerURL: URL? = nil, - allowingCustomObjectIds: Bool = false, - usingTransactions: Bool = false, - usingEqualQueryConstraint: Bool = false, - usingPostForQuery: Bool = false, - keyValueStore: ParseKeyValueStore? = nil, - requestCachePolicy: URLRequest.CachePolicy = .useProtocolCachePolicy, - cacheMemoryCapacity: Int = 512_000, - cacheDiskCapacity: Int = 10_000_000, - migratingFromObjcSDK: Bool = false, - deletingKeychainIfNeeded: Bool = false, - httpAdditionalHeaders: [AnyHashable: Any]? = nil, - maxConnectionAttempts: Int = 5, - authentication: ((URLAuthenticationChallenge, - (URLSession.AuthChallengeDisposition, - URLCredential?) -> Void) -> Void)? = nil - ) { - var configuration = ParseConfiguration(applicationId: applicationId, - clientKey: clientKey, - masterKey: masterKey, - serverURL: serverURL, - liveQueryServerURL: liveQueryServerURL, - allowingCustomObjectIds: allowingCustomObjectIds, - usingTransactions: usingTransactions, - usingEqualQueryConstraint: usingEqualQueryConstraint, - usingPostForQuery: usingPostForQuery, - keyValueStore: keyValueStore, - requestCachePolicy: requestCachePolicy, - cacheMemoryCapacity: cacheMemoryCapacity, - cacheDiskCapacity: cacheDiskCapacity, - deletingKeychainIfNeeded: deletingKeychainIfNeeded, - httpAdditionalHeaders: httpAdditionalHeaders, - maxConnectionAttempts: maxConnectionAttempts, - authentication: authentication) - configuration.isMigratingFromObjcSDK = migratingFromObjcSDK - initialize(configuration: configuration) - } +/** + Configure the Parse Swift client. This should only be used when starting your app. Typically in the + `application(... didFinishLaunchingWithOptions launchOptions...)`. + - parameter applicationId: The application id for your Parse application. + - parameter clientKey: The client key for your Parse application. + - parameter masterKey: The master key for your Parse application. This key should only be + specified when using the SDK on a server. + - parameter serverURL: The server URL to connect to Parse Server. + - parameter liveQueryServerURL: The live query server URL to connect to Parse Server. + - parameter allowingCustomObjectIds: Allows objectIds to be created on the client. + side for each object. Must be enabled on the server to work. + - parameter usingTransactions: Use transactions when saving/updating multiple objects. + - parameter usingEqualQueryConstraint: Use the **$eq** query constraint when querying. + - parameter usingPostForQuery: Use **POST** instead of **GET** when making query calls. + Defaults to **false**. + - parameter keyValueStore: A key/value store that conforms to the `ParseKeyValueStore` + protocol. Defaults to `nil` in which one will be created an memory, but never persisted. For Linux, this + this is the only store available since there is no Keychain. Linux users should replace this store with an + encrypted one. + - parameter requestCachePolicy: The default caching policy for all http requests that determines + when to return a response from the cache. Defaults to `useProtocolCachePolicy`. See Apple's [documentation](https://developer.apple.com/documentation/foundation/url_loading_system/accessing_cached_data) + for more info. + - parameter cacheMemoryCapacity: The memory capacity of the cache, in bytes. Defaults to 512KB. + - parameter cacheDiskCapacity: The disk capacity of the cache, in bytes. Defaults to 10MB. + - parameter migratingFromObjcSDK: If your app previously used the iOS Objective-C SDK, setting this value + to **true** will attempt to migrate relevant data stored in the Keychain to ParseSwift. Defaults to **false**. + - parameter deletingKeychainIfNeeded: Deletes the Parse Keychain when the app is running for the first time. + Defaults to **false**. + - parameter httpAdditionalHeaders: A dictionary of additional headers to send with requests. See Apple's + [documentation](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1411532-httpadditionalheaders) + for more info. + - parameter authentication: A callback block that will be used to receive/accept/decline network challenges. + Defaults to `nil` in which the SDK will use the default OS authentication methods for challenges. + It should have the following argument signature: `(challenge: URLAuthenticationChallenge, + completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void`. + See Apple's [documentation](https://developer.apple.com/documentation/foundation/urlsessiontaskdelegate/1411595-urlsession) for more for details. + - warning: `usingTransactions` is experimental. + - warning: It is recomended to only specify `masterKey` when using the SDK on a server. Do not use this key on the client. + - warning: Setting `usingPostForQuery` to **true** will require all queries to access the server instead of following the `requestCachePolicy`. + */ +@available(*, deprecated, message: "Remove the migratingFromObjcSDK argument") +public func initialize( + applicationId: String, + clientKey: String? = nil, + masterKey: String? = nil, + serverURL: URL, + liveQueryServerURL: URL? = nil, + allowingCustomObjectIds: Bool = false, + usingTransactions: Bool = false, + usingEqualQueryConstraint: Bool = false, + usingPostForQuery: Bool = false, + keyValueStore: ParseKeyValueStore? = nil, + requestCachePolicy: URLRequest.CachePolicy = .useProtocolCachePolicy, + cacheMemoryCapacity: Int = 512_000, + cacheDiskCapacity: Int = 10_000_000, + migratingFromObjcSDK: Bool = false, + deletingKeychainIfNeeded: Bool = false, + httpAdditionalHeaders: [AnyHashable: Any]? = nil, + maxConnectionAttempts: Int = 5, + authentication: ((URLAuthenticationChallenge, + (URLSession.AuthChallengeDisposition, + URLCredential?) -> Void) -> Void)? = nil +) { + var configuration = ParseConfiguration(applicationId: applicationId, + clientKey: clientKey, + masterKey: masterKey, + serverURL: serverURL, + liveQueryServerURL: liveQueryServerURL, + allowingCustomObjectIds: allowingCustomObjectIds, + usingTransactions: usingTransactions, + usingEqualQueryConstraint: usingEqualQueryConstraint, + usingPostForQuery: usingPostForQuery, + keyValueStore: keyValueStore, + requestCachePolicy: requestCachePolicy, + cacheMemoryCapacity: cacheMemoryCapacity, + cacheDiskCapacity: cacheDiskCapacity, + deletingKeychainIfNeeded: deletingKeychainIfNeeded, + httpAdditionalHeaders: httpAdditionalHeaders, + maxConnectionAttempts: maxConnectionAttempts, + authentication: authentication) + configuration.isMigratingFromObjcSDK = migratingFromObjcSDK + initialize(configuration: configuration) +} - internal static func initialize(applicationId: String, - clientKey: String? = nil, - masterKey: String? = nil, - serverURL: URL, - liveQueryServerURL: URL? = nil, - allowingCustomObjectIds: Bool = false, - usingTransactions: Bool = false, - usingEqualQueryConstraint: Bool = false, - usingPostForQuery: Bool = false, - keyValueStore: ParseKeyValueStore? = nil, - requestCachePolicy: URLRequest.CachePolicy = .useProtocolCachePolicy, - cacheMemoryCapacity: Int = 512_000, - cacheDiskCapacity: Int = 10_000_000, - migratingFromObjcSDK: Bool = false, - deletingKeychainIfNeeded: Bool = false, - httpAdditionalHeaders: [AnyHashable: Any]? = nil, - maxConnectionAttempts: Int = 5, - testing: Bool = false, - authentication: ((URLAuthenticationChallenge, - (URLSession.AuthChallengeDisposition, - URLCredential?) -> Void) -> Void)? = nil) { - var configuration = ParseConfiguration(applicationId: applicationId, - clientKey: clientKey, - masterKey: masterKey, - serverURL: serverURL, - liveQueryServerURL: liveQueryServerURL, - allowingCustomObjectIds: allowingCustomObjectIds, - usingTransactions: usingTransactions, - usingEqualQueryConstraint: usingEqualQueryConstraint, - usingPostForQuery: usingPostForQuery, - keyValueStore: keyValueStore, - requestCachePolicy: requestCachePolicy, - cacheMemoryCapacity: cacheMemoryCapacity, - cacheDiskCapacity: cacheDiskCapacity, - deletingKeychainIfNeeded: deletingKeychainIfNeeded, - httpAdditionalHeaders: httpAdditionalHeaders, - maxConnectionAttempts: maxConnectionAttempts, - authentication: authentication) - configuration.isMigratingFromObjcSDK = migratingFromObjcSDK - configuration.isTestingSDK = testing - initialize(configuration: configuration) - } +internal func initialize(applicationId: String, + clientKey: String? = nil, + masterKey: String? = nil, + serverURL: URL, + liveQueryServerURL: URL? = nil, + allowingCustomObjectIds: Bool = false, + usingTransactions: Bool = false, + usingEqualQueryConstraint: Bool = false, + usingPostForQuery: Bool = false, + keyValueStore: ParseKeyValueStore? = nil, + requestCachePolicy: URLRequest.CachePolicy = .useProtocolCachePolicy, + cacheMemoryCapacity: Int = 512_000, + cacheDiskCapacity: Int = 10_000_000, + migratingFromObjcSDK: Bool = false, + deletingKeychainIfNeeded: Bool = false, + httpAdditionalHeaders: [AnyHashable: Any]? = nil, + maxConnectionAttempts: Int = 5, + testing: Bool = false, + authentication: ((URLAuthenticationChallenge, + (URLSession.AuthChallengeDisposition, + URLCredential?) -> Void) -> Void)? = nil) { + var configuration = ParseConfiguration(applicationId: applicationId, + clientKey: clientKey, + masterKey: masterKey, + serverURL: serverURL, + liveQueryServerURL: liveQueryServerURL, + allowingCustomObjectIds: allowingCustomObjectIds, + usingTransactions: usingTransactions, + usingEqualQueryConstraint: usingEqualQueryConstraint, + usingPostForQuery: usingPostForQuery, + keyValueStore: keyValueStore, + requestCachePolicy: requestCachePolicy, + cacheMemoryCapacity: cacheMemoryCapacity, + cacheDiskCapacity: cacheDiskCapacity, + deletingKeychainIfNeeded: deletingKeychainIfNeeded, + httpAdditionalHeaders: httpAdditionalHeaders, + maxConnectionAttempts: maxConnectionAttempts, + authentication: authentication) + configuration.isMigratingFromObjcSDK = migratingFromObjcSDK + configuration.isTestingSDK = testing + initialize(configuration: configuration) +} #if !os(Linux) && !os(Android) && !os(Windows) - /** - Sets all of the items in the Parse Keychain to a specific access group. - Apps in the same access group can share Keychain items. See Apple's - [documentation](https://developer.apple.com/documentation/security/ksecattraccessgroup) - for more information. - - parameter accessGroup: The name of the access group. - - parameter synchronizeAcrossDevices: **true** to synchronize all necessary Parse Keychain items to - other devices using iCloud. See Apple's [documentation](https://developer.apple.com/documentation/security/ksecattrsynchronizable) - for more information. **false** to disable synchronization. - - throws: An error of type `ParseError`. - - returns: **true** if the Keychain was moved to the new `accessGroup`, **false** otherwise. - - warning: Setting `synchronizeAcrossDevices == true` requires `accessGroup` to be - set to a valid [keychain group](https://developer.apple.com/documentation/security/ksecattraccessgroup). - */ - @discardableResult static public func setAccessGroup(_ accessGroup: String?, - synchronizeAcrossDevices: Bool) throws -> Bool { - if synchronizeAcrossDevices && accessGroup == nil { - throw ParseError(code: .unknownError, - message: "\"accessGroup\" must be set to a valid string when \"synchronizeAcrossDevices == true\"") - } - guard let currentAccessGroup = ParseKeychainAccessGroup.current else { - throw ParseError(code: .unknownError, - message: "Problem unwrapping the current access group. Did you initialize the SDK before calling this method?") - } - let newKeychainAccessGroup = ParseKeychainAccessGroup(accessGroup: accessGroup, - isSyncingKeychainAcrossDevices: synchronizeAcrossDevices) - guard newKeychainAccessGroup != currentAccessGroup else { - ParseKeychainAccessGroup.current = newKeychainAccessGroup - return true - } - do { - try KeychainStore.shared.copy(KeychainStore.shared, - oldAccessGroup: currentAccessGroup, - newAccessGroup: newKeychainAccessGroup) - ParseKeychainAccessGroup.current = newKeychainAccessGroup - } catch { - ParseKeychainAccessGroup.current = currentAccessGroup - throw error - } +/** + Sets all of the items in the Parse Keychain to a specific access group. + Apps in the same access group can share Keychain items. See Apple's + [documentation](https://developer.apple.com/documentation/security/ksecattraccessgroup) + for more information. + - parameter accessGroup: The name of the access group. + - parameter synchronizeAcrossDevices: **true** to synchronize all necessary Parse Keychain items to + other devices using iCloud. See Apple's [documentation](https://developer.apple.com/documentation/security/ksecattrsynchronizable) + for more information. **false** to disable synchronization. + - throws: An error of type `ParseError`. + - returns: **true** if the Keychain was moved to the new `accessGroup`, **false** otherwise. + - warning: Setting `synchronizeAcrossDevices == true` requires `accessGroup` to be + set to a valid [keychain group](https://developer.apple.com/documentation/security/ksecattraccessgroup). + */ +@discardableResult public func setAccessGroup(_ accessGroup: String?, + synchronizeAcrossDevices: Bool) throws -> Bool { + if synchronizeAcrossDevices && accessGroup == nil { + throw ParseError(code: .unknownError, + message: "\"accessGroup\" must be set to a valid string when \"synchronizeAcrossDevices == true\"") + } + guard let currentAccessGroup = ParseKeychainAccessGroup.current else { + throw ParseError(code: .unknownError, + message: "Problem unwrapping the current access group. Did you initialize the SDK before calling this method?") + } + let newKeychainAccessGroup = ParseKeychainAccessGroup(accessGroup: accessGroup, + isSyncingKeychainAcrossDevices: synchronizeAcrossDevices) + guard newKeychainAccessGroup != currentAccessGroup else { + ParseKeychainAccessGroup.current = newKeychainAccessGroup return true } + do { + try KeychainStore.shared.copy(KeychainStore.shared, + oldAccessGroup: currentAccessGroup, + newAccessGroup: newKeychainAccessGroup) + ParseKeychainAccessGroup.current = newKeychainAccessGroup + } catch { + ParseKeychainAccessGroup.current = currentAccessGroup + throw error + } + return true +} #endif - static internal func deleteKeychainIfNeeded() { - #if !os(Linux) && !os(Android) && !os(Windows) - // Clear items out of the Keychain on app first run. - if UserDefaults.standard.object(forKey: ParseConstants.bundlePrefix) == nil { - if Self.configuration.isDeletingKeychainIfNeeded { - try? KeychainStore.old.deleteAll() - try? KeychainStore.shared.deleteAll() - } - ParseSwift.configuration.keychainAccessGroup = .init() - clearCache() - // This is no longer the first run - UserDefaults.standard.setValue(String(ParseConstants.bundlePrefix), - forKey: ParseConstants.bundlePrefix) - UserDefaults.standard.synchronize() +internal func deleteKeychainIfNeeded() { + #if !os(Linux) && !os(Android) && !os(Windows) + // Clear items out of the Keychain on app first run. + if UserDefaults.standard.object(forKey: ParseConstants.bundlePrefix) == nil { + if Parse.configuration.isDeletingKeychainIfNeeded { + try? KeychainStore.old.deleteAll() + try? KeychainStore.shared.deleteAll() } - #endif + Parse.configuration.keychainAccessGroup = .init() + clearCache() + // This is no longer the first run + UserDefaults.standard.setValue(String(ParseConstants.bundlePrefix), + forKey: ParseConstants.bundlePrefix) + UserDefaults.standard.synchronize() } + #endif +} - /** - Update the authentication callback. - - parameter authentication: A callback block that will be used to receive/accept/decline network challenges. - Defaults to `nil` in which the SDK will use the default OS authentication methods for challenges. - It should have the following argument signature: `(challenge: URLAuthenticationChallenge, - completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void`. - See Apple's [documentation](https://developer.apple.com/documentation/foundation/urlsessiontaskdelegate/1411595-urlsession) for more for details. - */ - static public func updateAuthentication(_ authentication: ((URLAuthenticationChallenge, - (URLSession.AuthChallengeDisposition, - URLCredential?) -> Void) -> Void)?) { - Self.sessionDelegate = ParseURLSessionDelegate(callbackQueue: .main, - authentication: authentication) - URLSession.updateParseURLSession() - } +/** + Update the authentication callback. + - parameter authentication: A callback block that will be used to receive/accept/decline network challenges. + Defaults to `nil` in which the SDK will use the default OS authentication methods for challenges. + It should have the following argument signature: `(challenge: URLAuthenticationChallenge, + completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void`. + See Apple's [documentation](https://developer.apple.com/documentation/foundation/urlsessiontaskdelegate/1411595-urlsession) for more for details. + */ +public func updateAuthentication(_ authentication: ((URLAuthenticationChallenge, + (URLSession.AuthChallengeDisposition, + URLCredential?) -> Void) -> Void)?) { + Parse.sessionDelegate = ParseURLSessionDelegate(callbackQueue: .main, + authentication: authentication) + URLSession.updateParseURLSession() +} - #if !os(Linux) && !os(Android) && !os(Windows) - /** - Delete the Parse iOS Objective-C SDK Keychain from the device. - - note: ParseSwift uses a different Keychain. After migration, the iOS Objective-C SDK Keychain is no longer needed. - - warning: The keychain cannot be recovered after deletion. - */ - static public func deleteObjectiveCKeychain() throws { - try KeychainStore.objectiveC?.deleteAll() - } - #endif +#if !os(Linux) && !os(Android) && !os(Windows) +/** + Delete the Parse iOS Objective-C SDK Keychain from the device. + - note: ParseSwift uses a different Keychain. After migration, the iOS Objective-C SDK Keychain is no longer needed. + - warning: The keychain cannot be recovered after deletion. + */ +public func deleteObjectiveCKeychain() throws { + try KeychainStore.objectiveC?.deleteAll() +} +#endif - /** - Manually remove all stored cache. - - note: The OS typically handles this automatically. - */ - static public func clearCache() { - URLSession.parse.configuration.urlCache?.removeAllCachedResponses() - } +/** + Manually remove all stored cache. + - note: The OS typically handles this automatically. + */ +public func clearCache() { + URLSession.parse.configuration.urlCache?.removeAllCachedResponses() } diff --git a/Sources/ParseSwift/ParseConstants.swift b/Sources/ParseSwift/ParseConstants.swift index 5e54c38ab..9565c055e 100644 --- a/Sources/ParseSwift/ParseConstants.swift +++ b/Sources/ParseSwift/ParseConstants.swift @@ -10,7 +10,7 @@ import Foundation enum ParseConstants { static let sdk = "swift" - static let version = "4.9.1" + static let version = "4.9.2" static let fileManagementDirectory = "parse/" static let fileManagementPrivateDocumentsDirectory = "Private Documents/" static let fileManagementLibraryDirectory = "Library/" diff --git a/Sources/ParseSwift/Protocols/Objectable.swift b/Sources/ParseSwift/Protocols/Objectable.swift index 5d9f9bd4c..62643b97e 100644 --- a/Sources/ParseSwift/Protocols/Objectable.swift +++ b/Sources/ParseSwift/Protocols/Objectable.swift @@ -74,7 +74,7 @@ extension Objectable { /// Specifies if a `ParseObject` has been saved. public var isSaved: Bool { - if !ParseSwift.configuration.isAllowingCustomObjectIds { + if !Parse.configuration.isAllowingCustomObjectIds { return objectId != nil } else { return objectId != nil && createdAt != nil @@ -86,7 +86,7 @@ extension Objectable { } func endpoint(_ method: API.Method) -> API.Endpoint { - if !ParseSwift.configuration.isAllowingCustomObjectIds || method != .POST { + if !Parse.configuration.isAllowingCustomObjectIds || method != .POST { return endpoint } else { return .objects(className: className) diff --git a/Sources/ParseSwift/Storage/KeychainStore.swift b/Sources/ParseSwift/Storage/KeychainStore.swift index 2191c4127..637478da6 100644 --- a/Sources/ParseSwift/Storage/KeychainStore.swift +++ b/Sources/ParseSwift/Storage/KeychainStore.swift @@ -130,7 +130,7 @@ struct KeychainStore: SecureStorage { query[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly as String } #if os(macOS) - if !ParseSwift.configuration.isTestingSDK { + if !Parse.configuration.isTestingSDK { query[kSecUseDataProtectionKeychain as String] = kCFBooleanTrue } #endif @@ -243,7 +243,7 @@ extension KeychainStore { func object(forKey key: String) -> T? where T: Decodable { guard let data = synchronizationQueue.sync(execute: { () -> Data? in return self.data(forKey: key, - accessGroup: ParseSwift.configuration.keychainAccessGroup) + accessGroup: Parse.configuration.keychainAccessGroup) }) else { return nil } @@ -263,8 +263,8 @@ extension KeychainStore { let data = try ParseCoding.jsonEncoder().encode(object) try set(data, forKey: key, - oldAccessGroup: ParseSwift.configuration.keychainAccessGroup, - newAccessGroup: ParseSwift.configuration.keychainAccessGroup) + oldAccessGroup: Parse.configuration.keychainAccessGroup, + newAccessGroup: Parse.configuration.keychainAccessGroup) return true } catch { return false @@ -283,7 +283,7 @@ extension KeychainStore { func removeObject(forKey key: String) -> Bool { return synchronizationQueue.sync { return removeObject(forKey: key, - accessGroup: ParseSwift.configuration.keychainAccessGroup) + accessGroup: Parse.configuration.keychainAccessGroup) } } @@ -306,8 +306,8 @@ extension KeychainStore { continue } let removedDefaultObject = self.removeObject(forKey: key, - accessGroup: ParseSwift.configuration.keychainAccessGroup) - var mutatedKeychainAccessGroup = ParseSwift.configuration.keychainAccessGroup + accessGroup: Parse.configuration.keychainAccessGroup) + var mutatedKeychainAccessGroup = Parse.configuration.keychainAccessGroup mutatedKeychainAccessGroup.isSyncingKeychainAcrossDevices.toggle() let removedToggledObject = self.removeObject(forKey: key, accessGroup: mutatedKeychainAccessGroup) diff --git a/Sources/ParseSwift/Storage/ParseFileManager.swift b/Sources/ParseSwift/Storage/ParseFileManager.swift index b6b4f93bb..4542cf4ec 100644 --- a/Sources/ParseSwift/Storage/ParseFileManager.swift +++ b/Sources/ParseSwift/Storage/ParseFileManager.swift @@ -88,7 +88,7 @@ public struct ParseFileManager { /// - returns: If an instance cannot be created, nil is returned. public init?() { #if os(Linux) || os(Android) || os(Windows) - let applicationId = ParseSwift.configuration.applicationId + let applicationId = Parse.configuration.applicationId applicationIdentifier = "\(ParseConstants.bundlePrefix).\(applicationId)" #else if let identifier = Bundle.main.bundleIdentifier { diff --git a/Sources/ParseSwift/Types/ParseKeychainAccessGroup.swift b/Sources/ParseSwift/Types/ParseKeychainAccessGroup.swift index e016ee912..bfe9df57f 100644 --- a/Sources/ParseSwift/Types/ParseKeychainAccessGroup.swift +++ b/Sources/ParseSwift/Types/ParseKeychainAccessGroup.swift @@ -32,19 +32,19 @@ struct ParseKeychainAccessGroup: ParseTypeable, Hashable { let defaultKeychainAccessGroup = Self() try? ParseStorage.shared.set(defaultKeychainAccessGroup, for: ParseStorage.Keys.currentAccessGroup) try? KeychainStore.shared.set(defaultKeychainAccessGroup, for: ParseStorage.Keys.currentAccessGroup) - ParseSwift.configuration.keychainAccessGroup = defaultKeychainAccessGroup + Parse.configuration.keychainAccessGroup = defaultKeychainAccessGroup return } try? ParseStorage.shared.set(updatedKeychainAccessGroup, for: ParseStorage.Keys.currentAccessGroup) try? KeychainStore.shared.set(updatedKeychainAccessGroup, for: ParseStorage.Keys.currentAccessGroup) - ParseSwift.configuration.keychainAccessGroup = updatedKeychainAccessGroup + Parse.configuration.keychainAccessGroup = updatedKeychainAccessGroup } } static func deleteCurrentContainerFromKeychain() { try? ParseStorage.shared.delete(valueFor: ParseStorage.Keys.currentAccessGroup) try? KeychainStore.shared.delete(valueFor: ParseStorage.Keys.currentAccessGroup) - ParseSwift.configuration.keychainAccessGroup = Self() + Parse.configuration.keychainAccessGroup = Self() } } #endif diff --git a/Sources/ParseSwift/Types/Query.swift b/Sources/ParseSwift/Types/Query.swift index 5da83add2..9fdc761b4 100644 --- a/Sources/ParseSwift/Types/Query.swift +++ b/Sources/ParseSwift/Types/Query.swift @@ -1446,7 +1446,7 @@ extension Query: Queryable { extension Query { func findCommand() throws -> API.NonParseBodyCommand, [ResultType]> { - if !ParseSwift.configuration.isUsingPostForQuery { + if !Parse.configuration.isUsingPostForQuery { return API.NonParseBodyCommand(method: .GET, path: endpoint, params: try getQueryParameters()) { @@ -1464,7 +1464,7 @@ extension Query { func firstCommand() throws -> API.NonParseBodyCommand, ResultType> { var query = self query.limit = 1 - if !ParseSwift.configuration.isUsingPostForQuery { + if !Parse.configuration.isUsingPostForQuery { return API.NonParseBodyCommand(method: .GET, path: query.endpoint, params: try getQueryParameters()) { @@ -1489,7 +1489,7 @@ extension Query { var query = self query.limit = 1 query.isCount = true - if !ParseSwift.configuration.isUsingPostForQuery { + if !Parse.configuration.isUsingPostForQuery { return API.NonParseBodyCommand(method: .GET, path: query.endpoint, params: try getQueryParameters()) { @@ -1507,7 +1507,7 @@ extension Query { func withCountCommand() throws -> API.NonParseBodyCommand, ([ResultType], Int)> { var query = self query.isCount = true - if !ParseSwift.configuration.isUsingPostForQuery { + if !Parse.configuration.isUsingPostForQuery { return API.NonParseBodyCommand(method: .GET, path: query.endpoint, params: try getQueryParameters()) { @@ -1526,7 +1526,7 @@ extension Query { func aggregateCommand() throws -> API.NonParseBodyCommand, [ResultType]> { let body = AggregateBody(query: self) - if !ParseSwift.configuration.isUsingPostForQuery { + if !Parse.configuration.isUsingPostForQuery { return API.NonParseBodyCommand(method: .GET, path: .aggregate(className: T.className), params: try body.getQueryParameters()) { @@ -1545,7 +1545,7 @@ extension Query { var query = self query.distinct = key let body = DistinctBody(query: query) - if !ParseSwift.configuration.isUsingPostForQuery { + if !Parse.configuration.isUsingPostForQuery { return API.NonParseBodyCommand(method: .GET, path: .aggregate(className: T.className), params: try body.getQueryParameters()) { @@ -1563,7 +1563,7 @@ extension Query { func findExplainCommand() throws -> API.NonParseBodyCommand, [U]> { var query = self query.explain = true - if !ParseSwift.configuration.isUsingPostForQuery { + if !Parse.configuration.isUsingPostForQuery { return API.NonParseBodyCommand(method: .GET, path: query.endpoint, params: try query.getQueryParameters()) { @@ -1582,7 +1582,7 @@ extension Query { var query = self query.limit = 1 query.explain = true - if !ParseSwift.configuration.isUsingPostForQuery { + if !Parse.configuration.isUsingPostForQuery { return API.NonParseBodyCommand(method: .GET, path: query.endpoint, params: try query.getQueryParameters()) { @@ -1616,7 +1616,7 @@ extension Query { query.limit = 1 query.isCount = true query.explain = true - if !ParseSwift.configuration.isUsingPostForQuery { + if !Parse.configuration.isUsingPostForQuery { return API.NonParseBodyCommand(method: .GET, path: query.endpoint, params: try query.getQueryParameters()) { @@ -1635,7 +1635,7 @@ extension Query { var query = self query.isCount = true query.explain = true - if !ParseSwift.configuration.isUsingPostForQuery { + if !Parse.configuration.isUsingPostForQuery { return API.NonParseBodyCommand(method: .GET, path: query.endpoint, params: try query.getQueryParameters()) { @@ -1654,7 +1654,7 @@ extension Query { var query = self query.explain = true let body = AggregateBody(query: query) - if !ParseSwift.configuration.isUsingPostForQuery { + if !Parse.configuration.isUsingPostForQuery { return API.NonParseBodyCommand(method: .GET, path: .aggregate(className: T.className), params: try body.getQueryParameters()) { @@ -1675,7 +1675,7 @@ extension Query { query.explain = true query.distinct = key let body = DistinctBody(query: query) - if !ParseSwift.configuration.isUsingPostForQuery { + if !Parse.configuration.isUsingPostForQuery { return API.NonParseBodyCommand(method: .GET, path: .aggregate(className: T.className), params: try body.getQueryParameters()) { @@ -1691,7 +1691,7 @@ extension Query { func findExplainMongoCommand() throws -> API.NonParseBodyCommand, [U]> { var query = self query.explain = true - if !ParseSwift.configuration.isUsingPostForQuery { + if !Parse.configuration.isUsingPostForQuery { return API.NonParseBodyCommand(method: .GET, path: query.endpoint, params: try query.getQueryParameters()) { @@ -1710,7 +1710,7 @@ extension Query { var query = self query.limit = 1 query.explain = true - if !ParseSwift.configuration.isUsingPostForQuery { + if !Parse.configuration.isUsingPostForQuery { return API.NonParseBodyCommand(method: .GET, path: query.endpoint, params: try query.getQueryParameters()) { @@ -1740,7 +1740,7 @@ extension Query { query.limit = 1 query.isCount = true query.explain = true - if !ParseSwift.configuration.isUsingPostForQuery { + if !Parse.configuration.isUsingPostForQuery { return API.NonParseBodyCommand(method: .GET, path: query.endpoint, params: try query.getQueryParameters()) { @@ -1759,7 +1759,7 @@ extension Query { var query = self query.isCount = true query.explain = true - if !ParseSwift.configuration.isUsingPostForQuery { + if !Parse.configuration.isUsingPostForQuery { return API.NonParseBodyCommand(method: .GET, path: query.endpoint, params: try query.getQueryParameters()) { @@ -1779,7 +1779,7 @@ extension Query { var query = self query.explain = true let body = AggregateBody(query: query) - if !ParseSwift.configuration.isUsingPostForQuery { + if !Parse.configuration.isUsingPostForQuery { return API.NonParseBodyCommand(method: .GET, path: .aggregate(className: T.className), params: try body.getQueryParameters()) { @@ -1800,7 +1800,7 @@ extension Query { query.explain = true query.distinct = key let body = DistinctBody(query: query) - if !ParseSwift.configuration.isUsingPostForQuery { + if !Parse.configuration.isUsingPostForQuery { return API.NonParseBodyCommand(method: .GET, path: .aggregate(className: T.className), params: try body.getQueryParameters()) { diff --git a/Sources/ParseSwift/Types/QueryConstraint.swift b/Sources/ParseSwift/Types/QueryConstraint.swift index 23dfa275b..fde656542 100644 --- a/Sources/ParseSwift/Types/QueryConstraint.swift +++ b/Sources/ParseSwift/Types/QueryConstraint.swift @@ -156,7 +156,7 @@ public func == (key: String, value: T) -> QueryConstraint where T: Codable { public func equalTo (key: String, value: T, //swiftlint:disable:next line_length - usingEqComparator: Bool = ParseSwift.configuration.isUsingEqualQueryConstraint) -> QueryConstraint where T: Codable { + usingEqComparator: Bool = configuration.isUsingEqualQueryConstraint) -> QueryConstraint where T: Codable { if !usingEqComparator { return QueryConstraint(key: key, value: value) } else { @@ -195,7 +195,7 @@ public func == (key: String, value: T) throws -> QueryConstraint where T: Par public func equalTo (key: String, value: T, //swiftlint:disable:next line_length - usingEqComparator: Bool = ParseSwift.configuration.isUsingEqualQueryConstraint) throws -> QueryConstraint where T: ParseObject { + usingEqComparator: Bool = configuration.isUsingEqualQueryConstraint) throws -> QueryConstraint where T: ParseObject { if !usingEqComparator { return try QueryConstraint(key: key, value: value.toPointer()) } else { diff --git a/Tests/ParseSwiftTests/ExtensionsTests.swift b/Tests/ParseSwiftTests/ExtensionsTests.swift index 08595d973..3712b7e30 100644 --- a/Tests/ParseSwiftTests/ExtensionsTests.swift +++ b/Tests/ParseSwiftTests/ExtensionsTests.swift @@ -41,7 +41,7 @@ class ExtensionsTests: XCTestCase { func testURLSession() throws { let headerKey = "User-Agent" let headerValue = "ParseSwift/\(ParseConstants.version) (\(ParseConstants.deviceType)" - ParseSwift.configuration.httpAdditionalHeaders = [headerKey: headerValue] + Parse.configuration.httpAdditionalHeaders = [headerKey: headerValue] let session = URLSession.parse XCTAssertNotNil(session.configuration.urlCache) XCTAssertEqual(session.configuration.requestCachePolicy, ParseSwift.configuration.requestCachePolicy) diff --git a/Tests/ParseSwiftTests/InitializeSDKTests.swift b/Tests/ParseSwiftTests/InitializeSDKTests.swift index 80807515d..7824009d3 100644 --- a/Tests/ParseSwiftTests/InitializeSDKTests.swift +++ b/Tests/ParseSwiftTests/InitializeSDKTests.swift @@ -42,9 +42,9 @@ class InitializeSDKTests: XCTestCase { XCTFail("Should create valid URL") return } - ParseSwift.configuration = .init(applicationId: "applicationId", - serverURL: url) - ParseSwift.configuration.isTestingSDK = true + Parse.configuration = .init(applicationId: "applicationId", + serverURL: url) + Parse.configuration.isTestingSDK = true } override func tearDownWithError() throws { @@ -90,7 +90,7 @@ class InitializeSDKTests: XCTestCase { XCTFail("Should have unwrapped") return } - ParseSwift.configuration = ParseConfiguration(applicationId: "yo", + Parse.configuration = ParseConfiguration(applicationId: "yo", serverURL: server, isDeletingKeychainIfNeeded: false) let key = "Hello" @@ -274,9 +274,9 @@ class InitializeSDKTests: XCTestCase { testing: true) { (_, credential) in credential(.performDefaultHandling, nil) } - XCTAssertNotNil(ParseSwift.sessionDelegate.authentication) + XCTAssertNotNil(Parse.sessionDelegate.authentication) ParseSwift.updateAuthentication(nil) - XCTAssertNil(ParseSwift.sessionDelegate.authentication) + XCTAssertNil(Parse.sessionDelegate.authentication) } #if !os(Linux) && !os(Android) && !os(Windows) diff --git a/Tests/ParseSwiftTests/ParseFileAsyncTests.swift b/Tests/ParseSwiftTests/ParseFileAsyncTests.swift index 3da17c34e..a70396646 100644 --- a/Tests/ParseSwiftTests/ParseFileAsyncTests.swift +++ b/Tests/ParseSwiftTests/ParseFileAsyncTests.swift @@ -273,29 +273,29 @@ class ParseFileAsyncTests: XCTestCase { // swiftlint:disable:this type_body_leng let downloadCompletion: ((URLSessionDownloadTask, Int64, Int64, Int64) -> Void) = { (_: URLSessionDownloadTask, _: Int64, _: Int64, _: Int64) -> Void in } // Add tasks - ParseSwift.sessionDelegate.streamDelegates[task] = .init(data: .init()) - XCTAssertEqual(ParseSwift.sessionDelegate.streamDelegates.count, 1) - await ParseSwift.sessionDelegate.delegates.updateTask(task, queue: DispatchQueue.main) - let taskCount = await ParseSwift.sessionDelegate.delegates.taskCallbackQueues.count + Parse.sessionDelegate.streamDelegates[task] = .init(data: .init()) + XCTAssertEqual(Parse.sessionDelegate.streamDelegates.count, 1) + await Parse.sessionDelegate.delegates.updateTask(task, queue: DispatchQueue.main) + let taskCount = await Parse.sessionDelegate.delegates.taskCallbackQueues.count XCTAssertEqual(taskCount, 1) - await ParseSwift.sessionDelegate.delegates.updateUpload(task, callback: uploadCompletion) - let uploadCount = await ParseSwift.sessionDelegate.delegates.uploadDelegates.count + await Parse.sessionDelegate.delegates.updateUpload(task, callback: uploadCompletion) + let uploadCount = await Parse.sessionDelegate.delegates.uploadDelegates.count XCTAssertEqual(uploadCount, 1) - await ParseSwift.sessionDelegate.delegates.updateDownload(downloadTask, callback: downloadCompletion) - let downloadCount = await ParseSwift.sessionDelegate.delegates.downloadDelegates.count + await Parse.sessionDelegate.delegates.updateDownload(downloadTask, callback: downloadCompletion) + let downloadCount = await Parse.sessionDelegate.delegates.downloadDelegates.count XCTAssertEqual(downloadCount, 1) // Remove tasks - ParseSwift.sessionDelegate.streamDelegates.removeValue(forKey: task) - XCTAssertEqual(ParseSwift.sessionDelegate.streamDelegates.count, 0) - await ParseSwift.sessionDelegate.delegates.removeTask(task) - let taskCount2 = await ParseSwift.sessionDelegate.delegates.taskCallbackQueues.count + Parse.sessionDelegate.streamDelegates.removeValue(forKey: task) + XCTAssertEqual(Parse.sessionDelegate.streamDelegates.count, 0) + await Parse.sessionDelegate.delegates.removeTask(task) + let taskCount2 = await Parse.sessionDelegate.delegates.taskCallbackQueues.count XCTAssertEqual(taskCount2, 0) - await ParseSwift.sessionDelegate.delegates.removeUpload(task) - let uploadCount2 = await ParseSwift.sessionDelegate.delegates.uploadDelegates.count + await Parse.sessionDelegate.delegates.removeUpload(task) + let uploadCount2 = await Parse.sessionDelegate.delegates.uploadDelegates.count XCTAssertEqual(uploadCount2, 0) - await ParseSwift.sessionDelegate.delegates.removeDownload(downloadTask) - let downloadCount2 = await ParseSwift.sessionDelegate.delegates.downloadDelegates.count + await Parse.sessionDelegate.delegates.removeDownload(downloadTask) + let downloadCount2 = await Parse.sessionDelegate.delegates.downloadDelegates.count XCTAssertEqual(downloadCount2, 0) } @@ -313,9 +313,9 @@ class ParseFileAsyncTests: XCTestCase { // swiftlint:disable:this type_body_leng let uploadCompletion: ((URLSessionTask, Int64, Int64, Int64) -> Void) = { (_: URLSessionTask, _: Int64, sent: Int64, total: Int64) -> Void in if sent < total { Task { - let uploadCount = await ParseSwift.sessionDelegate.delegates.uploadDelegates.count - let taskCount = await ParseSwift.sessionDelegate.delegates.taskCallbackQueues.count - ParseSwift.sessionDelegate.urlSession(URLSession.parse, + let uploadCount = await Parse.sessionDelegate.delegates.uploadDelegates.count + let taskCount = await Parse.sessionDelegate.delegates.taskCallbackQueues.count + Parse.sessionDelegate.urlSession(URLSession.parse, task: task, didCompleteWithError: nil) DispatchQueue.main.asyncAfter(deadline: .now() + 4) { @@ -324,8 +324,8 @@ class ParseFileAsyncTests: XCTestCase { // swiftlint:disable:this type_body_leng expectation1.fulfill() Task { - let uploadCount = await ParseSwift.sessionDelegate.delegates.uploadDelegates.count - let taskCount = await ParseSwift.sessionDelegate.delegates.taskCallbackQueues.count + let uploadCount = await Parse.sessionDelegate.delegates.uploadDelegates.count + let taskCount = await Parse.sessionDelegate.delegates.taskCallbackQueues.count XCTAssertEqual(uploadCount, 0) XCTAssertEqual(taskCount, 0) expectation2.fulfill() @@ -336,10 +336,10 @@ class ParseFileAsyncTests: XCTestCase { // swiftlint:disable:this type_body_leng } // Add tasks - await ParseSwift.sessionDelegate.delegates.updateUpload(task, callback: uploadCompletion) - await ParseSwift.sessionDelegate.delegates.updateTask(task, queue: queue) + await Parse.sessionDelegate.delegates.updateUpload(task, callback: uploadCompletion) + await Parse.sessionDelegate.delegates.updateTask(task, queue: queue) - ParseSwift.sessionDelegate.urlSession(URLSession.parse, + Parse.sessionDelegate.urlSession(URLSession.parse, task: task, didSendBodyData: 0, totalBytesSent: 0, @@ -365,9 +365,9 @@ class ParseFileAsyncTests: XCTestCase { // swiftlint:disable:this type_body_leng let downloadCompletion: ((URLSessionDownloadTask, Int64, Int64, Int64) -> Void) = { (_: URLSessionDownloadTask, _: Int64, sent: Int64, total: Int64) -> Void in if sent < total { Task { - let downloadCount = await ParseSwift.sessionDelegate.delegates.downloadDelegates.count - let taskCount = await ParseSwift.sessionDelegate.delegates.taskCallbackQueues.count - ParseSwift.sessionDelegate.urlSession(URLSession.parse, + let downloadCount = await Parse.sessionDelegate.delegates.downloadDelegates.count + let taskCount = await Parse.sessionDelegate.delegates.taskCallbackQueues.count + Parse.sessionDelegate.urlSession(URLSession.parse, downloadTask: downloadTask, didFinishDownloadingTo: filePath) DispatchQueue.main.asyncAfter(deadline: .now() + 4) { @@ -376,8 +376,8 @@ class ParseFileAsyncTests: XCTestCase { // swiftlint:disable:this type_body_leng expectation1.fulfill() Task { - let downloadCount = await ParseSwift.sessionDelegate.delegates.downloadDelegates.count - let taskCount = await ParseSwift.sessionDelegate.delegates.taskCallbackQueues.count + let downloadCount = await Parse.sessionDelegate.delegates.downloadDelegates.count + let taskCount = await Parse.sessionDelegate.delegates.taskCallbackQueues.count XCTAssertEqual(downloadCount, 0) XCTAssertEqual(taskCount, 0) expectation2.fulfill() @@ -388,10 +388,10 @@ class ParseFileAsyncTests: XCTestCase { // swiftlint:disable:this type_body_leng } // Add tasks - await ParseSwift.sessionDelegate.delegates.updateDownload(downloadTask, callback: downloadCompletion) - await ParseSwift.sessionDelegate.delegates.updateTask(task, queue: queue) + await Parse.sessionDelegate.delegates.updateDownload(downloadTask, callback: downloadCompletion) + await Parse.sessionDelegate.delegates.updateTask(task, queue: queue) - ParseSwift.sessionDelegate.urlSession(URLSession.parse, + Parse.sessionDelegate.urlSession(URLSession.parse, downloadTask: downloadTask, didWriteData: 0, totalBytesWritten: 0, @@ -410,9 +410,9 @@ class ParseFileAsyncTests: XCTestCase { // swiftlint:disable:this type_body_leng let streamCompletion: ((InputStream?) -> Void) = { (_: InputStream?) -> Void in Task { - let streamCount = ParseSwift.sessionDelegate.streamDelegates.count - let taskCount = await ParseSwift.sessionDelegate.delegates.taskCallbackQueues.count - ParseSwift.sessionDelegate.urlSession(URLSession.parse, task: task, didCompleteWithError: nil) + let streamCount = Parse.sessionDelegate.streamDelegates.count + let taskCount = await Parse.sessionDelegate.delegates.taskCallbackQueues.count + Parse.sessionDelegate.urlSession(URLSession.parse, task: task, didCompleteWithError: nil) DispatchQueue.main.asyncAfter(deadline: .now() + 4) { XCTAssertEqual(streamCount, 1) @@ -420,8 +420,8 @@ class ParseFileAsyncTests: XCTestCase { // swiftlint:disable:this type_body_leng expectation1.fulfill() Task { - let streamCount = ParseSwift.sessionDelegate.streamDelegates.count - let taskCount = await ParseSwift.sessionDelegate.delegates.taskCallbackQueues.count + let streamCount = Parse.sessionDelegate.streamDelegates.count + let taskCount = await Parse.sessionDelegate.delegates.taskCallbackQueues.count XCTAssertEqual(streamCount, 0) XCTAssertEqual(taskCount, 0) expectation2.fulfill() @@ -431,10 +431,10 @@ class ParseFileAsyncTests: XCTestCase { // swiftlint:disable:this type_body_leng } // Add tasks - ParseSwift.sessionDelegate.streamDelegates[task] = .init(data: .init()) - await ParseSwift.sessionDelegate.delegates.updateTask(task, queue: queue) + Parse.sessionDelegate.streamDelegates[task] = .init(data: .init()) + await Parse.sessionDelegate.delegates.updateTask(task, queue: queue) - ParseSwift.sessionDelegate.urlSession(URLSession.parse, task: task, needNewBodyStream: streamCompletion) + Parse.sessionDelegate.urlSession(URLSession.parse, task: task, needNewBodyStream: streamCompletion) wait(for: [expectation1, expectation2], timeout: 20.0) } #endif diff --git a/Tests/ParseSwiftTests/ParseFileTests.swift b/Tests/ParseSwiftTests/ParseFileTests.swift index 24afbdcff..df1ba2685 100644 --- a/Tests/ParseSwiftTests/ParseFileTests.swift +++ b/Tests/ParseSwiftTests/ParseFileTests.swift @@ -691,24 +691,24 @@ class ParseFileTests: XCTestCase { // swiftlint:disable:this type_body_length let dowbloadCompletion: ((URLSessionDownloadTask, Int64, Int64, Int64) -> Void) = { (_: URLSessionDownloadTask, _: Int64, _: Int64, _: Int64) -> Void in } // Add tasks - ParseSwift.sessionDelegate.taskCallbackQueues[task] = DispatchQueue.main - XCTAssertEqual(ParseSwift.sessionDelegate.taskCallbackQueues.count, 1) - ParseSwift.sessionDelegate.streamDelegates[task] = .init(data: .init()) - XCTAssertEqual(ParseSwift.sessionDelegate.streamDelegates.count, 1) - ParseSwift.sessionDelegate.uploadDelegates[task] = uploadCompletion - XCTAssertEqual(ParseSwift.sessionDelegate.uploadDelegates.count, 1) - ParseSwift.sessionDelegate.downloadDelegates[dowloadTask] = dowbloadCompletion - XCTAssertEqual(ParseSwift.sessionDelegate.downloadDelegates.count, 1) + Parse.sessionDelegate.taskCallbackQueues[task] = DispatchQueue.main + XCTAssertEqual(Parse.sessionDelegate.taskCallbackQueues.count, 1) + Parse.sessionDelegate.streamDelegates[task] = .init(data: .init()) + XCTAssertEqual(Parse.sessionDelegate.streamDelegates.count, 1) + Parse.sessionDelegate.uploadDelegates[task] = uploadCompletion + XCTAssertEqual(Parse.sessionDelegate.uploadDelegates.count, 1) + Parse.sessionDelegate.downloadDelegates[dowloadTask] = dowbloadCompletion + XCTAssertEqual(Parse.sessionDelegate.downloadDelegates.count, 1) // Remove tasks - ParseSwift.sessionDelegate.taskCallbackQueues.removeValue(forKey: task) - XCTAssertEqual(ParseSwift.sessionDelegate.taskCallbackQueues.count, 0) - ParseSwift.sessionDelegate.streamDelegates.removeValue(forKey: task) - XCTAssertEqual(ParseSwift.sessionDelegate.streamDelegates.count, 0) - ParseSwift.sessionDelegate.uploadDelegates.removeValue(forKey: task) - XCTAssertEqual(ParseSwift.sessionDelegate.uploadDelegates.count, 0) - ParseSwift.sessionDelegate.downloadDelegates.removeValue(forKey: dowloadTask) - XCTAssertEqual(ParseSwift.sessionDelegate.downloadDelegates.count, 0) + Parse.sessionDelegate.taskCallbackQueues.removeValue(forKey: task) + XCTAssertEqual(Parse.sessionDelegate.taskCallbackQueues.count, 0) + Parse.sessionDelegate.streamDelegates.removeValue(forKey: task) + XCTAssertEqual(Parse.sessionDelegate.streamDelegates.count, 0) + Parse.sessionDelegate.uploadDelegates.removeValue(forKey: task) + XCTAssertEqual(Parse.sessionDelegate.uploadDelegates.count, 0) + Parse.sessionDelegate.downloadDelegates.removeValue(forKey: dowloadTask) + XCTAssertEqual(Parse.sessionDelegate.downloadDelegates.count, 0) } func testParseURLSessionDelegateUpload() throws { @@ -723,15 +723,15 @@ class ParseFileTests: XCTestCase { // swiftlint:disable:this type_body_length // swiftlint:disable:next line_length let uploadCompletion: ((URLSessionTask, Int64, Int64, Int64) -> Void) = { (_: URLSessionTask, _: Int64, sent: Int64, total: Int64) -> Void in if sent < total { - let uploadCount = ParseSwift.sessionDelegate.uploadDelegates.count - let taskCount = ParseSwift.sessionDelegate.taskCallbackQueues.count + let uploadCount = Parse.sessionDelegate.uploadDelegates.count + let taskCount = Parse.sessionDelegate.taskCallbackQueues.count XCTAssertEqual(uploadCount, 1) XCTAssertEqual(taskCount, 1) expectation1.fulfill() - ParseSwift.sessionDelegate.urlSession(URLSession.parse, task: task, didCompleteWithError: nil) + Parse.sessionDelegate.urlSession(URLSession.parse, task: task, didCompleteWithError: nil) DispatchQueue.main.asyncAfter(deadline: .now() + 2) { - let uploadCount = ParseSwift.sessionDelegate.uploadDelegates.count - let taskCount = ParseSwift.sessionDelegate.taskCallbackQueues.count + let uploadCount = Parse.sessionDelegate.uploadDelegates.count + let taskCount = Parse.sessionDelegate.taskCallbackQueues.count XCTAssertEqual(uploadCount, 0) XCTAssertEqual(taskCount, 0) expectation2.fulfill() @@ -740,10 +740,10 @@ class ParseFileTests: XCTestCase { // swiftlint:disable:this type_body_length } // Add tasks - ParseSwift.sessionDelegate.uploadDelegates[task] = uploadCompletion - ParseSwift.sessionDelegate.taskCallbackQueues[task] = queue + Parse.sessionDelegate.uploadDelegates[task] = uploadCompletion + Parse.sessionDelegate.taskCallbackQueues[task] = queue - ParseSwift.sessionDelegate.urlSession(URLSession.parse, + Parse.sessionDelegate.urlSession(URLSession.parse, task: task, didSendBodyData: 0, totalBytesSent: 0, @@ -768,17 +768,17 @@ class ParseFileTests: XCTestCase { // swiftlint:disable:this type_body_length // swiftlint:disable:next line_length let downloadCompletion: ((URLSessionDownloadTask, Int64, Int64, Int64) -> Void) = { (_: URLSessionDownloadTask, _: Int64, sent: Int64, total: Int64) -> Void in if sent < total { - let downloadCount = ParseSwift.sessionDelegate.downloadDelegates.count - let taskCount = ParseSwift.sessionDelegate.taskCallbackQueues.count + let downloadCount = Parse.sessionDelegate.downloadDelegates.count + let taskCount = Parse.sessionDelegate.taskCallbackQueues.count XCTAssertEqual(downloadCount, 1) XCTAssertEqual(taskCount, 1) expectation1.fulfill() - ParseSwift.sessionDelegate.urlSession(URLSession.parse, + Parse.sessionDelegate.urlSession(URLSession.parse, downloadTask: downloadTask, didFinishDownloadingTo: filePath) DispatchQueue.main.asyncAfter(deadline: .now() + 2) { - let downloadCount = ParseSwift.sessionDelegate.downloadDelegates.count - let taskCount = ParseSwift.sessionDelegate.taskCallbackQueues.count + let downloadCount = Parse.sessionDelegate.downloadDelegates.count + let taskCount = Parse.sessionDelegate.taskCallbackQueues.count XCTAssertEqual(downloadCount, 0) XCTAssertEqual(taskCount, 0) expectation2.fulfill() @@ -787,10 +787,10 @@ class ParseFileTests: XCTestCase { // swiftlint:disable:this type_body_length } // Add tasks - ParseSwift.sessionDelegate.downloadDelegates[downloadTask] = downloadCompletion - ParseSwift.sessionDelegate.taskCallbackQueues[task] = queue + Parse.sessionDelegate.downloadDelegates[downloadTask] = downloadCompletion + Parse.sessionDelegate.taskCallbackQueues[task] = queue - ParseSwift.sessionDelegate.urlSession(URLSession.parse, + Parse.sessionDelegate.urlSession(URLSession.parse, downloadTask: downloadTask, didWriteData: 0, totalBytesWritten: 0, @@ -808,15 +808,15 @@ class ParseFileTests: XCTestCase { // swiftlint:disable:this type_body_length let expectation2 = XCTestExpectation(description: "Call delegate 2") let streamCompletion: ((InputStream?) -> Void) = { (_: InputStream?) -> Void in - let streamCount = ParseSwift.sessionDelegate.streamDelegates.count - let taskCount = ParseSwift.sessionDelegate.taskCallbackQueues.count + let streamCount = Parse.sessionDelegate.streamDelegates.count + let taskCount = Parse.sessionDelegate.taskCallbackQueues.count XCTAssertEqual(streamCount, 1) XCTAssertEqual(taskCount, 1) expectation1.fulfill() - ParseSwift.sessionDelegate.urlSession(URLSession.parse, task: task, didCompleteWithError: nil) + Parse.sessionDelegate.urlSession(URLSession.parse, task: task, didCompleteWithError: nil) DispatchQueue.main.asyncAfter(deadline: .now() + 2) { - let streamCount = ParseSwift.sessionDelegate.streamDelegates.count - let taskCount = ParseSwift.sessionDelegate.taskCallbackQueues.count + let streamCount = Parse.sessionDelegate.streamDelegates.count + let taskCount = Parse.sessionDelegate.taskCallbackQueues.count XCTAssertEqual(streamCount, 0) XCTAssertEqual(taskCount, 0) expectation2.fulfill() @@ -824,10 +824,10 @@ class ParseFileTests: XCTestCase { // swiftlint:disable:this type_body_length } // Add tasks - ParseSwift.sessionDelegate.streamDelegates[task] = .init(data: .init()) - ParseSwift.sessionDelegate.taskCallbackQueues[task] = queue + Parse.sessionDelegate.streamDelegates[task] = .init(data: .init()) + Parse.sessionDelegate.taskCallbackQueues[task] = queue - ParseSwift.sessionDelegate.urlSession(URLSession.parse, task: task, needNewBodyStream: streamCompletion) + Parse.sessionDelegate.urlSession(URLSession.parse, task: task, needNewBodyStream: streamCompletion) wait(for: [expectation1, expectation2], timeout: 20.0) } #endif diff --git a/Tests/ParseSwiftTests/ParseRoleTests.swift b/Tests/ParseSwiftTests/ParseRoleTests.swift index e01f1a643..7d5235209 100644 --- a/Tests/ParseSwiftTests/ParseRoleTests.swift +++ b/Tests/ParseSwiftTests/ParseRoleTests.swift @@ -452,7 +452,7 @@ class ParseRoleTests: XCTestCase { acl.publicWrite = false acl.publicRead = true - ParseSwift.configuration.isAllowingCustomObjectIds = true + Parse.configuration.isAllowingCustomObjectIds = true var role = try Role(name: "Administrator", acl: acl) role.createdAt = Date() role.updatedAt = Date() @@ -495,7 +495,7 @@ class ParseRoleTests: XCTestCase { acl.publicWrite = false acl.publicRead = true - ParseSwift.configuration.isAllowingCustomObjectIds = true + Parse.configuration.isAllowingCustomObjectIds = true var role = try Role(name: "Administrator", acl: acl) role.createdAt = Date() role.updatedAt = Date() @@ -575,7 +575,7 @@ class ParseRoleTests: XCTestCase { acl.publicWrite = false acl.publicRead = true - ParseSwift.configuration.isAllowingCustomObjectIds = true + Parse.configuration.isAllowingCustomObjectIds = true var role = try Role(name: "Administrator", acl: acl) role.createdAt = Date() role.updatedAt = Date() @@ -609,7 +609,7 @@ class ParseRoleTests: XCTestCase { acl.publicWrite = false acl.publicRead = true - ParseSwift.configuration.isAllowingCustomObjectIds = true + Parse.configuration.isAllowingCustomObjectIds = true var role = try Role(name: "Administrator", acl: acl) role.createdAt = Date() role.updatedAt = Date() diff --git a/Tests/ParseSwiftTests/ParseSessionTests.swift b/Tests/ParseSwiftTests/ParseSessionTests.swift index 63f54e6b1..f174d102f 100644 --- a/Tests/ParseSwiftTests/ParseSessionTests.swift +++ b/Tests/ParseSwiftTests/ParseSessionTests.swift @@ -76,7 +76,7 @@ class ParseSessionTests: XCTestCase { try KeychainStore.shared.deleteAll() #endif try ParseStorage.shared.deleteAll() - ParseSwift.configuration = nil + Parse.configuration = nil } func testFetchCommand() throws { @@ -113,7 +113,7 @@ class ParseSessionTests: XCTestCase { XCTFail("Should have casted") return } - XCTAssertEqual(delegate, ParseSwift.sessionDelegate) + XCTAssertEqual(delegate, Parse.sessionDelegate) } func testParseURLSessionDefaultCertificatePinning() throws { From d2c2e4ee3638051ee91b01a73e94e149d8a8843e Mon Sep 17 00:00:00 2001 From: Corey Baker Date: Tue, 30 Aug 2022 12:03:48 -0400 Subject: [PATCH 2/4] improve file organization --- ParseSwift.xcodeproj/project.pbxproj | 10 + Sources/ParseSwift/Parse.swift | 434 ++++-------------- .../ParseSwift/Types/ParseConfiguration.swift | 256 +++++++++++ Sources/ParseSwift/Types/ParseField.swift | 1 + .../ParsePushPayloadAny.swift | 4 + Sources/ParseSwift/Types/QueryWhere.swift | 1 + 6 files changed, 369 insertions(+), 337 deletions(-) create mode 100644 Sources/ParseSwift/Types/ParseConfiguration.swift diff --git a/ParseSwift.xcodeproj/project.pbxproj b/ParseSwift.xcodeproj/project.pbxproj index 634671003..15c6ed524 100644 --- a/ParseSwift.xcodeproj/project.pbxproj +++ b/ParseSwift.xcodeproj/project.pbxproj @@ -315,6 +315,10 @@ 7045769E26BD934000F86F71 /* ParseFile+async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7045769C26BD934000F86F71 /* ParseFile+async.swift */; }; 7045769F26BD934000F86F71 /* ParseFile+async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7045769C26BD934000F86F71 /* ParseFile+async.swift */; }; 704576A026BD934000F86F71 /* ParseFile+async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7045769C26BD934000F86F71 /* ParseFile+async.swift */; }; + 704C886C28BE69A8008E6B01 /* ParseConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 704C886B28BE69A8008E6B01 /* ParseConfiguration.swift */; }; + 704C886D28BE69A8008E6B01 /* ParseConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 704C886B28BE69A8008E6B01 /* ParseConfiguration.swift */; }; + 704C886E28BE69A8008E6B01 /* ParseConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 704C886B28BE69A8008E6B01 /* ParseConfiguration.swift */; }; + 704C886F28BE69A8008E6B01 /* ParseConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 704C886B28BE69A8008E6B01 /* ParseConfiguration.swift */; }; 705025992842FD3B008D6624 /* ParseCLPTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 705025982842FD3B008D6624 /* ParseCLPTests.swift */; }; 7050259A2842FD3B008D6624 /* ParseCLPTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 705025982842FD3B008D6624 /* ParseCLPTests.swift */; }; 7050259B2842FD3B008D6624 /* ParseCLPTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 705025982842FD3B008D6624 /* ParseCLPTests.swift */; }; @@ -1229,6 +1233,7 @@ 7045769226BD8F8100F86F71 /* ParseInstallation+async.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ParseInstallation+async.swift"; sourceTree = ""; }; 7045769726BD917500F86F71 /* Query+async.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Query+async.swift"; sourceTree = ""; }; 7045769C26BD934000F86F71 /* ParseFile+async.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ParseFile+async.swift"; sourceTree = ""; }; + 704C886B28BE69A8008E6B01 /* ParseConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseConfiguration.swift; sourceTree = ""; }; 705025982842FD3B008D6624 /* ParseCLPTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseCLPTests.swift; sourceTree = ""; }; 7050259C2843F0CF008D6624 /* ParseSchemaAsyncTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseSchemaAsyncTests.swift; sourceTree = ""; }; 705025A02843F0E7008D6624 /* ParseSchemaCombineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseSchemaCombineTests.swift; sourceTree = ""; }; @@ -2112,6 +2117,7 @@ 70D1BDB925BB17A600A42E7C /* ParseConfig.swift */, 703B090B26BD984D005A112F /* ParseConfig+async.swift */, 7044C18225C4EFC10011F6E7 /* ParseConfig+combine.swift */, + 704C886B28BE69A8008E6B01 /* ParseConfiguration.swift */, F97B45BF24D9C6F200F4A88B /* ParseError.swift */, 709A148628396B1C00BF85E5 /* ParseField.swift */, 705025A828441C96008D6624 /* ParseFieldOptions.swift */, @@ -2733,6 +2739,7 @@ 705A9A2F25991C1400B3547F /* Fileable.swift in Sources */, 89899D342603CF36002E2043 /* ParseTwitter.swift in Sources */, 7C55F9F12860CEEF002A352D /* ParseSpotify+combine.swift in Sources */, + 704C886C28BE69A8008E6B01 /* ParseConfiguration.swift in Sources */, 70B4E0BC2762F1D5004C9757 /* QueryConstraint.swift in Sources */, 70C167B427304F09009F4E30 /* Pointer+async.swift in Sources */, 705025AE28456106008D6624 /* ParsePushStatusable.swift in Sources */, @@ -3041,6 +3048,7 @@ 89899D332603CF36002E2043 /* ParseTwitter.swift in Sources */, 70B4E0BD2762F1D5004C9757 /* QueryConstraint.swift in Sources */, 7C55F9F22860CEEF002A352D /* ParseSpotify+combine.swift in Sources */, + 704C886D28BE69A8008E6B01 /* ParseConfiguration.swift in Sources */, 70C167B527304F09009F4E30 /* Pointer+async.swift in Sources */, F97B464B24D9C78B00F4A88B /* Delete.swift in Sources */, 705025AF28456106008D6624 /* ParsePushStatusable.swift in Sources */, @@ -3481,6 +3489,7 @@ 705A9A3225991C1400B3547F /* Fileable.swift in Sources */, 70B4E0BF2762F1D5004C9757 /* QueryConstraint.swift in Sources */, 7C55F9F42860CEEF002A352D /* ParseSpotify+combine.swift in Sources */, + 704C886F28BE69A8008E6B01 /* ParseConfiguration.swift in Sources */, 89899D282603CF35002E2043 /* ParseTwitter.swift in Sources */, 70C167B727304F09009F4E30 /* Pointer+async.swift in Sources */, 705025B128456106008D6624 /* ParsePushStatusable.swift in Sources */, @@ -3666,6 +3675,7 @@ 705A9A3125991C1400B3547F /* Fileable.swift in Sources */, 70B4E0BE2762F1D5004C9757 /* QueryConstraint.swift in Sources */, 7C55F9F32860CEEF002A352D /* ParseSpotify+combine.swift in Sources */, + 704C886E28BE69A8008E6B01 /* ParseConfiguration.swift in Sources */, 89899D322603CF35002E2043 /* ParseTwitter.swift in Sources */, 70C167B627304F09009F4E30 /* Pointer+async.swift in Sources */, 705025B028456106008D6624 /* ParsePushStatusable.swift in Sources */, diff --git a/Sources/ParseSwift/Parse.swift b/Sources/ParseSwift/Parse.swift index 890b4cf77..24644aa35 100644 --- a/Sources/ParseSwift/Parse.swift +++ b/Sources/ParseSwift/Parse.swift @@ -5,260 +5,81 @@ import FoundationNetworking // swiftlint:disable line_length -/// The Configuration for a Parse client. -/// - warning: It is recomended to only specify `masterKey` when using the -/// SDK on a server. Do not use this key on the client. -public struct ParseConfiguration { +// MARK: Internal - /// The application id for your Parse application. - public internal(set) var applicationId: String - - /// The master key for your Parse application. This key should only - /// be specified when using the SDK on a server. - public internal(set) var masterKey: String? // swiftlint:disable:this inclusive_language - - /// The client key for your Parse application. - public internal(set) var clientKey: String? - - /// The server URL to connect to Parse Server. - public internal(set) var serverURL: URL - - /// The live query server URL to connect to Parse Server. - public internal(set) var liveQuerysServerURL: URL? - - /// Allows objectIds to be created on the client. - public internal(set) var isAllowingCustomObjectIds = false - - /// Use transactions when saving/updating multiple objects. - /// - warning: This is experimental. - public internal(set) var isUsingTransactions = false - - /// Use the **$eq** query constraint when querying. - /// - warning: This is known not to work for LiveQuery on Parse Servers <= 5.0.0. - public internal(set) var isUsingEqualQueryConstraint = false - - /// Use **POST** instead of **GET** when making query calls. - /// Defaults to **false**. - /// - warning: **POST** calls are not cached and will require all queries to access the - /// server instead of following the `requestCachePolicy`. - public internal(set) var isUsingPostForQuery = false - - /// The default caching policy for all http requests that determines when to - /// return a response from the cache. Defaults to `useProtocolCachePolicy`. - /// See Apple's [documentation](https://developer.apple.com/documentation/foundation/url_loading_system/accessing_cached_data) - /// for more info. - public internal(set) var requestCachePolicy = URLRequest.CachePolicy.useProtocolCachePolicy - - /// A dictionary of additional headers to send with requests. See Apple's - /// [documentation](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1411532-httpadditionalheaders) - /// for more info. - public internal(set) var httpAdditionalHeaders: [AnyHashable: Any]? - - /// The memory capacity of the cache, in bytes. Defaults to 512KB. - public internal(set) var cacheMemoryCapacity = 512_000 - - /// The disk capacity of the cache, in bytes. Defaults to 10MB. - public internal(set) var cacheDiskCapacity = 10_000_000 - - /// If your app previously used the iOS Objective-C SDK, setting this value - /// to **true** will attempt to migrate relevant data stored in the Keychain to - /// ParseSwift. Defaults to **false**. - public internal(set) var isMigratingFromObjcSDK: Bool = false - - /// Deletes the Parse Keychain when the app is running for the first time. - /// Defaults to **false**. - public internal(set) var isDeletingKeychainIfNeeded: Bool = false +internal struct Parse { + static var configuration: ParseConfiguration! + static var sessionDelegate: ParseURLSessionDelegate! +} - /// Maximum number of times to try to connect to Parse Server. - /// Defaults to 5. - public internal(set) var maxConnectionAttempts: Int = 5 +internal func initialize(applicationId: String, + clientKey: String? = nil, + masterKey: String? = nil, + serverURL: URL, + liveQueryServerURL: URL? = nil, + allowingCustomObjectIds: Bool = false, + usingTransactions: Bool = false, + usingEqualQueryConstraint: Bool = false, + usingPostForQuery: Bool = false, + keyValueStore: ParseKeyValueStore? = nil, + requestCachePolicy: URLRequest.CachePolicy = .useProtocolCachePolicy, + cacheMemoryCapacity: Int = 512_000, + cacheDiskCapacity: Int = 10_000_000, + migratingFromObjcSDK: Bool = false, + deletingKeychainIfNeeded: Bool = false, + httpAdditionalHeaders: [AnyHashable: Any]? = nil, + maxConnectionAttempts: Int = 5, + testing: Bool = false, + authentication: ((URLAuthenticationChallenge, + (URLSession.AuthChallengeDisposition, + URLCredential?) -> Void) -> Void)? = nil) { + var configuration = ParseConfiguration(applicationId: applicationId, + clientKey: clientKey, + masterKey: masterKey, + serverURL: serverURL, + liveQueryServerURL: liveQueryServerURL, + allowingCustomObjectIds: allowingCustomObjectIds, + usingTransactions: usingTransactions, + usingEqualQueryConstraint: usingEqualQueryConstraint, + usingPostForQuery: usingPostForQuery, + keyValueStore: keyValueStore, + requestCachePolicy: requestCachePolicy, + cacheMemoryCapacity: cacheMemoryCapacity, + cacheDiskCapacity: cacheDiskCapacity, + deletingKeychainIfNeeded: deletingKeychainIfNeeded, + httpAdditionalHeaders: httpAdditionalHeaders, + maxConnectionAttempts: maxConnectionAttempts, + authentication: authentication) + configuration.isMigratingFromObjcSDK = migratingFromObjcSDK + configuration.isTestingSDK = testing + initialize(configuration: configuration) +} - internal var authentication: ((URLAuthenticationChallenge, - (URLSession.AuthChallengeDisposition, - URLCredential?) -> Void) -> Void)? - internal var mountPath: String - internal var isTestingSDK = false // Enable this only for certain tests like ParseFile +internal func deleteKeychainIfNeeded() { #if !os(Linux) && !os(Android) && !os(Windows) - internal var keychainAccessGroup = ParseKeychainAccessGroup() - #endif - - /** - Create a Parse Swift configuration. - - parameter applicationId: The application id for your Parse application. - - parameter clientKey: The client key for your Parse application. - - parameter masterKey: The master key for your Parse application. This key should only be - specified when using the SDK on a server. - - parameter serverURL: The server URL to connect to Parse Server. - - parameter liveQueryServerURL: The live query server URL to connect to Parse Server. - - parameter allowingCustomObjectIds: Allows objectIds to be created on the client. - side for each object. Must be enabled on the server to work. - - parameter usingTransactions: Use transactions when saving/updating multiple objects. - - parameter usingEqualQueryConstraint: Use the **$eq** query constraint when querying. - - parameter usingPostForQuery: Use **POST** instead of **GET** when making query calls. - Defaults to **false**. - - parameter keyValueStore: A key/value store that conforms to the `ParseKeyValueStore` - protocol. Defaults to `nil` in which one will be created an memory, but never persisted. For Linux, this - this is the only store available since there is no Keychain. Linux users should replace this store with an - encrypted one. - - parameter requestCachePolicy: The default caching policy for all http requests that determines - when to return a response from the cache. Defaults to `useProtocolCachePolicy`. See Apple's [documentation](https://developer.apple.com/documentation/foundation/url_loading_system/accessing_cached_data) - for more info. - - parameter cacheMemoryCapacity: The memory capacity of the cache, in bytes. Defaults to 512KB. - - parameter cacheDiskCapacity: The disk capacity of the cache, in bytes. Defaults to 10MB. - - parameter migratingFromObjcSDK: If your app previously used the iOS Objective-C SDK, setting this value - to **true** will attempt to migrate relevant data stored in the Keychain to ParseSwift. Defaults to **false**. - - parameter deletingKeychainIfNeeded: Deletes the Parse Keychain when the app is running for the first time. - Defaults to **false**. - - parameter httpAdditionalHeaders: A dictionary of additional headers to send with requests. See Apple's - [documentation](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1411532-httpadditionalheaders) - for more info. - - parameter maxConnectionAttempts: Maximum number of times to try to connect to Parse Server. - Defaults to 5. - - parameter authentication: A callback block that will be used to receive/accept/decline network challenges. - Defaults to `nil` in which the SDK will use the default OS authentication methods for challenges. - It should have the following argument signature: `(challenge: URLAuthenticationChallenge, - completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void`. - See Apple's [documentation](https://developer.apple.com/documentation/foundation/urlsessiontaskdelegate/1411595-urlsession) for more for details. - - warning: `usingTransactions` is experimental. - - warning: It is recomended to only specify `masterKey` when using the SDK on a server. Do not use this key on the client. - - warning: Setting `usingPostForQuery` to **true** will require all queries to access the server instead of following the `requestCachePolicy`. - */ - public init(applicationId: String, - clientKey: String? = nil, - masterKey: String? = nil, - webhookKey: String? = nil, - serverURL: URL, - liveQueryServerURL: URL? = nil, - allowingCustomObjectIds: Bool = false, - usingTransactions: Bool = false, - usingEqualQueryConstraint: Bool = false, - usingPostForQuery: Bool = false, - keyValueStore: ParseKeyValueStore? = nil, - requestCachePolicy: URLRequest.CachePolicy = .useProtocolCachePolicy, - cacheMemoryCapacity: Int = 512_000, - cacheDiskCapacity: Int = 10_000_000, - deletingKeychainIfNeeded: Bool = false, - httpAdditionalHeaders: [AnyHashable: Any]? = nil, - maxConnectionAttempts: Int = 5, - authentication: ((URLAuthenticationChallenge, - (URLSession.AuthChallengeDisposition, - URLCredential?) -> Void) -> Void)? = nil) { - self.applicationId = applicationId - self.clientKey = clientKey - self.masterKey = masterKey - self.serverURL = serverURL - self.liveQuerysServerURL = liveQueryServerURL - self.isAllowingCustomObjectIds = allowingCustomObjectIds - self.isUsingTransactions = usingTransactions - self.isUsingEqualQueryConstraint = usingEqualQueryConstraint - self.isUsingPostForQuery = usingPostForQuery - self.mountPath = "/" + serverURL.pathComponents - .filter { $0 != "/" } - .joined(separator: "/") - self.authentication = authentication - self.requestCachePolicy = requestCachePolicy - self.cacheMemoryCapacity = cacheMemoryCapacity - self.cacheDiskCapacity = cacheDiskCapacity - self.isDeletingKeychainIfNeeded = deletingKeychainIfNeeded - self.httpAdditionalHeaders = httpAdditionalHeaders - self.maxConnectionAttempts = maxConnectionAttempts - ParseStorage.shared.use(keyValueStore ?? InMemoryKeyValueStore()) - } - - /** - Create a Parse Swift configuration. - - parameter applicationId: The application id for your Parse application. - - parameter clientKey: The client key for your Parse application. - - parameter masterKey: The master key for your Parse application. This key should only be - specified when using the SDK on a server. - - parameter serverURL: The server URL to connect to Parse Server. - - parameter liveQueryServerURL: The live query server URL to connect to Parse Server. - - parameter allowingCustomObjectIds: Allows objectIds to be created on the client. - side for each object. Must be enabled on the server to work. - - parameter usingTransactions: Use transactions when saving/updating multiple objects. - - parameter usingEqualQueryConstraint: Use the **$eq** query constraint when querying. - - parameter usingPostForQuery: Use **POST** instead of **GET** when making query calls. - Defaults to **false**. - - parameter keyValueStore: A key/value store that conforms to the `ParseKeyValueStore` - protocol. Defaults to `nil` in which one will be created an memory, but never persisted. For Linux, this - this is the only store available since there is no Keychain. Linux users should replace this store with an - encrypted one. - - parameter requestCachePolicy: The default caching policy for all http requests that determines - when to return a response from the cache. Defaults to `useProtocolCachePolicy`. See Apple's [documentation](https://developer.apple.com/documentation/foundation/url_loading_system/accessing_cached_data) - for more info. - - parameter cacheMemoryCapacity: The memory capacity of the cache, in bytes. Defaults to 512KB. - - parameter cacheDiskCapacity: The disk capacity of the cache, in bytes. Defaults to 10MB. - - parameter migratingFromObjcSDK: If your app previously used the iOS Objective-C SDK, setting this value - to **true** will attempt to migrate relevant data stored in the Keychain to ParseSwift. Defaults to **false**. - - parameter deletingKeychainIfNeeded: Deletes the Parse Keychain when the app is running for the first time. - Defaults to **false**. - - parameter httpAdditionalHeaders: A dictionary of additional headers to send with requests. See Apple's - [documentation](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1411532-httpadditionalheaders) - for more info. - - parameter maxConnectionAttempts: Maximum number of times to try to connect to Parse Server. - Defaults to 5. - - parameter authentication: A callback block that will be used to receive/accept/decline network challenges. - Defaults to `nil` in which the SDK will use the default OS authentication methods for challenges. - It should have the following argument signature: `(challenge: URLAuthenticationChallenge, - completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void`. - See Apple's [documentation](https://developer.apple.com/documentation/foundation/urlsessiontaskdelegate/1411595-urlsession) for more for details. - - warning: `usingTransactions` is experimental. - - warning: It is recomended to only specify `masterKey` when using the SDK on a server. Do not use this key on the client. - - warning: Setting `usingPostForQuery` to **true** will require all queries to access the server instead of following the `requestCachePolicy`. - */ - @available(*, deprecated, message: "Remove the migratingFromObjcSDK argument") - public init(applicationId: String, - clientKey: String? = nil, - masterKey: String? = nil, - webhookKey: String? = nil, - serverURL: URL, - liveQueryServerURL: URL? = nil, - allowingCustomObjectIds: Bool = false, - usingTransactions: Bool = false, - usingEqualQueryConstraint: Bool = false, - usingPostForQuery: Bool = false, - keyValueStore: ParseKeyValueStore? = nil, - requestCachePolicy: URLRequest.CachePolicy = .useProtocolCachePolicy, - cacheMemoryCapacity: Int = 512_000, - cacheDiskCapacity: Int = 10_000_000, - migratingFromObjcSDK: Bool = false, - deletingKeychainIfNeeded: Bool = false, - httpAdditionalHeaders: [AnyHashable: Any]? = nil, - maxConnectionAttempts: Int = 5, - authentication: ((URLAuthenticationChallenge, - (URLSession.AuthChallengeDisposition, - URLCredential?) -> Void) -> Void)? = nil) { - self.init(applicationId: applicationId, - clientKey: clientKey, - masterKey: masterKey, - webhookKey: webhookKey, - serverURL: serverURL, - liveQueryServerURL: liveQueryServerURL, - allowingCustomObjectIds: allowingCustomObjectIds, - usingTransactions: usingTransactions, - usingEqualQueryConstraint: usingEqualQueryConstraint, - usingPostForQuery: usingPostForQuery, - keyValueStore: keyValueStore, - requestCachePolicy: requestCachePolicy, - cacheMemoryCapacity: cacheMemoryCapacity, - cacheDiskCapacity: cacheDiskCapacity, - deletingKeychainIfNeeded: deletingKeychainIfNeeded, - httpAdditionalHeaders: httpAdditionalHeaders, - maxConnectionAttempts: maxConnectionAttempts, - authentication: authentication) - self.isMigratingFromObjcSDK = migratingFromObjcSDK + // Clear items out of the Keychain on app first run. + if UserDefaults.standard.object(forKey: ParseConstants.bundlePrefix) == nil { + if Parse.configuration.isDeletingKeychainIfNeeded { + try? KeychainStore.old.deleteAll() + try? KeychainStore.shared.deleteAll() + } + Parse.configuration.keychainAccessGroup = .init() + clearCache() + // This is no longer the first run + UserDefaults.standard.setValue(String(ParseConstants.bundlePrefix), + forKey: ParseConstants.bundlePrefix) + UserDefaults.standard.synchronize() } + #endif } +// MARK: Public - All Platforms + +/// The current `ParseConfiguration` for the ParseSwift client. public var configuration: ParseConfiguration { Parse.configuration } -internal struct Parse { - static var configuration: ParseConfiguration! - static var sessionDelegate: ParseURLSessionDelegate! -} - /** Configure the Parse Swift client. This should only be used when starting your app. Typically in the `application(... didFinishLaunchingWithOptions launchOptions...)`. @@ -509,51 +330,43 @@ public func initialize( initialize(configuration: configuration) } -internal func initialize(applicationId: String, - clientKey: String? = nil, - masterKey: String? = nil, - serverURL: URL, - liveQueryServerURL: URL? = nil, - allowingCustomObjectIds: Bool = false, - usingTransactions: Bool = false, - usingEqualQueryConstraint: Bool = false, - usingPostForQuery: Bool = false, - keyValueStore: ParseKeyValueStore? = nil, - requestCachePolicy: URLRequest.CachePolicy = .useProtocolCachePolicy, - cacheMemoryCapacity: Int = 512_000, - cacheDiskCapacity: Int = 10_000_000, - migratingFromObjcSDK: Bool = false, - deletingKeychainIfNeeded: Bool = false, - httpAdditionalHeaders: [AnyHashable: Any]? = nil, - maxConnectionAttempts: Int = 5, - testing: Bool = false, - authentication: ((URLAuthenticationChallenge, - (URLSession.AuthChallengeDisposition, - URLCredential?) -> Void) -> Void)? = nil) { - var configuration = ParseConfiguration(applicationId: applicationId, - clientKey: clientKey, - masterKey: masterKey, - serverURL: serverURL, - liveQueryServerURL: liveQueryServerURL, - allowingCustomObjectIds: allowingCustomObjectIds, - usingTransactions: usingTransactions, - usingEqualQueryConstraint: usingEqualQueryConstraint, - usingPostForQuery: usingPostForQuery, - keyValueStore: keyValueStore, - requestCachePolicy: requestCachePolicy, - cacheMemoryCapacity: cacheMemoryCapacity, - cacheDiskCapacity: cacheDiskCapacity, - deletingKeychainIfNeeded: deletingKeychainIfNeeded, - httpAdditionalHeaders: httpAdditionalHeaders, - maxConnectionAttempts: maxConnectionAttempts, - authentication: authentication) - configuration.isMigratingFromObjcSDK = migratingFromObjcSDK - configuration.isTestingSDK = testing - initialize(configuration: configuration) +/** + Update the authentication callback. + - parameter authentication: A callback block that will be used to receive/accept/decline network challenges. + Defaults to `nil` in which the SDK will use the default OS authentication methods for challenges. + It should have the following argument signature: `(challenge: URLAuthenticationChallenge, + completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void`. + See Apple's [documentation](https://developer.apple.com/documentation/foundation/urlsessiontaskdelegate/1411595-urlsession) for more for details. + */ +public func updateAuthentication(_ authentication: ((URLAuthenticationChallenge, + (URLSession.AuthChallengeDisposition, + URLCredential?) -> Void) -> Void)?) { + Parse.sessionDelegate = ParseURLSessionDelegate(callbackQueue: .main, + authentication: authentication) + URLSession.updateParseURLSession() +} + +/** + Manually remove all stored cache. + - note: The OS typically handles this automatically. + */ +public func clearCache() { + URLSession.parse.configuration.urlCache?.removeAllCachedResponses() } +// MARK: Public - Apple Platforms + #if !os(Linux) && !os(Android) && !os(Windows) +/** + Delete the Parse iOS Objective-C SDK Keychain from the device. + - note: ParseSwift uses a different Keychain. After migration, the iOS Objective-C SDK Keychain is no longer needed. + - warning: The keychain cannot be recovered after deletion. + */ +public func deleteObjectiveCKeychain() throws { + try KeychainStore.objectiveC?.deleteAll() +} + /** Sets all of the items in the Parse Keychain to a specific access group. Apps in the same access group can share Keychain items. See Apple's @@ -596,56 +409,3 @@ internal func initialize(applicationId: String, return true } #endif - -internal func deleteKeychainIfNeeded() { - #if !os(Linux) && !os(Android) && !os(Windows) - // Clear items out of the Keychain on app first run. - if UserDefaults.standard.object(forKey: ParseConstants.bundlePrefix) == nil { - if Parse.configuration.isDeletingKeychainIfNeeded { - try? KeychainStore.old.deleteAll() - try? KeychainStore.shared.deleteAll() - } - Parse.configuration.keychainAccessGroup = .init() - clearCache() - // This is no longer the first run - UserDefaults.standard.setValue(String(ParseConstants.bundlePrefix), - forKey: ParseConstants.bundlePrefix) - UserDefaults.standard.synchronize() - } - #endif -} - -/** - Update the authentication callback. - - parameter authentication: A callback block that will be used to receive/accept/decline network challenges. - Defaults to `nil` in which the SDK will use the default OS authentication methods for challenges. - It should have the following argument signature: `(challenge: URLAuthenticationChallenge, - completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void`. - See Apple's [documentation](https://developer.apple.com/documentation/foundation/urlsessiontaskdelegate/1411595-urlsession) for more for details. - */ -public func updateAuthentication(_ authentication: ((URLAuthenticationChallenge, - (URLSession.AuthChallengeDisposition, - URLCredential?) -> Void) -> Void)?) { - Parse.sessionDelegate = ParseURLSessionDelegate(callbackQueue: .main, - authentication: authentication) - URLSession.updateParseURLSession() -} - -#if !os(Linux) && !os(Android) && !os(Windows) -/** - Delete the Parse iOS Objective-C SDK Keychain from the device. - - note: ParseSwift uses a different Keychain. After migration, the iOS Objective-C SDK Keychain is no longer needed. - - warning: The keychain cannot be recovered after deletion. - */ -public func deleteObjectiveCKeychain() throws { - try KeychainStore.objectiveC?.deleteAll() -} -#endif - -/** - Manually remove all stored cache. - - note: The OS typically handles this automatically. - */ -public func clearCache() { - URLSession.parse.configuration.urlCache?.removeAllCachedResponses() -} diff --git a/Sources/ParseSwift/Types/ParseConfiguration.swift b/Sources/ParseSwift/Types/ParseConfiguration.swift new file mode 100644 index 000000000..0ef335dd4 --- /dev/null +++ b/Sources/ParseSwift/Types/ParseConfiguration.swift @@ -0,0 +1,256 @@ +// +// ParseConfiguration.swift +// ParseSwift +// +// Created by Corey Baker on 8/30/22. +// Copyright © 2022 Parse Community. All rights reserved. +// + +import Foundation + +// swiftlint:disable line_length + +/// The Configuration for a Parse client. +/// - warning: It is recomended to only specify `masterKey` when using the +/// SDK on a server. Do not use this key on the client. +public struct ParseConfiguration { + + /// The application id for your Parse application. + public internal(set) var applicationId: String + + /// The master key for your Parse application. This key should only + /// be specified when using the SDK on a server. + public internal(set) var masterKey: String? // swiftlint:disable:this inclusive_language + + /// The client key for your Parse application. + public internal(set) var clientKey: String? + + /// The server URL to connect to Parse Server. + public internal(set) var serverURL: URL + + /// The live query server URL to connect to Parse Server. + public internal(set) var liveQuerysServerURL: URL? + + /// Allows objectIds to be created on the client. + public internal(set) var isAllowingCustomObjectIds = false + + /// Use transactions when saving/updating multiple objects. + /// - warning: This is experimental. + public internal(set) var isUsingTransactions = false + + /// Use the **$eq** query constraint when querying. + /// - warning: This is known not to work for LiveQuery on Parse Servers <= 5.0.0. + public internal(set) var isUsingEqualQueryConstraint = false + + /// Use **POST** instead of **GET** when making query calls. + /// Defaults to **false**. + /// - warning: **POST** calls are not cached and will require all queries to access the + /// server instead of following the `requestCachePolicy`. + public internal(set) var isUsingPostForQuery = false + + /// The default caching policy for all http requests that determines when to + /// return a response from the cache. Defaults to `useProtocolCachePolicy`. + /// See Apple's [documentation](https://developer.apple.com/documentation/foundation/url_loading_system/accessing_cached_data) + /// for more info. + public internal(set) var requestCachePolicy = URLRequest.CachePolicy.useProtocolCachePolicy + + /// A dictionary of additional headers to send with requests. See Apple's + /// [documentation](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1411532-httpadditionalheaders) + /// for more info. + public internal(set) var httpAdditionalHeaders: [AnyHashable: Any]? + + /// The memory capacity of the cache, in bytes. Defaults to 512KB. + public internal(set) var cacheMemoryCapacity = 512_000 + + /// The disk capacity of the cache, in bytes. Defaults to 10MB. + public internal(set) var cacheDiskCapacity = 10_000_000 + + /// If your app previously used the iOS Objective-C SDK, setting this value + /// to **true** will attempt to migrate relevant data stored in the Keychain to + /// ParseSwift. Defaults to **false**. + public internal(set) var isMigratingFromObjcSDK: Bool = false + + /// Deletes the Parse Keychain when the app is running for the first time. + /// Defaults to **false**. + public internal(set) var isDeletingKeychainIfNeeded: Bool = false + + /// Maximum number of times to try to connect to Parse Server. + /// Defaults to 5. + public internal(set) var maxConnectionAttempts: Int = 5 + + internal var authentication: ((URLAuthenticationChallenge, + (URLSession.AuthChallengeDisposition, + URLCredential?) -> Void) -> Void)? + internal var mountPath: String + internal var isTestingSDK = false // Enable this only for certain tests like ParseFile + #if !os(Linux) && !os(Android) && !os(Windows) + internal var keychainAccessGroup = ParseKeychainAccessGroup() + #endif + + /** + Create a Parse Swift configuration. + - parameter applicationId: The application id for your Parse application. + - parameter clientKey: The client key for your Parse application. + - parameter masterKey: The master key for your Parse application. This key should only be + specified when using the SDK on a server. + - parameter serverURL: The server URL to connect to Parse Server. + - parameter liveQueryServerURL: The live query server URL to connect to Parse Server. + - parameter allowingCustomObjectIds: Allows objectIds to be created on the client. + side for each object. Must be enabled on the server to work. + - parameter usingTransactions: Use transactions when saving/updating multiple objects. + - parameter usingEqualQueryConstraint: Use the **$eq** query constraint when querying. + - parameter usingPostForQuery: Use **POST** instead of **GET** when making query calls. + Defaults to **false**. + - parameter keyValueStore: A key/value store that conforms to the `ParseKeyValueStore` + protocol. Defaults to `nil` in which one will be created an memory, but never persisted. For Linux, this + this is the only store available since there is no Keychain. Linux users should replace this store with an + encrypted one. + - parameter requestCachePolicy: The default caching policy for all http requests that determines + when to return a response from the cache. Defaults to `useProtocolCachePolicy`. See Apple's [documentation](https://developer.apple.com/documentation/foundation/url_loading_system/accessing_cached_data) + for more info. + - parameter cacheMemoryCapacity: The memory capacity of the cache, in bytes. Defaults to 512KB. + - parameter cacheDiskCapacity: The disk capacity of the cache, in bytes. Defaults to 10MB. + - parameter migratingFromObjcSDK: If your app previously used the iOS Objective-C SDK, setting this value + to **true** will attempt to migrate relevant data stored in the Keychain to ParseSwift. Defaults to **false**. + - parameter deletingKeychainIfNeeded: Deletes the Parse Keychain when the app is running for the first time. + Defaults to **false**. + - parameter httpAdditionalHeaders: A dictionary of additional headers to send with requests. See Apple's + [documentation](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1411532-httpadditionalheaders) + for more info. + - parameter maxConnectionAttempts: Maximum number of times to try to connect to Parse Server. + Defaults to 5. + - parameter authentication: A callback block that will be used to receive/accept/decline network challenges. + Defaults to `nil` in which the SDK will use the default OS authentication methods for challenges. + It should have the following argument signature: `(challenge: URLAuthenticationChallenge, + completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void`. + See Apple's [documentation](https://developer.apple.com/documentation/foundation/urlsessiontaskdelegate/1411595-urlsession) for more for details. + - warning: `usingTransactions` is experimental. + - warning: It is recomended to only specify `masterKey` when using the SDK on a server. Do not use this key on the client. + - warning: Setting `usingPostForQuery` to **true** will require all queries to access the server instead of following the `requestCachePolicy`. + */ + public init(applicationId: String, + clientKey: String? = nil, + masterKey: String? = nil, + webhookKey: String? = nil, + serverURL: URL, + liveQueryServerURL: URL? = nil, + allowingCustomObjectIds: Bool = false, + usingTransactions: Bool = false, + usingEqualQueryConstraint: Bool = false, + usingPostForQuery: Bool = false, + keyValueStore: ParseKeyValueStore? = nil, + requestCachePolicy: URLRequest.CachePolicy = .useProtocolCachePolicy, + cacheMemoryCapacity: Int = 512_000, + cacheDiskCapacity: Int = 10_000_000, + deletingKeychainIfNeeded: Bool = false, + httpAdditionalHeaders: [AnyHashable: Any]? = nil, + maxConnectionAttempts: Int = 5, + authentication: ((URLAuthenticationChallenge, + (URLSession.AuthChallengeDisposition, + URLCredential?) -> Void) -> Void)? = nil) { + self.applicationId = applicationId + self.clientKey = clientKey + self.masterKey = masterKey + self.serverURL = serverURL + self.liveQuerysServerURL = liveQueryServerURL + self.isAllowingCustomObjectIds = allowingCustomObjectIds + self.isUsingTransactions = usingTransactions + self.isUsingEqualQueryConstraint = usingEqualQueryConstraint + self.isUsingPostForQuery = usingPostForQuery + self.mountPath = "/" + serverURL.pathComponents + .filter { $0 != "/" } + .joined(separator: "/") + self.authentication = authentication + self.requestCachePolicy = requestCachePolicy + self.cacheMemoryCapacity = cacheMemoryCapacity + self.cacheDiskCapacity = cacheDiskCapacity + self.isDeletingKeychainIfNeeded = deletingKeychainIfNeeded + self.httpAdditionalHeaders = httpAdditionalHeaders + self.maxConnectionAttempts = maxConnectionAttempts + ParseStorage.shared.use(keyValueStore ?? InMemoryKeyValueStore()) + } + + /** + Create a Parse Swift configuration. + - parameter applicationId: The application id for your Parse application. + - parameter clientKey: The client key for your Parse application. + - parameter masterKey: The master key for your Parse application. This key should only be + specified when using the SDK on a server. + - parameter serverURL: The server URL to connect to Parse Server. + - parameter liveQueryServerURL: The live query server URL to connect to Parse Server. + - parameter allowingCustomObjectIds: Allows objectIds to be created on the client. + side for each object. Must be enabled on the server to work. + - parameter usingTransactions: Use transactions when saving/updating multiple objects. + - parameter usingEqualQueryConstraint: Use the **$eq** query constraint when querying. + - parameter usingPostForQuery: Use **POST** instead of **GET** when making query calls. + Defaults to **false**. + - parameter keyValueStore: A key/value store that conforms to the `ParseKeyValueStore` + protocol. Defaults to `nil` in which one will be created an memory, but never persisted. For Linux, this + this is the only store available since there is no Keychain. Linux users should replace this store with an + encrypted one. + - parameter requestCachePolicy: The default caching policy for all http requests that determines + when to return a response from the cache. Defaults to `useProtocolCachePolicy`. See Apple's [documentation](https://developer.apple.com/documentation/foundation/url_loading_system/accessing_cached_data) + for more info. + - parameter cacheMemoryCapacity: The memory capacity of the cache, in bytes. Defaults to 512KB. + - parameter cacheDiskCapacity: The disk capacity of the cache, in bytes. Defaults to 10MB. + - parameter migratingFromObjcSDK: If your app previously used the iOS Objective-C SDK, setting this value + to **true** will attempt to migrate relevant data stored in the Keychain to ParseSwift. Defaults to **false**. + - parameter deletingKeychainIfNeeded: Deletes the Parse Keychain when the app is running for the first time. + Defaults to **false**. + - parameter httpAdditionalHeaders: A dictionary of additional headers to send with requests. See Apple's + [documentation](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1411532-httpadditionalheaders) + for more info. + - parameter maxConnectionAttempts: Maximum number of times to try to connect to Parse Server. + Defaults to 5. + - parameter authentication: A callback block that will be used to receive/accept/decline network challenges. + Defaults to `nil` in which the SDK will use the default OS authentication methods for challenges. + It should have the following argument signature: `(challenge: URLAuthenticationChallenge, + completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void`. + See Apple's [documentation](https://developer.apple.com/documentation/foundation/urlsessiontaskdelegate/1411595-urlsession) for more for details. + - warning: `usingTransactions` is experimental. + - warning: It is recomended to only specify `masterKey` when using the SDK on a server. Do not use this key on the client. + - warning: Setting `usingPostForQuery` to **true** will require all queries to access the server instead of following the `requestCachePolicy`. + */ + @available(*, deprecated, message: "Remove the migratingFromObjcSDK argument") + public init(applicationId: String, + clientKey: String? = nil, + masterKey: String? = nil, + webhookKey: String? = nil, + serverURL: URL, + liveQueryServerURL: URL? = nil, + allowingCustomObjectIds: Bool = false, + usingTransactions: Bool = false, + usingEqualQueryConstraint: Bool = false, + usingPostForQuery: Bool = false, + keyValueStore: ParseKeyValueStore? = nil, + requestCachePolicy: URLRequest.CachePolicy = .useProtocolCachePolicy, + cacheMemoryCapacity: Int = 512_000, + cacheDiskCapacity: Int = 10_000_000, + migratingFromObjcSDK: Bool = false, + deletingKeychainIfNeeded: Bool = false, + httpAdditionalHeaders: [AnyHashable: Any]? = nil, + maxConnectionAttempts: Int = 5, + authentication: ((URLAuthenticationChallenge, + (URLSession.AuthChallengeDisposition, + URLCredential?) -> Void) -> Void)? = nil) { + self.init(applicationId: applicationId, + clientKey: clientKey, + masterKey: masterKey, + webhookKey: webhookKey, + serverURL: serverURL, + liveQueryServerURL: liveQueryServerURL, + allowingCustomObjectIds: allowingCustomObjectIds, + usingTransactions: usingTransactions, + usingEqualQueryConstraint: usingEqualQueryConstraint, + usingPostForQuery: usingPostForQuery, + keyValueStore: keyValueStore, + requestCachePolicy: requestCachePolicy, + cacheMemoryCapacity: cacheMemoryCapacity, + cacheDiskCapacity: cacheDiskCapacity, + deletingKeychainIfNeeded: deletingKeychainIfNeeded, + httpAdditionalHeaders: httpAdditionalHeaders, + maxConnectionAttempts: maxConnectionAttempts, + authentication: authentication) + self.isMigratingFromObjcSDK = migratingFromObjcSDK + } +} diff --git a/Sources/ParseSwift/Types/ParseField.swift b/Sources/ParseSwift/Types/ParseField.swift index 0d7dbd14c..7d322a0f3 100644 --- a/Sources/ParseSwift/Types/ParseField.swift +++ b/Sources/ParseSwift/Types/ParseField.swift @@ -8,6 +8,7 @@ import Foundation +/// A type used to create internal fields for `ParseSchema`. public struct ParseField: ParseTypeable { var __op: Operation? // swiftlint:disable:this identifier_name var type: FieldType? diff --git a/Sources/ParseSwift/Types/ParsePushPayload/ParsePushPayloadAny.swift b/Sources/ParseSwift/Types/ParsePushPayload/ParsePushPayloadAny.swift index 19fd2cffb..56802eb1b 100644 --- a/Sources/ParseSwift/Types/ParsePushPayload/ParsePushPayloadAny.swift +++ b/Sources/ParseSwift/Types/ParsePushPayload/ParsePushPayloadAny.swift @@ -8,6 +8,10 @@ import Foundation +/** + The payload data for both a `ParsePushPayloadApple` and + `ParsePushPayloadFirebase` push notification. + */ public struct ParsePushPayloadAny: ParsePushApplePayloadable, ParsePushFirebasePayloadable { public var topic: String? public var collapseId: String? diff --git a/Sources/ParseSwift/Types/QueryWhere.swift b/Sources/ParseSwift/Types/QueryWhere.swift index d3d93c377..54d15a202 100644 --- a/Sources/ParseSwift/Types/QueryWhere.swift +++ b/Sources/ParseSwift/Types/QueryWhere.swift @@ -8,6 +8,7 @@ import Foundation +/// The **where** of a `Query`. public struct QueryWhere: ParseTypeable { var constraints = [String: Set]() From 7e7651e23dbdb8e3c5183463af0da252a269d138 Mon Sep 17 00:00:00 2001 From: Corey Baker Date: Tue, 30 Aug 2022 12:06:17 -0400 Subject: [PATCH 3/4] import for linux --- Sources/ParseSwift/Types/ParseConfiguration.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Sources/ParseSwift/Types/ParseConfiguration.swift b/Sources/ParseSwift/Types/ParseConfiguration.swift index 0ef335dd4..2b00d4ec1 100644 --- a/Sources/ParseSwift/Types/ParseConfiguration.swift +++ b/Sources/ParseSwift/Types/ParseConfiguration.swift @@ -7,6 +7,9 @@ // import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif // swiftlint:disable line_length From d514ad1477d4992b2a54207e80a0718dc0107e31 Mon Sep 17 00:00:00 2001 From: Corey Baker Date: Tue, 30 Aug 2022 12:26:14 -0400 Subject: [PATCH 4/4] add test --- Tests/ParseSwiftTests/ParseFileTests.swift | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Tests/ParseSwiftTests/ParseFileTests.swift b/Tests/ParseSwiftTests/ParseFileTests.swift index df1ba2685..c737bfef9 100644 --- a/Tests/ParseSwiftTests/ParseFileTests.swift +++ b/Tests/ParseSwiftTests/ParseFileTests.swift @@ -207,6 +207,20 @@ class ParseFileTests: XCTestCase { // swiftlint:disable:this type_body_length "{\"__type\":\"File\",\"name\":\"sampleData.txt\"}") } + func testDebugStringWithFolderInName() throws { + guard let sampleData = "Hello World".data(using: .utf8) else { + throw ParseError(code: .unknownError, message: "Should have converted to data") + } + let parseFile = ParseFile(name: "myFolder/sampleData.txt", + data: sampleData, + metadata: ["Testing": "123"], + tags: ["Hey": "now"]) + XCTAssertEqual(parseFile.debugDescription, + "{\"__type\":\"File\",\"name\":\"myFolder\\/sampleData.txt\"}") + XCTAssertEqual(parseFile.description, + "{\"__type\":\"File\",\"name\":\"myFolder\\/sampleData.txt\"}") + } + func testSave() throws { guard let sampleData = "Hello World".data(using: .utf8) else { throw ParseError(code: .unknownError, message: "Should have converted to data")