feat: Initial commit
This commit is contained in:
35
Sources/App/Extensions/ApiController+respond.swift
Normal file
35
Sources/App/Extensions/ApiController+respond.swift
Normal file
@@ -0,0 +1,35 @@
|
||||
import ApiController
|
||||
import Routes
|
||||
import Vapor
|
||||
|
||||
extension ApiController {
|
||||
|
||||
func respond(_ route: SiteRoute.Api, request: Vapor.Request) async throws -> any AsyncResponseEncodable {
|
||||
guard let encodable = try await json(route, request.logger) else {
|
||||
return HTTPStatus.ok
|
||||
}
|
||||
return AnyJSONResponse(value: encodable)
|
||||
}
|
||||
}
|
||||
|
||||
struct AnyJSONResponse: AsyncResponseEncodable {
|
||||
public var headers: HTTPHeaders = ["Content-Type": "application/json"]
|
||||
let value: any Encodable
|
||||
|
||||
init(additionalHeaders: HTTPHeaders = [:], value: any Encodable) {
|
||||
if additionalHeaders.contains(name: .contentType) {
|
||||
self.headers = additionalHeaders
|
||||
} else {
|
||||
headers.add(contentsOf: additionalHeaders)
|
||||
}
|
||||
self.value = value
|
||||
}
|
||||
|
||||
func encodeResponse(for request: Request) async throws -> Response {
|
||||
try Response(
|
||||
status: .ok,
|
||||
headers: headers,
|
||||
body: .init(data: JSONEncoder().encode(value))
|
||||
)
|
||||
}
|
||||
}
|
||||
57
Sources/App/Extensions/ViewController+respond.swift
Normal file
57
Sources/App/Extensions/ViewController+respond.swift
Normal file
@@ -0,0 +1,57 @@
|
||||
import Elementary
|
||||
import Routes
|
||||
import Vapor
|
||||
import VaporElementary
|
||||
import ViewController
|
||||
|
||||
extension ViewController {
|
||||
func respond(route: SiteRoute.View, request: Vapor.Request) async throws -> any AsyncResponseEncodable {
|
||||
// let html = try await view(
|
||||
// for: route,
|
||||
// isHtmxRequest: request.isHtmxRequest,
|
||||
// logger: request.logger,
|
||||
// authenticate: { request.session.authenticate($0) },
|
||||
// currentUser: {
|
||||
// try request.auth.require(User.self)
|
||||
// }
|
||||
// )
|
||||
let html = try await view(route)
|
||||
return AnyHTMLResponse(value: html)
|
||||
}
|
||||
}
|
||||
|
||||
// Re-adapted from `HTMLResponse` in the VaporElementary package to work with any html types
|
||||
// returned from the view controller.
|
||||
struct AnyHTMLResponse: AsyncResponseEncodable {
|
||||
|
||||
public var chunkSize: Int
|
||||
public var headers: HTTPHeaders = ["Content-Type": "text/html; charset=utf-8"]
|
||||
var value: _SendableAnyHTMLBox
|
||||
|
||||
init(chunkSize: Int = 1024, additionalHeaders: HTTPHeaders = [:], value: AnySendableHTML) {
|
||||
self.chunkSize = chunkSize
|
||||
if additionalHeaders.contains(name: .contentType) {
|
||||
self.headers = additionalHeaders
|
||||
} else {
|
||||
headers.add(contentsOf: additionalHeaders)
|
||||
}
|
||||
self.value = .init(value)
|
||||
}
|
||||
|
||||
func encodeResponse(for request: Request) async throws -> Response {
|
||||
Response(
|
||||
status: .ok,
|
||||
headers: headers,
|
||||
body: .init(asyncStream: { [value, chunkSize] writer in
|
||||
guard let html = value.tryTake() else {
|
||||
assertionFailure("Non-sendable HTML value consumed more than once")
|
||||
request.logger.error("Non-sendable HTML value consumed more than once")
|
||||
throw Abort(.internalServerError)
|
||||
}
|
||||
try await writer.writeHTML(html, chunkSize: chunkSize)
|
||||
try await writer.write(.end)
|
||||
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user