How to add (and read) custom arguments when launching a vapor app.
In app.swift
I have added a struct AppOptions to keep track of custom options and added another parameter options to the app(_:) function:
import Vapor
public struct AppOptions {
public var foo: String?
public init(foo: String? = nil) {
self.foo = foo
}
}
/// Creates an instance of `Application`. This is called from `main.swift` in the run target.
public func app(_ env: Environment, options: AppOptions? = nil) throws -> Application {
var config = Config.default()
var env = env
var services = Services.default()
try configure(&config, &env, &services)
let app = try Application(config: config, environment: env, services: services)
try boot(app)
return app
}
In main.swift
I have added a step to parse custom flags from the commandline (and feed them into the AppOptions
struct). Then I hand this AppOptions
struct to my app.
import App
import Vapor
var appOptions = AppOptions()
var commandInput = CommandInput(arguments: CommandLine.arguments)
if let value = try commandInput.parse(option: .value(name: "foo")) {
print("foo: \(value)")
appOptions.foo = value
}
try app(.detect(from: &commandInput), options: appOptions).run()
From there you could further use it to customize your boot/config routine.
Tested with running:
vapor run serve --env staging --hostname 127.0.0.1 --port 8099 --foo bar
Prints:
foo: 'bar'
Calling commandInput.parse(option:)
will remove the parsed option from the input. Hence vapors ServeCommand
won't see it (and therefore won't complain)
You can probably use the same method for your custom commands so you dont have to spin up the vapor app server etc just to perform a command.
Or even simpler: use Environment.arguments
to get the command you are running. Based on that you could skip steps in your configure.swift
.