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

Overview

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

Comments
  • [BUG] Cannot build on Linux because LinuxMain.swift is missing

    [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
    bug 
    opened by jhoogstraat 8
  • Feature/input dtos

    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.
    enhancement 
    opened by jhoogstraat 6
  • [FEATURE] Allow authentication via JWTs

    [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.

    enhancement 
    opened by jhoogstraat 4
  • [FEATURE] Implement Mediator types

    [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.

    enhancement 
    opened by jhoogstraat 4
  • Adds GuardGroup

    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.
    opened by jhoogstraat 3
  • [FEATURE] Allow passing related objects as id for creating objects

    [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.

    enhancement 
    opened by bmikaili 2
  • Adds JWTAuthGroup

    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.
    opened by jhoogstraat 1
  • [FEATURE] GuardGroup to allow for basic authorization

    [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....

    enhancement 
    opened by jhoogstraat 1
  • [BUG] Auth Groups block incoming requests with valid auth

    [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()
    ])
    
    bug 
    opened by jhoogstraat 1
  • Provide a functional default implementation of register in Endpoints

    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.
    enhancement 
    opened by PSchmiedmayer 1
  • Feature/refactor tests

    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.
    enhancement 
    opened by bmikaili 0
Releases(0.0.16)
  • 0.0.16(Jun 7, 2020)

  • 0.0.15(May 30, 2020)

  • 0.0.14(May 15, 2020)

    Changes

    • [FEATURE] User endpoint auto-hash and validate @bmikaili (#31)
    • Feature/api class @jhoogstraat (#32)
    • Conforms Array to CorvusResponse @jhoogstraat (#33)
    • [BUG] Auth Groups block incoming requests with valid auth @bmikaili (#30)

    🚀 Features

    • Feature/modifier rework @bmikaili (#35)
    • Added buildEither method and updated CRUDs @bmikaili (#36)

    🐛 Bug Fixes

    • Feature/modifier rework @bmikaili (#35)
    Source code(tar.gz)
    Source code(zip)
  • 0.0.13(Apr 17, 2020)

  • 0.0.12(Apr 17, 2020)

  • 0.0.11(Apr 16, 2020)

  • 0.0.10(Apr 14, 2020)

  • 0.0.9(Apr 10, 2020)

    🚀 Features

    • Implemented soft delete and restore @jhoogstraat (#5)
    • Adds RestEndpoint to decouple Endpoint from http. @jhoogstraat (#6)
    • Provide a functional default implementation of register in Endpoints @PSchmiedmayer (#8)
    • Feature/user endpoint @bmikaili (#9)
    • Feature/response modifier @jhoogstraat (#10)

    Changes

    • Fixes Corvus for Vapor 4.0.0 @jhoogstraat (#2) @jhoogstraat (#16)
    Source code(tar.gz)
    Source code(zip)
💧 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

Vapor 22.4k Jan 7, 2023
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

Kitura 7.6k Dec 27, 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

Kyle Fuller Archive 397 Oct 30, 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

Envoy 540 Dec 15, 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

null 3.6k Jan 3, 2023
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

Zewo 1.9k Dec 22, 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

Envoy 170 Nov 15, 2022
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

SkyLab 316 Oct 6, 2022
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

null 42 Jun 29, 2022
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

Catch 5.9k Dec 24, 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

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

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

Mohammed Albahal 0 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…)

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

PerfectlySoft Inc. 13.9k Dec 29, 2022
💧 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

Vapor 22.4k Jan 7, 2023
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

PerfectlySoft Inc. 13.9k Jan 6, 2023
💧 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

Vapor 22.4k Jan 2, 2023
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

Cap.雪ノ下八幡 2 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

PerfectlySoft Inc. 13.9k Dec 29, 2022
💧 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

Vapor 22.4k Jan 3, 2023
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

Amazon 1.4k Dec 22, 2022