Skip to content

Commit

Permalink
feat: Add fetchAll method for Parse pointers
Browse files Browse the repository at this point in the history
  • Loading branch information
cbaker6 committed Jan 8, 2024
1 parent c0a3a45 commit 5dd98bd
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 80 deletions.
4 changes: 4 additions & 0 deletions ParseSwift.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@
918CED592684C74000CFDC83 /* ParseLiveQuery+combine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 918CED582684C74000CFDC83 /* ParseLiveQuery+combine.swift */; };
918CED5E268618C600CFDC83 /* ParseLiveQueryCombineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 918CED5D268618C600CFDC83 /* ParseLiveQueryCombineTests.swift */; };
9194657824F16E330070296B /* ParseACLTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9194657724F16E330070296B /* ParseACLTests.swift */; };
919823652B3A134000E9591A /* ParsePointerable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 919823642B3A134000E9591A /* ParsePointerable.swift */; };
91B40651267A66ED00B129CD /* ParseErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91B40650267A66ED00B129CD /* ParseErrorTests.swift */; };
91B79AC326EE3A4E00073F2C /* API+NonParseBodyCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91B79AC226EE3A4E00073F2C /* API+NonParseBodyCommand.swift */; };
91B79AC826EE3C5D00073F2C /* API+BatchCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91B79AC726EE3C5D00073F2C /* API+BatchCommand.swift */; };
Expand Down Expand Up @@ -625,6 +626,7 @@
918CED582684C74000CFDC83 /* ParseLiveQuery+combine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ParseLiveQuery+combine.swift"; sourceTree = "<group>"; };
918CED5D268618C600CFDC83 /* ParseLiveQueryCombineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseLiveQueryCombineTests.swift; sourceTree = "<group>"; };
9194657724F16E330070296B /* ParseACLTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseACLTests.swift; sourceTree = "<group>"; };
919823642B3A134000E9591A /* ParsePointerable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParsePointerable.swift; sourceTree = "<group>"; };
91B40650267A66ED00B129CD /* ParseErrorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseErrorTests.swift; sourceTree = "<group>"; };
91B79AC226EE3A4E00073F2C /* API+NonParseBodyCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "API+NonParseBodyCommand.swift"; sourceTree = "<group>"; };
91B79AC726EE3C5D00073F2C /* API+BatchCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "API+BatchCommand.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -942,6 +944,7 @@
705025EF2851542D008D6624 /* ParsePushFirebasePayloadable.swift */,
705025CB284CE4C2008D6624 /* ParsePushPayloadable.swift */,
70A98D812794AB3C009B58F2 /* ParseQueryScorable.swift */,
919823642B3A134000E9591A /* ParsePointerable.swift */,
916E206F29D8C83100C21EC6 /* ParseRelationOperationable.swift */,
70CE0ABB285F8FF900DAEA86 /* ParseTypeable.swift */,
F97B45C824D9C6F200F4A88B /* Queryable.swift */,
Expand Down Expand Up @@ -1654,6 +1657,7 @@
F97B45F624D9C6F200F4A88B /* ParseError.swift in Sources */,
7045769D26BD934000F86F71 /* ParseFile+async.swift in Sources */,
F97B463324D9C74400F4A88B /* URLSession.swift in Sources */,
919823652B3A134000E9591A /* ParsePointerable.swift in Sources */,
F97B464E24D9C78B00F4A88B /* ParseOperationAdd.swift in Sources */,
70D41D8028B520E200613510 /* ParseKeychainAccessGroup.swift in Sources */,
70385E762858E1000084D306 /* ParseHookFunctionable.swift in Sources */,
Expand Down
97 changes: 97 additions & 0 deletions Sources/ParseSwift/Protocols/ParsePointerable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//
// ParsePointerable.swift
// ParseSwift
//
// Created by Corey Baker on 12/25/23.
// Copyright © 2023 Network Reconnaissance Lab. All rights reserved.
//

import Foundation

protocol ParsePointer: Encodable {

var __type: String { get } // swiftlint:disable:this identifier_name

var className: String { get }

var objectId: String { get set }
}

extension ParsePointer {
/**
Determines if two objects have the same objectId.
- parameter as: Object to compare.
- returns: Returns a **true** if the other object has the same `objectId` or **false** if unsuccessful.
*/
func hasSameObjectId(as other: any ParsePointer) -> Bool {
return other.className == className && other.objectId == objectId
}
}

protocol ParsePointerObject: ParsePointer, ParseTypeable, Fetchable, Hashable {
associatedtype Object: ParseObject
}

extension ParsePointerObject {

/**
Determines if a `ParseObject` and `Pointer`have the same `objectId`.
- parameter as: `ParseObject` to compare.
- returns: Returns a **true** if the other object has the same `objectId` or **false** if unsuccessful.
*/
func hasSameObjectId(as other: Object) -> Bool {
return other.className == className && other.objectId == objectId
}

/**
Determines if two `Pointer`'s have the same `objectId`.
- parameter as: `Pointer` to compare.
- returns: Returns a **true** if the other object has the same `objectId` or **false** if unsuccessful.
*/
func hasSameObjectId(as other: Self) -> Bool {
return other.className == className && other.objectId == objectId
}

/**
Fetches the `ParseObject` *asynchronously* and executes the given callback block.
- parameter includeKeys: The name(s) of the key(s) to include. Use `["*"]` to include
all keys.
- parameter options: A set of header options sent to the server. Defaults to an empty set.
- parameter callbackQueue: The queue to return to after completion. Default
value of .main.
- parameter completion: The block to execute when completed.
It should have the following argument signature: `(Result<T, ParseError>)`.
- note: The default cache policy for this method is `.reloadIgnoringLocalCacheData`. If a developer
desires a different policy, it should be inserted in `options`.
*/
func fetch(includeKeys: [String]? = nil,
options: API.Options = [],
callbackQueue: DispatchQueue = .main,
completion: @escaping (Result<Object, ParseError>) -> Void) {
Task {
var options = options
options.insert(.cachePolicy(.reloadIgnoringLocalCacheData))

let method = API.Method.GET
let path = API.Endpoint.object(className: className, objectId: objectId)
let params: [String: String]? = {
guard let includeKeys = includeKeys else {
return nil
}
return ["include": "\(Set(includeKeys))"]

Check warning on line 81 in Sources/ParseSwift/Protocols/ParsePointerable.swift

View check run for this annotation

Codecov / codecov/patch

Sources/ParseSwift/Protocols/ParsePointerable.swift#L81

Added line #L81 was not covered by tests
}()
let mapper = { (data) -> Object in
try ParseCoding.jsonDecoder().decode(Object.self, from: data)
}
await API.NonParseBodyCommand<NoBody, Object>(method: method, path: path, params: params, mapper: mapper)
.execute(options: options,
callbackQueue: callbackQueue,
completion: completion)
}
}
}

// MARK: Batch Support
extension Sequence where Element: ParsePointerObject {

}
82 changes: 2 additions & 80 deletions Sources/ParseSwift/Types/Pointer.swift
Original file line number Diff line number Diff line change
@@ -1,25 +1,5 @@
import Foundation

protocol ParsePointer: Encodable {

var __type: String { get } // swiftlint:disable:this identifier_name

var className: String { get }

var objectId: String { get set }
}

extension ParsePointer {
/**
Determines if two objects have the same objectId.
- parameter as: Object to compare.
- returns: Returns a **true** if the other object has the same `objectId` or **false** if unsuccessful.
*/
func hasSameObjectId(as other: ParsePointer) -> Bool {
return other.className == className && other.objectId == objectId
}
}

private func getObjectId(target: Objectable) throws -> String {
guard let objectId = target.objectId else {
throw ParseError(code: .missingObjectId, message: "Cannot set a pointer to an unsaved object")
Expand All @@ -28,8 +8,9 @@ private func getObjectId(target: Objectable) throws -> String {
}

/// A Pointer referencing a ParseObject.
public struct Pointer<T: ParseObject>: ParsePointer, ParseTypeable, Fetchable, Hashable {
public struct Pointer<T: ParseObject>: ParsePointerObject {

typealias Object = T
internal let __type: String = "Pointer" // swiftlint:disable:this identifier_name

/**
Expand Down Expand Up @@ -76,65 +57,6 @@ public struct Pointer<T: ParseObject>: ParsePointer, ParseTypeable, Fetchable, H
}
}

public extension Pointer {

/**
Determines if a `ParseObject` and `Pointer`have the same `objectId`.
- parameter as: `ParseObject` to compare.
- returns: Returns a **true** if the other object has the same `objectId` or **false** if unsuccessful.
*/
func hasSameObjectId(as other: T) -> Bool {
return other.className == className && other.objectId == objectId
}

/**
Determines if two `Pointer`'s have the same `objectId`.
- parameter as: `Pointer` to compare.
- returns: Returns a **true** if the other object has the same `objectId` or **false** if unsuccessful.
*/
func hasSameObjectId(as other: Self) -> Bool {
return other.className == className && other.objectId == objectId
}

/**
Fetches the `ParseObject` *asynchronously* and executes the given callback block.
- parameter includeKeys: The name(s) of the key(s) to include. Use `["*"]` to include
all keys.
- parameter options: A set of header options sent to the server. Defaults to an empty set.
- parameter callbackQueue: The queue to return to after completion. Default
value of .main.
- parameter completion: The block to execute when completed.
It should have the following argument signature: `(Result<T, ParseError>)`.
- note: The default cache policy for this method is `.reloadIgnoringLocalCacheData`. If a developer
desires a different policy, it should be inserted in `options`.
*/
func fetch(includeKeys: [String]? = nil,
options: API.Options = [],
callbackQueue: DispatchQueue = .main,
completion: @escaping (Result<T, ParseError>) -> Void) {
Task {
var options = options
options.insert(.cachePolicy(.reloadIgnoringLocalCacheData))

let method = API.Method.GET
let path = API.Endpoint.object(className: className, objectId: objectId)
let params: [String: String]? = {
guard let includeKeys = includeKeys else {
return nil
}
return ["include": "\(Set(includeKeys))"]
}()
let mapper = { (data) -> T in
try ParseCoding.jsonDecoder().decode(T.self, from: data)
}
await API.NonParseBodyCommand<NoBody, T>(method: method, path: path, params: params, mapper: mapper)
.execute(options: options,
callbackQueue: callbackQueue,
completion: completion)
}
}
}

internal struct PointerType: ParsePointer, Codable {
var __type: String = "Pointer" // swiftlint:disable:this identifier_name
var className: String
Expand Down

0 comments on commit 5dd98bd

Please sign in to comment.