├── Config
├── secrets
│ ├── .gitkeep
│ └── app.json
├── production
│ ├── app.json
│ └── servers.json
├── app.json
├── development
│ └── app.json
└── servers.json
├── .swift-version
├── Procfile
├── .gitignore
├── Resources
└── Views
│ ├── template.leaf
│ ├── embeds
│ └── header.leaf
│ └── welcome.html
├── Public
├── images
│ └── vapor-logo.png
└── styles
│ └── app.css
├── Localization
├── en.json
├── es.json
└── default.json
├── app.json
├── .travis.yml
├── Package.swift
├── Sources
└── App
│ ├── Middleware
│ └── SampleMiddleware.swift
│ ├── Models
│ └── User.swift
│ ├── Controllers
│ └── UserController.swift
│ └── main.swift
├── license
└── README.md
/Config/secrets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.swift-version:
--------------------------------------------------------------------------------
1 | 3.0-GM-CANDIDATE
2 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: App --env=production --workdir="./"
2 |
--------------------------------------------------------------------------------
/Config/secrets/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "key": "secret-key"
3 | }
--------------------------------------------------------------------------------
/Config/production/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "key": "$VAPOR_APP_KEY"
3 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | Packages
2 | .build
3 | xcuserdata
4 | *.xcodeproj
5 |
--------------------------------------------------------------------------------
/Config/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "key": "default-key",
3 | "foo": "bar"
4 | }
--------------------------------------------------------------------------------
/Config/development/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "key": "development-key"
3 | }
--------------------------------------------------------------------------------
/Config/production/servers.json:
--------------------------------------------------------------------------------
1 | {
2 | "production": {
3 | "port": "$PORT"
4 | }
5 | }
--------------------------------------------------------------------------------
/Resources/Views/template.leaf:
--------------------------------------------------------------------------------
1 | #embed("embeds/header")
2 |
3 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Sources/App/Middleware/SampleMiddleware.swift:
--------------------------------------------------------------------------------
1 | import Vapor
2 | import HTTP
3 |
4 | class SampleMiddleware: Middleware {
5 |
6 | func respond(to request: Request, chainingTo chain: Responder) throws -> Response {
7 | // You can manipulate the request before calling the handler
8 | // and abort early if necessary, a good injection point for
9 | // handling auth.
10 |
11 | // return Response(status: .Forbidden, text: "Permission denied")
12 |
13 | let response = try chain.respond(to: request)
14 |
15 | // You can also manipulate the response to add headers
16 | // cookies, etc.
17 |
18 | return response
19 |
20 | // Vapor Middleware is based on S4 Middleware.
21 | // This means you can share it with any other project
22 | // that uses S4 Middleware.
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/App/Models/User.swift:
--------------------------------------------------------------------------------
1 | import Vapor
2 | import Fluent
3 |
4 | final class User: Model {
5 | var id: Node?
6 | var name: String
7 |
8 | init(name: String) {
9 | self.name = name
10 | }
11 |
12 | init(node: Node, in context: Context) throws {
13 | id = try node.extract("id")
14 | name = try node.extract("name")
15 | }
16 |
17 | public func makeNode(context: Context) throws -> Node {
18 | return try Node(node: [
19 | "name": name
20 | ])
21 | }
22 |
23 | static func prepare(_ database: Database) throws {
24 | //
25 | }
26 |
27 | static func revert(_ database: Database) throws {
28 | //
29 | }
30 | }
31 |
32 | extension User {
33 | public convenience init?(from string: String) throws {
34 | self.init(name: string)
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/license:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Tanner Nelson
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Public/styles/app.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | }
4 |
5 | body, html {
6 | padding: 0;
7 | margin: 0;
8 | height: 100%;
9 | }
10 |
11 | body {
12 | font-family: sans-serif;
13 | color: #333;
14 | position: relative;
15 | }
16 |
17 |
18 | a {
19 | color: #92A8D1;
20 | text-decoration: none;
21 | border-bottom: 1px dotted;
22 | }
23 |
24 | a:hover {
25 | color: #F7CAC9;
26 | }
27 |
28 | div.wrapper {
29 | width: 100%;
30 | max-width: 600px;
31 | margin: 0 auto;
32 | position: relative;
33 | top: 50%;
34 | transform: translateY(-50%);
35 | margin-top: -25px; //adjust eye level
36 | }
37 |
38 | h1#logo {
39 | text-indent: -9999px;
40 | background-image: url(../images/vapor-logo.png);
41 | background-size: 100%;
42 | width: 347.5px;
43 | height: 84px;
44 | margin: 0 auto;
45 | }
46 |
47 | nav.main {
48 | text-align: center;
49 | margin-top: 20px;
50 | }
51 | nav.main ul {
52 | margin: 0;
53 | padding: 0;
54 | }
55 | nav.main ul li {
56 | display: inline-block;
57 | padding: 0 5px;
58 | }
59 |
60 |
61 | footer.main {
62 | position: absolute;
63 | width: 100%;
64 | text-align: center;
65 | bottom: 10px;
66 | }
67 |
68 | footer.main p {
69 | margin: 0;
70 | padding: 0;
71 | color: #ccc;
72 | font-weight: 300;
73 | }
74 |
75 | footer.main p a {
76 | color: #ccc;
77 | }
--------------------------------------------------------------------------------
/Sources/App/Controllers/UserController.swift:
--------------------------------------------------------------------------------
1 | import Vapor
2 | import HTTP
3 |
4 | final class UserController: ResourceRepresentable {
5 | typealias Item = User
6 |
7 | let drop: Droplet
8 | init(droplet: Droplet) {
9 | drop = droplet
10 | }
11 |
12 | func index(request: Request) throws -> ResponseRepresentable {
13 | return try JSON(node: [
14 | "controller": "UserController.index"
15 | ])
16 | }
17 |
18 | func store(request: Request) throws -> ResponseRepresentable {
19 | return try JSON(node: [
20 | "controller": "UserController.store"
21 | ])
22 | }
23 |
24 | /**
25 | Since item is of type User,
26 | only instances of user will be received
27 | */
28 | func show(request: Request, item user: User) throws -> ResponseRepresentable {
29 | //User can be used like JSON with JsonRepresentable
30 | return try JSON(node: [
31 | "controller": "UserController.show",
32 | "user": user
33 | ])
34 | }
35 |
36 | func update(request: Request, item user: User) throws -> ResponseRepresentable {
37 | //User is JsonRepresentable
38 | return try user.makeJSON()
39 | }
40 |
41 | func destroy(request: Request, item user: User) throws -> ResponseRepresentable {
42 | //User is ResponseRepresentable by proxy of JsonRepresentable
43 | return user
44 | }
45 |
46 | func makeResource() -> Resource