Skip to content

Commit 2ed87dd

Browse files
authored
fix: Always register routes on event loop (#14)
* fix: Always register routes on event loop * update ParseSwift * Update README.md * Update ci.yml * fix web hook tests * update to latest Parse-Swift
1 parent 82c1a08 commit 2ed87dd

File tree

10 files changed

+85
-75
lines changed

10 files changed

+85
-75
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
- name: Use multiple cores
2727
run: defaults write com.apple.dt.XCBuild EnableSwiftBuildSystemIntegration 1
2828
- name: Build and Test
29-
run: swift test --enable-code-coverage -v
29+
run: swift test --enable-code-coverage
3030
env:
3131
DEVELOPER_DIR: ${{ env.CI_XCODE }}
3232
- name: Prepare codecov
@@ -55,7 +55,7 @@ jobs:
5555
release-version: "5"
5656
github-token: ${{ secrets.GITHUB_TOKEN }}
5757
- name: Build and Test
58-
run: swift test --enable-test-discovery --enable-code-coverage -v
58+
run: swift test --enable-test-discovery --enable-code-coverage
5959
- name: Update codecov config
6060
run: cat .codecov.yml | curl --data-binary @- https://codecov.io/validate
6161
- name: Prepare codecov

Package.resolved

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,20 @@ import PackageDescription
44
let package = Package(
55
name: "ParseServerSwift",
66
platforms: [
7-
.macOS(.v12)
7+
.iOS(.v13),
8+
.macCatalyst(.v13),
9+
.macOS(.v10_15),
10+
.tvOS(.v13),
11+
.watchOS(.v6)
812
],
913
products: [
1014
.library(name: "ParseServerSwift", targets: ["ParseServerSwift"])
1115
],
1216
dependencies: [
13-
// 💧 A server-side Swift web framework.
1417
.package(url: "https://github.com/vapor/vapor.git", .upToNextMajor(from: "4.69.1")),
1518
.package(url: "https://github.com/vapor/leaf.git", .upToNextMajor(from: "4.2.4")),
1619
.package(url: "https://github.com/netreconlab/Parse-Swift.git",
17-
.upToNextMajor(from: "5.0.0-beta.4")),
20+
.upToNextMajor(from: "5.0.0-beta.6")),
1821
],
1922
targets: [
2023
.target(

README.md

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ Technically, complete apps can be written with `ParseServerSwift`, the only diff
2727
The following enviroment variables are available and can be configured directly or through `.env`, `.env.production`, etc. See the [Vapor Docs for more details](https://docs.vapor.codes/basics/environment/).
2828

2929
```
30-
PARSE_SWIFT_SERVER_HOST_NAME: cloud-code # The name of your host. If you are running in Docker it should be same name as the docker service
31-
PARSE_SWIFT_SERVER_PORT: # This is the default port on the docker image
32-
PARSE_SWIFT_SERVER_DEFAULT_MAX_BODY_SIZE: 500kb # Set the default size for bodies that are collected into memory before calling your handlers (See Vapor docs for more details)
33-
PARSE_SWIFT_SERVER_URLS: http://parse:1337/parse # (Required) Specify one of your Parse Servers to connect to. Can connect to multiple by seperating URLs with commas
34-
PARSE_SWIFT_SERVER_APPLICATION_ID: appId # (Required) The application id of your Parse Server
35-
PARSE_SWIFT_SERVER_PRIMARY_KEY: primaryKey # (Required) The master key of your Parse Server
36-
PARSE_SWIFT_SERVER_WEBHOOK_KEY: webookKey # The webhookKey of your Parse Server
30+
PARSE_SERVER_SWIFT_HOST_NAME: cloud-code # The name of your host. If you are running in Docker it should be same name as the docker service
31+
PARSE_SERVER_SWIFT_PORT: # This is the default port on the docker image
32+
PARSE_SERVER_SWIFT_DEFAULT_MAX_BODY_SIZE: 500kb # Set the default size for bodies that are collected into memory before calling your handlers (See Vapor docs for more details)
33+
PARSE_SERVER_SWIFT_URLS: http://parse:1337/parse # (Required) Specify one of your Parse Servers to connect to. Can connect to multiple by seperating URLs with commas
34+
PARSE_SERVER_SWIFT_APPLICATION_ID: appId # (Required) The application id of your Parse Server
35+
PARSE_SERVER_SWIFT_PRIMARY_KEY: primaryKey # (Required) The master key of your Parse Server
36+
PARSE_SERVER_SWIFT_WEBHOOK_KEY: webookKey # The webhookKey of your Parse Server
3737
```
3838

3939
If you need to customize your configuration you will need to edit [ParseServerSwift/Sources/ParseServerSwift/configure.swift](https://github.com/netreconlab/ParseServerSwift/blob/main/Sources/ParseServerSwift/configure.swift) directly.
@@ -107,6 +107,7 @@ Cloud Code Functions can also take parameters. It's recommended to place all par
107107
[ParseServerSwift/Sources/ParseServerSwift/Models/Parameters](https://github.com/netreconlab/ParseServerSwift/blob/main/Sources/ParseServerSwift/Models/Parameters)
108108

109109
```swift
110+
// A Parse Hook Function route.
110111
app.post("hello",
111112
name: "hello") { req async throws -> ParseHookResponse<String> in
112113
if let error: ParseHookResponse<String> = checkHeaders(req) {
@@ -133,13 +134,13 @@ app.post("hello",
133134
```swift
134135
// A Parse Hook Trigger route.
135136
app.post("score", "save", "before",
136-
className: "GameScore",
137+
className: GameScore.className,
137138
triggerName: .beforeSave) { req async throws -> ParseHookResponse<GameScore> in
138139
if let error: ParseHookResponse<GameScore> = checkHeaders(req) {
139140
return error
140141
}
141142
var parseRequest = try req.content
142-
.decode(ParseHookTriggerRequest<User, GameScore>.self)
143+
.decode(ParseHookTriggerObjectRequest<User, GameScore>.self)
143144

144145
// If a User called the request, fetch the complete user.
145146
if parseRequest.user != nil {
@@ -148,59 +149,62 @@ app.post("score", "save", "before",
148149

149150
guard let object = parseRequest.object else {
150151
return ParseHookResponse(error: .init(code: .missingObjectId,
151-
message: "Object not sent in request."))
152+
message: "Object not sent in request."))
152153
}
153154
// To query using the primaryKey pass the `usePrimaryKey` option
154155
// to ther query.
155156
let scores = try await GameScore.query.findAll(options: [.usePrimaryKey])
156-
req.logger.info("All scores: \(scores)")
157+
req.logger.info("Before save is being made. Showing all scores before saving new ones: \(scores)")
157158
return ParseHookResponse(success: object)
158159
}
159160

160161
// Another Parse Hook Trigger route.
161162
app.post("score", "find", "before",
162-
className: "GameScore",
163+
className: GameScore.className,
163164
triggerName: .beforeFind) { req async throws -> ParseHookResponse<[GameScore]> in
164165
if let error: ParseHookResponse<[GameScore]> = checkHeaders(req) {
165166
return error
166167
}
167168
let parseRequest = try req.content
168-
.decode(ParseHookTriggerRequest<User, GameScore>.self)
169+
.decode(ParseHookTriggerObjectRequest<User, GameScore>.self)
169170
req.logger.info("A query is being made: \(parseRequest)")
170171

171172
// Return two custom scores instead.
172173
let score1 = GameScore(objectId: "yolo",
173-
createdAt: Date(),
174-
points: 50)
174+
createdAt: Date(),
175+
points: 50)
175176
let score2 = GameScore(objectId: "nolo",
176-
createdAt: Date(),
177-
points: 60)
177+
createdAt: Date(),
178+
points: 60)
179+
req.logger.info("""
180+
Returning custom objects to the user from Cloud Code instead of querying:
181+
\(score1); \(score2)
182+
""")
178183
return ParseHookResponse(success: [score1, score2])
179184
}
180185

181186
// Another Parse Hook Trigger route.
182187
app.post("user", "login", "after",
183-
className: "_User",
188+
className: User.className,
184189
triggerName: .afterLogin) { req async throws -> ParseHookResponse<Bool> in
185190
if let error: ParseHookResponse<Bool> = checkHeaders(req) {
186191
return error
187192
}
188193
let parseRequest = try req.content
189-
.decode(ParseHookTriggerRequest<User, GameScore>.self)
194+
.decode(ParseHookTriggerObjectRequest<User, GameScore>.self)
190195

191196
req.logger.info("A user has logged in: \(parseRequest)")
192197
return ParseHookResponse(success: true)
193198
}
194199

195-
// A Parse Hook Trigger route for `ParseFile` where the body will not be collected into a buffer.
200+
// A Parse Hook Trigger route for `ParseFile`.
196201
app.on("file", "save", "before",
197-
body: .stream,
198202
triggerName: .beforeSave) { req async throws -> ParseHookResponse<Bool> in
199203
if let error: ParseHookResponse<Bool> = checkHeaders(req) {
200204
return error
201205
}
202206
let parseRequest = try req.content
203-
.decode(ParseHookTriggerRequest<User, GameScore>.self)
207+
.decode(ParseHookTriggerRequest<User>.self)
204208

205209
req.logger.info("A ParseFile is being saved: \(parseRequest)")
206210
return ParseHookResponse(success: true)
@@ -213,7 +217,7 @@ app.post("file", "delete", "before",
213217
return error
214218
}
215219
let parseRequest = try req.content
216-
.decode(ParseHookTriggerRequest<User, GameScore>.self)
220+
.decode(ParseHookTriggerRequest<User>.self)
217221

218222
req.logger.info("A ParseFile is being deleted: \(parseRequest)")
219223
return ParseHookResponse(success: true)
@@ -226,35 +230,35 @@ app.post("connect", "before",
226230
return error
227231
}
228232
let parseRequest = try req.content
229-
.decode(ParseHookTriggerRequest<User, GameScore>.self)
233+
.decode(ParseHookTriggerRequest<User>.self)
230234

231235
req.logger.info("A LiveQuery connection is being made: \(parseRequest)")
232236
return ParseHookResponse(success: true)
233237
}
234238

235239
// Another Parse Hook Trigger route for `ParseLiveQuery`.
236240
app.post("score", "subscribe", "before",
237-
className: "GameScore",
241+
className: GameScore.className,
238242
triggerName: .beforeSubscribe) { req async throws -> ParseHookResponse<Bool> in
239243
if let error: ParseHookResponse<Bool> = checkHeaders(req) {
240244
return error
241245
}
242246
let parseRequest = try req.content
243-
.decode(ParseHookTriggerRequest<User, GameScore>.self)
247+
.decode(ParseHookTriggerObjectRequest<User, GameScore>.self)
244248

245-
req.logger.info("A LiveQuery subscribe is being made: \(parseRequest)")
249+
req.logger.info("A LiveQuery subscription is being made: \(parseRequest)")
246250
return ParseHookResponse(success: true)
247251
}
248252

249253
// Another Parse Hook Trigger route for `ParseLiveQuery`.
250254
app.post("score", "event", "after",
251-
className: "GameScore",
255+
className: GameScore.className,
252256
triggerName: .afterEvent) { req async throws -> ParseHookResponse<Bool> in
253257
if let error: ParseHookResponse<Bool> = checkHeaders(req) {
254258
return error
255259
}
256260
let parseRequest = try req.content
257-
.decode(ParseHookTriggerRequest<User, GameScore>.self)
261+
.decode(ParseHookTriggerObjectRequest<User, GameScore>.self)
258262

259263
req.logger.info("A LiveQuery event occured: \(parseRequest)")
260264
return ParseHookResponse(success: true)

Sources/ParseServerSwift/Utility/Functions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public func deleteHooks(_ app: Application) async {
9898
}
9999

100100
func getParseServerURLs(_ urls: String? = nil) throws -> (String, [String]) {
101-
let serverURLs = urls ?? Environment.process.PARSE_SWIFT_SERVER_URLS ?? "http://localhost:1337/parse"
101+
let serverURLs = urls ?? Environment.process.PARSE_SERVER_SWIFT_URLS ?? "http://localhost:1337/parse"
102102
var allServers = serverURLs.replacingOccurrences(of: " ", with: "").split(separator: ",").compactMap { String($0) }
103103
guard let mainServer = allServers.popLast() else {
104104
throw ParseError(code: .otherCause, message: "At least 1 server URL is required")

Sources/ParseServerSwift/configure.swift

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import ParseSwift
33
import Vapor
44

55
/// The key used to authenticate incoming webhook calls from a Parse Server
6-
public var webhookKey: String? = Environment.process.PARSE_SWIFT_SERVER_WEBHOOK_KEY
6+
public var webhookKey: String?
77

88
/// The current Hook Functions and Triggers.
99
public var hooks = Hooks()
@@ -31,13 +31,14 @@ func configure(_ app: Application, testing: Bool) throws {
3131

3232
app.views.use(.leaf)
3333
// Setup current host
34-
app.http.server.configuration.hostname = Environment.process.PARSE_SWIFT_SERVER_HOST_NAME ?? "localhost"
35-
app.http.server.configuration.port = Int(Environment.process.PARSE_SWIFT_SERVER_PORT ?? 8081)
34+
app.http.server.configuration.hostname = Environment.process.PARSE_SERVER_SWIFT_HOST_NAME ?? "localhost"
35+
app.http.server.configuration.port = Int(Environment.process.PARSE_SERVER_SWIFT_PORT ?? 8081)
3636
app.http.server.configuration.tlsConfiguration = .none
3737
serverPathname = app.http.server.configuration.buildServerURL()
38+
webhookKey = Environment.process.PARSE_SERVER_SWIFT_WEBHOOK_KEY
3839

3940
// Increases the streaming body collection limit to 500kb
40-
app.routes.defaultMaxBodySize = ByteCount(stringLiteral: Environment.process.PARSE_SWIFT_SERVER_DEFAULT_MAX_BODY_SIZE ?? "500kb")
41+
app.routes.defaultMaxBodySize = ByteCount(stringLiteral: Environment.process.PARSE_SERVER_SWIFT_DEFAULT_MAX_BODY_SIZE ?? "500kb")
4142

4243
// Parse uses tailored encoders/decoders. These can be retrieved from any ParseObject
4344
ContentConfiguration.global.use(encoder: User.getJSONEncoder(), for: .json)
@@ -55,8 +56,8 @@ func configure(_ app: Application, testing: Bool) throws {
5556
}
5657

5758
// Initialize the Parse-Swift SDK. Add any additional parameters you need
58-
try ParseSwift.initialize(applicationId: Environment.process.PARSE_SWIFT_SERVER_APPLICATION_ID ?? "applicationId",
59-
primaryKey: Environment.process.PARSE_SWIFT_SERVER_PRIMARY_KEY ?? "primaryKey",
59+
try ParseSwift.initialize(applicationId: Environment.process.PARSE_SERVER_SWIFT_APPLICATION_ID ?? "applicationId",
60+
primaryKey: Environment.process.PARSE_SERVER_SWIFT_PRIMARY_KEY ?? "primaryKey",
6061
serverURL: parseServerURL,
6162
usingPostForQuery: true) { _, completionHandler in
6263
// Setup to use default certificate pinning. See Parse-Swift docs for more info
@@ -68,14 +69,12 @@ func configure(_ app: Application, testing: Bool) throws {
6869
do {
6970
// Check the health of all Parse-Server
7071
try await checkServerHealth(app)
71-
// register routes
72-
try routes(app)
7372
} catch {
7473
app.shutdown()
7574
}
7675
}
77-
} else {
78-
// register routes
79-
try routes(app)
8076
}
77+
78+
// register routes
79+
try routes(app)
8180
}

0 commit comments

Comments
 (0)