Skip to content

Commit

Permalink
Make TrieRouter register/unregister receive URLs 📒 (#246)
Browse files Browse the repository at this point in the history
When we updated `Router` and `RouteHandler` to have an additional
`R: Routable` associated type, we also migrated all public `TrieRouter`
APIs to receive an `R` instance, replacing `URL`.

However, the main purpose of the new `R: Routable` is to allow having
more data when effectively _being routed_ (i.e. in `route()`), and not
on all other "events", like registering/unregistering routes.

So, if we for instance define `R` as being some sort of HTTP request
type (which makes total sense to be routed), it doesn't make much sense
to use that same type to register/unregister routes, because it forces
us to create "dummy" requests only for those purposes.

With that in mind, `TrieRouter` `register()` and `unregister()` now
expect (annotated) URLs like before, and only receive an `R` instance
in `route()`.

## Changes

- Update `TrieRouter` `register()` and `unregister()` receive a `URL`
route.

- Update some `TrieRouter` public API documentation.
  • Loading branch information
p4checo authored Sep 1, 2021
1 parent 23ebbba commit d398f3b
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 11 deletions.
35 changes: 26 additions & 9 deletions Sources/DeepLinking/Route+TrieRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,22 @@ extension Route {
/// Creates an instance of a trie router.
public init() {}

/// Registers a new route in the router with the given handler.
/// Registers a new *annotated URL* route in the router with the given handler.
///
/// Annotated URLs contain additional information in their path components that allow matching routes as:
///
/// - constant values (`value`)
/// - arbitrary parameters (`:variable`)
/// - any value (wildcard, `*`)
/// - any remaining route (catchAll, `**` or `**variable`)
///
/// - Parameters:
/// - route: The route to register.
/// - route: The URL route to register.
/// - handler: The handler to associate with the route and handle it on match.
/// - Throws: A `TrieRouterError` error if the route is invalid or a conflict exists.
public func register(_ route: R, handler: AnyRouteHandler<R, T>) throws {
public func register(_ route: URL, handler: AnyRouteHandler<R, T>) throws {

let routeComponents = try parseAnnotatedRoute(route.route)
let routeComponents = try parseAnnotatedRoute(route)

try trie.modify { node in

Expand All @@ -109,15 +116,22 @@ extension Route {
}
}

/// Unregisters the given route from the router, and returns the associated handler if found.
/// Unregisters the given *annotated URL* route from the router, and returns the associated handler if found.
///
/// Annotated URLs contain additional information in their path components that allow matching routes as:
///
/// - Parameter route: The route to unregister
/// - constant values (`value`)
/// - arbitrary parameters (`:variable`)
/// - any value (wildcard, `*`)
/// - any remaining route (catchAll, `**` or `**variable`)
///
/// - Parameter route: The URL route to unregister
/// - Throws: A `TrieRouterError` error if the route is invalid or wasn't found.
/// - Returns: The unregistered handler associated with the route.
@discardableResult
public func unregister(_ route: R) throws -> AnyRouteHandler<R, T> {
public func unregister(_ route: URL) throws -> AnyRouteHandler<R, T> {

let routeComponents = try parseAnnotatedRoute(route.route)
let routeComponents = try parseAnnotatedRoute(route)

return try trie.modify { node in

Expand All @@ -134,9 +148,12 @@ extension Route {
}
}

/// Routes the given route by matching it against the current trie, and optionally notifies routing success
/// Routes the given `R` route by matching it against the current trie, and optionally notifies routing success
/// with a custom payload from the route handler.
///
/// - Important: `R` routes should **not** return *annotated URL* routes. Those should only be used in
/// `register`/`unregister`.
///
/// - Parameters:
/// - route: The route to route.
/// - handleCompletion: The closure to notify routing success with custom payload from the route handler.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,8 @@ class Route_TrieRouter_RouteTests: XCTestCase {
let handleExpectation = expectation(description: "handle")
defer { waitForExpectations(timeout: 1) }

let route = TestRoute(route: "scheme://some/path".url())
let url = "scheme://some/path".url()
let route = TestRoute(route: url)

let router = TestRouter()
var handler = TestHandler()
Expand All @@ -560,7 +561,7 @@ class Route_TrieRouter_RouteTests: XCTestCase {
handleExpectation.fulfill()
}

XCTAssertNoThrow(try router.register(route, handler: handler.eraseToAnyRouteHandler()))
XCTAssertNoThrow(try router.register(url, handler: handler.eraseToAnyRouteHandler()))
XCTAssertNoThrow(try router.route(route))
}
}
Expand Down

0 comments on commit d398f3b

Please sign in to comment.