This is a Swift Package using result builder to build a DSL on top of the Vapor framework inspired by SwiftUI.
VaporDSL provides a declarative API that allows you to build back-end server with simple and structured syntax, you can understand your server's structure while you code.
Important: There is a similar name called
RoutesBuilder
, which is a protocol provided by the Vapor framework, is different fromRouteBuilder
, which is the result builder of VaporDSL. This name might be change in the future if a better name that could better represents the RouteBuilder is founded to prevent misunderstanding.
dependencies: [
// ...
.package(name: "VaporDSL", url: "https://github.com/danny1113/vapor-dsl.git", from: "1.0.0")
]
You can create your entire web application just by writing your code inside the Application
content closure. You can also do additional setup like Leaf, Fluent, Middlewares after initialize the application inside then()
function.
try Application {
// Group, Route, Controller...
}
.then { app in
print(app.routes.all)
// other additional setup...
}
.run()
Or if you're using the template provided by Vapor, because Group
conforms to the RouteCollection
protocol provided by Vapor, you can register it directly.
func routes(_ app: Application) throws {
let collection = Group {
// Group, Route, Controller...
}
try app.register(collection: collection)
}
Group
is a struct which conforms to the RouteCollection
protocol, it will group and add all of its child routes. You can create even more complex structure by create a group inside a group.
Note: Initialize
Group
without the_ path
parameter will has no effect on server structure.
// root path
Group {
// api
Group("api") {
// Route, Controller...
}
}
Route represents a endpoint on the server, it use use(method:path:body:closure:)
provided by the Vapor framework to create new route.
Note: Initialize
Route
without the_ path
parameter will create a route on its parent's root path.
Group("api") {
// default HTTPMethod: .GET
// GET /api/
Route(use: index)
// GET /api/todos
Route("todos") { req in
return req.view.render("todos")
}
// POST /api/todos
Route("todos", on: .POST, use: todo)
}
You can also group the routes in its own controller, just simply conforms to the RouteBuildable
protocol.
struct LoginController: RouteBuildable {
var body: some RouteBuildable {
Group {
Route("login", on: .GET, use: login)
// Group, Route, Controller...
}
}
func login(req: Request) async throws -> View {
return try await req.view.render("login")
}
}
Now you learned how to use Group
and Route
, you can composite your server with structure syntax:
try Application {
// GET /
Route { req in
return "Hello, world!"
}
Group("api") {
// GET /api/status
Route("status", on: .GET) { req in
return "ok"
}
}
LoginController()
}
.run()
MiddlewareGroup groups all its routes inside a middleware, you can also chain multiple middlewares together.
MiddlewareGroup(
UserAuthenticator(),
UserModel.guardMiddleware()
) {
Route("hello") { req in
return req.view.render("hello")
}
}