└── Day1
├── Morning
├── Public
│ └── .gitkeep
├── Sources
│ ├── App
│ │ ├── Controllers
│ │ │ ├── .gitkeep
│ │ │ ├── CategoriesControllers.swift
│ │ │ ├── UserController.swift
│ │ │ └── ReminderController.swift
│ │ ├── Migrations
│ │ │ ├── CreateCategory.swift
│ │ │ ├── CreateUser.swift
│ │ │ ├── CreateReminder.swift
│ │ │ └── CreateReminderCategoryPivot.swift
│ │ ├── Models
│ │ │ ├── ReminderCategoryPivot.swift
│ │ │ ├── Category.swift
│ │ │ ├── User.swift
│ │ │ └── Reminder.swift
│ │ ├── configure.swift
│ │ └── routes.swift
│ └── Run
│ │ └── main.swift
├── .dockerignore
├── .gitignore
├── Tests
│ └── AppTests
│ │ └── AppTests.swift
├── Package.swift
├── docker-compose.yml
├── Dockerfile
└── Package.resolved
└── Afternoon
├── final
├── Public
│ └── .gitkeep
├── Sources
│ ├── App
│ │ ├── Controllers
│ │ │ ├── .gitkeep
│ │ │ ├── LeafController.swift
│ │ │ ├── CategoriesControllers.swift
│ │ │ ├── ReminderController.swift
│ │ │ └── UserController.swift
│ │ ├── Migrations
│ │ │ ├── CreateCategory.swift
│ │ │ ├── CreateDefaultUser.swift
│ │ │ ├── CreateUser.swift
│ │ │ ├── CreateReminder.swift
│ │ │ ├── CreateToken.swift
│ │ │ └── CreateReminderCategoryPivot.swift
│ │ ├── Models
│ │ │ ├── Category.swift
│ │ │ ├── ReminderCategoryPivot.swift
│ │ │ ├── Reminder.swift
│ │ │ ├── Token.swift
│ │ │ └── User.swift
│ │ ├── configure.swift
│ │ └── routes.swift
│ └── Run
│ │ └── main.swift
├── .gitignore
├── Resources
│ └── Views
│ │ ├── base.leaf
│ │ └── index.leaf
├── Tests
│ └── AppTests
│ │ └── AppTests.swift
├── Package.swift
├── docker-compose.yml
├── Dockerfile
└── Package.resolved
└── starter
├── Public
└── .gitkeep
├── Sources
├── App
│ ├── Controllers
│ │ ├── .gitkeep
│ │ ├── CategoriesControllers.swift
│ │ ├── UserController.swift
│ │ └── ReminderController.swift
│ ├── Migrations
│ │ ├── CreateCategory.swift
│ │ ├── CreateUser.swift
│ │ ├── CreateReminder.swift
│ │ └── CreateReminderCategoryPivot.swift
│ ├── Models
│ │ ├── Category.swift
│ │ ├── ReminderCategoryPivot.swift
│ │ ├── User.swift
│ │ └── Reminder.swift
│ ├── configure.swift
│ └── routes.swift
└── Run
│ └── main.swift
├── .dockerignore
├── .gitignore
├── Tests
└── AppTests
│ └── AppTests.swift
├── Package.swift
├── docker-compose.yml
├── Dockerfile
└── Package.resolved
/Day1/Morning/Public/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Day1/Afternoon/final/Public/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Day1/Afternoon/starter/Public/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Day1/Morning/Sources/App/Controllers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Day1/Afternoon/final/Sources/App/Controllers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Day1/Morning/.dockerignore:
--------------------------------------------------------------------------------
1 | .build/
2 | .swiftpm/
3 |
--------------------------------------------------------------------------------
/Day1/Afternoon/starter/Sources/App/Controllers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Day1/Afternoon/starter/.dockerignore:
--------------------------------------------------------------------------------
1 | .git
2 | .build
3 | DerivedData
4 | Package.resolved
5 | *.xcodeproj
6 |
7 |
--------------------------------------------------------------------------------
/Day1/Afternoon/starter/.gitignore:
--------------------------------------------------------------------------------
1 | Packages
2 | .build
3 | xcuserdata
4 | *.xcodeproj
5 | DerivedData/
6 | .DS_Store
7 | .swiftpm
8 |
--------------------------------------------------------------------------------
/Day1/Morning/.gitignore:
--------------------------------------------------------------------------------
1 | Packages
2 | .build
3 | xcuserdata
4 | *.xcodeproj
5 | DerivedData/
6 | .DS_Store
7 | db.sqlite
8 | .swiftpm
9 | .env
10 |
--------------------------------------------------------------------------------
/Day1/Afternoon/final/.gitignore:
--------------------------------------------------------------------------------
1 | Packages
2 | .build
3 | xcuserdata
4 | *.xcodeproj
5 | DerivedData/
6 | .DS_Store
7 | db.sqlite
8 | .swiftpm
9 | .env
10 |
--------------------------------------------------------------------------------
/Day1/Morning/Sources/Run/main.swift:
--------------------------------------------------------------------------------
1 | import App
2 | import Vapor
3 |
4 | var env = try Environment.detect()
5 | try LoggingSystem.bootstrap(from: &env)
6 | let app = Application(env)
7 | defer { app.shutdown() }
8 | try configure(app)
9 | try app.run()
10 |
--------------------------------------------------------------------------------
/Day1/Afternoon/final/Sources/Run/main.swift:
--------------------------------------------------------------------------------
1 | import App
2 | import Vapor
3 |
4 | var env = try Environment.detect()
5 | try LoggingSystem.bootstrap(from: &env)
6 | let app = Application(env)
7 | defer { app.shutdown() }
8 | try configure(app)
9 | try app.run()
10 |
--------------------------------------------------------------------------------
/Day1/Afternoon/starter/Sources/Run/main.swift:
--------------------------------------------------------------------------------
1 | import App
2 | import Vapor
3 |
4 | var env = try Environment.detect()
5 | try LoggingSystem.bootstrap(from: &env)
6 | let app = Application(env)
7 | defer { app.shutdown() }
8 | try configure(app)
9 | try app.run()
10 |
--------------------------------------------------------------------------------
/Day1/Afternoon/final/Resources/Views/base.leaf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | #(title) | Reminders
7 |
8 |
9 |
10 | #import("content")
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Day1/Morning/Tests/AppTests/AppTests.swift:
--------------------------------------------------------------------------------
1 | @testable import App
2 | import XCTVapor
3 |
4 | final class AppTests: XCTestCase {
5 | func testHelloWorld() throws {
6 | let app = Application(.testing)
7 | defer { app.shutdown() }
8 | try configure(app)
9 |
10 | try app.test(.GET, "hello", afterResponse: { res in
11 | XCTAssertEqual(res.status, .ok)
12 | XCTAssertEqual(res.body.string, "Hello, world!")
13 | })
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Day1/Afternoon/final/Tests/AppTests/AppTests.swift:
--------------------------------------------------------------------------------
1 | @testable import App
2 | import XCTVapor
3 |
4 | final class AppTests: XCTestCase {
5 | func testHelloWorld() throws {
6 | let app = Application(.testing)
7 | defer { app.shutdown() }
8 | try configure(app)
9 |
10 | try app.test(.GET, "hello", afterResponse: { res in
11 | XCTAssertEqual(res.status, .ok)
12 | XCTAssertEqual(res.body.string, "Hello, world!")
13 | })
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Day1/Afternoon/starter/Tests/AppTests/AppTests.swift:
--------------------------------------------------------------------------------
1 | @testable import App
2 | import XCTVapor
3 |
4 | final class AppTests: XCTestCase {
5 | func testHelloWorld() throws {
6 | let app = Application(.testing)
7 | defer { app.shutdown() }
8 | try configure(app)
9 |
10 | try app.test(.GET, "hello", afterResponse: { res in
11 | XCTAssertEqual(res.status, .ok)
12 | XCTAssertEqual(res.body.string, "Hello, world!")
13 | })
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Day1/Morning/Sources/App/Migrations/CreateCategory.swift:
--------------------------------------------------------------------------------
1 | import Fluent
2 |
3 | struct CreateCategory: AsyncMigration {
4 | func prepare(on database: Database) async throws {
5 | try await database.schema("categories")
6 | .field("id", .int, .identifier(auto: true))
7 | .field("name", .string, .required)
8 | .create()
9 | }
10 |
11 | func revert(on database: Database) async throws {
12 | try await database.schema("categories").delete()
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Day1/Morning/Sources/App/Migrations/CreateUser.swift:
--------------------------------------------------------------------------------
1 | import Fluent
2 |
3 | struct CreateUser: AsyncMigration {
4 | func prepare(on database: Database) async throws {
5 | try await database.schema("users")
6 | .id()
7 | .field("name", .string, .required)
8 | .field("username", .string, .required)
9 | .create()
10 | }
11 |
12 | func revert(on database: Database) async throws {
13 | try await database.schema("users").delete()
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Day1/Afternoon/final/Sources/App/Migrations/CreateCategory.swift:
--------------------------------------------------------------------------------
1 | import Fluent
2 |
3 | struct CreateCategory: AsyncMigration {
4 | func prepare(on database: Database) async throws {
5 | try await database.schema("categories")
6 | .field("id", .int, .identifier(auto: true))
7 | .field("name", .string, .required)
8 | .create()
9 | }
10 |
11 | func revert(on database: Database) async throws {
12 | try await database.schema("categories").delete()
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Day1/Afternoon/starter/Sources/App/Migrations/CreateCategory.swift:
--------------------------------------------------------------------------------
1 | import Fluent
2 |
3 | struct CreateCategory: AsyncMigration {
4 | func prepare(on database: Database) async throws {
5 | try await database.schema("categories")
6 | .field("id", .int, .identifier(auto: true))
7 | .field("name", .string, .required)
8 | .create()
9 | }
10 |
11 | func revert(on database: Database) async throws {
12 | try await database.schema("categories").delete()
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Day1/Afternoon/starter/Sources/App/Migrations/CreateUser.swift:
--------------------------------------------------------------------------------
1 | import Fluent
2 |
3 | struct CreateUser: AsyncMigration {
4 | func prepare(on database: Database) async throws {
5 | try await database.schema("users")
6 | .id()
7 | .field("name", .string, .required)
8 | .field("username", .string, .required)
9 | .create()
10 | }
11 |
12 | func revert(on database: Database) async throws {
13 | try await database.schema("users").delete()
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Day1/Afternoon/final/Sources/App/Migrations/CreateDefaultUser.swift:
--------------------------------------------------------------------------------
1 | import Vapor
2 | import Fluent
3 |
4 | struct CreateDefaultUser: AsyncMigration {
5 | func prepare(on database: Database) async throws {
6 | let password = try Bcrypt.hash("password")
7 | let user = User(name: "default", username: "default", passwordHash: password)
8 | try await user.create(on: database)
9 | }
10 |
11 | func revert(on database: any Database) async throws {
12 | try await User.query(on: database).filter(\.$username == "default").delete()
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Day1/Afternoon/final/Sources/App/Migrations/CreateUser.swift:
--------------------------------------------------------------------------------
1 | import Fluent
2 |
3 | struct CreateUser: AsyncMigration {
4 | func prepare(on database: Database) async throws {
5 | try await database.schema("users")
6 | .id()
7 | .field("name", .string, .required)
8 | .field("username", .string, .required)
9 | .field("passwordHash", .string, .required)
10 | .create()
11 | }
12 |
13 | func revert(on database: Database) async throws {
14 | try await database.schema("users").delete()
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Day1/Morning/Sources/App/Migrations/CreateReminder.swift:
--------------------------------------------------------------------------------
1 | import Fluent
2 |
3 | struct CreateReminder: AsyncMigration {
4 | func prepare(on database: Database) async throws {
5 | try await database.schema("reminders")
6 | .id()
7 | .field("title", .string, .required)
8 | .field("userID", .uuid, .required,
9 | .references("users", "id"))
10 | .create()
11 | }
12 |
13 | func revert(on database: Database) async throws {
14 | try await database.schema("reminders").delete()
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Day1/Morning/Sources/App/Models/ReminderCategoryPivot.swift:
--------------------------------------------------------------------------------
1 | import Fluent
2 |
3 | final class ReminderCategoryPivot: Model {
4 | static let schema = "reminder+category"
5 |
6 | @ID
7 | var id: UUID?
8 |
9 | @Parent(key: "reminderID")
10 | var reminder: Reminder
11 |
12 | @Parent(key: "categoryID")
13 | var category: Category
14 |
15 | init() {}
16 |
17 | init(reminderID: Reminder.IDValue, categoryID: Category.IDValue) {
18 | self.$reminder.id = reminderID
19 | self.$category.id = categoryID
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Day1/Afternoon/final/Sources/App/Migrations/CreateReminder.swift:
--------------------------------------------------------------------------------
1 | import Fluent
2 |
3 | struct CreateReminder: AsyncMigration {
4 | func prepare(on database: Database) async throws {
5 | try await database.schema("reminders")
6 | .id()
7 | .field("title", .string, .required)
8 | .field("userID", .uuid, .required,
9 | .references("users", "id"))
10 | .create()
11 | }
12 |
13 | func revert(on database: Database) async throws {
14 | try await database.schema("reminders").delete()
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Day1/Afternoon/starter/Sources/App/Migrations/CreateReminder.swift:
--------------------------------------------------------------------------------
1 | import Fluent
2 |
3 | struct CreateReminder: AsyncMigration {
4 | func prepare(on database: Database) async throws {
5 | try await database.schema("reminders")
6 | .id()
7 | .field("title", .string, .required)
8 | .field("userID", .uuid, .required,
9 | .references("users", "id"))
10 | .create()
11 | }
12 |
13 | func revert(on database: Database) async throws {
14 | try await database.schema("reminders").delete()
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Day1/Morning/Sources/App/Models/Category.swift:
--------------------------------------------------------------------------------
1 | import Fluent
2 | import Vapor
3 |
4 | final class Category: Model, Content {
5 | static let schema = "categories"
6 |
7 | @ID(custom: "id")
8 | var id: Int?
9 |
10 | @Field(key: "name")
11 | var name: String
12 |
13 | @Siblings(through: ReminderCategoryPivot.self,
14 | from: \.$category, to: \.$reminder)
15 | var reminders: [Reminder]
16 |
17 | init() {}
18 |
19 | init(id: Int? = nil, name: String) {
20 | self.id = id
21 | self.name = name
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Day1/Afternoon/final/Resources/Views/index.leaf:
--------------------------------------------------------------------------------
1 | #extend("base"):
2 | #export("content"):
3 | Reminders
4 | #if(count(reminders) > 0):
5 |
6 | | Number | Title |
7 |
8 | #for(reminder in reminders):
9 | | #(reminder.id) | #(reminder.title) |
10 | #endfor
11 |
12 |
13 | #else:
14 | You haven't created any reminder yet!
15 | #endif
16 |