Added some more cases to the File enumeration in the library target.
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
import AppLibrary
|
||||
import ArgumentParser
|
||||
|
||||
@main
|
||||
struct App: AsyncParsableCommand {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
@OptionGroup var options: Options
|
||||
|
||||
// MARK: Functions
|
||||
|
||||
mutating func run() async throws {
|
||||
let builder = AppBuilder(name: "App")
|
||||
let app = try await builder(options)
|
||||
|
||||
try await app.runService()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import AppLibrary
|
||||
import ArgumentParser
|
||||
import Logging
|
||||
|
||||
extension App {
|
||||
struct Options: AppArguments, ParsableArguments {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
@Option(name: .shortAndLong)
|
||||
var hostname: String = "127.0.0.1"
|
||||
|
||||
@Option(name: .shortAndLong)
|
||||
var port: Int = 8080
|
||||
|
||||
@Option(name: .shortAndLong)
|
||||
var logLevel: Logger.Level?
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import Logging
|
||||
|
||||
public protocol AppArguments {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
var hostname: String { get }
|
||||
var logLevel: Logger.Level? { get }
|
||||
var port: Int { get }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import Hummingbird
|
||||
import Logging
|
||||
|
||||
public struct AppBuilder {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
private let environment: Environment
|
||||
private let name: String
|
||||
|
||||
// MARK: Initialisers
|
||||
|
||||
public init(name: String) {
|
||||
self.environment = Environment()
|
||||
self.name = name
|
||||
}
|
||||
|
||||
// MARK: Functions
|
||||
|
||||
public func callAsFunction(
|
||||
_ arguments: some AppArguments
|
||||
) async throws -> some ApplicationProtocol {
|
||||
let logger = {
|
||||
var logger = Logger(label: name)
|
||||
|
||||
logger.logLevel = arguments.logLevel
|
||||
?? environment.logLevel.flatMap { Logger.Level(rawValue: $0) ?? .info }
|
||||
?? .info
|
||||
|
||||
return logger
|
||||
}()
|
||||
|
||||
let router = router(logger: logger)
|
||||
|
||||
return Application(
|
||||
router: router,
|
||||
configuration: .init(
|
||||
address: .hostname(arguments.hostname, port: arguments.port),
|
||||
serverName: name
|
||||
),
|
||||
logger: logger
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
private extension AppBuilder {
|
||||
|
||||
// MARK: Type aliases
|
||||
|
||||
typealias AppRequestContext = BasicRequestContext
|
||||
|
||||
// MARK: Functions
|
||||
|
||||
func router(logger: Logger) -> Router<AppRequestContext> {
|
||||
let router = Router()
|
||||
|
||||
router.add(middleware: LogRequestsMiddleware(logger.logLevel))
|
||||
|
||||
router.get("/") { _,_ in
|
||||
""
|
||||
}
|
||||
|
||||
return router
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import Hummingbird
|
||||
|
||||
extension Environment {
|
||||
|
||||
// MARK: Computed
|
||||
|
||||
public var logLevel: String? {
|
||||
self.get("LOG_LEVEL")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import ArgumentParser
|
||||
import Logging
|
||||
|
||||
/// Extend `Logger.Level` so it can be used as an argument
|
||||
#if hasFeature(RetroactiveAttribute)
|
||||
extension Logger.Level: @retroactive ExpressibleByArgument {}
|
||||
#else
|
||||
extension Logger.Level: ExpressibleByArgument {}
|
||||
#endif
|
||||
@@ -5,7 +5,7 @@ import PackageDescription
|
||||
let package = Package(
|
||||
name: "App",
|
||||
platforms: [
|
||||
.macOS(.v10_15)
|
||||
.macOS(.v14)
|
||||
],
|
||||
products: [
|
||||
.executable(name: "App", targets: ["App"]),
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import AppLibrary
|
||||
import Hummingbird
|
||||
import HummingbirdTesting
|
||||
import Testing
|
||||
|
||||
struct AppTests {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
private let arguments = TestArguments()
|
||||
private let builder = AppBuilder(name: "App")
|
||||
|
||||
// MARK: Route tests
|
||||
|
||||
@Test(arguments: ["/"])
|
||||
func routes(_ uri: String) async throws {
|
||||
let app = try await builder(arguments)
|
||||
|
||||
try await app.test(.router) { client in
|
||||
try await client.execute(uri: uri, method: .get) { response in
|
||||
#expect(response.status == .ok)
|
||||
#expect(response.body == .empty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: ByteBuffer+Constants
|
||||
|
||||
private extension ByteBuffer {
|
||||
static let empty = ByteBuffer(string: "")
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import AppLibrary
|
||||
import Logging
|
||||
|
||||
struct TestArguments: AppArguments {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
let hostname = "127.0.0.1"
|
||||
let port = 0
|
||||
let logLevel: Logger.Level? = .trace
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user