Skip to content

Commit

Permalink
feat: Add configuration to framework (#16)
Browse files Browse the repository at this point in the history
* feat: Add configuration to framework

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* nits
  • Loading branch information
cbaker6 authored Jan 25, 2023
1 parent 1ca2997 commit 48aa9af
Show file tree
Hide file tree
Showing 13 changed files with 501 additions and 287 deletions.
139 changes: 96 additions & 43 deletions README.md

Large diffs are not rendered by default.

13 changes: 9 additions & 4 deletions Sources/ParseServerSwift/Documentation.docc/ParseServerSwift.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ Write Parse Cloud Code in Swift!
## Overview

What is Cloud Code? For complex apps, sometimes you just need logic that isn’t running on a mobile device. Cloud Code makes this possible.
Cloud Code in ParseServerSwift is easy to use because it’s built using [Parse-Swift](https://github.com/parse-community/Parse-Swift)
and [Vapor](https://github.com/vapor/vapor). The only difference is that this code runs in your ParseServerSwift rather than running on the user’s mobile device. When you update your Cloud Code,
it becomes available to all mobile environments instantly. You don’t have to wait for a new release of your application.
This lets you change app behavior on the fly and add new features faster.
Cloud Code in `ParseServerSwift` is easy to use because it’s built using [Parse-Swift<sup>OG</sup>](https://github.com/netreconlab/Parse-Swift)
and [Vapor](https://github.com/vapor/vapor). `ParseServerSwift` provides many additional benefits over the traditional [JS based Cloud Code](https://docs.parseplatform.org/cloudcode/guide/) that runs on the [Node.js parse-server](https://github.com/parse-community/parse-server):

* Write code with the [Parse-Swift SDK](https://github.com/netreconlab/Parse-Swift) vs the [Parse JS SDK](https://github.com/parse-community/Parse-SDK-JS) allowing you to take advantage of a modern SDK which is strongly typed
* Runs on a dedicated server/container, allowing the [Node.js parse-server](https://github.com/parse-community/parse-server) to focus on request reducing the burden by offloading intensive tasks and providing a true [microservice](https://microservices.io)
* All Cloud Code is in one place, but automatically connects supports the [Node.js parse-server](https://github.com/parse-community/parse-server) at scale. This circumvents the issues faced when using [JS based Cloud Code](https://docs.parseplatform.org/cloudcode/guide/) with [PM2](https://pm2.keymetrics.io)
* Leverage the capabilities of [server-side-swift](https://www.swift.org/server/) with [Vapor](https://github.com/vapor/vapor)

Technically, complete apps can be written with `ParseServerSwift`, the only difference is that this code runs in your `ParseServerSwift` rather than running on the user’s mobile device. When you update your Cloud Code, it becomes available to all mobile environments instantly. You don’t have to wait for a new release of your application. This lets you change app behavior on the fly and add new features faster.
5 changes: 3 additions & 2 deletions Sources/ParseServerSwift/Extensions/Parse+Vapor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public extension ParseHookRequestable {
In a single Parse Server environment, use options().
*/
func options(_ request: Request,
parseServerURLStrings: [String]) throws -> API.Options {
parseServerURLStrings: [String] = ParseServerSwift.configuration.parseServerURLStrings) throws -> API.Options {
var options = self.options()
options.insert(.serverURL(try serverURLString(request.url,
parseServerURLStrings: parseServerURLStrings)))
Expand All @@ -35,14 +35,15 @@ public extension ParseHookRequestable {
- parameter options: A set of header options sent to the server. Defaults to an empty set.
- parameter request: The HTTP request of the application.
- parameter parseServerURLStrings: A set of Parse Server `URL`'s.
Defaults to the set of servers added during configuration.
- returns: Returns the `ParseHookRequestable` with the hydrated `ParseCloudUser`.
- throws: An error of type `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 hydrateUser(options: API.Options = [],
request: Request,
parseServerURLStrings: [String]) async throws -> Self {
parseServerURLStrings: [String] = ParseServerSwift.configuration.parseServerURLStrings) async throws -> Self {
var updatedOptions = try self.options(request, parseServerURLStrings: parseServerURLStrings)
updatedOptions = updatedOptions.union(options)
return try await withCheckedThrowingContinuation { continuation in
Expand Down
47 changes: 19 additions & 28 deletions Sources/ParseServerSwift/Models/HookFunction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ extension HookFunction {
throw ParseError(code: .otherCause,
message: "Method \(method) is not supported for Hook Function: \"\(String(describing: hookFunction))\"")
}
logger.notice("Successful \(method); Hook Function: \"\(String(describing: hookFunction))\" on server: \(parseServerURLString)")
configuration.logger.notice("Successful \(method); Hook Function: \"\(String(describing: hookFunction))\" on server: \(parseServerURLString)")
} catch {
if error.containedIn([.webhookError]) && method == .POST {
logger.warning("Hook Function: \"\(String(describing: hookFunction))\"; warning: \(error); on server: \(parseServerURLString)")
configuration.logger.warning("Hook Function: \"\(String(describing: hookFunction))\"; warning: \(error); on server: \(parseServerURLString)")
} else {
logger.error("Could not \(method) Hook Function: \"\(String(describing: hookFunction))\"; error: \(error); on server: \(parseServerURLString)")
configuration.logger.error("Could not \(method) Hook Function: \"\(String(describing: hookFunction))\"; error: \(error); on server: \(parseServerURLString)")
}
}
}
Expand Down Expand Up @@ -140,7 +140,7 @@ public extension HookFunction {
hookFunctions[parseServerURLString] = try await hookFunction
.fetchAll(options: [.serverURL(parseServerURLString)])
} catch {
logger.error("Could not fetchAll function: \"\(String(describing: hookFunction))\"; error: \(error); on server: \(parseServerURLString)")
configuration.logger.error("Could not fetchAll function: \"\(String(describing: hookFunction))\"; error: \(error); on server: \(parseServerURLString)")
}
}
return hookFunctions
Expand All @@ -155,14 +155,15 @@ public extension HookFunction {
- parameter path: A variadic list of paths.
- parameter name: The name of the function.
- parameter parseServerURLStrings: A set of Parse Server `URL`'s to create hook functions for.
Defaults to the set of servers added during configuration.
- returns: A dictionary where the keys are Parse Server `URL`'s and the respective `HookFunction`.
- throws: An error of `ParseError` type.
- note: WIll attempt to create functions on all `parseServerURLStrings`.
Will log an error for each `parseServerURLString` that returns an error.
*/
static func create(_ path: PathComponent...,
name: String,
parseServerURLStrings: [String]) async throws -> [String: HookFunction] {
parseServerURLStrings: [String] = ParseServerSwift.configuration.parseServerURLStrings) async throws -> [String: HookFunction] {
try await create(path, name: name, parseServerURLStrings: parseServerURLStrings)
}

Expand All @@ -171,14 +172,15 @@ public extension HookFunction {
- parameter path: An array of paths.
- parameter name: The name of the function.
- parameter parseServerURLStrings: A set of Parse Server `URL`'s to create hook functions for.
Defaults to the set of servers added during configuration.
- returns: A dictionary where the keys are Parse Server `URL`'s and the respective `HookFunction`.
- throws: An error of `ParseError` type.
- note: WIll attempt to create functions on all `parseServerURLStrings`.
Will log an error for each `parseServerURLString` that returns an error.
*/
static func create(_ path: [PathComponent],
name: String,
parseServerURLStrings: [String]) async throws -> [String: HookFunction] {
parseServerURLStrings: [String] = ParseServerSwift.configuration.parseServerURLStrings) async throws -> [String: HookFunction] {
try await method(.POST, path, name: name, parseServerURLStrings: parseServerURLStrings)
}
}
Expand All @@ -191,14 +193,15 @@ public extension HookFunction {
- parameter path: A variadic list of paths.
- parameter name: The name of the function.
- parameter parseServerURLStrings: A set of Parse Server `URL`'s to create hook functions for.
Defaults to the set of servers added during configuration.
- returns: A dictionary where the keys are Parse Server `URL`'s and the respective `HookFunction`.
- throws: An error of `ParseError` type.
- note: WIll attempt to create functions on all `parseServerURLStrings`.
Will log an error for each `parseServerURLString` that returns an error.
*/
static func update(_ path: PathComponent...,
name: String,
parseServerURLStrings: [String]) async throws -> [String: HookFunction] {
parseServerURLStrings: [String] = ParseServerSwift.configuration.parseServerURLStrings) async throws -> [String: HookFunction] {
try await update(path, name: name, parseServerURLStrings: parseServerURLStrings)
}

Expand All @@ -207,14 +210,15 @@ public extension HookFunction {
- parameter path: An array of paths.
- parameter name: The name of the function.
- parameter parseServerURLStrings: A set of Parse Server `URL`'s to create hook functions for.
Defaults to the set of servers added during configuration.
- returns: A dictionary where the keys are Parse Server `URL`'s and the respective `HookFunction`.
- throws: An error of `ParseError` type.
- note: WIll attempt to create functions on all `parseServerURLStrings`.
Will log an error for each `parseServerURLString` that returns an error.
*/
static func update(_ path: [PathComponent],
name: String,
parseServerURLStrings: [String]) async throws -> [String: HookFunction] {
parseServerURLStrings: [String] = ParseServerSwift.configuration.parseServerURLStrings) async throws -> [String: HookFunction] {
try await method(.PUT, path, name: name, parseServerURLStrings: parseServerURLStrings)
}
}
Expand All @@ -227,13 +231,14 @@ public extension HookFunction {
- parameter path: A variadic list of paths.
- parameter name: The name of the function.
- parameter parseServerURLStrings: A set of Parse Server `URL`'s to create hook functions for.
Defaults to the set of servers added during configuration.
- throws: An error of `ParseError` type.
- note: WIll attempt to create functions on all `parseServerURLStrings`.
Will log an error for each `parseServerURLString` that returns an error.
*/
static func delete(_ path: PathComponent...,
name: String,
parseServerURLStrings: [String]) async throws {
parseServerURLStrings: [String] = ParseServerSwift.configuration.parseServerURLStrings) async throws {
try await delete(path, name: name, parseServerURLStrings: parseServerURLStrings)
}

Expand All @@ -243,12 +248,13 @@ public extension HookFunction {
- parameter name: The name of the function.
- parameter parseServerURLStrings: A set of Parse Server `URL`'s to create hook functions for.
- throws: An error of `ParseError` type.
Defaults to the set of servers added during configuration.
- note: WIll attempt to create functions on all `parseServerURLStrings`.
Will log an error for each `parseServerURLString` that returns an error.
*/
static func delete(_ path: [PathComponent],
name: String,
parseServerURLStrings: [String]) async throws {
parseServerURLStrings: [String] = ParseServerSwift.configuration.parseServerURLStrings) async throws {
try await method(.DELETE, path, name: name, parseServerURLStrings: parseServerURLStrings)
}
}
Expand All @@ -268,16 +274,12 @@ public extension RoutesBuilder {
func post<Response>(
_ path: PathComponent...,
name: String,
parseServerURLStrings: [String],
hooks: Hooks,
use closure: @escaping (Request) async throws -> Response
) -> Route
where Response: AsyncResponseEncodable
{
self.on(path,
name: name,
parseServerURLStrings: parseServerURLStrings,
hooks: hooks,
use: closure)
}

Expand All @@ -294,16 +296,12 @@ public extension RoutesBuilder {
func post<Response>(
_ path: [PathComponent],
name: String,
parseServerURLStrings: [String],
hooks: Hooks,
use closure: @escaping (Request) async throws -> Response
) -> Route
where Response: AsyncResponseEncodable
{
self.on(path,
name: name,
parseServerURLStrings: parseServerURLStrings,
hooks: hooks,
use: closure)
}

Expand All @@ -322,17 +320,13 @@ public extension RoutesBuilder {
_ path: PathComponent...,
body: HTTPBodyStreamStrategy = .collect,
name: String,
parseServerURLStrings: [String],
hooks: Hooks,
use closure: @escaping (Request) async throws -> Response
) -> Route
where Response: AsyncResponseEncodable
{
self.on(path,
body: body,
name: name,
parseServerURLStrings: parseServerURLStrings,
hooks: hooks,
use: closure)
}

Expand All @@ -351,19 +345,16 @@ public extension RoutesBuilder {
_ path: [PathComponent],
body: HTTPBodyStreamStrategy = .collect,
name: String,
parseServerURLStrings: [String],
hooks: Hooks,
use closure: @escaping (Request) async throws -> Response
) -> Route
where Response: AsyncResponseEncodable
{
Task {
do {
await hooks.updateFunctions(try await HookFunction.create(path,
name: name,
parseServerURLStrings: parseServerURLStrings))
await configuration.hooks.updateFunctions(try await HookFunction.create(path,
name: name))
} catch {
logger.error("Could not create HookFunction route for path: \(path); name: \(name) on servers: \(parseServerURLStrings) because of error: \(error)")
configuration.logger.error("Could not create HookFunction route for path: \(path); name: \(name) on servers: \(configuration.parseServerURLStrings) because of error: \(error)")
}
}
return self.on(.POST, path, body: body, use: closure)
Expand Down
Loading

0 comments on commit 48aa9af

Please sign in to comment.