Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add cloud function/job calls and user password reset. #43

Merged
merged 46 commits into from
Jan 4, 2021
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
f0f4809
Add cloud function/job calls and user password reset.
cbaker6 Dec 29, 2020
b23edca
Fixed bug. Make sure the right encoders are always used
cbaker6 Dec 30, 2020
4a5822a
Add results response for Cloud Code
cbaker6 Dec 30, 2020
9552ae1
Clean up docs
cbaker6 Dec 30, 2020
e33fc27
Fix Password Reset error. Add playgrounds example
cbaker6 Dec 30, 2020
374b7b6
Fix CloudCode server response error
cbaker6 Dec 30, 2020
8200cf0
Add Cloud function/job error tests
cbaker6 Dec 30, 2020
f261ef3
Merge remote-tracking branch 'refs/remotes/origin/main'
cbaker6 Dec 30, 2020
2e2a45b
Improve server error responses (established priority of errors).
cbaker6 Dec 30, 2020
9843145
Bug fix: User logout was calling incorrect endpoint for server
cbaker6 Dec 30, 2020
676cce2
Clean up docs
cbaker6 Dec 31, 2020
d120749
Added direct calls to Users and Installations endpoints. Added reques…
cbaker6 Dec 31, 2020
2903c3d
Fixed URL error
cbaker6 Dec 31, 2020
5814335
Bump codecov
cbaker6 Dec 31, 2020
f1d820d
Update Sources/ParseSwift/Types/ParseFile.swift
cbaker6 Dec 31, 2020
95d9b59
Update Sources/ParseSwift/Types/ParseFile.swift
cbaker6 Dec 31, 2020
4ca7b3d
Update Sources/ParseSwift/Types/ParseFile.swift
cbaker6 Dec 31, 2020
40c93bb
Resolve review, fix playground project
cbaker6 Dec 31, 2020
24c66d9
Fix backwards compatability with Swift < 5.3. Add a build to CI for S…
cbaker6 Dec 31, 2020
6c370b6
make Swift 5.2 build go after others
cbaker6 Dec 31, 2020
ab827fd
make other CI builds go after watchOS build since it never tests
cbaker6 Dec 31, 2020
bad1648
Add LocallyIdentifiable protocol
cbaker6 Dec 31, 2020
d79984f
wip
cbaker6 Dec 31, 2020
5ebb087
Improved batch and encoder
cbaker6 Jan 1, 2021
c4122ef
Remove json encoder from ParseEncoder
cbaker6 Jan 1, 2021
b5a8cfa
Reduce codecov
cbaker6 Jan 1, 2021
509885a
Update .codecov.yml
cbaker6 Jan 1, 2021
42c2080
clean up
cbaker6 Jan 1, 2021
cfa3110
Merge remote-tracking branch 'refs/remotes/origin/cloudCode'
cbaker6 Jan 1, 2021
9a95280
Improve LocallyIdentifiable protocol, change file structure of project
cbaker6 Jan 1, 2021
2c31d59
Save for later: ParseObject with localID, but doesn't work. This will…
cbaker6 Jan 1, 2021
f8566e8
cleaned up code
cbaker6 Jan 2, 2021
56906d3
Switch to localId
cbaker6 Jan 2, 2021
f1de7e4
Batch in waves of 50 by default.
cbaker6 Jan 2, 2021
616c11c
Update Sources/ParseSwift/Objects/ParseObject.swift
cbaker6 Jan 3, 2021
9dedf81
Update Sources/ParseSwift/Objects/ParseObject.swift
cbaker6 Jan 3, 2021
b0ce82f
Update Sources/ParseSwift/Objects/ParseObject.swift
cbaker6 Jan 3, 2021
7def6db
Update Sources/ParseSwift/Objects/ParseInstallation.swift
cbaker6 Jan 3, 2021
1859921
Update Sources/ParseSwift/Objects/ParseInstallation.swift
cbaker6 Jan 3, 2021
75aa62b
Update Sources/ParseSwift/Objects/ParseInstallation.swift
cbaker6 Jan 3, 2021
e50e129
Update Sources/ParseSwift/Objects/ParseInstallation.swift
cbaker6 Jan 3, 2021
323f428
Update Sources/ParseSwift/Objects/ParseUser.swift
cbaker6 Jan 3, 2021
306b219
Update Sources/ParseSwift/Objects/ParseUser.swift
cbaker6 Jan 3, 2021
f305e5b
Update Sources/ParseSwift/Objects/ParseUser.swift
cbaker6 Jan 3, 2021
59eb3fb
Update Sources/ParseSwift/Objects/ParseObject.swift
cbaker6 Jan 3, 2021
5241554
Update Sources/ParseSwift/Objects/ParseUser.swift
cbaker6 Jan 3, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//: [Previous](@previous)

import PlaygroundSupport
import Foundation
import ParseSwift

PlaygroundPage.current.needsIndefiniteExecution = true
initializeParse()

//: Create your own ValueTyped ParseCloud type
struct Cloud: ParseCloud {
//: These are required for Object
var functionJobName: String

//: If your cloud function takes arguments, they can be passed by creating properties
//var argument1: [String: Int] = ["test": 5]
}

/*: Assuming you have the Cloud Function named "hello" on your parse-server:
// main.js
Parse.Cloud.define('hello', async () => {
return 'Hello world!';
});
*/
let cloud = Cloud(functionJobName: "hello")

cloud.callFunction { result in
switch result {
case .success(let response):
print("Response from cloud function: \(response)")
case .failure(let error):
assertionFailure("Error calling cloud function: \(error)")
}
}

//: Jobs can be run the same way by using the method `callJob()`

//: [Next](@next)
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ do {
assertionFailure("Error logging out: \(error)")
}

//: Password Reset Request - synchronously
do {
try User.passwordReset(email: "hello@parse.org")
print("Successfully requested password reset")
} catch let error {
print("Error requesting password reset: \(error)")
}

//: Another way to sign up
var newUser = User()
newUser.username = "hello10"
Expand Down
18 changes: 18 additions & 0 deletions ParseSwift.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@
912C9BDC24D3011F009947C3 /* ParseSwift_tvOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 912C9BDA24D3011F009947C3 /* ParseSwift_tvOS.h */; settings = {ATTRIBUTES = (Public, ); }; };
912C9BE024D302B0009947C3 /* Parse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A82B7EE1F254B820063D731 /* Parse.swift */; };
912C9BFD24D302B2009947C3 /* Parse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A82B7EE1F254B820063D731 /* Parse.swift */; };
916786E2259B7DDA00BB5B4E /* ParseCloud.swift in Sources */ = {isa = PBXBuildFile; fileRef = 916786E1259B7DDA00BB5B4E /* ParseCloud.swift */; };
916786E3259B7DDA00BB5B4E /* ParseCloud.swift in Sources */ = {isa = PBXBuildFile; fileRef = 916786E1259B7DDA00BB5B4E /* ParseCloud.swift */; };
916786E4259B7DDA00BB5B4E /* ParseCloud.swift in Sources */ = {isa = PBXBuildFile; fileRef = 916786E1259B7DDA00BB5B4E /* ParseCloud.swift */; };
916786E5259B7DDA00BB5B4E /* ParseCloud.swift in Sources */ = {isa = PBXBuildFile; fileRef = 916786E1259B7DDA00BB5B4E /* ParseCloud.swift */; };
91678706259BC5D400BB5B4E /* ParseCloudTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 916786EF259BC59600BB5B4E /* ParseCloudTests.swift */; };
91678710259BC5D600BB5B4E /* ParseCloudTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 916786EF259BC59600BB5B4E /* ParseCloudTests.swift */; };
9167871A259BC5D600BB5B4E /* ParseCloudTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 916786EF259BC59600BB5B4E /* ParseCloudTests.swift */; };
9194657824F16E330070296B /* ACLTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9194657724F16E330070296B /* ACLTests.swift */; };
F971F4F624DE381A006CB79B /* ParseEncoderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F971F4F524DE381A006CB79B /* ParseEncoderTests.swift */; };
F97B45CE24D9C6F200F4A88B /* ParseCoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = F97B45B424D9C6F200F4A88B /* ParseCoding.swift */; };
Expand Down Expand Up @@ -330,6 +337,8 @@
912C9BDA24D3011F009947C3 /* ParseSwift_tvOS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ParseSwift_tvOS.h; sourceTree = "<group>"; };
912C9BDB24D3011F009947C3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
9158916A256A07DD0024BE9A /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
916786E1259B7DDA00BB5B4E /* ParseCloud.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseCloud.swift; sourceTree = "<group>"; };
916786EF259BC59600BB5B4E /* ParseCloudTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseCloudTests.swift; sourceTree = "<group>"; };
9194657724F16E330070296B /* ACLTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ACLTests.swift; sourceTree = "<group>"; };
F971F4F524DE381A006CB79B /* ParseEncoderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseEncoderTests.swift; sourceTree = "<group>"; };
F97B45B424D9C6F200F4A88B /* ParseCoding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ParseCoding.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -491,6 +500,7 @@
70CE1D882545BF730018D572 /* ParsePointerTests.swift */,
70C7DC1F24D20F180050419B /* ParseQueryTests.swift */,
70C7DC1D24D20E530050419B /* ParseUserTests.swift */,
916786EF259BC59600BB5B4E /* ParseCloudTests.swift */,
7FFF552A2217E729007C3B4E /* AnyCodableTests */,
911DB12A24C3F7260027F3C7 /* NetworkMocking */,
);
Expand Down Expand Up @@ -674,6 +684,7 @@
F97B45C124D9C6F200F4A88B /* File.swift */,
F97B45BC24D9C6F200F4A88B /* ParseGeoPoint.swift */,
F97B45BF24D9C6F200F4A88B /* ParseError.swift */,
916786E1259B7DDA00BB5B4E /* ParseCloud.swift */,
F97B45BE24D9C6F200F4A88B /* Pointer.swift */,
F97B45BB24D9C6F200F4A88B /* Query.swift */,
70110D5D250849B30091CC1D /* Internal */,
Expand Down Expand Up @@ -1125,6 +1136,7 @@
buildActionMask = 2147483647;
files = (
F97B463724D9C74400F4A88B /* Responses.swift in Sources */,
916786E2259B7DDA00BB5B4E /* ParseCloud.swift in Sources */,
F97B461624D9C6F200F4A88B /* Queryable.swift in Sources */,
F97B45DA24D9C6F200F4A88B /* Extensions.swift in Sources */,
F97B465F24D9C7B500F4A88B /* KeychainStore.swift in Sources */,
Expand Down Expand Up @@ -1178,6 +1190,7 @@
911DB12C24C3F7720027F3C7 /* MockURLResponse.swift in Sources */,
70110D5C2506ED0E0091CC1D /* ParseInstallationTests.swift in Sources */,
70BC0B33251903D1001556DB /* ParseGeoPointTests.swift in Sources */,
91678706259BC5D400BB5B4E /* ParseCloudTests.swift in Sources */,
7FFF552E2217E72A007C3B4E /* AnyEncodableTests.swift in Sources */,
7FFF55302217E72A007C3B4E /* AnyDecodableTests.swift in Sources */,
70C7DC2224D20F190050419B /* ParseObjectBatchTests.swift in Sources */,
Expand All @@ -1196,6 +1209,7 @@
buildActionMask = 2147483647;
files = (
F97B463824D9C74400F4A88B /* Responses.swift in Sources */,
916786E3259B7DDA00BB5B4E /* ParseCloud.swift in Sources */,
F97B461724D9C6F200F4A88B /* Queryable.swift in Sources */,
F97B45DB24D9C6F200F4A88B /* Extensions.swift in Sources */,
F97B466024D9C7B500F4A88B /* KeychainStore.swift in Sources */,
Expand Down Expand Up @@ -1258,6 +1272,7 @@
709B984D2556ECAA00507778 /* AnyDecodableTests.swift in Sources */,
709B98572556ECAA00507778 /* ACLTests.swift in Sources */,
709B984F2556ECAA00507778 /* AnyCodableTests.swift in Sources */,
9167871A259BC5D600BB5B4E /* ParseCloudTests.swift in Sources */,
709B98592556ECAA00507778 /* MockURLResponse.swift in Sources */,
709B98522556ECAA00507778 /* ParseUserTests.swift in Sources */,
709B984E2556ECAA00507778 /* ParseGeoPointTests.swift in Sources */,
Expand All @@ -1281,6 +1296,7 @@
70F2E2C2254F283000B2EA5C /* APICommandTests.swift in Sources */,
70F2E2BC254F283000B2EA5C /* ParseObjectTests.swift in Sources */,
70F2E2BD254F283000B2EA5C /* AnyDecodableTests.swift in Sources */,
91678710259BC5D600BB5B4E /* ParseCloudTests.swift in Sources */,
70F2E2C1254F283000B2EA5C /* AnyCodableTests.swift in Sources */,
70F2E2B3254F283000B2EA5C /* ParseUserTests.swift in Sources */,
70F2E2C0254F283000B2EA5C /* MockURLResponse.swift in Sources */,
Expand All @@ -1299,6 +1315,7 @@
buildActionMask = 2147483647;
files = (
F97B45D524D9C6F200F4A88B /* AnyDecodable.swift in Sources */,
916786E5259B7DDA00BB5B4E /* ParseCloud.swift in Sources */,
F97B45E924D9C6F200F4A88B /* Query.swift in Sources */,
F97B463624D9C74400F4A88B /* URLSession+extensions.swift in Sources */,
F97B460524D9C6F200F4A88B /* NoBody.swift in Sources */,
Expand Down Expand Up @@ -1347,6 +1364,7 @@
buildActionMask = 2147483647;
files = (
F97B45D424D9C6F200F4A88B /* AnyDecodable.swift in Sources */,
916786E4259B7DDA00BB5B4E /* ParseCloud.swift in Sources */,
F97B45E824D9C6F200F4A88B /* Query.swift in Sources */,
F97B463524D9C74400F4A88B /* URLSession+extensions.swift in Sources */,
F97B460424D9C6F200F4A88B /* NoBody.swift in Sources */,
Expand Down
30 changes: 21 additions & 9 deletions Sources/ParseSwift/API/API+Commands.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ internal extension API {
return try response.get()
}

// swiftlint:disable:next function_body_length
// swiftlint:disable:next function_body_length cyclomatic_complexity
func executeAsync(options: API.Options, callbackQueue: DispatchQueue?,
childObjects: [NSDictionary: PointerType]? = nil,
completion: @escaping(Result<U, ParseError>) -> Void) {
Expand Down Expand Up @@ -86,12 +86,21 @@ internal extension API {
}
urlRequest.httpBody = bodyData.encoded
} else {
guard let bodyData = try? ParseCoding.parseEncoder().encode(urlBody) else {
completion(.failure(ParseError(code: .unknownError,
message: "couldn't encode body \(urlBody)")))
return
if (urlBody as? ParseCloud) != nil {
guard let bodyData = try? ParseCoding.parseEncoder().encode(urlBody) else {
completion(.failure(ParseError(code: .unknownError,
message: "couldn't encode body \(urlBody)")))
return
}
urlRequest.httpBody = bodyData
} else {
guard let bodyData = try? ParseCoding.jsonEncoder().encode(urlBody) else {
completion(.failure(ParseError(code: .unknownError,
message: "couldn't encode body \(urlBody)")))
return
}
urlRequest.httpBody = bodyData
}
urlRequest.httpBody = bodyData
}
}
urlRequest.httpMethod = method.rawValue
Expand Down Expand Up @@ -143,7 +152,7 @@ internal extension API.Command {
}

private static func updateCommand<T>(_ object: T) -> API.Command<T, T> where T: ParseObject {
let mapper = { (data: Data) -> T in
let mapper = { (data) -> T in
try ParseCoding.jsonDecoder().decode(UpdateResponse.self, from: data).apply(to: object)
}
return API.Command<T, T>(method: .PUT,
Expand Down Expand Up @@ -315,11 +324,14 @@ extension API.Command where T: ParseObject {
}
}

//This has been disabled, looking into getting it working in the future.
//It's only needed for sending batches of childObjects which currently isn't being used.
/*
extension API.Command where T: Encodable {

internal var data: Data? {
guard let body = body else { return nil }
return try? ParseCoding.parseEncoder().encode(body)
return try? ParseCoding.jsonEncoder().encode(body)
}

static func batch(commands: [API.Command<T, PointerType>]) -> RESTBatchCommandTypeEncodable<T> {
Expand Down Expand Up @@ -366,4 +378,4 @@ extension API.Command where T: Encodable {
let batchCommand = BatchCommand(requests: commands)
return RESTBatchCommandTypeEncodable<T>(method: .POST, path: .batch, body: batchCommand, mapper: mapper)
}
}
}*/
9 changes: 9 additions & 0 deletions Sources/ParseSwift/API/API.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ public struct API {
case login
case signup
case logout
case passwordReset
case functions(name: String)
case jobs(name: String)
case any(String)

var urlComponent: String {
Expand All @@ -37,6 +40,12 @@ public struct API {
return "/users"
case .logout:
return "/users/logout"
case .passwordReset:
return "/requestPasswordReset"
case .functions(name: let name):
return "/functions/\(name)"
case .jobs(name: let name):
return "/jobs/\(name)"
case .any(let path):
return path
}
Expand Down
5 changes: 5 additions & 0 deletions Sources/ParseSwift/API/Responses.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,8 @@ internal struct LoginSignupResponse: Codable {
let sessionToken: String
var updatedAt: Date?
}

// MARK: AnyResultsResponse
internal struct AnyResultsResponse: Codable {
let result: AnyCodable?
}
4 changes: 3 additions & 1 deletion Sources/ParseSwift/Coding/ParseCoding.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public enum ParseCoding {}
// MARK: Coders
extension ParseCoding {
private static let forbiddenKeys = Set(["createdAt", "updatedAt", "objectId", "className"])
private static let forbiddenCloudKeys = Set(["functionJobName"])

///This should only be used for Unit tests, don't use in SDK
static func jsonEncoder() -> JSONEncoder {
Expand All @@ -31,7 +32,8 @@ extension ParseCoding {
static func parseEncoder(skipKeys: Bool = true) -> ParseEncoder {
ParseEncoder(
dateEncodingStrategy: parseDateEncodingStrategy,
skippingKeys: skipKeys ? forbiddenKeys : []
skippingKeys: skipKeys ? forbiddenKeys : [],
skippingCloudKeys: skipKeys ? forbiddenCloudKeys : []
)
}
}
Expand Down
11 changes: 9 additions & 2 deletions Sources/ParseSwift/Coding/ParseEncoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,22 +53,29 @@ public struct ParseEncoder {
let dateEncodingStrategy: AnyCodable.DateEncodingStrategy?
let jsonEncoder: JSONEncoder
let skippedKeys: Set<String>
let skippedCloudKeys: Set<String>

init(
dateEncodingStrategy: AnyCodable.DateEncodingStrategy? = nil,
jsonEncoder: JSONEncoder = JSONEncoder(),
skippingKeys: Set<String> = []
skippingKeys: Set<String> = [],
skippingCloudKeys: Set<String> = []
) {
self.dateEncodingStrategy = dateEncodingStrategy
self.jsonEncoder = jsonEncoder
self.skippedKeys = skippingKeys
self.skippedCloudKeys = skippingCloudKeys
if let dateEncodingStrategy = dateEncodingStrategy {
self.jsonEncoder.dateEncodingStrategy = .custom(dateEncodingStrategy)
}
}

public func encode<T: Encodable>(_ value: T) throws -> Data {
try jsonEncoder.encode(value)
let encoder = _ParseEncoder(codingPath: [], dictionary: NSMutableDictionary(), skippingKeys: skippedCloudKeys)
if let dateEncodingStrategy = dateEncodingStrategy {
encoder.dateEncodingStrategy = .custom(dateEncodingStrategy)
}
return try encoder.encodeObject(value, collectChildren: false, objectsSavedBeforeThisOne: nil).encoded
}

public func encode<T: ParseObject>(_ value: T) throws -> Data {
Expand Down
8 changes: 4 additions & 4 deletions Sources/ParseSwift/Object Protocols/ParseObject.swift
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ public extension Sequence where Element: ParseObject {
}

// MARK: Batch Support
internal extension Sequence where Element: Encodable {
/*internal extension Sequence where Element: Encodable {

/**
Saves a collection of objects *synchronously* all at once and throws an error if necessary.
Expand All @@ -243,7 +243,7 @@ internal extension Sequence where Element: Encodable {
.batch(commands: commands)
.execute(options: options)
}
}
}*/

// MARK: CustomDebugStringConvertible
extension ParseObject {
Expand Down Expand Up @@ -449,14 +449,14 @@ internal extension Encodable {
func saveCommand() throws -> API.Command<Self, PointerType> {
try API.Command<Self, PointerType>.saveCommand(self)
}

/*
func saveAll<T: Encodable>(options: API.Options = [],
encodableObjects: [T]) throws -> [(Result<PointerType, ParseError>)] {
let commands = try encodableObjects.map { try $0.saveCommand() }
return try API.Command<T, BaseObjectable>
.batch(commands: commands)
.execute(options: options)
}
}*/
}

// MARK: Deletable
Expand Down
Loading