feat: Refactoring route declarations.

This commit is contained in:
2025-01-26 01:16:59 -05:00
parent 0fad024350
commit 4dc928e1f4
34 changed files with 592 additions and 606 deletions

View File

@@ -14,15 +14,15 @@ public extension DependencyValues {
public struct ApiController: Sendable { public struct ApiController: Sendable {
public var json: @Sendable (Request) async throws -> (any Encodable)? public var json: @Sendable (Request) async throws -> (any Encodable)?
public func json(_ route: ApiRoute, logger: Logger) async throws -> (any Encodable)? { public func json(_ route: SiteRoute.Api, logger: Logger) async throws -> (any Encodable)? {
try await json(.init(route, logger: logger)) try await json(.init(route, logger: logger))
} }
public struct Request: Sendable { public struct Request: Sendable {
public let route: ApiRoute public let route: SiteRoute.Api
public let logger: Logger public let logger: Logger
public init(_ route: ApiRoute, logger: Logger) { public init(_ route: SiteRoute.Api, logger: Logger) {
self.route = route self.route = route
self.logger = logger self.logger = logger
} }

View File

@@ -41,7 +41,7 @@ private struct TokenResponse: Encodable {
} }
private extension ApiRoute.EmployeeRoute { private extension SiteRoute.Api.EmployeeRoute {
func handleApiRequest(logger: Logger) async throws -> (any Encodable)? { func handleApiRequest(logger: Logger) async throws -> (any Encodable)? {
@Dependency(\.database) var database @Dependency(\.database) var database
@@ -66,7 +66,7 @@ private extension ApiRoute.EmployeeRoute {
} }
} }
private extension ApiRoute.PurchaseOrderRoute { private extension SiteRoute.Api.PurchaseOrderRoute {
func handleApiRequest(logger: Logger) async throws -> (any Encodable)? { func handleApiRequest(logger: Logger) async throws -> (any Encodable)? {
@Dependency(\.database.purchaseOrders) var purchaseOrders @Dependency(\.database.purchaseOrders) var purchaseOrders
@@ -90,8 +90,7 @@ private extension ApiRoute.PurchaseOrderRoute {
} }
} }
// TODO: Add Login. private extension SiteRoute.Api.UserRoute {
private extension ApiRoute.UserRoute {
func handleApiRequest(logger: Logger) async throws -> (any Encodable)? { func handleApiRequest(logger: Logger) async throws -> (any Encodable)? {
@Dependency(\.database.users) var users @Dependency(\.database.users) var users
@@ -117,7 +116,7 @@ private extension ApiRoute.UserRoute {
} }
} }
private extension ApiRoute.VendorRoute { private extension SiteRoute.Api.VendorRoute {
func handleApiRequest(logger: Logger) async throws -> (any Encodable)? { func handleApiRequest(logger: Logger) async throws -> (any Encodable)? {
@Dependency(\.database.vendors) var vendors @Dependency(\.database.vendors) var vendors
switch self { switch self {
@@ -143,7 +142,7 @@ private extension ApiRoute.VendorRoute {
} }
} }
private extension ApiRoute.VendorBranchRoute { private extension SiteRoute.Api.VendorBranchRoute {
func handleApiRequest(logger: Logger) async throws -> (any Encodable)? { func handleApiRequest(logger: Logger) async throws -> (any Encodable)? {
@Dependency(\.database.vendorBranches) var vendorBranches @Dependency(\.database.vendorBranches) var vendorBranches
switch self { switch self {

View File

@@ -4,7 +4,7 @@ import Vapor
extension ApiController { extension ApiController {
func respond(_ route: ApiRoute, request: Vapor.Request) async throws -> any AsyncResponseEncodable { func respond(_ route: SiteRoute.Api, request: Vapor.Request) async throws -> any AsyncResponseEncodable {
guard let encodable = try await json(route, logger: request.logger) else { guard let encodable = try await json(route, logger: request.logger) else {
return HTTPStatus.ok return HTTPStatus.ok
} }

View File

@@ -5,7 +5,7 @@ import VaporElementary
import ViewController import ViewController
extension ViewController { extension ViewController {
func respond(route: ViewRoute, request: Vapor.Request) async throws -> any AsyncResponseEncodable { func respond(route: SiteRoute.View, request: Vapor.Request) async throws -> any AsyncResponseEncodable {
let html = try await view( let html = try await view(
for: route, for: route,
isHtmxRequest: request.isHtmxRequest, isHtmxRequest: request.isHtmxRequest,

View File

@@ -9,7 +9,7 @@ private let apiMiddleware: [any Middleware] = [
User.guardMiddleware() User.guardMiddleware()
] ]
extension ApiRoute { extension SiteRoute.Api {
var middleware: [any Middleware]? { var middleware: [any Middleware]? {
switch self { switch self {
case .login: return nil case .login: return nil

View File

@@ -12,7 +12,7 @@ private let viewProtectedMiddleware: [any Middleware] = [
} }
] ]
extension SharedModels.ViewRoute { extension SiteRoute.View {
var middleware: [any Middleware]? { var middleware: [any Middleware]? {
switch self { switch self {

View File

@@ -73,7 +73,7 @@ private func setupDatabase(
private func addRoutes(to app: Application) { private func addRoutes(to app: Application) {
// Redirect the index path to purchase order route. // Redirect the index path to purchase order route.
app.get { req in app.get { req in
req.redirect(to: ViewRoute.router.path(for: .purchaseOrder(.index))) req.redirect(to: SiteRoute.View.router.path(for: .purchaseOrder(.index)))
} }
app.mount( app.mount(

View File

@@ -2,227 +2,230 @@ import CasePaths
import Foundation import Foundation
@preconcurrency import URLRouting @preconcurrency import URLRouting
public enum ApiRoute: Sendable, Equatable { public extension SiteRoute {
case employee(EmployeeRoute) enum Api: Sendable, Equatable {
case login(User.Login)
case purchaseOrder(PurchaseOrderRoute)
case user(UserRoute)
case vendor(VendorRoute)
case vendorBranch(VendorBranchRoute)
static let rootPath = Path { "api"; "v1" } case employee(EmployeeRoute)
case login(User.Login)
case purchaseOrder(PurchaseOrderRoute)
case user(UserRoute)
case vendor(VendorRoute)
case vendorBranch(VendorBranchRoute)
public static let router = OneOf { static let rootPath = Path { "api"; "v1" }
Route(.case(Self.employee)) {
rootPath
EmployeeRoute.router
}
Route(.case(Self.login)) {
Path { "api"; "v1"; "login" }
Method.post
Body(.json(User.Login.self))
}
Route(.case(Self.purchaseOrder)) {
rootPath
PurchaseOrderRoute.router
}
Route(.case(Self.user)) {
rootPath
UserRoute.router
}
Route(.case(Self.vendor)) {
rootPath
VendorRoute.router
}
Route(.case(Self.vendorBranch)) {
rootPath
VendorBranchRoute.router
}
}
public enum EmployeeRoute: Sendable, Equatable {
case create(Employee.Create)
case delete(id: Employee.ID)
case get(id: Employee.ID)
case index
case update(id: Employee.ID, updates: Employee.Update)
static let rootPath = "employees"
public static let router = OneOf { public static let router = OneOf {
Route(.case(Self.create)) { Route(.case(Self.employee)) {
Path { rootPath } rootPath
EmployeeRoute.router
}
Route(.case(Self.login)) {
Path { "api"; "v1"; "login" }
Method.post Method.post
Body(.json(Employee.Create.self)) Body(.json(User.Login.self))
} }
Route(.case(Self.delete(id:))) { Route(.case(Self.purchaseOrder)) {
Path { rootPath; Employee.ID.parser() } rootPath
Method.delete PurchaseOrderRoute.router
} }
Route(.case(Self.index)) { Route(.case(Self.user)) {
Path { rootPath } rootPath
Method.get UserRoute.router
} }
Route(.case(Self.get(id:))) { Route(.case(Self.vendor)) {
Path { rootPath; Employee.ID.parser() } rootPath
Method.get VendorRoute.router
} }
Route(.case(Self.update(id:updates:))) { Route(.case(Self.vendorBranch)) {
Path { rootPath; Employee.ID.parser() } rootPath
Method.put VendorBranchRoute.router
Body(.json(Employee.Update.self))
} }
} }
}
public enum PurchaseOrderRoute: Sendable, Equatable { public enum EmployeeRoute: Sendable, Equatable {
case create(PurchaseOrder.Create) case create(Employee.Create)
case delete(id: PurchaseOrder.ID) case delete(id: Employee.ID)
case get(id: PurchaseOrder.ID) case get(id: Employee.ID)
case index case index
case page(page: Int, limit: Int) case update(id: Employee.ID, updates: Employee.Update)
static let rootPath = "purchase-orders" static let rootPath = "employees"
public static let router = OneOf { public static let router = OneOf {
Route(.case(Self.create)) { Route(.case(Self.create)) {
Path { rootPath } Path { rootPath }
Method.post Method.post
Body(.json(PurchaseOrder.Create.self)) Body(.json(Employee.Create.self))
} }
Route(.case(Self.delete(id:))) { Route(.case(Self.delete(id:))) {
Path { rootPath; PurchaseOrder.ID.parser() } Path { rootPath; Employee.ID.parser() }
Method.delete Method.delete
} }
Route(.case(Self.get(id:))) { Route(.case(Self.index)) {
Path { rootPath; Digits() } Path { rootPath }
Method.get Method.get
} }
Route(.case(Self.index)) { Route(.case(Self.get(id:))) {
Path { rootPath } Path { rootPath; Employee.ID.parser() }
Method.get Method.get
} }
Route(.case(Self.page(page:limit:))) { Route(.case(Self.update(id:updates:))) {
Path { rootPath; "next" } Path { rootPath; Employee.ID.parser() }
Method.get Method.put
Query { Body(.json(Employee.Update.self))
Field("page", default: 1) { Digits() }
Field("limit", default: 25) { Digits() }
} }
} }
} }
}
public enum UserRoute: Sendable, Equatable { public enum PurchaseOrderRoute: Sendable, Equatable {
case delete(id: User.ID) case create(PurchaseOrder.Create)
case create(User.Create) case delete(id: PurchaseOrder.ID)
case get(id: User.ID) case get(id: PurchaseOrder.ID)
case index case index
case update(id: User.ID, updates: User.Update) case page(page: Int, limit: Int)
static let rootPath = "users" static let rootPath = "purchase-orders"
public static let router = OneOf { public static let router = OneOf {
Route(.case(Self.create)) { Route(.case(Self.create)) {
Path { rootPath } Path { rootPath }
Method.post Method.post
Body(.json(User.Create.self)) Body(.json(PurchaseOrder.Create.self))
} }
Route(.case(Self.delete(id:))) { Route(.case(Self.delete(id:))) {
Path { rootPath; User.ID.parser() } Path { rootPath; PurchaseOrder.ID.parser() }
Method.delete Method.delete
} }
Route(.case(Self.get(id:))) { Route(.case(Self.get(id:))) {
Path { rootPath; User.ID.parser() } Path { rootPath; Digits() }
Method.get Method.get
} }
Route(.case(Self.index)) { Route(.case(Self.index)) {
Path { rootPath } Path { rootPath }
Method.get Method.get
} }
Route(.case(Self.update(id:updates:))) { Route(.case(Self.page(page:limit:))) {
Path { rootPath; User.ID.parser() } Path { rootPath; "next" }
Method.patch Method.get
Body(.json(User.Update.self)) Query {
} Field("page", default: 1) { Digits() }
} Field("limit", default: 25) { Digits() }
}
public enum VendorRoute: Sendable, Equatable {
case delete(id: Vendor.ID)
case index(withBranches: Bool? = nil)
case create(Vendor.Create)
case get(id: Vendor.ID)
case update(id: Vendor.ID, updates: Vendor.Update)
static let rootPath = "vendors"
public static let router = OneOf {
Route(.case(Self.delete(id:))) {
Path { rootPath; Vendor.ID.parser() }
Method.delete
}
Route(.case(Self.create)) {
Path { rootPath }
Method.post
Body(.json(Vendor.Create.self))
}
Route(.case(Self.get(id:))) {
Path { rootPath; Vendor.ID.parser() }
Method.get
}
Route(.case(Self.index(withBranches:))) {
Path { rootPath }
Method.get
Query {
Optionally {
Field("branches", default: nil) {
Bool.parser()
}
} }
} }
} }
Route(.case(Self.update(id:updates:))) {
Path { rootPath; Vendor.ID.parser() }
Method.put
Body(.json(Vendor.Update.self))
}
} }
}
public enum VendorBranchRoute: Sendable, Equatable { public enum UserRoute: Sendable, Equatable {
case delete(id: VendorBranch.ID) case delete(id: User.ID)
case create(VendorBranch.Create) case create(User.Create)
case get(id: VendorBranch.ID) case get(id: User.ID)
case index(for: Vendor.ID? = nil) case index
case update(id: VendorBranch.ID, updates: VendorBranch.Update) case update(id: User.ID, updates: User.Update)
public static let router = OneOf { static let rootPath = "users"
Route(.case(Self.create)) {
Path { "vendors"; "branches" } public static let router = OneOf {
Method.post Route(.case(Self.create)) {
Body(.json(VendorBranch.Create.self)) Path { rootPath }
} Method.post
Route(.case(Self.delete(id:))) { Body(.json(User.Create.self))
Path { "vendors"; "branches"; VendorBranch.ID.parser() } }
Method.delete Route(.case(Self.delete(id:))) {
} Path { rootPath; User.ID.parser() }
Route(.case(Self.get(id:))) { Method.delete
Path { "vendors"; "branches"; VendorBranch.ID.parser() } }
Method.get Route(.case(Self.get(id:))) {
} Path { rootPath; User.ID.parser() }
Route(.case(Self.index(for:))) { Method.get
Path { "vendors"; "branches" } }
Method.get Route(.case(Self.index)) {
Query { Path { rootPath }
Optionally { Field("vendorID", default: nil) { VendorBranch.ID.parser() } } Method.get
}
Route(.case(Self.update(id:updates:))) {
Path { rootPath; User.ID.parser() }
Method.patch
Body(.json(User.Update.self))
} }
} }
Route(.case(Self.update(id:updates:))) { }
Path { "vendors"; "branches"; VendorBranch.ID.parser() }
Method.put public enum VendorRoute: Sendable, Equatable {
Body(.json(VendorBranch.Update.self)) case delete(id: Vendor.ID)
case index(withBranches: Bool? = nil)
case create(Vendor.Create)
case get(id: Vendor.ID)
case update(id: Vendor.ID, updates: Vendor.Update)
static let rootPath = "vendors"
public static let router = OneOf {
Route(.case(Self.delete(id:))) {
Path { rootPath; Vendor.ID.parser() }
Method.delete
}
Route(.case(Self.create)) {
Path { rootPath }
Method.post
Body(.json(Vendor.Create.self))
}
Route(.case(Self.get(id:))) {
Path { rootPath; Vendor.ID.parser() }
Method.get
}
Route(.case(Self.index(withBranches:))) {
Path { rootPath }
Method.get
Query {
Optionally {
Field("branches", default: nil) {
Bool.parser()
}
}
}
}
Route(.case(Self.update(id:updates:))) {
Path { rootPath; Vendor.ID.parser() }
Method.put
Body(.json(Vendor.Update.self))
}
}
}
public enum VendorBranchRoute: Sendable, Equatable {
case delete(id: VendorBranch.ID)
case create(VendorBranch.Create)
case get(id: VendorBranch.ID)
case index(for: Vendor.ID? = nil)
case update(id: VendorBranch.ID, updates: VendorBranch.Update)
public static let router = OneOf {
Route(.case(Self.create)) {
Path { "vendors"; "branches" }
Method.post
Body(.json(VendorBranch.Create.self))
}
Route(.case(Self.delete(id:))) {
Path { "vendors"; "branches"; VendorBranch.ID.parser() }
Method.delete
}
Route(.case(Self.get(id:))) {
Path { "vendors"; "branches"; VendorBranch.ID.parser() }
Method.get
}
Route(.case(Self.index(for:))) {
Path { "vendors"; "branches" }
Method.get
Query {
Optionally { Field("vendorID", default: nil) { VendorBranch.ID.parser() } }
}
}
Route(.case(Self.update(id:updates:))) {
Path { "vendors"; "branches"; VendorBranch.ID.parser() }
Method.put
Body(.json(VendorBranch.Update.self))
}
} }
} }
} }

View File

@@ -3,16 +3,16 @@ import Foundation
@preconcurrency import URLRouting @preconcurrency import URLRouting
public enum SiteRoute: Sendable { public enum SiteRoute: Sendable {
case api(ApiRoute) case api(SiteRoute.Api)
case health case health
case view(ViewRoute) case view(SiteRoute.View)
public static let router = OneOf { public static let router = OneOf {
Route(.case(Self.view)) { ViewRoute.router } Route(.case(Self.view)) { SiteRoute.View.router }
Route(.case(Self.health)) { Route(.case(Self.health)) {
Path { "health" } Path { "health" }
Method.get Method.get
} }
Route(.case(Self.api)) { ApiRoute.router } Route(.case(Self.api)) { SiteRoute.Api.router }
} }
} }

View File

@@ -2,393 +2,375 @@ import CasePathsCore
import Foundation import Foundation
@preconcurrency import URLRouting @preconcurrency import URLRouting
public enum ViewRoute: Sendable, Equatable { public extension SiteRoute {
enum View: Sendable, Equatable {
case employee(EmployeeRoute) case employee(SiteRoute.View.EmployeeRoute)
case login(LoginRoute) case login(SiteRoute.View.LoginRoute)
case purchaseOrder(PurchaseOrderRoute) case purchaseOrder(SiteRoute.View.PurchaseOrderRoute)
case user(UserRoute) case user(SiteRoute.View.UserRoute)
case vendor(VendorRoute) case vendor(SiteRoute.View.VendorRoute)
case vendorBranch(VendorBranchRoute) case vendorBranch(SiteRoute.View.VendorBranchRoute)
public static let router = OneOf {
Route(.case(Self.employee)) { EmployeeRoute.router }
Route(.case(Self.login)) { LoginRoute.router }
Route(.case(Self.purchaseOrder)) { PurchaseOrderRoute.router }
Route(.case(Self.user)) { UserRoute.router }
Route(.case(Self.vendor)) { VendorRoute.router }
Route(.case(Self.vendorBranch)) { VendorBranchRoute.router }
}
}
public extension ViewRoute {
enum EmployeeRoute: Sendable, Equatable {
case create(Employee.Create)
case form
case get(id: Employee.ID)
case index
case select(context: SelectContext)
case update(id: Employee.ID, updates: Employee.Update)
static let rootPath = "employees"
public static let router = OneOf { public static let router = OneOf {
Route(.case(Self.create)) { Route(.case(Self.employee)) { SiteRoute.View.EmployeeRoute.router }
Path { rootPath } Route(.case(Self.login)) { SiteRoute.View.LoginRoute.router }
Method.post Route(.case(Self.purchaseOrder)) { SiteRoute.View.PurchaseOrderRoute.router }
Body { Route(.case(Self.user)) { SiteRoute.View.UserRoute.router }
FormData { Route(.case(Self.vendor)) { SiteRoute.View.VendorRoute.router }
Field("firstName", .string) Route(.case(Self.vendorBranch)) { SiteRoute.View.VendorBranchRoute.router }
Field("lastName", .string) }
Optionally { Field("active") { Bool.parser() } }
public enum EmployeeRoute: Sendable, Equatable {
case create(Employee.Create)
case form
case get(id: Employee.ID)
case index
case select(context: SiteRoute.View.SelectContext)
case update(id: Employee.ID, updates: Employee.Update)
static let rootPath = "employees"
public static let router = OneOf {
Route(.case(Self.create)) {
Path { rootPath }
Method.post
Body {
FormData {
Field("firstName", .string)
Field("lastName", .string)
Optionally { Field("active") { Bool.parser() } }
}
.map(.memberwise(Employee.Create.init))
} }
.map(.memberwise(Employee.Create.init))
} }
} Route(.case(Self.get(id:))) {
Route(.case(Self.get(id:))) { Path { rootPath; Employee.ID.parser() }
Path { rootPath; Employee.ID.parser() } Method.get
Method.get }
} Route(.case(Self.form)) {
Route(.case(Self.form)) { Path { rootPath; "create" }
Path { rootPath; "create" } Method.get
Method.get }
} Route(.case(Self.index)) {
Route(.case(Self.index)) { Path { rootPath }
Path { rootPath } Method.get
Method.get }
} Route(.case(Self.update(id:updates:))) {
Route(.case(Self.update(id:updates:))) { Path { rootPath; Employee.ID.parser() }
Path { rootPath; Employee.ID.parser() } Method.put
Method.put Body {
Body { FormData {
FormData { Optionally { Field("firstName") { CharacterSet.alphanumerics.map(.string) } }
Optionally { Field("firstName") { CharacterSet.alphanumerics.map(.string) } } Optionally { Field("lastName") { CharacterSet.alphanumerics.map(.string) } }
Optionally { Field("lastName") { CharacterSet.alphanumerics.map(.string) } } Optionally { Field("active") { Bool.parser() } }
Optionally { Field("active") { Bool.parser() } } }
.map(.memberwise(Employee.Update.init))
} }
.map(.memberwise(Employee.Update.init))
} }
} Route(.case(Self.select(context:))) {
Route(.case(Self.select(context:))) { Path { rootPath; "select" }
Path { rootPath; "select" } Method.get
Method.get Query {
Query { Field("context") { SelectContext.parser() }
Field("context") { SelectContext.parser() } }
} }
} }
} }
}
}
public extension ViewRoute { public enum LoginRoute: Sendable, Equatable {
case index(next: String? = nil)
case post(Request)
enum LoginRoute: Sendable, Equatable { static let rootPath = "login"
case index(next: String? = nil)
case post(Request)
static let rootPath = "login" public static let router = OneOf {
Route(.case(Self.index)) {
public static let router = OneOf { Method.get
Route(.case(Self.index)) { Path { rootPath }
Method.get Query {
Path { rootPath }
Query {
Optionally {
Field("next", default: nil) {
CharacterSet.urlPathAllowed.map(.string)
}
}
}
}
Route(.case(Self.post)) {
Path { rootPath }
Method.post
Body {
FormData {
Field("username", .string)
Field("password", .string)
Optionally { Optionally {
Field("next", default: nil) { Field("next", default: nil) {
CharacterSet.urlPathAllowed.map(.string) CharacterSet.urlPathAllowed.map(.string)
} }
} }
} }
.map(.memberwise(Request.init))
} }
} Route(.case(Self.post)) {
} Path { rootPath }
public struct Request: Codable, Equatable, Sendable {
public let username: String
public let password: String
public let next: String?
public init(username: String, password: String, next: String? = nil) {
self.username = username
self.password = password
self.next = next
}
}
}
}
public extension ViewRoute {
enum PurchaseOrderRoute: Sendable, Equatable {
case create(PurchaseOrder.Create)
case form
case get(id: PurchaseOrder.ID)
case index
case page(page: Int, limit: Int)
case search(Search)
static let rootPath = "purchase-orders"
public static let router = OneOf {
Route(.case(Self.create)) {
Path { rootPath }
Method.post
Body {
FormData {
Optionally { Field("id") { PurchaseOrder.ID.parser() } }
Optionally { Field("workOrder") { Int.parser() } }
Field("materials", .string)
Field("customer", .string)
Optionally { Field("truckStock") { Bool.parser() } }
Field("createdByID") { User.ID.parser() }
Field("createdForID") { Employee.ID.parser() }
Field("vendorBranchID") { VendorBranch.ID.parser() }
}
.map(.memberwise(PurchaseOrder.Create.init))
}
}
Route(.case(Self.form)) {
Path { rootPath; "create" }
Method.get
}
Route(.case(Self.get(id:))) {
Path { rootPath; Digits() }
Method.get
}
Route(.case(Self.index)) {
Path { rootPath }
Method.get
}
Route(.case(Self.page(page:limit:))) {
Path { rootPath; "next" }
Method.get
Query {
Field("page", default: 1) { Digits() }
Field("limit", default: 25) { Digits() }
}
}
Route(.case(Self.search)) {
Search.router
}
}
public enum Search: Sendable, Equatable {
case index(context: Context? = nil, table: Bool? = nil)
case request(Request)
static let rootPath = Path { "purchase-orders"; "search" }
static let router = OneOf {
Route(.case(Search.index(context:table:))) {
rootPath
Method.get
Query {
Optionally { Field("context", default: .employee) { Search.Context.parser() } }
Optionally { Field("table", default: nil) { Bool.parser() } }
}
}
Route(.case(Search.request)) {
rootPath
Method.post Method.post
Body { Body {
FormData { FormData {
Field("context") { Context.parser() } Field("username", .string)
Optionally { Field("createdForID") { Employee.ID.parser() } } Field("password", .string)
Optionally { Field("customerSearch", .string) } Optionally {
Optionally { Field("vendorBranchID") { VendorBranch.ID.parser() } } Field("next", default: nil) {
CharacterSet.urlPathAllowed.map(.string)
}
}
} }
.map(.memberwise(Request.init)) .map(.memberwise(Request.init))
} }
} }
} }
public enum Context: String, Codable, CaseIterable, Equatable, Sendable {
case employee
case customer
case vendor
}
// TODO: Create a validation or potentially turn this into an enum with the valid states.
public struct Request: Codable, Equatable, Sendable { public struct Request: Codable, Equatable, Sendable {
public let context: Context public let username: String
public let createdForID: Employee.ID? public let password: String
public let customerSearch: String? public let next: String?
public let vendorBranchID: VendorBranch.ID?
public init( public init(username: String, password: String, next: String? = nil) {
context: Context, self.username = username
createdForID: Employee.ID? = nil, self.password = password
customerSearch: String? = nil, self.next = next
vendorBranchID: VendorBranch.ID? = nil
) {
self.context = context
self.createdForID = createdForID
self.customerSearch = customerSearch
self.vendorBranchID = vendorBranchID
} }
} }
} }
}
}
public extension ViewRoute { public enum PurchaseOrderRoute: Sendable, Equatable {
case create(PurchaseOrder.Create)
case form
case get(id: PurchaseOrder.ID)
case index
case page(page: Int, limit: Int)
case search(Search)
enum SelectContext: String, Codable, Equatable, Sendable, CaseIterable { static let rootPath = "purchase-orders"
case purchaseOrderForm
case purchaseOrderSearch
}
} public static let router = OneOf {
Route(.case(Self.create)) {
public extension ViewRoute { Path { rootPath }
enum UserRoute: Sendable, Equatable { Method.post
case create(User.Create) Body {
case form FormData {
case get(id: User.ID) Optionally { Field("id") { PurchaseOrder.ID.parser() } }
case index Optionally { Field("workOrder") { Int.parser() } }
case update(id: User.ID, updates: User.Update) Field("materials", .string)
Field("customer", .string)
static let rootPath = "users" Optionally { Field("truckStock") { Bool.parser() } }
Field("createdByID") { User.ID.parser() }
public static let router = OneOf { Field("createdForID") { Employee.ID.parser() }
Route(.case(Self.create)) { Field("vendorBranchID") { VendorBranch.ID.parser() }
Path { rootPath }
Method.post
Body {
FormData {
Field("username", .string)
Field("email", .string)
Field("password", .string)
Field("confirmPassword", .string)
}
.map(.memberwise(User.Create.init))
}
}
Route(.case(Self.form)) {
Path { rootPath; "create" }
Method.get
}
Route(.case(Self.get(id:))) {
Path { rootPath; User.ID.parser() }
Method.get
}
Route(.case(Self.index)) {
Path { rootPath }
Method.get
}
Route(.case(Self.update(id:updates:))) {
Path { rootPath; User.ID.parser() }
Method.patch
Body {
FormData {
Optionally { Field("username") {
CharacterSet.alphanumerics.map(.string)
} }
.map(.memberwise(PurchaseOrder.Create.init))
}
}
Route(.case(Self.form)) {
Path { rootPath; "create" }
Method.get
}
Route(.case(Self.get(id:))) {
Path { rootPath; Digits() }
Method.get
}
Route(.case(Self.index)) {
Path { rootPath }
Method.get
}
Route(.case(Self.page(page:limit:))) {
Path { rootPath; "next" }
Method.get
Query {
Field("page", default: 1) { Digits() }
Field("limit", default: 25) { Digits() }
}
}
Route(.case(Self.search)) {
Search.router
}
}
public enum Search: Sendable, Equatable {
case index(context: Context? = nil, table: Bool? = nil)
case request(Request)
static let rootPath = Path { "purchase-orders"; "search" }
static let router = OneOf {
Route(.case(Search.index(context:table:))) {
rootPath
Method.get
Query {
Optionally { Field("context", default: .employee) { Search.Context.parser() } }
Optionally { Field("table", default: nil) { Bool.parser() } }
} }
Optionally { Field("email", .string) }
} }
.map(.memberwise(User.Update.init)) Route(.case(Search.request)) {
} rootPath
} Method.post
} Body {
} FormData {
} Field("context") { Context.parser() }
Optionally { Field("createdForID") { Employee.ID.parser() } }
public extension ViewRoute { Optionally { Field("customerSearch", .string) }
Optionally { Field("vendorBranchID") { VendorBranch.ID.parser() } }
enum VendorRoute: Sendable, Equatable { }
case create(Vendor.Create) .map(.memberwise(Request.init))
case form }
case get(id: Vendor.ID) }
case index }
case update(id: Vendor.ID, updates: Vendor.Update)
public enum Context: String, Codable, CaseIterable, Equatable, Sendable {
static let rootPath = "vendors" case employee
case customer
public static let router = OneOf { case vendor
Route(.case(Self.create)) { }
Path { rootPath }
Method.post // TODO: Create a validation or potentially turn this into an enum with the valid states.
Body { public struct Request: Codable, Equatable, Sendable {
FormData { public let context: Context
Field("name", .string) public let createdForID: Employee.ID?
} public let customerSearch: String?
.map(.memberwise(Vendor.Create.init)) public let vendorBranchID: VendorBranch.ID?
}
} public init(
Route(.case(Self.get(id:))) { context: Context,
Path { rootPath; Vendor.ID.parser() } createdForID: Employee.ID? = nil,
Method.get customerSearch: String? = nil,
} vendorBranchID: VendorBranch.ID? = nil
) {
Route(.case(Self.form)) { self.context = context
Path { rootPath; "create" } self.createdForID = createdForID
Method.get self.customerSearch = customerSearch
} self.vendorBranchID = vendorBranchID
Route(.case(Self.index)) { }
Path { rootPath } }
Method.get }
} }
Route(.case(Self.update(id:updates:))) {
Path { rootPath; Vendor.ID.parser() } public enum SelectContext: String, Codable, Equatable, Sendable, CaseIterable {
Method.put case purchaseOrderForm
Body { case purchaseOrderSearch
FormData { }
Field("name", .string)
} public enum UserRoute: Sendable, Equatable {
.map(.memberwise(Vendor.Update.init)) case create(User.Create)
} case form
} case get(id: User.ID)
} case index
} case update(id: User.ID, updates: User.Update)
}
static let rootPath = "users"
public extension ViewRoute {
public static let router = OneOf {
enum VendorBranchRoute: Sendable, Equatable { Route(.case(Self.create)) {
case create(VendorBranch.Create) Path { rootPath }
case index(for: Vendor.ID? = nil) Method.post
case select(context: ViewRoute.SelectContext) Body {
FormData {
public static let router = OneOf { Field("username", .string)
Route(.case(Self.create)) { Field("email", .string)
Path { "vendors"; "branches" } Field("password", .string)
Method.post Field("confirmPassword", .string)
Body { }
FormData { .map(.memberwise(User.Create.init))
Field("name", .string) }
Field("vendorID") { Vendor.ID.parser() } }
} Route(.case(Self.form)) {
.map(.memberwise(VendorBranch.Create.init)) Path { rootPath; "create" }
} Method.get
} }
Route(.case(Self.index(for:))) { Route(.case(Self.get(id:))) {
Path { "vendors"; "branches" } Path { rootPath; User.ID.parser() }
Method.get Method.get
Query { }
Optionally { Field("vendorID") { Vendor.ID.parser() } } Route(.case(Self.index)) {
} Path { rootPath }
} Method.get
Route(.case(Self.select(context:))) { }
Path { "vendors"; "branches"; "select" } Route(.case(Self.update(id:updates:))) {
Method.get Path { rootPath; User.ID.parser() }
Query { Method.patch
Field("context") { SelectContext.parser() } Body {
FormData {
Optionally { Field("username") {
CharacterSet.alphanumerics.map(.string)
}
}
Optionally { Field("email", .string) }
}
.map(.memberwise(User.Update.init))
}
}
}
}
public enum VendorRoute: Sendable, Equatable {
case create(Vendor.Create)
case form
case get(id: Vendor.ID)
case index
case update(id: Vendor.ID, updates: Vendor.Update)
static let rootPath = "vendors"
public static let router = OneOf {
Route(.case(Self.create)) {
Path { rootPath }
Method.post
Body {
FormData {
Field("name", .string)
}
.map(.memberwise(Vendor.Create.init))
}
}
Route(.case(Self.get(id:))) {
Path { rootPath; Vendor.ID.parser() }
Method.get
}
Route(.case(Self.form)) {
Path { rootPath; "create" }
Method.get
}
Route(.case(Self.index)) {
Path { rootPath }
Method.get
}
Route(.case(Self.update(id:updates:))) {
Path { rootPath; Vendor.ID.parser() }
Method.put
Body {
FormData {
Field("name", .string)
}
.map(.memberwise(Vendor.Update.init))
}
}
}
}
public enum VendorBranchRoute: Sendable, Equatable {
case create(VendorBranch.Create)
case index(for: Vendor.ID? = nil)
case select(context: SiteRoute.View.SelectContext)
public static let router = OneOf {
Route(.case(Self.create)) {
Path { "vendors"; "branches" }
Method.post
Body {
FormData {
Field("name", .string)
Field("vendorID") { Vendor.ID.parser() }
}
.map(.memberwise(VendorBranch.Create.init))
}
}
Route(.case(Self.index(for:))) {
Path { "vendors"; "branches" }
Method.get
Query {
Optionally { Field("vendorID") { Vendor.ID.parser() } }
}
}
Route(.case(Self.select(context:))) {
Path { "vendors"; "branches"; "select" }
Method.get
Query {
Field("context") { SiteRoute.View.SelectContext.parser() }
}
} }
} }
} }

View File

@@ -21,7 +21,7 @@ public struct ViewController: Sendable {
@Sendable @Sendable
public func view( public func view(
for route: ViewRoute, for route: SiteRoute.View,
isHtmxRequest: Bool, isHtmxRequest: Bool,
logger: Logger, logger: Logger,
authenticate: @escaping AuthenticateHandler authenticate: @escaping AuthenticateHandler
@@ -30,13 +30,13 @@ public struct ViewController: Sendable {
} }
public struct Request: Sendable { public struct Request: Sendable {
public let route: ViewRoute public let route: SiteRoute.View
public let isHtmxRequest: Bool public let isHtmxRequest: Bool
public let authenticate: AuthenticateHandler public let authenticate: AuthenticateHandler
public let logger: Logger public let logger: Logger
public init( public init(
_ route: ViewRoute, _ route: SiteRoute.View,
isHtmxRequest: Bool, isHtmxRequest: Bool,
authenticate: @escaping AuthenticateHandler, authenticate: @escaping AuthenticateHandler,
logger: Logger logger: Logger

View File

@@ -6,7 +6,7 @@ import SharedModels
import Vapor import Vapor
import ViewController import ViewController
public extension SharedModels.ViewRoute { public extension SiteRoute.View {
@Sendable @Sendable
func view( func view(
@@ -52,7 +52,7 @@ public extension SharedModels.ViewRoute {
} }
} }
extension SharedModels.ViewRoute.EmployeeRoute { extension SiteRoute.View.EmployeeRoute {
private func mainPage<C: HTML>( private func mainPage<C: HTML>(
_ html: C _ html: C
@@ -98,7 +98,7 @@ extension SharedModels.ViewRoute.EmployeeRoute {
} }
extension SharedModels.ViewRoute.PurchaseOrderRoute { extension SiteRoute.View.PurchaseOrderRoute {
private func mainPage<C: HTML>( private func mainPage<C: HTML>(
_ html: C _ html: C
) async throws -> AnySendableHTML where C: Sendable { ) async throws -> AnySendableHTML where C: Sendable {
@@ -148,7 +148,7 @@ extension SharedModels.ViewRoute.PurchaseOrderRoute {
} }
extension SharedModels.ViewRoute.PurchaseOrderRoute.Search { extension SiteRoute.View.PurchaseOrderRoute.Search {
func mainPage(search: PurchaseOrderSearch = .init()) -> AnySendableHTML { func mainPage(search: PurchaseOrderSearch = .init()) -> AnySendableHTML {
MainPage(displayNav: true, route: .purchaseOrders) { MainPage(displayNav: true, route: .purchaseOrders) {
@@ -180,7 +180,7 @@ extension SharedModels.ViewRoute.PurchaseOrderRoute.Search {
} }
} }
extension SharedModels.ViewRoute.UserRoute { extension SiteRoute.View.UserRoute {
private func mainPage<C: HTML>(_ html: C) async throws -> AnySendableHTML where C: Sendable { private func mainPage<C: HTML>(_ html: C) async throws -> AnySendableHTML where C: Sendable {
@Dependency(\.database) var database @Dependency(\.database) var database
@@ -220,7 +220,7 @@ extension SharedModels.ViewRoute.UserRoute {
} }
extension SharedModels.ViewRoute.VendorRoute { extension SiteRoute.View.VendorRoute {
private func mainPage<C: HTML>(_ html: C) async throws -> AnySendableHTML where C: Sendable { private func mainPage<C: HTML>(_ html: C) async throws -> AnySendableHTML where C: Sendable {
@Dependency(\.database) var database @Dependency(\.database) var database
let vendors = try await database.vendors.fetchAll(.withBranches) let vendors = try await database.vendors.fetchAll(.withBranches)
@@ -267,7 +267,7 @@ extension SharedModels.ViewRoute.VendorRoute {
} }
} }
extension SharedModels.ViewRoute.VendorBranchRoute { extension SiteRoute.View.VendorBranchRoute {
@Sendable @Sendable
func view(isHtmxRequest: Bool) async throws -> AnySendableHTML { func view(isHtmxRequest: Bool) async throws -> AnySendableHTML {
@@ -292,7 +292,7 @@ extension SharedModels.ViewRoute.VendorBranchRoute {
} }
} }
extension SharedModels.ViewRoute.PurchaseOrderRoute.Search.Request { extension SiteRoute.View.PurchaseOrderRoute.Search.Request {
@Sendable @Sendable
func toDatabaseQuery() throws -> PurchaseOrder.SearchContext { func toDatabaseQuery() throws -> PurchaseOrder.SearchContext {
@@ -316,7 +316,7 @@ extension SharedModels.ViewRoute.PurchaseOrderRoute.Search.Request {
} }
} }
extension SharedModels.ViewRoute.SelectContext { extension SiteRoute.View.SelectContext {
@Sendable @Sendable
func toHTML(employees: [Employee]) -> EmployeeSelect { func toHTML(employees: [Employee]) -> EmployeeSelect {

View File

@@ -74,7 +74,7 @@ struct EmployeeForm: HTML {
return "Update" return "Update"
} }
private var targetURL: SharedModels.ViewRoute { private var targetURL: SiteRoute.View {
guard let employee else { return .employee(.index) } guard let employee else { return .employee(.index) }
return .employee(.get(id: employee.id)) return .employee(.get(id: employee.id))
} }

View File

@@ -4,23 +4,23 @@ import SharedModels
extension HTMLAttribute.hx { extension HTMLAttribute.hx {
@Sendable @Sendable
static func get(route: SharedModels.ViewRoute) -> HTMLAttribute { static func get(route: SiteRoute.View) -> HTMLAttribute {
get(SharedModels.ViewRoute.router.path(for: route)) get(SiteRoute.View.router.path(for: route))
} }
@Sendable @Sendable
static func post(route: SharedModels.ViewRoute) -> HTMLAttribute { static func post(route: SiteRoute.View) -> HTMLAttribute {
post(SharedModels.ViewRoute.router.path(for: route)) post(SiteRoute.View.router.path(for: route))
} }
@Sendable @Sendable
static func put(route: SharedModels.ViewRoute) -> HTMLAttribute { static func put(route: SiteRoute.View) -> HTMLAttribute {
put(SharedModels.ViewRoute.router.path(for: route)) put(SiteRoute.View.router.path(for: route))
} }
@Sendable @Sendable
static func delete(route: SharedModels.ApiRoute) -> HTMLAttribute { static func delete(route: SiteRoute.Api) -> HTMLAttribute {
delete(SharedModels.ApiRoute.router.path(for: route)) delete(SiteRoute.Api.router.path(for: route))
} }
} }
@@ -65,8 +65,8 @@ indirect enum HXOnValue: Sendable {
} }
@Sendable @Sendable
static func setWindowLocation(to route: ViewRoute) -> Self { static func setWindowLocation(to route: SiteRoute.View) -> Self {
setWindowLocation(ViewRoute.router.path(for: route)) setWindowLocation(SiteRoute.View.router.path(for: route))
} }
@Sendable @Sendable

View File

@@ -53,7 +53,7 @@ struct LoggedIn: HTML, Sendable {
let next: String? let next: String?
var content: some HTML { var content: some HTML {
div( div(
.hx.get(nextRoute ?? ViewRoute.router.path(for: .purchaseOrder(.index))), .hx.get(nextRoute ?? SiteRoute.View.router.path(for: .purchaseOrder(.index))),
.hx.pushURL(true), .hx.pushURL(true),
.hx.target(.body), .hx.target(.body),
.hx.trigger(.event(.revealed)), .hx.trigger(.event(.revealed)),
@@ -66,7 +66,9 @@ struct LoggedIn: HTML, Sendable {
// HACK: to get search route to work after login. // HACK: to get search route to work after login.
var nextRoute: String? { var nextRoute: String? {
if let next, next.contains("search") { if let next, next.contains("search") {
return ViewRoute.router.path(for: .purchaseOrder(.search(.index(context: .employee, table: true)))) return SiteRoute.View.router.path(
for: .purchaseOrder(.search(.index(context: .employee, table: true)))
)
} }
return next return next
} }

View File

@@ -5,7 +5,7 @@ import Vapor
struct PurchaseOrderSearch: HTML, Sendable { struct PurchaseOrderSearch: HTML, Sendable {
typealias Context = SharedModels.ViewRoute.PurchaseOrderRoute.Search.Context typealias Context = SiteRoute.View.PurchaseOrderRoute.Search.Context
let context: Context let context: Context

View File

@@ -5,7 +5,7 @@ import SharedModels
import Vapor import Vapor
struct PurchaseOrderTable: HTML, Sendable { struct PurchaseOrderTable: HTML, Sendable {
typealias SearchContext = SharedModels.ViewRoute.PurchaseOrderRoute.Search.Context typealias SearchContext = SiteRoute.View.PurchaseOrderRoute.Search.Context
let page: Page<PurchaseOrder> let page: Page<PurchaseOrder>
let context: Context let context: Context

View File

@@ -101,7 +101,7 @@ struct UserForm: HTML, Sendable {
} }
} }
var targetURL: ViewRoute { var targetURL: SiteRoute.View {
switch self { switch self {
case .create: case .create:
return .user(.index) return .user(.index)

View File

@@ -22,10 +22,10 @@ enum Button {
} }
@Sendable @Sendable
static func close(id: IDKey, resetURL route: ViewRoute? = nil) -> some HTML<HTMLTag.button> { static func close(id: IDKey, resetURL route: SiteRoute.View? = nil) -> some HTML<HTMLTag.button> {
close( close(
id: id.description, id: id.description,
resetURL: route != nil ? ViewRoute.router.path(for: route!) : nil resetURL: route != nil ? SiteRoute.View.router.path(for: route!) : nil
) )
} }

View File

@@ -62,7 +62,7 @@ extension Float where B == DefaultCloseButton {
init( init(
id: String = "float", id: String = "float",
shouldDisplay: Bool, shouldDisplay: Bool,
resetURL route: ViewRoute? = nil, resetURL route: SiteRoute.View? = nil,
@HTMLBuilder body: () -> C @HTMLBuilder body: () -> C
) { ) {
self.init( self.init(
@@ -71,7 +71,7 @@ extension Float where B == DefaultCloseButton {
body: body, body: body,
closeButton: { DefaultCloseButton( closeButton: { DefaultCloseButton(
id: id, id: id,
resetURL: route != nil ? ViewRoute.router.path(for: route!) : nil resetURL: route != nil ? SiteRoute.View.router.path(for: route!) : nil
) } ) }
) )
} }

View File

@@ -6,7 +6,7 @@ import Vapor
struct EmployeeSelect: HTML, Sendable { struct EmployeeSelect: HTML, Sendable {
let employees: [Employee]? let employees: [Employee]?
let context: ViewRoute.SelectContext let context: SiteRoute.View.SelectContext
var content: some HTML { var content: some HTML {
if let employees { if let employees {
@@ -42,7 +42,7 @@ struct EmployeeSelect: HTML, Sendable {
struct VendorBranchSelect: HTML, Sendable { struct VendorBranchSelect: HTML, Sendable {
let branches: [VendorBranch.Detail]? let branches: [VendorBranch.Detail]?
let context: ViewRoute.SelectContext let context: SiteRoute.View.SelectContext
var content: some HTML { var content: some HTML {
if let branches { if let branches {
@@ -79,7 +79,7 @@ struct VendorBranchSelect: HTML, Sendable {
// case purchaseOrderForm // case purchaseOrderForm
// case purchaseOrderSearch // case purchaseOrderSearch
extension ViewRoute.SelectContext { extension SiteRoute.View.SelectContext {
var classString: String { var classString: String {
switch self { switch self {
case .purchaseOrderForm: return "col-3" case .purchaseOrderForm: return "col-3"

View File

@@ -85,7 +85,7 @@ struct VendorForm: HTML, Sendable {
return "Update" return "Update"
} }
var targetURL: SharedModels.ViewRoute { var targetURL: SiteRoute.View {
guard let vendor else { return .vendor(.index) } guard let vendor else { return .vendor(.index) }
return .vendor(.get(id: vendor.id)) return .vendor(.get(id: vendor.id))
} }

View File

@@ -6,7 +6,7 @@ import URLRouting
@Suite("EmployeeApiRouteTests") @Suite("EmployeeApiRouteTests")
struct EmployeeApiRouteTests { struct EmployeeApiRouteTests {
let router = ApiRoute.router let router = SiteRoute.Api.router
@Test @Test
func employeeCreate() throws { func employeeCreate() throws {

View File

@@ -6,7 +6,7 @@ import URLRouting
@Suite("PurchaseOrderApiRouteTests") @Suite("PurchaseOrderApiRouteTests")
struct PurchaseOrderApiRouteTests { struct PurchaseOrderApiRouteTests {
let router = ApiRoute.router let router = SiteRoute.Api.router
@Test @Test
func create() throws { func create() throws {

View File

@@ -6,7 +6,7 @@ import URLRouting
@Suite("UserApiRouteTests") @Suite("UserApiRouteTests")
struct UserApiRouteTests { struct UserApiRouteTests {
let router = ApiRoute.router let router = SiteRoute.Api.router
@Test @Test
func create() throws { func create() throws {

View File

@@ -6,7 +6,7 @@ import URLRouting
@Suite("VendorApiRouteTests") @Suite("VendorApiRouteTests")
struct VendorApiRouteTests { struct VendorApiRouteTests {
let router = ApiRoute.router let router = SiteRoute.Api.router
@Test @Test
func create() throws { func create() throws {

View File

@@ -6,7 +6,7 @@ import URLRouting
@Suite("VendorBranchApiRouteTests") @Suite("VendorBranchApiRouteTests")
struct VendorBranchApiRouteTests { struct VendorBranchApiRouteTests {
let router = ApiRoute.router let router = SiteRoute.Api.router
@Test @Test
func create() throws { func create() throws {

View File

@@ -90,7 +90,7 @@ struct ViewControllerTests {
htmlString = try await viewController.render(.purchaseOrder(.page(page: 1, limit: 25))) htmlString = try await viewController.render(.purchaseOrder(.page(page: 1, limit: 25)))
assertSnapshot(of: htmlString, as: .html) assertSnapshot(of: htmlString, as: .html)
for context in ViewRoute.PurchaseOrderRoute.Search.Context.allCases { for context in SiteRoute.View.PurchaseOrderRoute.Search.Context.allCases {
htmlString = try await viewController.render(.purchaseOrder(.search(.index( htmlString = try await viewController.render(.purchaseOrder(.search(.index(
context: context, context: context,
table: true table: true
@@ -189,7 +189,7 @@ struct ViewControllerTests {
extension ViewController { extension ViewController {
func render(_ route: ViewRoute) async throws -> String { func render(_ route: SiteRoute.View) async throws -> String {
let html = try await view( let html = try await view(
for: route, for: route,
isHtmxRequest: true, isHtmxRequest: true,

View File

@@ -6,7 +6,7 @@ import URLRouting
@Suite("EmployeeViewRouteTests") @Suite("EmployeeViewRouteTests")
struct EmployeeViewRouteTests { struct EmployeeViewRouteTests {
let router = ViewRoute.router let router = SiteRoute.View.router
@Test @Test
func employeeCreate() throws { func employeeCreate() throws {

View File

@@ -6,7 +6,7 @@ import URLRouting
@Suite("LoginViewRouteTests") @Suite("LoginViewRouteTests")
struct LoginViewRouteTests { struct LoginViewRouteTests {
let router = ViewRoute.router let router = SiteRoute.View.router
@Test @Test
func get() throws { func get() throws {

View File

@@ -6,7 +6,7 @@ import URLRouting
@Suite("PurchaseOrderViewRouteTests") @Suite("PurchaseOrderViewRouteTests")
struct PurchaseOrderViewRouteTests { struct PurchaseOrderViewRouteTests {
let router = ViewRoute.router let router = SiteRoute.View.router
@Test @Test
func create() throws { func create() throws {

View File

@@ -6,7 +6,7 @@ import URLRouting
@Suite("UserViewRouteTests") @Suite("UserViewRouteTests")
struct UserViewRouteTests { struct UserViewRouteTests {
let router = ViewRoute.router let router = SiteRoute.View.router
@Test @Test
func create() throws { func create() throws {

View File

@@ -6,7 +6,7 @@ import URLRouting
@Suite("VendorBranchViewRouteTests") @Suite("VendorBranchViewRouteTests")
struct VendorBranchViewRouteTests { struct VendorBranchViewRouteTests {
let router = ViewRoute.router let router = SiteRoute.View.router
@Test @Test
func create() throws { func create() throws {

View File

@@ -6,7 +6,7 @@ import URLRouting
@Suite("VendorViewRouteTests") @Suite("VendorViewRouteTests")
struct VendorViewRouteTests { struct VendorViewRouteTests {
let router = ViewRoute.router let router = SiteRoute.View.router
@Test @Test
func create() throws { func create() throws {