Meet Corvus, the first strongly declarative server-side framework.

Last update: Jan 29, 2022

Corvus

Documentation MIT License Continuous Integration Swift 5.2


Corvus is the first truly declarative server-side framework for Swift. It provides a declarative, composable syntax which makes it easy to get APIs up and running. It is based heavily on the existing work from Vapor.

Example

Below is an example of a full-featured API that manages Bank Accounts and Transactions belonging to certain users. It also showcases the ease of using authentication and setting authorization rules for specific routes.

let xpenseApi = Api("api") {
    User<CorvusUser>("users")
    
    Login<CorvusToken>("login")
    
    BearerAuthGroup<CorvusToken> {
        AccountsEndpoint()
        TransactionsEndpoint()
    }
}

Because Corvus is composable, it is easy to use a group of components as its own component:

final class AccountsEndpoint: Endpoint {
    let parameter = Parameter<Account>()
    
    var content: Endpoint {
        Group("accounts") {
            Create<Account>().auth(\.$user)
            ReadAll<Account>().auth(\.$user)
            
            Group(parameter.id) {
                ReadOne<Account>(parameter.id).auth(\.$user)
                Update<Account>(parameter.id).auth(\.$user)
                Delete<Account>(parameter.id).auth(\.$user)
            }
        }
    }
}

How to set up

After your Swift Project, in the Package.Swift file, you will need to add the dependencies for Corvus and a Fluent database driver of your choice. Below is an example with an SQLite driver:

// swift-tools-version:5.2
import PackageDescription

let package = Package(
    name: "XpenseServer",
    platforms: [
        .macOS(.v10_15)
    ],
    products: [
        .library(name: "XpenseServer", targets: ["XpenseServer"])
    ],
    dependencies: [
        .package(url: "https://github.com/Apodini/corvus.git", from: "0.0.14"),
        .package(url: "https://github.com/vapor/vapor.git", from: "4.0.0"),
        .package(url: "https://github.com/vapor/fluent-sqlite-driver.git", from: "4.0.0-rc")
    ],
    targets: [
        .target(name: "Run",
                dependencies: [
                    .target(name: "XpenseServer")
                ]),
        .target(name: "XpenseServer",
                dependencies: [
                    .product(name: "Corvus", package: "corvus"),
                    .product(name: "FluentSQLiteDriver", package: "fluent-sqlite-driver")
                ]),
        .testTarget(name: "XpenseServerTests",
                    dependencies: [
                        .target(name: "XpenseServer"),
                        .product(name: "XCTVapor", package: "vapor"),
                        .product(name: "FluentSQLiteDriver", package: "fluent-sqlite-driver")
                    ])
    ]
)

Additionally, under the application's Source folder (by default that is Sources/App), two setup functions need to be present:

configure.swift, in which you can configure middlewares, databases and migrations used in the application:

import Corvus
import Vapor
import FluentSQLiteDriver

public func configure(_ app: Application) throws {
    app.middleware.use(CorvusUser.authenticator())
    app.middleware.use(CorvusToken.authenticator())
    
    app.databases.use(.sqlite(.file("db.sqlite")), as: .sqlite)
    app.migrations.add(CreateAccount())
    app.migrations.add(CreateTransaction())
    app.migrations.add(CreateCorvusUser())
    app.migrations.add(CreateCorvusToken())

    try app.autoMigrate().wait()
}

And routes.swift, which registers the routes from the Corvus API:

import Corvus
import Vapor

public func routes(_ app: Application) throws {
    try app.register(collection: xpenseApi)
}

Finally the application's main.swift file (which is usually under the path Sources/Run) should look like this:

import App
import Vapor

var environment = try Environment.detect()
try LoggingSystem.bootstrap(from: &environment)
let app = Application(environment)
try configure(app)
try routes(app)
defer {
    app.shutdown()
}
try app.run()

How to use

In general, there are two types of building blocks for a Corvus API: Group components, which allow users to group more groups or concrete endpoints under a common route path, or components that provide concrete functionality, like Create or ReadAll. Check out the docs and the example project to learn more!

How to contribute

Review our contribution guidelines for contribution formalities.

Sources

The logo: Made by Freepik

Vapor

Fluent

GitHub

https://github.com/apodini/corvus
Comments
  • 1. [BUG] Cannot build on Linux because LinuxMain.swift is missing

    Describe the bug swift build fails because there is no LinuxMain.swift in the Test directory.

    To Reproduce Run swift build on Linux

    Expected behavior Corvus should be built successfully

    Environment (enter your versions):

    • Swift Version: 5.2.2
    • Xcode Version: -
    • Corvus Version: Head
    Reviewed by jhoogstraat at 2020-04-23 11:38
  • 2. Feature/input dtos

    Provide a way to define the layout of request bodies and how the data is processed.

    Description

    Adds two Modifiers (SaveDTOModifier and UpdateDTOModifier) which require the programmer to define a struct conforming to either SaveDTOor UpdateDTO. These types are then decoded from the request body and used to save or update a model to the database.

    Ideas

    • Use Validations if present
    • use OperationType .patch for updating, because of its 'partial updating' nature.

    Related Issue

    Fixes 50% of #3

    Types of changes

    • [ ] Bug fix (non-breaking change which fixes an issue)
    • [x] New feature (non-breaking change which adds functionality)
    • [ ] Breaking change (fix or feature that would cause existing functionality to change)

    Checklist:

    • [x] SwiftLint throws no warnings or errors.
    • [x] I have updated the documentation accordingly.
    • [x] I have added tests to cover my changes.
    • [x] All new and existing tests passed.
    Reviewed by jhoogstraat at 2020-04-07 13:45
  • 3. [FEATURE] Allow authentication via JWTs

    Is your feature request related to a problem? Please describe. I'd like to authenticate a User via a JWT that contains a payload.

    Describe the solution you'd like Implement a JWTAuthGroup that authenticates a JWT and injects it into req.auth. A CorvusJWTAuthenticator can be used to seperate the authentication from the group type.

    Reviewed by jhoogstraat at 2020-05-23 11:52
  • 4. [FEATURE] Implement Mediator types

    Problem

    It may not be desirable to always use CorvusModel for decoding the body of certain requests, like create or update requests.

    Solution

    To have more control over what the user is able to provide in a request body 'mediator', or 'carrier' types can be used. These types are also refered to as 'Data Transfer Objects' or DTOs. These can be implemented as DTOModifiers and ResponseModifier.

    Alternative Solutions

    Altering Create and Update endpoint to support these operations. Altering CorvusModel to inherit this functionality.

    Reviewed by jhoogstraat at 2020-03-10 16:58
  • 5. Adds GuardGroup

    This PR implements GuardGroup in conjuction with Guard.

    Related Issue

    Fixes #39

    Types of changes

    • [ ] Bug fix (non-breaking change which fixes an issue)
    • [x] New feature (non-breaking change which adds functionality)
    • [ ] Breaking change (fix or feature that would cause existing functionality to change)

    Checklist:

    • [x] SwiftLint throws no warnings or errors.
    • [x] I have updated the documentation accordingly.
    • [ ] I have added tests to cover my changes.
    • [x] All new and existing tests passed.
    Reviewed by jhoogstraat at 2020-05-23 12:04
  • 6. [FEATURE] Allow passing related objects as id for creating objects

    Currently, json has to be written like this to create objects:

    {
      "name": "Account",
      "user": {
        "id": "26132E11-6D13-4983-9FAE-71B705439BD8"
      }
    }
    

    It would be nice to only have to do this:

    {
      "name": "Account",
      "user": "26132E11-6D13-4983-9FAE-71B705439BD8"
    }
    

    This should be possible with DTOs.

    Reviewed by bmikaili at 2020-04-22 13:57
  • 7. Adds JWTAuthGroup

    Fixes #40

    Description

    Related Issue

    Types of changes

    • [ ] Bug fix (non-breaking change which fixes an issue)
    • [x] New feature (non-breaking change which adds functionality)
    • [ ] Breaking change (fix or feature that would cause existing functionality to change)

    Checklist:

    • [ ] SwiftLint throws no warnings or errors.
    • [ ] I have updated the documentation accordingly.
    • [ ] I have added tests to cover my changes.
    • [ ] All new and existing tests passed.
    Reviewed by jhoogstraat at 2020-05-23 14:20
  • 8. [FEATURE] GuardGroup to allow for basic authorization

    Is your feature request related to a problem? Please describe. A new Type GuardGroup could be used to allow for the authorization of requests. This would allow a simple Role system, where each role has different access levels.

    Describe the solution you'd like Implement a new Group called GuardGroup which takes an array of Guard instances. A Guard is responsible for evaluating if the user is authorized to access the endpoint.

    Describe alternatives you've considered All other group types could get a new parameter guards: Guard....

    Reviewed by jhoogstraat at 2020-05-23 11:28
  • 9. [BUG] Auth Groups block incoming requests with valid auth

    Describe the bug I am getting User not authenticated with auth groups.

    To Reproduce Just

    BasicAuthGroup<User>("login") {
        Custom<String>(type: .get) { req in
            req.eventLoop.makeSucceededFuture("Test")
        }
    }
    

    Expected behavior User should be authenticated.

    Environment:

    • Swift Version: 5.2
    • Xcode Version: 11.4.1
    • Corvus Version: develop branch
    • Database driver Version: Fluent SQLite Driver

    Additional context Works, if order is inverted:

    let guardedRoutesBuilder = groupedRoutesBuilder.grouped([
        T.authenticator(),
        T.guardMiddleware()
    ])
    
    Reviewed by jhoogstraat at 2020-04-18 21:52
  • 10. Provide a functional default implementation of register in Endpoints

    Provide a functional default implementation of register in Endpoints

    Description

    Provide a functional default implementation of register(to routes: RoutesBuilder) for an Endpoint to enable Corvus Users to write composable Endpoints without the need to write a register(to routes: RoutesBuilder) function

    Related Issue

    Closes #7

    How Has This Been Tested?

    Ran the test suite

    Types of changes

    • [x] New feature (non-breaking change which adds functionality)

    Checklist:

    • [x] My code follows the code style of this project.
    • [x] My change requires a change to the documentation.
    • [x] I have updated the documentation accordingly.
    • [x] I have read the CONTRIBUTING document.
    • [x] I have added tests to cover my changes.
    • [x] All new and existing tests passed.
    Reviewed by PSchmiedmayer at 2020-04-04 12:25
  • 11. Feature/refactor tests

    Refactors the tests by splitting into separate files and following best practices in the Example Project.

    Types of changes

    • [ ] Bug fix (non-breaking change which fixes an issue)
    • [ ] New feature (non-breaking change which adds functionality)
    • [x] Breaking change (fix or feature that would cause existing functionality to change)

    Checklist:

    • [x] SwiftLint throws no warnings or errors.
    • [x] I have updated the documentation accordingly.
    • [x] I have added tests to cover my changes.
    • [x] All new and existing tests passed.
    Reviewed by bmikaili at 2020-05-16 14:31
💧 A server-side Swift web framework.
💧 A server-side Swift web framework.

Vapor is a web framework for Swift. It provides a beautifully expressive and easy to use foundation for your next website, API, or cloud project. Take

Jun 23, 2022
A Swift web framework and HTTP server.
A Swift web framework and HTTP server.

A Swift Web Framework and HTTP Server Summary Kitura is a web framework and web server that is created for web services written in Swift. For more inf

Jun 24, 2022
Swift HTTP server using the pre-fork worker model

Curassow Curassow is a Swift Nest HTTP Server. It uses the pre-fork worker model and it's similar to Python's Gunicorn and Ruby's Unicorn. It exposes

Mar 20, 2022
Super lightweight async HTTP server library in pure Swift runs in iOS / MacOS / Linux

Embassy Super lightweight async HTTP server in pure Swift. Please read: Embedded web server for iOS UI testing. See also: Our lightweight web framewor

Jun 8, 2022
Tiny http server engine written in Swift programming language.

What is Swifter? Tiny http server engine written in Swift programming language. Branches * stable - lands on CocoaPods and others. Supports the latest

Jun 21, 2022
Lightweight library for web server applications in Swift on macOS and Linux powered by coroutines.
Lightweight library for web server applications in Swift on macOS and Linux powered by coroutines.

Why Zewo? • Support • Community • Contributing Zewo Zewo is a lightweight library for web applications in Swift. What sets Zewo apart? Zewo is not a w

May 30, 2022
Super lightweight web framework in Swift based on SWSGI

Ambassador Super lightweight web framework in Swift based on SWSGI Features Super lightweight Easy to use, designed for UI automatic testing API mocki

Mar 18, 2022
A Swift Multiplatform Single-threaded Non-blocking Web and Networking Framework
A Swift Multiplatform Single-threaded Non-blocking Web and Networking Framework

Serverside non-blocking IO in Swift Ask questions in our Slack channel! Lightning (formerly Edge) Node Lightning is an HTTP Server and TCP Client/Serv

Jan 29, 2022
Meet Corvus, the first strongly declarative server-side framework.
Meet Corvus, the first strongly declarative server-side framework.

Corvus Corvus is the first truly declarative server-side framework for Swift. It provides a declarative, composable syntax which makes it easy to get

Jan 29, 2022
Meet Genius - A community where geniuses meet
Meet Genius - A community where geniuses meet

Yep A community where geniuses meet https://soyep.com Yep: Project Introductory Guide Please build with the latest CocoaPods v0.39.0 and Xcode 7.2. In

Jun 20, 2022
FreshPlan - meet-up app that plans when you guys want to meet

FreshPlan meet-up app that plans when you guys want to meet. Requirements Cocoap

Jan 4, 2022
Left Side Menu \ Side Bar with modern interface for iOS

SideMenu A customizable, interactive, auto expanding and collapsing side menu fo

Dec 18, 2021
Server-side Swift. The Perfect core toolset and framework for Swift Developers. (For mobile back-end development, website and API development, and more…)
Server-side Swift. The Perfect core toolset and framework for Swift Developers. (For mobile back-end development, website and API development, and more…)

Perfect: Server-Side Swift 简体中文 Perfect: Server-Side Swift Perfect is a complete and powerful toolbox, framework, and application server for Linux, iO

Jun 22, 2022
💧 A server-side Swift web framework.
💧 A server-side Swift web framework.

Vapor is a web framework for Swift. It provides a beautifully expressive and easy to use foundation for your next website, API, or cloud project. Take

Jun 23, 2022
Server-side Swift. The Perfect core toolset and framework for Swift Developers. (For mobile back-end development, website and API development, and more…)
Server-side Swift. The Perfect core toolset and framework for Swift Developers. (For mobile back-end development, website and API development, and more…)

Perfect: Server-Side Swift 简体中文 Perfect: Server-Side Swift Perfect is a complete and powerful toolbox, framework, and application server for Linux, iO

Jun 27, 2022
💧 A server-side Swift web framework.
💧 A server-side Swift web framework.

Vapor is a web framework for Swift. It provides a beautifully expressive and easy to use foundation for your next website, API, or cloud project. Take

Jun 22, 2022
A Slack API Client for the Perfect Server-Side Swift Framework

PerfectSlackAPIClient is an API Client to access the Slack API from your Perfect Server Side Swift application. It is build on top of PerfectAPIClient

Dec 1, 2019
Server-side Swift. The Perfect core toolset and framework for Swift Developers. (For mobile back-end development, website and API development, and more…)

Perfect: Server-Side Swift 简体中文 Perfect: Server-Side Swift Perfect is a complete and powerful toolbox, framework, and application server for Linux, iO

Jun 21, 2022
💧 A server-side Swift HTTP web framework.
💧 A server-side Swift HTTP web framework.

Vapor is an HTTP web framework for Swift. It provides a beautifully expressive and easy-to-use foundation for your next website, API, or cloud project

Jun 24, 2022
A light-weight server-side service framework written in the Swift programming language.

Smoke Framework The Smoke Framework is a light-weight server-side service framework written in Swift and using SwiftNIO for its networking layer by de

Jun 17, 2022