Skip to content

Commit c2d164f

Browse files
committed
Initial Implementation
1 parent dc4be9b commit c2d164f

15 files changed

+1273
-1
lines changed

.github/workflows/build.yml

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
name: build
2+
3+
on:
4+
push:
5+
pull_request:
6+
workflow_dispatch:
7+
8+
jobs:
9+
xcode_16:
10+
runs-on: macos-14
11+
steps:
12+
- name: Checkout
13+
uses: actions/checkout@v4
14+
- name: 🔍 Xcode Select
15+
run: |
16+
XCODE_PATH=`mdfind "kMDItemCFBundleIdentifier == 'com.apple.dt.Xcode' && kMDItemVersion = '16.*'" -onlyin /Applications | head -1`
17+
echo "DEVELOPER_DIR=$XCODE_PATH/Contents/Developer" >> $GITHUB_ENV
18+
- name: Version
19+
run: swift --version
20+
- name: Build
21+
run: swift build --build-tests
22+
- name: Test
23+
run: swift test --skip-build
24+
25+
xcode_15_4:
26+
runs-on: macos-14
27+
env:
28+
DEVELOPER_DIR: /Applications/Xcode_15.4.app/Contents/Developer
29+
steps:
30+
- name: Checkout
31+
uses: actions/checkout@v4
32+
- name: Version
33+
run: swift --version
34+
- name: Build
35+
run: swift build --build-tests
36+
- name: Test
37+
run: swift test --skip-build
38+
39+
xcode_15_2:
40+
runs-on: macos-14
41+
env:
42+
DEVELOPER_DIR: /Applications/Xcode_15.2.app/Contents/Developer
43+
steps:
44+
- name: Checkout
45+
uses: actions/checkout@v4
46+
- name: Version
47+
run: swift --version
48+
- name: Build
49+
run: swift build --build-tests
50+
- name: Test
51+
run: swift test --skip-build
52+
53+
linux_swift_5_10:
54+
runs-on: ubuntu-latest
55+
container: swift:5.10
56+
steps:
57+
- name: Checkout
58+
uses: actions/checkout@v4
59+
- name: Version
60+
run: swift --version
61+
- name: Build
62+
run: swift build --build-tests
63+
- name: Test
64+
run: swift test --skip-build
65+
66+
linux_swift_5_9:
67+
runs-on: ubuntu-latest
68+
container: swift:5.9
69+
steps:
70+
- name: Checkout
71+
uses: actions/checkout@v4
72+
- name: Version
73+
run: swift --version
74+
- name: Build
75+
run: swift build --build-tests
76+
- name: Test
77+
run: swift test --skip-build
78+
79+
linux_swift_6_0:
80+
runs-on: ubuntu-latest
81+
container: swiftlang/swift:nightly-6.0-jammy
82+
steps:
83+
- name: Checkout
84+
uses: actions/checkout@v4
85+
- name: Version
86+
run: swift --version
87+
- name: Build
88+
run: swift build --build-tests
89+
- name: Test
90+
run: swift test --skip-build

.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//
2+
// HTTPHandlerMacro.swift
3+
// FlyingFoxMacros
4+
//
5+
// Created by Simon Whitty on 26/10/2023.
6+
// Copyright © 2023 Simon Whitty. All rights reserved.
7+
//
8+
// Distributed under the permissive MIT license
9+
// Get the latest version from here:
10+
//
11+
// https://github.com/swhitty/FlyingFox
12+
//
13+
// Permission is hereby granted, free of charge, to any person obtaining a copy
14+
// of this software and associated documentation files (the "Software"), to deal
15+
// in the Software without restriction, including without limitation the rights
16+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17+
// copies of the Software, and to permit persons to whom the Software is
18+
// furnished to do so, subject to the following conditions:
19+
//
20+
// The above copyright notice and this permission notice shall be included in all
21+
// copies or substantial portions of the Software.
22+
//
23+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29+
// SOFTWARE.
30+
//
31+
32+
import FlyingFox
33+
import Foundation
34+
35+
@attached(peer)
36+
public macro HTTPRoute(
37+
_ route: StringLiteralType,
38+
statusCode: HTTPStatusCode = .ok,
39+
headers: [HTTPHeader: String] = [:]
40+
) = #externalMacro(module: "Plugins", type: "HTTPRouteMacro")
41+
42+
@attached(peer)
43+
public macro JSONRoute(
44+
_ route: StringLiteralType,
45+
statusCode: HTTPStatusCode = .ok,
46+
headers: [HTTPHeader: String] = [.contentType: "application/json"],
47+
encoder: JSONEncoder = JSONEncoder(),
48+
decoder: JSONDecoder = JSONDecoder()
49+
) = #externalMacro(module: "Plugins", type: "JSONRouteMacro")
50+
51+
@attached(member, names: named(performAction), named(Action), named(handleRequest))
52+
@attached(extension, conformances: HTTPHandler, Sendable)
53+
public macro HTTPHandler() = #externalMacro(module: "Plugins", type: "HTTPHandlerMacro")
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
//
2+
// HTTPHandlerMacroTests.swift
3+
// FlyingFoxMacros
4+
//
5+
// Created by Simon Whitty on 28/10/2023.
6+
// Copyright © 2023 Simon Whitty. All rights reserved.
7+
//
8+
// Distributed under the permissive MIT license
9+
// Get the latest version from here:
10+
//
11+
// https://github.com/swhitty/FlyingFox
12+
//
13+
// Permission is hereby granted, free of charge, to any person obtaining a copy
14+
// of this software and associated documentation files (the "Software"), to deal
15+
// in the Software without restriction, including without limitation the rights
16+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17+
// copies of the Software, and to permit persons to whom the Software is
18+
// furnished to do so, subject to the following conditions:
19+
//
20+
// The above copyright notice and this permission notice shall be included in all
21+
// copies or substantial portions of the Software.
22+
//
23+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29+
// SOFTWARE.
30+
//
31+
32+
import FlyingFox
33+
import FlyingFoxMacros
34+
import XCTest
35+
36+
#if compiler(>=5.9)
37+
final class HTTPHandlerMacroTests: XCTestCase {
38+
39+
func testHandler() async throws {
40+
let handler = MacroHandler()
41+
42+
await AsyncAssertEqual(
43+
try await handler.handleRequest(.make(path: "/ok")).statusCode,
44+
.ok
45+
)
46+
await AsyncAssertEqual(
47+
try await handler.handleRequest(.make(path: "/accepted")).statusCode,
48+
.accepted
49+
)
50+
await AsyncAssertEqual(
51+
try await handler.handleRequest(.make(path: "/teapot")).statusCode,
52+
.teapot
53+
)
54+
55+
await AsyncAssertEqual(
56+
try await handler.handleRequest(.make(path: "/fish")).jsonDictionaryBody,
57+
["name": "Pickles"]
58+
)
59+
}
60+
}
61+
62+
@HTTPHandler
63+
struct MacroHandler {
64+
65+
@HTTPRoute("/ok")
66+
func didAppear() -> HTTPResponse {
67+
HTTPResponse(statusCode: .ok)
68+
}
69+
70+
@HTTPRoute("/accepted")
71+
func willAppear(_ val: HTTPRequest) async -> HTTPResponse {
72+
HTTPResponse(statusCode: .accepted)
73+
}
74+
75+
@HTTPRoute("/teapot", statusCode: .teapot)
76+
func getTeapot() throws { }
77+
78+
@JSONRoute("/fish")
79+
func getFish() -> Fish {
80+
Fish(name: "Pickles")
81+
}
82+
83+
struct Fish: Encodable {
84+
var name: String
85+
}
86+
}
87+
88+
private extension HTTPResponse {
89+
90+
var jsonDictionaryBody: NSDictionary? {
91+
get async {
92+
guard let data = try? await bodyData,
93+
let object = try? JSONSerialization.jsonObject(with: data, options: []) else {
94+
return nil
95+
}
96+
return object as? NSDictionary
97+
}
98+
}
99+
}
100+
101+
#endif
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//
2+
// HTTPRequest+Mock.swift
3+
// FlyingFoxMacros
4+
//
5+
// Created by Simon Whitty on 18/02/2022.
6+
// Copyright © 2022 Simon Whitty. All rights reserved.
7+
//
8+
// Distributed under the permissive MIT license
9+
// Get the latest version from here:
10+
//
11+
// https://github.com/swhitty/FlyingFox
12+
//
13+
// Permission is hereby granted, free of charge, to any person obtaining a copy
14+
// of this software and associated documentation files (the "Software"), to deal
15+
// in the Software without restriction, including without limitation the rights
16+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17+
// copies of the Software, and to permit persons to whom the Software is
18+
// furnished to do so, subject to the following conditions:
19+
//
20+
// The above copyright notice and this permission notice shall be included in all
21+
// copies or substantial portions of the Software.
22+
//
23+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29+
// SOFTWARE.
30+
//
31+
32+
@testable import FlyingFox
33+
import Foundation
34+
35+
extension HTTPRequest {
36+
static func make(method: HTTPMethod = .GET,
37+
version: HTTPVersion = .http11,
38+
path: String = "/",
39+
query: [QueryItem] = [],
40+
headers: [HTTPHeader: String] = [:],
41+
body: Data = Data()) -> Self {
42+
HTTPRequest(method: method,
43+
version: version,
44+
path: path,
45+
query: query,
46+
headers: headers,
47+
body: body)
48+
}
49+
}

0 commit comments

Comments
 (0)