Thursday, April 30, 2026
HomeiOS DevelopmentThe best way to write Swift scripts utilizing the brand new Command...

The best way to write Swift scripts utilizing the brand new Command API in Vapor 4?

[ad_1]

Shell scripts are necessities on the server aspect. Learn to construct Swift scripts on your backend apps utilizing property wrappers.

Vapor

Swift Argument Parser vs Vapor Instructions

Apple open-sourced a brand new library that may assist you numerous if you wish to construct scripts that written in Swift. The Swift Argument Parser was beforehand a part of the Swift Package deal Supervisor instruments, however now it’s even highly effective & has it is personal life (I imply repository). 😉

Alternatively Vapor already had a considerably related method to construct scripts, however in Vapor 4 the Command API is healthier than ever. Property Wrappers (obtainable from Swift 5.1) are utilized in each instances to deal with arguments, flags & choices. Personally I like this method lots.

Let me present you a easy good day command:


import ArgumentParser

struct HelloCommand: ParsableCommand {
    @Argument(assist: "The title to say good day")
    var title: String

    func run() throws {
        print("Hi there (self.title)!")
    }
}
HelloCommand.essential()

Now I am going to present you easy methods to implement the same command utilizing Vapor:


import Vapor

closing class HelloCommand: Command {
    
    let assist = "This command will say good day to a given title."

    struct Signature: CommandSignature {
        @Argument(title: "title", assist: "The title to say good day")
        var title: String
    }

    func run(utilizing context: CommandContext, signature: Signature) throws {
        print("Hi there (signature.title)!")
    }
}

public func configure(_ app: Utility) throws {
    app.instructions.use(HelloCommand(), as: "good day")
}

As you’ll be able to see they nearly appear to be the identical.


In case you love scripting, it’s best to positively test swift-sh and Brisk


The Swift Argument Parser library is a light-weight resolution if you’re solely in search of a easy Swift script. An excellent instance is a software that manipulates information on the system or one thing related. It is only one little dependency, however it removes a lot boilerplate out of your scripts. It means that you can give attention to the script itself, as a substitute of parsing the command line inputs. You’ll find extra detailed examples and an in depth documentation contained in the GitHub repository. 🙏


Vapor’s Command API is beneficial if you wish to carry out extra sophisticated duties together with your scripts. Something that is a part of your Vapor utility might be triggered from a command, so you’ll be able to simply create a backend software that reads (or writes) information from the database utilizing Fluent 4. That is the primary benefit of utilizing a Vapor command, as a substitute a stanadlone Swift script.




Arguments, choices, flags

Let’s lengthen the good day command with a brand new possibility and a flag. The primary distinction between an possibility and a flag is that an possibility has an related worth, however a flag is simply one thing that you just give to the command or not. Each choices and flags begin with a single - or a double sprint --, normally the only dashed model makes use of a brief title for a similar factor. 🤓

Arguments are consumer offered values learn so as (eg.: ./good day joe bob john).

Now that you recognize the essential definitions, right here is the instance:

closing class HelloCommand: Command {
        
    struct Signature: CommandSignature {

        @Argument(title: "title", assist: "The title to say good day")
        var title: String

        @Possibility(title: "greeting", brief: "g", assist: "Greeting used")
        var greeting: String?

        @Flag(title: "capitalize", brief: "c", assist: "Capitalizes the title")
        var capitalize: Bool
    }

    let assist = "This command will say good day to a given title."

    func run(utilizing context: CommandContext, signature: Signature) throws {
        let greeting = signature.greeting ?? "Hi there"
        var title = signature.title
        if signature.capitalize {
            title = title.capitalized
        }
        print("(greeting) (title)!")
    }
}

Arguments are required by default, choices and flags are optionals. You possibly can have a customized title (brief and lengthy) for all the things, plus you’ll be able to customise the assistance message for each part.

swift run Run good day john


swift run Run good day john --greeting Hello


swift run Run good day john --greeting Hello --capitalized


swift run Run good day john -g Szia -c

You possibly can name the command utilizing a number of kinds. Be happy to select a most popular model. ⭐️



Subcommands

When command-line packages develop bigger, it may be helpful to divide them into a bunch of smaller packages, offering an interface by means of subcommands. Utilities similar to git and the Swift bundle supervisor are capable of present different interfaces for every of their sub-functions by implementing subcommands similar to git department or swift bundle init.

Vapor can deal with command teams in a extremely cool manner. I am going to add an additional static property to call our instructions, since I do not prefer to repeat myself or bloat the code with pointless strings:

closing class HelloCommand: Command {
    
    static var title = "good day"
        
    
}

struct WelcomeCommandGroup: CommandGroup {
    
    static var title = "welcome"

    let assist: String
    let instructions: [String: AnyCommand]
    
    var defaultCommand: AnyCommand? {
        self.instructions[HelloCommand.name]
    }

    init() {
        self.assist = "search engine optimization command group assist"

        self.instructions = [
            HelloCommand.name: HelloCommand(),
        ]
    }
}

public func configure(_ app: Utility) throws {

    app.instructions.use(WelcomeCommandGroup(), as: WelcomeCommandGroup.title)
}


That is it, we simply moved our good day command beneath the welcome namespace.

swift run Run welcome good day john --greeting "Hello" --capitalize

In case you learn the Swift Argument Parser docs, you’ll be able to obtain the very same conduct by means of a customized CommandConfiguration. Personally, I favor Vapor’s method right here… 🤷‍♂️



Ready for async duties

Vapor builds on prime of SwiftNIO together with EventLoops, Futures & Guarantees. A lot of the API is asynchronous, however within the CLI world it’s important to look ahead to the async operations to complete.

closing class TodoCommand: Command {
    
    static let title = "todo"

    struct Signature: CommandSignature { }
        
    let assist = "This command will create a dummy Todo merchandise"

    func run(utilizing context: CommandContext, signature: Signature) throws {
        let app = context.utility
        app.logger.discover("Creating todos...")
        
        let todo = Todo(title: "Look ahead to async duties...")
        attempt todo.create(on: app.db).wait()
        
        app.logger.discover("Todo is prepared.")
    }
}

There’s a throwing wait() methodology that you could make the most of to “keep within the loop” till all the things is finished. You too can get a pointer for the appliance object through the use of the present context. The app has the database connection, so you’ll be able to inform Fluent to create a brand new mannequin. Additionally you should utilize the built-in logger to print information to the console whereas the consumer waits. ⏳




Utilizing ConsoleKit with out Vapor

Let’s speak about overheads. Vapor comes with this neat instructions API, but in addition bundles a number of different core issues. What if I simply need the goodies for my Swift scripts? No downside. You need to use the underlying ConsoleKit by including it as a dependency.


import PackageDescription

let bundle = Package deal(
    title: "myProject",
    platforms: [
       .macOS(.v10_15)
    ],
    dependencies: [
        .package(url: "https://github.com/vapor/console-kit", from: "4.1.0"),
    ],
    targets: [
        .target(name: "myProject", dependencies: [
            .product(name: "ConsoleKit", package: "console-kit"),
        ])
    ]
)

You continue to should do some extra work in your essential.swift file, however nothing severe:

import ConsoleKit
import Basis

let console: Console = Terminal()
var enter = CommandInput(arguments: CommandLine.arguments)
var context = CommandContext(console: console, enter: enter)

var instructions = Instructions(enableAutocomplete: true)
instructions.use(HelloCommand(), as: HelloCommand.title, isDefault: false)

do {
    let group = instructions.group(assist: "Utilizing ConsoleKit with out Vapor.")
    attempt console.run(group, enter: enter)
}
catch {
    console.error("(error)")
    exit(1)
}

This manner you’ll be able to do away with a lot of the community associated core packages (which might be included by default should you use Vapor). This method solely fetches swift-log as a 3rd social gathering dependency. 😍




Abstract

ConsoleKit in Vapor is an effective way to put in writing CLI instruments and small scripts. The brand new Swift Argument Parser is a extra light-weight resolution for a similar downside. In case your plan is to keep up databases by means of scripts otherwise you carry out a number of networking or asynchronous operations it may be higher to go along with Vapor, since you’ll be able to all the time develop by importing a brand new part from the ecosystem.


[ad_2]

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments