diff --git a/README.md b/README.md index 0261437..ab4cc4c 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,11 @@ Every `URL` in the list is called an **`Endpoint`** Endpoint has the following structure: ``` - Endpoint -┌───────────────────────────┴────────────────────────────────┐ -https://myservercom.com:123/api/new/posts?date=today&userId=id -└────────────┬────────────┘└───────────────┬─────────────────┘ - Environment Route + Endpoint +┌─────────────────────────────────┴────────────────────────────────────┐ +https://myservercom.com:123/api/new/posts?date=today&userId=id#paragraph +└────────────┬────────────┘└────────────────────┬──────────────────────┘ + Environment Route ``` Endpoint is represented with `EndpointType` `protocol`. @@ -38,7 +38,7 @@ Environment has the following structure: ``` Environment ┌────────────┴────────────┐ -https://myservercom.com:123/api/new/posts?date=today&userId=id +https://myservercom.com:123/api/new/posts?date=today&userId=id#paragraph └─┬─┘ └───────┬───────┘└┬┘ scheme host port ``` @@ -55,18 +55,18 @@ URL.Environment.localhost(4001) // http://localhost:4001 Route has the following structure: ``` - Route - ┌──────────────┴──────────────────┐ -https://myservercom.com:123/api/new/posts?date=today&userId=id - └─────┬──────┘└─────────┬─────────┘ - path query + Route + ┌──────────────────────┴────────────────────┐ +https://myservercom.com:123/api/new/posts?date=today&userId=id#paragraph + └─────┬──────┘└─────────┬─────────┘└───┬────┘ + path query fragment ``` **Example of Route** ```swift -// /api/new/posts?date=today&userId=id -URL.Route(path: ["api", "new", "posts"], query: ("date", "today"), ("userId", "id")) +// /api/new/posts?date=today&userId=id#paragraph +URL.Route(at: "api", "new", "posts").query(("date", "today"), ("userId", "id")).fragment("paragraph") ``` ## Example of usage @@ -95,10 +95,10 @@ struct Api: EndpointType { var route: URL.Route { switch self { - case .me: return .init(path: ["me"]) - case .auth: return .init(path: ["auth"]) + case .me: return .init(at: "me") + case .auth: return .init(at: "auth") case let .posts(for: date): - return URL.Route(path: ["posts"], query: ("date", date), ("userId", "someId")) + return URL.Route(at: "posts").query(("date", date), ("userId", "someId")) } } } diff --git a/SweetRouter/Route.swift b/SweetRouter/Route.swift index 1433f58..b700ad1 100644 --- a/SweetRouter/Route.swift +++ b/SweetRouter/Route.swift @@ -12,21 +12,30 @@ public extension URL { public struct Route { public let path: Path public let query: Query? + public let fragment: String? - public init(path: Path, query: (name: String, value: QueryItemValue?)...) { + public init(path: Path, query: Query? = nil, fragment: String? = nil) { self.path = path - self.query = Query(query) + self.query = query + self.fragment = fragment } - public init(path: Path) { - self.path = path - self.query = nil + public init(at path: RoutePathComponent...) { + self.init(path: Path(path), query: nil, fragment: nil) + } + + public func query(_ query: (name: String, value: QueryItemValue?)...) -> Route { + return Route(path: path, query: Query(query), fragment: nil) + } + + public func fragment(_ fragment: String) -> Route { + return Route(path: path, query: query, fragment: fragment) } } } extension URL.Route: Equatable { public static func == (lhs: URL.Route, rhs: URL.Route) -> Bool { - return lhs.path == rhs.path && lhs.query == rhs.query + return lhs.path == rhs.path && lhs.query == rhs.query && lhs.fragment == rhs.fragment } } diff --git a/SweetRouter/Router.swift b/SweetRouter/Router.swift index b7d6cb2..fa85bbb 100644 --- a/SweetRouter/Router.swift +++ b/SweetRouter/Router.swift @@ -23,6 +23,7 @@ public struct Router: URLRepresentable { components.path = self.route.defaultPath.with(route.path).pathValue components.queryItems = route.query?.queryItems + components.fragment = route.fragment return components } diff --git a/SweetRouterTests/TestRoute.swift b/SweetRouterTests/TestRoute.swift index 38c649c..eb23e9e 100644 --- a/SweetRouterTests/TestRoute.swift +++ b/SweetRouterTests/TestRoute.swift @@ -12,8 +12,9 @@ import SweetRouter class TestRoute: XCTestCase { func testUrlRouteEquatable() { - XCTAssertEqual(URL.Route(path: ["myPath"], query: ("user", nil), ("date", "12.04.02")), URL.Route(path: ["myPath"], query: ("user", nil), ("date", "12.04.02"))) - XCTAssertNotEqual(URL.Route(path: ["myPath"]), URL.Route(path: ["myPath"], query: ("user", nil))) + XCTAssertEqual(URL.Route(at: "myPath").query(("user", nil), ("date", "12.04.02")), URL.Route(path: ["myPath"], query: URL.Query(("user", nil), ("date", "12.04.02")))) + XCTAssertEqual(URL.Route(at: "myPath").fragment("fragment"), URL.Route(path: ["myPath"], fragment: "fragment")) + XCTAssertNotEqual(URL.Route(at: "myPath").query(("user", nil)).fragment("fragment"), URL.Route(path: ["myPath"], fragment: "fragment")) } } diff --git a/SweetRouterTests/TestRouter.swift b/SweetRouterTests/TestRouter.swift index 57dff10..a0aaf72 100644 --- a/SweetRouterTests/TestRouter.swift +++ b/SweetRouterTests/TestRouter.swift @@ -30,10 +30,10 @@ struct Api: EndpointType { var route: URL.Route { switch self { - case .me: return .init(path: ["me"]) - case .auth: return .init(path: ["auth"]) + case .me: return URL.Route(at: "me").fragment("test") + case .auth: return .init(at: "auth") case let .posts(for: date): - return URL.Route(path: ["posts"], query: ("date", date), ("userId", "someId")) + return URL.Route(at: "posts").query(("date", date), ("userId", "someId")) } } } @@ -47,8 +47,8 @@ struct Auth: EndpointType { var route: URL.Route { switch self { - case .signIn: return .init(path: ["signIn"]) - case .signOut: return .init(path: ["signOut"]) + case .signIn: return .init(at: "signIn") + case .signOut: return .init(at: "me", "signOut") } } @@ -63,14 +63,14 @@ struct Auth: EndpointType { class TestRouter: XCTestCase { func testApiRouter() { - XCTAssertEqual(Router(at: .me).url, URL(string: "http://localhost:8080/me")) + XCTAssertEqual(Router(at: .me).url, URL(string: "http://localhost:8080/me#test")) XCTAssertEqual(Router(.test, at: .auth).url, URL(string: "http://126.251.20.32/auth")) XCTAssertEqual(Router(.production, at: .posts(for: "12.04.2017")).url, URL(string: "https://myproductionserver.com:3000/posts?date=12.04.2017&userId=someId")) } func testAuthRouter() { XCTAssertEqual(Router(at: .signIn).url, URL(string: "https://auth.server.com:8080/api/new/signIn")) - XCTAssertEqual(Router(at: .signOut).url, URL(string: "https://auth.server.com:8080/api/new/signOut")) + XCTAssertEqual(Router(at: .signOut).url, URL(string: "https://auth.server.com:8080/api/new/me/signOut")) } }