├── Public └── .gitkeep ├── Tests ├── .gitkeep ├── LinuxMain.swift └── AppTests │ └── AppTests.swift ├── Sources ├── App │ ├── Models │ │ ├── .gitkeep │ │ └── Todo.swift │ ├── Controllers │ │ ├── .gitkeep │ │ └── TodoController.swift │ ├── boot.swift │ ├── app.swift │ ├── routes.swift │ └── configure.swift └── Run │ └── main.swift ├── .dockerignore ├── cloud.yml ├── .gitignore ├── CONTRIBUTING.md ├── Package.swift ├── .circleci └── config.yml ├── README.md ├── web.Dockerfile └── Package.resolved /Public/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Tests/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Sources/App/Models/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Sources/App/Controllers/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Sources/Run/main.swift: -------------------------------------------------------------------------------- 1 | import App 2 | 3 | try app(.detect()).run() 4 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | .build 3 | DerivedData 4 | Package.resolved 5 | *.xcodeproj 6 | 7 | -------------------------------------------------------------------------------- /cloud.yml: -------------------------------------------------------------------------------- 1 | type: "vapor" 2 | swift_version: "5.1.1" 3 | run_parameters: "serve --port 8080 --hostname 0.0.0.0" 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Packages 2 | .build 3 | xcuserdata 4 | *.xcodeproj 5 | DerivedData/ 6 | .DS_Store 7 | .swiftpm 8 | db.sqlite 9 | -------------------------------------------------------------------------------- /Sources/App/boot.swift: -------------------------------------------------------------------------------- 1 | import Vapor 2 | 3 | /// Called after your application has initialized. 4 | public func boot(_ app: Application) throws { 5 | // Your code here 6 | } 7 | -------------------------------------------------------------------------------- /Tests/AppTests/AppTests.swift: -------------------------------------------------------------------------------- 1 | import App 2 | import XCTest 3 | 4 | final class AppTests: XCTestCase { 5 | func testNothing() throws { 6 | // Add your tests here 7 | XCTAssert(true) 8 | } 9 | 10 | static let allTests = [ 11 | ("testNothing", testNothing) 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /Sources/App/app.swift: -------------------------------------------------------------------------------- 1 | import Vapor 2 | 3 | /// Creates an instance of `Application`. This is called from `main.swift` in the run target. 4 | public func app(_ env: Environment) throws -> Application { 5 | var config = Config.default() 6 | var env = env 7 | var services = Services.default() 8 | try configure(&config, &env, &services) 9 | let app = try Application(config: config, environment: env, services: services) 10 | try boot(app) 11 | return app 12 | } 13 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Vapor API Template 2 | 3 | If you found a mistake or think of a cool new feature, please [create an issue](https://github.com/vapor/api-template/issues/new) or, if you want to implement it yourself, [fork this repo](https://github.com/vapor/api-template/fork) and open a Pull Request! 4 | 5 | We'll take a look as soon as we can. 6 | 7 | Thanks! 8 | 9 | ## Maintainers 10 | 11 | - [@0xTim](https://github.com/0xTim) 12 | 13 | See the [Vapor maintainers doc](https://github.com/vapor/vapor/blob/master/Docs/maintainers.md) for more information. 14 | -------------------------------------------------------------------------------- /Sources/App/routes.swift: -------------------------------------------------------------------------------- 1 | import Vapor 2 | 3 | /// Register your application's routes here. 4 | public func routes(_ router: Router) throws { 5 | // Basic "It works" example 6 | router.get { req in 7 | return "It works!" 8 | } 9 | 10 | // Basic "Hello, world!" example 11 | router.get("hello") { req in 12 | return "Hello, world!" 13 | } 14 | 15 | // Example of configuring a controller 16 | let todoController = TodoController() 17 | router.get("todos", use: todoController.index) 18 | router.post("todos", use: todoController.create) 19 | router.delete("todos", Todo.parameter, use: todoController.delete) 20 | } 21 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:4.0 2 | import PackageDescription 3 | 4 | let package = Package( 5 | name: "VaporApp", 6 | products: [ 7 | .library(name: "VaporApp", targets: ["App"]), 8 | ], 9 | dependencies: [ 10 | // 💧 A server-side Swift web framework. 11 | .package(url: "https://github.com/vapor/vapor.git", from: "3.0.0"), 12 | 13 | // 🔵 Swift ORM (queries, models, relations, etc) built on SQLite 3. 14 | .package(url: "https://github.com/vapor/fluent-sqlite.git", from: "3.0.0") 15 | ], 16 | targets: [ 17 | .target(name: "App", dependencies: ["FluentSQLite", "Vapor"]), 18 | .target(name: "Run", dependencies: ["App"]), 19 | .testTarget(name: "AppTests", dependencies: ["App"]) 20 | ] 21 | ) 22 | -------------------------------------------------------------------------------- /Sources/App/Models/Todo.swift: -------------------------------------------------------------------------------- 1 | import FluentSQLite 2 | import Vapor 3 | 4 | /// A single entry of a Todo list. 5 | final class Todo: SQLiteModel { 6 | typealias Database = SQLiteDatabase 7 | /// The unique identifier for this `Todo`. 8 | var id: Int? 9 | 10 | /// A title describing what this `Todo` entails. 11 | var title: String 12 | 13 | /// Creates a new `Todo`. 14 | init(id: Int? = nil, title: String) { 15 | self.id = id 16 | self.title = title 17 | } 18 | } 19 | 20 | /// Allows `Todo` to be used as a dynamic migration. 21 | extension Todo: Migration { } 22 | 23 | /// Allows `Todo` to be encoded to and decoded from HTTP messages. 24 | extension Todo: Content { } 25 | 26 | /// Allows `Todo` to be used as a dynamic parameter in route definitions. 27 | extension Todo: Parameter { } 28 | -------------------------------------------------------------------------------- /Sources/App/Controllers/TodoController.swift: -------------------------------------------------------------------------------- 1 | import Vapor 2 | 3 | /// Controls basic CRUD operations on `Todo`s. 4 | final class TodoController { 5 | /// Returns a list of all `Todo`s. 6 | func index(_ req: Request) throws -> Future<[Todo]> { 7 | return Todo.query(on: req).all() 8 | } 9 | 10 | /// Saves a decoded `Todo` to the database. 11 | func create(_ req: Request) throws -> Future { 12 | return try req.content.decode(Todo.self).flatMap { todo in 13 | return todo.save(on: req) 14 | } 15 | } 16 | 17 | /// Deletes a parameterized `Todo`. 18 | func delete(_ req: Request) throws -> Future { 19 | return try req.parameters.next(Todo.self).flatMap { todo in 20 | return todo.delete(on: req) 21 | }.transform(to: .ok) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | jobs: 4 | linux: 5 | docker: 6 | - image: swift:4.1 7 | steps: 8 | - checkout 9 | - run: 10 | name: Compile code 11 | command: swift build 12 | - run: 13 | name: Run unit tests 14 | command: swift test 15 | 16 | linux-release: 17 | docker: 18 | - image: swift:4.1 19 | steps: 20 | - checkout 21 | - run: 22 | name: Compile code with optimizations 23 | command: swift build -c release 24 | 25 | workflows: 26 | version: 2 27 | tests: 28 | jobs: 29 | - linux 30 | - linux-release 31 | 32 | nightly: 33 | triggers: 34 | - schedule: 35 | cron: "0 0 * * *" 36 | filters: 37 | branches: 38 | only: 39 | - master 40 | jobs: 41 | - linux 42 | - linux-release 43 | 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | API Template 3 |
4 |
5 | 6 | Documentation 7 | 8 | 9 | Team Chat 10 | 11 | 12 | MIT License 13 | 14 | 15 | Continuous Integration 16 | 17 | 18 | Swift 5.1 19 | 20 |

21 | -------------------------------------------------------------------------------- /Sources/App/configure.swift: -------------------------------------------------------------------------------- 1 | import FluentSQLite 2 | import Vapor 3 | 4 | /// Called before your application initializes. 5 | public func configure(_ config: inout Config, _ env: inout Environment, _ services: inout Services) throws { 6 | // Register providers first 7 | try services.register(FluentSQLiteProvider()) 8 | 9 | // Register routes to the router 10 | let router = EngineRouter.default() 11 | try routes(router) 12 | services.register(router, as: Router.self) 13 | 14 | // Register middleware 15 | var middlewares = MiddlewareConfig() // Create _empty_ middleware config 16 | // middlewares.use(FileMiddleware.self) // Serves files from `Public/` directory 17 | middlewares.use(ErrorMiddleware.self) // Catches errors and converts to HTTP response 18 | services.register(middlewares) 19 | 20 | // Configure a SQLite database 21 | let sqlite = try SQLiteDatabase(storage: .memory) 22 | 23 | // Register the configured SQLite database to the database config. 24 | var databases = DatabasesConfig() 25 | databases.add(database: sqlite, as: .sqlite) 26 | services.register(databases) 27 | 28 | // Configure migrations 29 | var migrations = MigrationConfig() 30 | migrations.add(model: Todo.self, database: .sqlite) 31 | services.register(migrations) 32 | } 33 | -------------------------------------------------------------------------------- /web.Dockerfile: -------------------------------------------------------------------------------- 1 | # You can set the Swift version to what you need for your app. Versions can be found here: https://hub.docker.com/_/swift 2 | FROM swift:5.1.1 as builder 3 | 4 | # For local build, add `--build-arg env=docker` 5 | # In your application, you can use `Environment.custom(name: "docker")` to check if you're in this env 6 | ARG env 7 | 8 | RUN apt-get -qq update && apt-get install -y \ 9 | libssl-dev zlib1g-dev \ 10 | && rm -r /var/lib/apt/lists/* 11 | WORKDIR /app 12 | COPY . . 13 | RUN mkdir -p /build/lib && cp -R /usr/lib/swift/linux/*.so* /build/lib 14 | RUN swift build -c release && mv `swift build -c release --show-bin-path` /build/bin 15 | 16 | # Production image 17 | FROM ubuntu:18.04 18 | ARG env 19 | # DEBIAN_FRONTEND=noninteractive for automatic UTC configuration in tzdata 20 | RUN apt-get -qq update && DEBIAN_FRONTEND=noninteractive apt-get install -y \ 21 | libatomic1 libicu60 libxml2 libcurl4 libz-dev libbsd0 tzdata \ 22 | && rm -r /var/lib/apt/lists/* 23 | WORKDIR /app 24 | COPY --from=builder /build/bin/Run . 25 | COPY --from=builder /build/lib/* /usr/lib/ 26 | # Uncomment the next line if you need to load resources from the `Public` directory 27 | #COPY --from=builder /app/Public ./Public 28 | # Uncomment the next line if you are using Leaf 29 | #COPY --from=builder /app/Resources ./Resources 30 | ENV ENVIRONMENT=$env 31 | 32 | ENTRYPOINT ./Run serve --env $ENVIRONMENT --hostname 0.0.0.0 --port 80 33 | -------------------------------------------------------------------------------- /Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "Console", 6 | "repositoryURL": "https://github.com/vapor/console.git", 7 | "state": { 8 | "branch": null, 9 | "revision": "74cfbea629d4aac34a97cead2447a6870af1950b", 10 | "version": "3.1.1" 11 | } 12 | }, 13 | { 14 | "package": "Core", 15 | "repositoryURL": "https://github.com/vapor/core.git", 16 | "state": { 17 | "branch": null, 18 | "revision": "18f2436bf7a6bc2224372c0885db2e0159af1649", 19 | "version": "3.9.2" 20 | } 21 | }, 22 | { 23 | "package": "Crypto", 24 | "repositoryURL": "https://github.com/vapor/crypto.git", 25 | "state": { 26 | "branch": null, 27 | "revision": "df8eb7d8ae51787b3a0628aa3975e67666da936c", 28 | "version": "3.3.3" 29 | } 30 | }, 31 | { 32 | "package": "DatabaseKit", 33 | "repositoryURL": "https://github.com/vapor/database-kit.git", 34 | "state": { 35 | "branch": null, 36 | "revision": "8f352c8e66dab301ab9bfef912a01ce1361ba1e4", 37 | "version": "1.3.3" 38 | } 39 | }, 40 | { 41 | "package": "Fluent", 42 | "repositoryURL": "https://github.com/vapor/fluent.git", 43 | "state": { 44 | "branch": null, 45 | "revision": "b915c321c6f9e83743ee5efa35a30895e1b02e51", 46 | "version": "3.2.0" 47 | } 48 | }, 49 | { 50 | "package": "FluentSQLite", 51 | "repositoryURL": "https://github.com/vapor/fluent-sqlite.git", 52 | "state": { 53 | "branch": null, 54 | "revision": "c32f5bda84bf4ea691d19afe183d40044f579e11", 55 | "version": "3.0.0" 56 | } 57 | }, 58 | { 59 | "package": "HTTP", 60 | "repositoryURL": "https://github.com/vapor/http.git", 61 | "state": { 62 | "branch": null, 63 | "revision": "3808ed0401379b6e9f4a053f03090ea9d658caa9", 64 | "version": "3.2.1" 65 | } 66 | }, 67 | { 68 | "package": "Multipart", 69 | "repositoryURL": "https://github.com/vapor/multipart.git", 70 | "state": { 71 | "branch": null, 72 | "revision": "f919a01c4d10a281d6236a21b0b1d1759a72b8eb", 73 | "version": "3.0.4" 74 | } 75 | }, 76 | { 77 | "package": "Routing", 78 | "repositoryURL": "https://github.com/vapor/routing.git", 79 | "state": { 80 | "branch": null, 81 | "revision": "d76f339c9716785e5079af9d7075d28ff7da3d92", 82 | "version": "3.1.0" 83 | } 84 | }, 85 | { 86 | "package": "Service", 87 | "repositoryURL": "https://github.com/vapor/service.git", 88 | "state": { 89 | "branch": null, 90 | "revision": "fa5b5de62bd68bcde9a69933f31319e46c7275fb", 91 | "version": "1.0.2" 92 | } 93 | }, 94 | { 95 | "package": "SQL", 96 | "repositoryURL": "https://github.com/vapor/sql.git", 97 | "state": { 98 | "branch": null, 99 | "revision": "50eaeb8f52a1ce63f1ff3880e1114dd8757a78a6", 100 | "version": "2.3.2" 101 | } 102 | }, 103 | { 104 | "package": "SQLite", 105 | "repositoryURL": "https://github.com/vapor/sqlite.git", 106 | "state": { 107 | "branch": null, 108 | "revision": "314d9cd21165bcf14215e336a23ff8214f40e411", 109 | "version": "3.2.1" 110 | } 111 | }, 112 | { 113 | "package": "swift-nio", 114 | "repositoryURL": "https://github.com/apple/swift-nio.git", 115 | "state": { 116 | "branch": null, 117 | "revision": "ba7970fe396e8198b84c6c1b44b38a1d4e2eb6bd", 118 | "version": "1.14.1" 119 | } 120 | }, 121 | { 122 | "package": "swift-nio-ssl", 123 | "repositoryURL": "https://github.com/apple/swift-nio-ssl.git", 124 | "state": { 125 | "branch": null, 126 | "revision": "0f3999f3e3c359cc74480c292644c3419e44a12f", 127 | "version": "1.4.0" 128 | } 129 | }, 130 | { 131 | "package": "swift-nio-ssl-support", 132 | "repositoryURL": "https://github.com/apple/swift-nio-ssl-support.git", 133 | "state": { 134 | "branch": null, 135 | "revision": "c02eec4e0e6d351cd092938cf44195a8e669f555", 136 | "version": "1.0.0" 137 | } 138 | }, 139 | { 140 | "package": "swift-nio-zlib-support", 141 | "repositoryURL": "https://github.com/apple/swift-nio-zlib-support.git", 142 | "state": { 143 | "branch": null, 144 | "revision": "37760e9a52030bb9011972c5213c3350fa9d41fd", 145 | "version": "1.0.0" 146 | } 147 | }, 148 | { 149 | "package": "TemplateKit", 150 | "repositoryURL": "https://github.com/vapor/template-kit.git", 151 | "state": { 152 | "branch": null, 153 | "revision": "51405c83e95e8adb09565278a5e9b959c605e56c", 154 | "version": "1.4.0" 155 | } 156 | }, 157 | { 158 | "package": "URLEncodedForm", 159 | "repositoryURL": "https://github.com/vapor/url-encoded-form.git", 160 | "state": { 161 | "branch": null, 162 | "revision": "82d8d63bdb76b6dd8febe916c639ab8608dbbaed", 163 | "version": "1.0.6" 164 | } 165 | }, 166 | { 167 | "package": "Validation", 168 | "repositoryURL": "https://github.com/vapor/validation.git", 169 | "state": { 170 | "branch": null, 171 | "revision": "4de213cf319b694e4ce19e5339592601d4dd3ff6", 172 | "version": "2.1.1" 173 | } 174 | }, 175 | { 176 | "package": "Vapor", 177 | "repositoryURL": "https://github.com/vapor/vapor.git", 178 | "state": { 179 | "branch": null, 180 | "revision": "92a58a9a84e4330500b99fe355a94d29f67abe58", 181 | "version": "3.3.1" 182 | } 183 | }, 184 | { 185 | "package": "WebSocket", 186 | "repositoryURL": "https://github.com/vapor/websocket.git", 187 | "state": { 188 | "branch": null, 189 | "revision": "d85e5b6dce4d04065865f77385fc3324f98178f6", 190 | "version": "1.1.2" 191 | } 192 | } 193 | ] 194 | }, 195 | "version": 1 196 | } 197 | --------------------------------------------------------------------------------