Skip to content

Commit 97885ce

Browse files
authored
feat: add Parse hook functions and triggers (#373)
* feat: add Parse hook capabilities * add ParseTypeable * switch CloudType to ParseCloudTypeable * refactor * Add working playgrounds for functions * update change log * add hook key * add hook trigger * remove webhookKey and fix docs * add tests and more docs * more codecov * codecov * make ParseHookResponse accept ParseError's * improve ParseHookResponse * fix playground * triggers work with ParseFile * testing file * Parse Server Hooks doesn't support triggers for file and beforeConnect * Update changelog * Make methods public * clean up playgrounds * nit
1 parent 36f9d1a commit 97885ce

File tree

97 files changed

+4654
-675
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

97 files changed

+4654
-675
lines changed

CHANGELOG.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@
22

33
### main
44

5-
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/4.5.0...main)
5+
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/4.6.0...main)
66
* _Contributing to this repo? Add info about your change here to be included in the next release_
77

8+
### 4.6.0
9+
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/4.5.0...4.6.0)
10+
811
__New features__
12+
- Add the ability to use Parse Hooks and Triggers ([#373](https://github.com/parse-community/Parse-Swift/pull/373)), thanks to [Corey Baker](https://github.com/cbaker6).
13+
- Add ParseInstagram authentication ([#372](https://github.com/parse-community/Parse-Swift/pull/372)), thanks to [Ulaş Sancak](https://github.com/rocxteady).
914
- Add the ability to send APN and FCM push notifications. Also adds the ability to query _PushStatus ([#371](https://github.com/parse-community/Parse-Swift/pull/371)), thanks to [Corey Baker](https://github.com/cbaker6).
1015
- Add ParseSchema, ParseCLP, and ParseFieldOptions. Should only be used when using the Swift SDK on a secured server ([#370](https://github.com/parse-community/Parse-Swift/pull/370)), thanks to [Corey Baker](https://github.com/cbaker6).
11-
- Add ParseInstagram authentication ([#372](https://github.com/parse-community/Parse-Swift/pull/372)), thanks to [Ulaş Sancak](https://github.com/rocxteady).
1216

1317
### 4.5.0
1418
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/4.4.0...4.5.0)

ParseSwift.playground/Pages/15 - Custom ObjectId.xcplaygroundpage/Contents.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,16 @@ import Foundation
1111
import ParseSwift
1212
PlaygroundPage.current.needsIndefiniteExecution = true
1313

14-
/*: start parse-server with
15-
npm start -- --appId applicationId --clientKey clientKey --masterKey masterKey --mountPath /1
14+
/*:
15+
start parse-server with
16+
npm start -- --appId applicationId --clientKey clientKey --masterKey masterKey --mountPath /1
1617
*/
1718

18-
/*: In Xcode, make sure you are building the "ParseSwift (macOS)" framework.
19+
/*:
20+
In Xcode, make sure you are building the "ParseSwift (macOS)" framework.
1921
*/
2022

21-
initializeParseCustomObjectId()
23+
initializeParse(customObjectId: true)
2224

2325
//: Create your own value typed `ParseObject`.
2426
struct GameScore: ParseObject {

ParseSwift.playground/Pages/20 - Schema.xcplaygroundpage/Contents.swift renamed to ParseSwift.playground/Pages/20 - Cloud Schemas.xcplaygroundpage/Contents.swift

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
//: [Previous](@previous)
22

3+
/*:
4+
The code in this Playground is intended to run at the
5+
server level only. It is not intended to be run in client
6+
applications as it requires the use of the master key.
7+
*/
8+
39
import PlaygroundSupport
410
import Foundation
511
import ParseSwift
@@ -80,8 +86,10 @@ struct GameScore2: ParseObject {
8086
}
8187
}
8288

83-
//: It's recommended to place custom initializers in an extension
84-
//: to preserve the memberwise initializer.
89+
/*:
90+
It's recommended to place custom initializers in an extension
91+
to preserve the memberwise initializer.
92+
*/
8593
extension GameScore2 {
8694

8795
init(points: Int) {
@@ -170,6 +178,16 @@ gameScoreSchema.update { result in
170178
}
171179
}
172180

181+
//: We can also fetch the schema.
182+
gameScoreSchema.fetch { result in
183+
switch result {
184+
case .success(let fetchedGameScore):
185+
print("The fetched GameScore2 schema is: \(fetchedGameScore)")
186+
case .failure(let error):
187+
print("Couldn't fetch schema: \(error)")
188+
}
189+
}
190+
173191
/*:
174192
Fields can also be deleted on a schema. Lets remove
175193
the **data** field since it's not going being used.

ParseSwift.playground/Pages/21 - Push Notifications.xcplaygroundpage/Contents.swift renamed to ParseSwift.playground/Pages/21 - Cloud Push Notifications.xcplaygroundpage/Contents.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
//: [Previous](@previous)
22

3+
/*:
4+
The code in this Playground is intended to run at the
5+
server level only. It is not intended to be run in client
6+
applications as it requires the use of the master key.
7+
*/
8+
39
import PlaygroundSupport
410
import Foundation
511
import ParseSwift
@@ -42,7 +48,7 @@ struct Installation: ParseInstallation {
4248
}
4349
}
4450

45-
/**
51+
/*:
4652
We will begin by creating the payload information we want to
4753
send in the push notification.
4854
*/
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
//: [Previous](@previous)
2+
3+
/*:
4+
The code in this Playground is intended to run at the
5+
server level only. It is not intended to be run in client
6+
applications as it requires the use of the master key.
7+
*/
8+
9+
import PlaygroundSupport
10+
import Foundation
11+
import ParseSwift
12+
13+
PlaygroundPage.current.needsIndefiniteExecution = true
14+
initializeParse()
15+
16+
/*:
17+
Parse Hook Functions can be created by conforming to
18+
`ParseHookFunctionable`.
19+
*/
20+
struct HookFunction: ParseHookFunctionable {
21+
var functionName: String?
22+
var url: URL?
23+
}
24+
25+
/*:
26+
Lets create our first Hook function by first creating an instance
27+
with the name of the function and url for the hook.
28+
*/
29+
var myFunction = HookFunction(name: "foo",
30+
url: URL(string: "https://api.example.com/foo"))
31+
32+
//: Then, create the function on the server.
33+
myFunction.create { result in
34+
switch result {
35+
case .success(let newFunction):
36+
print("Created: \"\(newFunction)\"")
37+
case .failure(let error):
38+
print("Could not create: \(error)")
39+
}
40+
}
41+
42+
/*:
43+
The function can be fetched at any time.
44+
*/
45+
myFunction.fetch { result in
46+
switch result {
47+
case .success(let fetchedFunction):
48+
print("Fetched: \"\(fetchedFunction)\"")
49+
case .failure(let error):
50+
print("Could not fetch: \(error)")
51+
}
52+
}
53+
54+
/*:
55+
There will be times you need to update a Hook function.
56+
You can update your hook at anytime.
57+
*/
58+
myFunction.url = URL(string: "https://api.example.com/bar")
59+
myFunction.update { result in
60+
switch result {
61+
case .success(let updated):
62+
print("Updated: \"\(updated)\"")
63+
case .failure(let error):
64+
print("Could not update: \(error)")
65+
}
66+
}
67+
68+
/*:
69+
Lets fetchAll using the instance method to see all of the
70+
available hook functions.
71+
*/
72+
myFunction.fetchAll { result in
73+
switch result {
74+
case .success(let functions):
75+
print("Current: \"\(functions)\"")
76+
case .failure(let error):
77+
print("Could not fetch: \(error)")
78+
}
79+
}
80+
81+
/*:
82+
Hook functions can also be deleted.
83+
*/
84+
myFunction.delete { result in
85+
switch result {
86+
case .success:
87+
print("The Parse Cloud function was deleted successfully")
88+
case .failure(let error):
89+
print("Could not delete: \(error)")
90+
}
91+
}
92+
93+
/*:
94+
You can also use the fetchAll type method to fetch all of
95+
the current Hook functions.
96+
*/
97+
HookFunction.fetchAll { result in
98+
switch result {
99+
case .success(let functions):
100+
print("Current: \"\(functions)\"")
101+
case .failure(let error):
102+
print("Could not fetch: \(error)")
103+
}
104+
}
105+
106+
PlaygroundPage.current.finishExecution()
107+
//: [Next](@next)
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
//: [Previous](@previous)
2+
3+
/*:
4+
The code in this Playground is intended to run at the
5+
server level only. It is not intended to be run in client
6+
applications as it requires the use of the master key.
7+
*/
8+
9+
import PlaygroundSupport
10+
import Foundation
11+
import ParseSwift
12+
13+
PlaygroundPage.current.needsIndefiniteExecution = true
14+
initializeParse()
15+
16+
//: Create your own value typed `ParseObject`.
17+
struct GameScore: ParseObject {
18+
//: These are required by ParseObject
19+
var objectId: String?
20+
var createdAt: Date?
21+
var updatedAt: Date?
22+
var ACL: ParseACL?
23+
var originalData: Data?
24+
25+
//: Your own properties.
26+
var points: Int?
27+
28+
//: Implement your own version of merge
29+
func merge(with object: Self) throws -> Self {
30+
var updated = try mergeParse(with: object)
31+
if updated.shouldRestoreKey(\.points,
32+
original: object) {
33+
updated.points = object.points
34+
}
35+
return updated
36+
}
37+
}
38+
39+
//: It's recommended to place custom initializers in an extension
40+
//: to preserve the memberwise initializer.
41+
extension GameScore {
42+
43+
init(points: Int) {
44+
self.points = points
45+
}
46+
47+
init(objectId: String?) {
48+
self.objectId = objectId
49+
}
50+
}
51+
52+
/*:
53+
Parse Hook Triggers can be created by conforming to
54+
`ParseHookFunctionable`.
55+
*/
56+
struct HookTrigger: ParseHookTriggerable {
57+
var className: String?
58+
var triggerName: ParseHookTriggerType?
59+
var url: URL?
60+
}
61+
62+
/*:
63+
Lets create our first Hook trigger by first creating an instance
64+
with the name of the trigger and url for the hook.
65+
*/
66+
let gameScore = GameScore()
67+
var myTrigger = HookTrigger(object: gameScore,
68+
triggerName: .afterSave,
69+
url: URL(string: "https://api.example.com/bar")!)
70+
71+
//: Then, create the trigger on the server.
72+
myTrigger.create { result in
73+
switch result {
74+
case .success(let newFunction):
75+
print("Created: \"\(newFunction)\"")
76+
case .failure(let error):
77+
print("Could not create: \(error)")
78+
}
79+
}
80+
81+
/*:
82+
The trigger can be fetched at any time.
83+
*/
84+
myTrigger.fetch { result in
85+
switch result {
86+
case .success(let fetchedFunction):
87+
print("Fetched: \"\(fetchedFunction)\"")
88+
case .failure(let error):
89+
print("Could not fetch: \(error)")
90+
}
91+
}
92+
93+
/*:
94+
There will be times you need to update a Hook trigger.
95+
You can update your hook at anytime.
96+
*/
97+
myTrigger.url = URL(string: "https://api.example.com/car")
98+
myTrigger.update { result in
99+
switch result {
100+
case .success(let updated):
101+
print("Updated: \"\(updated)\"")
102+
case .failure(let error):
103+
print("Could not update: \(error)")
104+
}
105+
}
106+
107+
/*:
108+
Lets fetchAll using the instance method to see all of the
109+
available hook triggers.
110+
*/
111+
myTrigger.fetchAll { result in
112+
switch result {
113+
case .success(let triggers):
114+
print("Current: \"\(triggers)\"")
115+
case .failure(let error):
116+
print("Could not fetch: \(error)")
117+
}
118+
}
119+
120+
/*:
121+
Hook triggers can also be deleted.
122+
*/
123+
myTrigger.delete { result in
124+
switch result {
125+
case .success:
126+
print("The Parse Cloud trigger was deleted successfully")
127+
case .failure(let error):
128+
print("Could not delete: \(error)")
129+
}
130+
}
131+
132+
/*:
133+
You can also use the fetchAll type method to fetch all of
134+
the current Hook triggers.
135+
*/
136+
HookTrigger.fetchAll { result in
137+
switch result {
138+
case .success(let triggers):
139+
print("Current: \"\(triggers)\"")
140+
case .failure(let error):
141+
print("Could not fetch: \(error)")
142+
}
143+
}
144+
145+
PlaygroundPage.current.finishExecution()
146+
147+
//: [Next](@next)

ParseSwift.playground/Pages/6 - Installation.xcplaygroundpage/Contents.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,5 +83,17 @@ installationToUpdate?.save { results in
8383
}
8484
}
8585

86+
//: You can fetch your installation at anytime.
87+
Installation.current?.fetch { results in
88+
89+
switch results {
90+
case .success(let fetchedInstallation):
91+
print("Successfully fetched installation from ParseServer: \(fetchedInstallation)")
92+
case .failure(let error):
93+
print("Failed to fetch installation: \(error)")
94+
}
95+
96+
}
97+
8698
PlaygroundPage.current.finishExecution()
8799
//: [Next](@next)
Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,11 @@
11
import Foundation
22
import ParseSwift
33

4-
public func initializeParse() {
4+
public func initializeParse(customObjectId: Bool = false) {
55
ParseSwift.initialize(applicationId: "applicationId",
66
clientKey: "clientKey",
77
masterKey: "masterKey",
88
serverURL: URL(string: "http://localhost:1337/1")!,
9-
usingTransactions: false,
10-
usingEqualQueryConstraint: false)
11-
}
12-
13-
public func initializeParseCustomObjectId() {
14-
ParseSwift.initialize(applicationId: "applicationId",
15-
clientKey: "clientKey",
16-
serverURL: URL(string: "http://localhost:1337/1")!,
17-
allowingCustomObjectIds: true,
9+
allowingCustomObjectIds: customObjectId,
1810
usingEqualQueryConstraint: false)
1911
}

0 commit comments

Comments
 (0)