Skip to content

Commit d57b7c9

Browse files
authored
feat: Add support for hook triggers on ParseConfig (#179)
* feat: Add support for hook triggers on ParseConfig * fix Swift backwards compatability * nit * doc nit * bump swift requirement * Update ci.yml
1 parent 1199b57 commit d57b7c9

File tree

6 files changed

+394
-32
lines changed

6 files changed

+394
-32
lines changed

.github/workflows/ci.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ on:
88
branches: [ main ]
99

1010
env:
11-
CI_XCODE_OLDEST: '/Applications/Xcode_13.3.1.app/Contents/Developer'
11+
CI_XCODE_OLDEST: '/Applications/Xcode_14.2.app/Contents/Developer'
1212
CI_XCODE_14: '/Applications/Xcode_14.3.1.app/Contents/Developer'
1313
CI_XCODE_LATEST: '/Applications/Xcode_15.4.app/Contents/Developer'
1414

@@ -101,7 +101,7 @@ jobs:
101101
env:
102102
DEVELOPER_DIR: ${{ env.CI_XCODE_LATEST }}
103103

104-
xcode-test-5_5:
104+
xcode-test-5_7:
105105
timeout-minutes: 25
106106
needs: linux
107107
runs-on: macos-12

CHANGELOG.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,15 @@
22
# Parse-Swift Changelog
33

44
### main
5-
[Full Changelog](https://github.com/netreconlab/Parse-Swift/compare/5.10.3...main), [Documentation](https://swiftpackageindex.com/netreconlab/Parse-Swift/main/documentation/parseswift)
5+
[Full Changelog](https://github.com/netreconlab/Parse-Swift/compare/5.11.0...main), [Documentation](https://swiftpackageindex.com/netreconlab/Parse-Swift/main/documentation/parseswift)
66
* _Contributing to this repo? Add info about your change here to be included in the next release_
77

8+
### 5.11.0
9+
[Full Changelog](https://github.com/netreconlab/Parse-Swift/compare/5.10.3...5.11.0), [Documentation](https://swiftpackageindex.com/netreconlab/Parse-Swift/5.11.0/documentation/parseswift)
10+
11+
__New features__
12+
* Allow hook triggers on ParseConfig and improve SDK ability to throw errors when the developer uses unsupported trigger combinations. Also changes lowest requirements to be Swift 5.7 and Xcode 14.0 which aligns with other Swift Packages ([#179](https://github.com/netreconlab/Parse-Swift/pull/179)), thanks to [Corey Baker](https://github.com/cbaker6).
13+
814
### 5.10.3
915
[Full Changelog](https://github.com/netreconlab/Parse-Swift/compare/5.10.2...5.10.3), [Documentation](https://swiftpackageindex.com/netreconlab/Parse-Swift/5.10.3/documentation/parseswift)
1016

Package.swift

+14-9
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,31 @@
1-
// swift-tools-version:5.5.2
1+
// swift-tools-version:5.7
22

33
import PackageDescription
44

55
let package = Package(
66
name: "ParseSwift",
7-
platforms: [.iOS(.v13),
8-
.macCatalyst(.v13),
9-
.macOS(.v10_15),
10-
.tvOS(.v13),
11-
.watchOS(.v6)],
7+
platforms: [
8+
.iOS(.v13),
9+
.macCatalyst(.v13),
10+
.macOS(.v10_15),
11+
.tvOS(.v13),
12+
.watchOS(.v6)
13+
],
1214
products: [
1315
.library(
1416
name: "ParseSwift",
15-
targets: ["ParseSwift"])
17+
targets: ["ParseSwift"]
18+
)
1619
],
1720
targets: [
1821
.target(
1922
name: "ParseSwift",
20-
dependencies: []),
23+
dependencies: []
24+
),
2125
.testTarget(
2226
name: "ParseSwiftTests",
2327
dependencies: ["ParseSwift"],
24-
exclude: ["Info.plist"])
28+
exclude: ["Info.plist"]
29+
)
2530
]
2631
)

Sources/ParseSwift/ParseConstants.swift

+38-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Foundation
1010

1111
enum ParseConstants {
1212
static let sdk = "swift"
13-
static let version = "5.10.3"
13+
static let version = "5.11.0"
1414
static let fileManagementDirectory = "parse/"
1515
static let fileManagementPrivateDocumentsDirectory = "Private Documents/"
1616
static let fileManagementLibraryDirectory = "Library/"
@@ -51,9 +51,9 @@ public enum ParseHookTriggerType: String, Codable, Sendable {
5151
case afterLogin
5252
/// Occurs after logout of a `ParseUser`.
5353
case afterLogout
54-
/// Occurs before saving a `ParseObject` or `ParseFile`.
54+
/// Occurs before saving a `ParseObject`, `ParseFile`, or `ParseConfig`.
5555
case beforeSave
56-
/// Occurs after saving a `ParseObject` or `ParseFile`.
56+
/// Occurs after saving a `ParseObject`, `ParseFile`, or `ParseConfig`.
5757
case afterSave
5858
/// Occurs before deleting a `ParseObject` or `ParseFile`.
5959
case beforeDelete
@@ -70,3 +70,38 @@ public enum ParseHookTriggerType: String, Codable, Sendable {
7070
/// Occurs after a `ParseLiveQuery` event.
7171
case afterEvent
7272
}
73+
74+
/**
75+
The objects that Parse Hooks can be triggered on.
76+
*/
77+
public enum ParseHookTriggerObject: Sendable {
78+
/// The type of `ParseObject` to trigger on.
79+
case objectType(any ParseObject.Type)
80+
/// An instance of a `ParseObject` to trigger on.
81+
case object(any ParseObject)
82+
/// Trigger on `ParseFile`'s.
83+
case file
84+
/// Trigger on `ParseConfig` updates.
85+
/// - warning: Requires Parse Server 7.3.0-alpha.6+.
86+
case config
87+
/// Trigger on `ParseLiveQuery` connections.
88+
case liveQueryConnect
89+
90+
/// The class name of the `ParseObject` to trigger on.
91+
var className: String {
92+
switch self {
93+
94+
case .objectType(let object):
95+
return object.className
96+
case .object(let object):
97+
return object.className
98+
case .file:
99+
return "@File"
100+
case .config:
101+
return "@Config"
102+
case .liveQueryConnect:
103+
return "@Connect"
104+
105+
}
106+
}
107+
}

Sources/ParseSwift/Protocols/ParseHookTriggerable.swift

+131-13
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@ public extension ParseHookTriggerable {
3131
- parameter trigger: The `ParseHookTriggerType` type.
3232
- parameter url: The endpoint of the hook.
3333
*/
34-
init(className: String, trigger: ParseHookTriggerType, url: URL) {
34+
init(
35+
className: String,
36+
trigger: ParseHookTriggerType,
37+
url: URL
38+
) {
3539
self.init()
3640
self.className = className
3741
self.triggerName = trigger
@@ -45,7 +49,11 @@ public extension ParseHookTriggerable {
4549
- parameter url: The endpoint of the hook.
4650
*/
4751
@available(*, deprecated, message: "Change \"triggerName\" to \"trigger\"")
48-
init(className: String, triggerName: ParseHookTriggerType, url: URL) {
52+
init(
53+
className: String,
54+
triggerName: ParseHookTriggerType,
55+
url: URL
56+
) {
4957
self.init(className: className, trigger: triggerName, url: url)
5058
}
5159

@@ -55,7 +63,11 @@ public extension ParseHookTriggerable {
5563
- parameter trigger: The `ParseHookTriggerType` type.
5664
- parameter url: The endpoint of the hook.
5765
*/
58-
init<T>(object: T.Type, trigger: ParseHookTriggerType, url: URL) where T: ParseObject {
66+
init<T>(
67+
object: T.Type,
68+
trigger: ParseHookTriggerType,
69+
url: URL
70+
) where T: ParseObject {
5971
self.init(className: object.className, trigger: trigger, url: url)
6072
}
6173

@@ -65,7 +77,11 @@ public extension ParseHookTriggerable {
6577
- parameter trigger: The `ParseHookTriggerType` type.
6678
- parameter url: The endpoint of the hook.
6779
*/
68-
init<T>(object: T, trigger: ParseHookTriggerType, url: URL) where T: ParseObject {
80+
init<T>(
81+
object: T,
82+
trigger: ParseHookTriggerType,
83+
url: URL
84+
) where T: ParseObject {
6985
self.init(className: T.className, trigger: trigger, url: url)
7086
}
7187

@@ -76,27 +92,129 @@ public extension ParseHookTriggerable {
7692
- parameter url: The endpoint of the hook.
7793
*/
7894
@available(*, deprecated, message: "Change \"triggerName\" to \"trigger\"")
79-
init<T>(object: T, triggerName: ParseHookTriggerType, url: URL) where T: ParseObject {
95+
init<T>(
96+
object: T,
97+
triggerName: ParseHookTriggerType,
98+
url: URL
99+
) where T: ParseObject {
80100
self.init(object: object, trigger: triggerName, url: url)
81101
}
82102

103+
/**
104+
Creates a new Parse hook trigger for any supported `ParseHookTriggerObject`.
105+
- parameter object: The `ParseHookTriggerObject` the trigger should act on.
106+
- parameter trigger: The `ParseHookTriggerType` type.
107+
- parameter url: The endpoint of the hook.
108+
*/
109+
init( // swiftlint:disable:this cyclomatic_complexity function_body_length
110+
object: ParseHookTriggerObject,
111+
trigger: ParseHookTriggerType,
112+
url: URL
113+
) throws {
114+
115+
let notSupportedError = ParseError(
116+
code: .otherCause,
117+
message: "This object \"\(object)\" currently does not support the hook trigger \"\(trigger)\""
118+
)
119+
120+
switch object {
121+
case .objectType(let parseObject):
122+
switch trigger {
123+
case .beforeLogin, .afterLogin, .afterLogout:
124+
guard parseObject is (any ParseUser.Type) else {
125+
throw notSupportedError
126+
}
127+
case .beforeSave, .afterSave, .beforeDelete,
128+
.afterDelete, .beforeFind, .afterFind,
129+
.beforeSubscribe, .afterEvent:
130+
break // No op
131+
default:
132+
throw notSupportedError
133+
}
134+
self.init(
135+
className: object.className,
136+
trigger: trigger,
137+
url: url
138+
)
139+
case .object(let parseObject):
140+
switch trigger {
141+
case .beforeLogin, .afterLogin, .afterLogout:
142+
guard parseObject is (any ParseUser) else {
143+
throw notSupportedError
144+
}
145+
case .beforeSave, .afterSave, .beforeDelete,
146+
.afterDelete, .beforeFind, .afterFind,
147+
.beforeSubscribe, .afterEvent:
148+
break // No op
149+
default:
150+
throw notSupportedError
151+
}
152+
self.init(
153+
className: object.className,
154+
trigger: trigger,
155+
url: url
156+
)
157+
case .file:
158+
switch trigger {
159+
case .beforeSave, .afterSave, .beforeDelete, .afterDelete:
160+
break // No op
161+
default:
162+
throw notSupportedError
163+
}
164+
self.init(
165+
className: object.className,
166+
trigger: trigger,
167+
url: url
168+
)
169+
case .config:
170+
switch trigger {
171+
case .beforeSave, .afterSave:
172+
break // No op
173+
default:
174+
throw notSupportedError
175+
}
176+
self.init(
177+
className: object.className,
178+
trigger: trigger,
179+
url: url
180+
)
181+
case .liveQueryConnect:
182+
guard trigger == .beforeConnect else {
183+
throw notSupportedError
184+
}
185+
self.init(
186+
className: object.className,
187+
trigger: trigger,
188+
url: url
189+
)
190+
}
191+
}
192+
83193
/**
84194
Creates a new `ParseFile` or `ParseHookTriggerType.beforeConnect` hook trigger.
85195
- parameter trigger: The `ParseHookTriggerType` type.
86196
- parameter url: The endpoint of the hook.
87197
*/
198+
@available(*, deprecated, message: "Add \"object\" as the first argument")
88199
init(trigger: ParseHookTriggerType, url: URL) throws {
89-
self.init()
90-
self.triggerName = trigger
91-
self.url = url
92-
switch triggerName {
200+
switch trigger {
93201
case .beforeSave, .afterSave, .beforeDelete, .afterDelete:
94-
self.className = "@File"
202+
self.init(
203+
className: ParseHookTriggerObject.file.className,
204+
trigger: trigger,
205+
url: url
206+
)
95207
case .beforeConnect:
96-
self.className = "@Connect"
208+
self.init(
209+
className: ParseHookTriggerObject.liveQueryConnect.className,
210+
trigger: trigger,
211+
url: url
212+
)
97213
default:
98-
throw ParseError(code: .otherCause,
99-
message: "This initializer should only be used for \"ParseFile\" and \"beforeConnect\"")
214+
throw ParseError(
215+
code: .otherCause,
216+
message: "This initializer should only be used for \"ParseFile\" and \"beforeConnect\""
217+
)
100218
}
101219
}
102220

0 commit comments

Comments
 (0)