Skip to content

Commit

Permalink
Added remaining response headers
Browse files Browse the repository at this point in the history
  • Loading branch information
RussBaz committed Nov 7, 2023
1 parent 95e7dae commit ae3fe52
Show file tree
Hide file tree
Showing 14 changed files with 187 additions and 32 deletions.
8 changes: 4 additions & 4 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/vapor/routing-kit.git",
"state" : {
"revision" : "88077f2c9d12777dcc89562fa581888ff7ba14ae",
"version" : "4.8.1"
"revision" : "17a7a3facce8285fd257aa7c72d5e480351e7698",
"version" : "4.8.2"
}
},
{
Expand Down Expand Up @@ -185,8 +185,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/vapor/vapor.git",
"state" : {
"revision" : "0fa646e517dff34aa5d0ae12d221021ec07a801d",
"version" : "4.85.1"
"revision" : "d682e05fdb64c9f7da01af096a73cd11bb7ab755",
"version" : "4.86.2"
}
},
{
Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ let package = Package(
),
],
dependencies: [
.package(url: "https://github.com/vapor/vapor.git", from: "4.85.1"),
.package(url: "https://github.com/vapor/vapor.git", from: "4.86.2"),
.package(url: "https://github.com/vapor/leaf.git", from: "4.2.4"),
],
targets: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import Vapor
// Code is taken from the following tutorial:
// https://theswiftdev.com/running-and-testing-async-vapor-commands/

public protocol CustomAsyncCommand: Command {
public protocol HXAsyncCommand: Command {
func command(
using context: CommandContext,
signature: Signature
) async throws
}

public extension CustomAsyncCommand {
public extension HXAsyncCommand {
func run(
using context: CommandContext,
signature: Signature
Expand Down
8 changes: 6 additions & 2 deletions Sources/VHX/Htmx/HXConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ public extension HtmxConfiguration {
pageSource = hxPageLeafSource(template: nil)
}

init(template: @escaping (_ name: String) -> String) {
pageSource = hxPageLeafSource(template: template)
init(pagePrefix prefix: String) {
pageSource = hxPageLeafSource(prefix: prefix, template: nil)
}

init(pagePrefix prefix: String = "--page", pageTemplate template: @escaping (_ name: String) -> String) {
pageSource = hxPageLeafSource(prefix: prefix, template: template)
}
}
6 changes: 5 additions & 1 deletion Sources/VHX/Htmx/ReponseHeaders/HXLocationHeader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,11 @@ public struct HXLocationHeader {
}

func add(to resp: Response) {
resp.headers.replaceOrAdd(name: "HX-Location", value: serialise())
let serialised = serialise()

if !serialised.isEmpty {
resp.headers.replaceOrAdd(name: "HX-Location", value: serialised)
}
}
}

Expand Down
14 changes: 9 additions & 5 deletions Sources/VHX/Htmx/ReponseHeaders/HXPushUrlHeader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,25 @@ public struct HXPushUrlHeader {
case disable
case custom(String)
}

let url: HXPushType

func serialise() -> String {
switch url {
case .enable:
"true"
case .disable:
"false"
case .custom(let custom):
case let .custom(custom):
"\(custom)"
}
}

func add(to resp: Response) {
resp.headers.replaceOrAdd(name: "HX-Push-Url", value: serialise())
let serialised = serialise()

if !serialised.isEmpty {
resp.headers.replaceOrAdd(name: "HX-Push-Url", value: serialised)
}
}
}
4 changes: 2 additions & 2 deletions Sources/VHX/Htmx/ReponseHeaders/HXRedirectHeader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import Vapor

public struct HXRedirectHeader {
let location: String

func serialise() -> String {
location
}

func add(to resp: Response) {
if !location.isEmpty {
resp.headers.replaceOrAdd(name: "HX-Redirect", value: serialise())
Expand Down
4 changes: 2 additions & 2 deletions Sources/VHX/Htmx/ReponseHeaders/HXRefreshHeader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import Vapor

public struct HXRefreshHeader {
let value: Bool

func serialise() -> String {
if value { "true" } else { "" }
}

func add(to resp: Response) {
if value {
resp.headers.replaceOrAdd(name: "HX-Refresh", value: serialise())
Expand Down
14 changes: 9 additions & 5 deletions Sources/VHX/Htmx/ReponseHeaders/HXReplaceUrlHeader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,25 @@ public struct HXReplaceUrlHeader {
case disable
case custom(String)
}

let url: HXReplaceType

func serialise() -> String {
switch url {
case .enable:
"true"
case .disable:
"false"
case .custom(let custom):
case let .custom(custom):
"\(custom)"
}
}

func add(to resp: Response) {
resp.headers.replaceOrAdd(name: "HX-Replace-Url", value: serialise())
let serialised = serialise()

if !serialised.isEmpty {
resp.headers.replaceOrAdd(name: "HX-Replace-Url", value: serialised)
}
}
}
4 changes: 2 additions & 2 deletions Sources/VHX/Htmx/ReponseHeaders/HXReselectHeader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import Vapor

public struct HXReselectHeader {
let value: String

func serialise() -> String {
value
}

func add(to resp: Response) {
if !value.isEmpty {
resp.headers.replaceOrAdd(name: "HX-Reselect", value: serialise())
Expand Down
29 changes: 29 additions & 0 deletions Sources/VHX/Htmx/ReponseHeaders/HXResponseHeaders.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Vapor

public struct HXResponseHeaders {
var location: HXLocationHeader?
var pushUrl: HXPushUrlHeader?
var redirect: HXRedirectHeader?
var refresh: HXRefreshHeader?
var replaceUrl: HXReplaceUrlHeader?
var reselect: HXReselectHeader?
var reswap: HXReswapHeader?
var retarget: HXRetargetHeader?
var trigger: HXTriggerHeader?
var triggerAfterSettle: HXTriggerAfterSettleHeader?
var triggerAfterSwap: HXTriggerAfterSwapHeader?

public func add(to resp: Response) {
location.map { $0.add(to: resp) }
pushUrl.map { $0.add(to: resp) }
redirect.map { $0.add(to: resp) }
refresh.map { $0.add(to: resp) }
replaceUrl.map { $0.add(to: resp) }
reselect.map { $0.add(to: resp) }
reswap.map { $0.add(to: resp) }
retarget.map { $0.add(to: resp) }
trigger.map { $0.add(to: resp) }
triggerAfterSettle.map { $0.add(to: resp) }
triggerAfterSwap.map { $0.add(to: resp) }
}
}
4 changes: 2 additions & 2 deletions Sources/VHX/Htmx/ReponseHeaders/HXRetargetHeader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import Vapor

public struct HXRetargetHeader {
let value: String

func serialise() -> String {
value
}

func add(to resp: Response) {
if !value.isEmpty {
resp.headers.replaceOrAdd(name: "HX-Retarget", value: serialise())
Expand Down
104 changes: 104 additions & 0 deletions Sources/VHX/Htmx/ReponseHeaders/HXTriggerHeader.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import Vapor

public enum HXTriggerEvent {
case basic([String])
case custom([HXTriggerEventKind])
}

public enum HXTriggerEventKind {
case message(name: String, value: String)
case object(name: String, value: any Encodable)
}

public struct HXTriggerHeader {
let value: HXTriggerEvent

func serialise() -> String {
value.serialise()
}

func add(to resp: Response) {
let serialised = serialise()

if !serialised.isEmpty {
resp.headers.replaceOrAdd(name: "HX-Trigger", value: serialised)
}
}
}

public struct HXTriggerAfterSettleHeader {
let value: HXTriggerEvent

func serialise() -> String {
value.serialise()
}

func add(to resp: Response) {
let serialised = serialise()

if !serialised.isEmpty {
resp.headers.replaceOrAdd(name: "HX-Trigger-After-Settle", value: serialised)
}
}
}

public struct HXTriggerAfterSwapHeader {
let value: HXTriggerEvent

func serialise() -> String {
value.serialise()
}

func add(to resp: Response) {
let serialised = serialise()

if !serialised.isEmpty {
resp.headers.replaceOrAdd(name: "HX-Trigger-After-Swap", value: serialised)
}
}
}

extension [HXTriggerEventKind] {
// The solution taken from:
// https://forums.swift.org/t/how-to-encode-objects-of-unknown-type/12253/2
private struct AnyEncodable: Encodable {
private let _encode: (Encoder) throws -> Void
public init(_ wrapped: some Encodable) {
_encode = wrapped.encode
}

func encode(to encoder: Encoder) throws {
try _encode(encoder)
}
}

func serialise() -> String {
var data: [String: AnyEncodable] = [:]

for i in self {
switch i {
case let .message(name: name, value: value):
data[name] = AnyEncodable(value)
case let .object(name: name, value: value):
data[name] = AnyEncodable(value)
}
}

guard let values = try? String(data: JSONEncoder().encode(data), encoding: .utf8) else {
return ""
}

return values
}
}

extension HXTriggerEvent {
func serialise() -> String {
switch self {
case let .basic(events):
events.joined(separator: ", ")
case let .custom(events):
events.serialise()
}
}
}
14 changes: 10 additions & 4 deletions Sources/VHX/VHX.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import Vapor

public func configureHtmx(_ app: Application, template: ((_ name: String) -> String)? = nil) throws {
if let template {
app.htmx = HtmxConfiguration(template: template)
public func configureHtmx(_ app: Application, pageTemplate template: ((_ name: String) -> String)? = nil) throws {
let config = if let template {
HtmxConfiguration(pageTemplate: template)
} else {
app.htmx = HtmxConfiguration()
HtmxConfiguration()
}

try configureHtmx(app, configuration: config)
}

public func configureHtmx(_ app: Application, configuration: HtmxConfiguration) throws {
app.htmx = configuration

// Saving currnet sources in case these are the default sources
app.leaf.sources = app.leaf.sources

Expand Down

0 comments on commit ae3fe52

Please sign in to comment.