Skip to content

Commit 64e959b

Browse files
committed
TodoListServer
Signed-off-by: Mike Packard <nguyenphong.mobile.engineer@gmail.com>
0 parents  commit 64e959b

File tree

17 files changed

+626
-0
lines changed

17 files changed

+626
-0
lines changed

.dockerignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.build/
2+
.swiftpm/

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Packages
2+
.build
3+
xcuserdata
4+
*.xcodeproj
5+
DerivedData/
6+
.DS_Store
7+
db.sqlite
8+
.swiftpm
9+

Dockerfile

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# ================================
2+
# Build image
3+
# ================================
4+
FROM swift:5.5-focal as build
5+
6+
# Install OS updates and, if needed, sqlite3
7+
RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \
8+
&& apt-get -q update \
9+
&& apt-get -q dist-upgrade -y \
10+
&& rm -rf /var/lib/apt/lists/*
11+
12+
# Set up a build area
13+
WORKDIR /build
14+
15+
# First just resolve dependencies.
16+
# This creates a cached layer that can be reused
17+
# as long as your Package.swift/Package.resolved
18+
# files do not change.
19+
COPY ./Package.* ./
20+
RUN swift package resolve
21+
22+
# Copy entire repo into container
23+
COPY . .
24+
25+
# Build everything, with optimizations
26+
RUN swift build -c release
27+
28+
# Switch to the staging area
29+
WORKDIR /staging
30+
31+
# Copy main executable to staging area
32+
RUN cp "$(swift build --package-path /build -c release --show-bin-path)/Run" ./
33+
34+
# Copy any resources from the public directory and views directory if the directories exist
35+
# Ensure that by default, neither the directory nor any of its contents are writable.
36+
RUN [ -d /build/Public ] && { mv /build/Public ./Public && chmod -R a-w ./Public; } || true
37+
RUN [ -d /build/Resources ] && { mv /build/Resources ./Resources && chmod -R a-w ./Resources; } || true
38+
39+
# ================================
40+
# Run image
41+
# ================================
42+
FROM swift:5.5-focal-slim
43+
44+
# Make sure all system packages are up to date.
45+
RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true && \
46+
apt-get -q update && apt-get -q dist-upgrade -y && rm -r /var/lib/apt/lists/*
47+
48+
# Create a vapor user and group with /app as its home directory
49+
RUN useradd --user-group --create-home --system --skel /dev/null --home-dir /app vapor
50+
51+
# Switch to the new home directory
52+
WORKDIR /app
53+
54+
# Copy built executable and any staged resources from builder
55+
COPY --from=build --chown=vapor:vapor /staging /app
56+
57+
# Ensure all further commands run as the vapor user
58+
USER vapor:vapor
59+
60+
# Let Docker bind to port 8080
61+
EXPOSE 8080
62+
63+
# Start the Vapor service when the image is run, default to listening on 8080 in production environment
64+
ENTRYPOINT ["./Run"]
65+
CMD ["serve", "--env", "production", "--hostname", "0.0.0.0", "--port", "8080"]

Package.resolved

Lines changed: 223 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// swift-tools-version:5.5
2+
import PackageDescription
3+
4+
let package = Package(
5+
name: "TodoListServer",
6+
platforms: [
7+
.macOS(.v10_15)
8+
],
9+
dependencies: [
10+
// 💧 A server-side Swift web framework.
11+
.package(url: "https://github.com/vapor/vapor.git", from: "4.0.0"),
12+
.package(url: "https://github.com/vapor/fluent.git", from: "4.0.0"),
13+
.package(url: "https://github.com/vapor/fluent-postgres-driver.git", from: "2.0.0"),
14+
.package(url: "https://github.com/vapor/leaf.git", from: "4.0.0"),
15+
],
16+
targets: [
17+
.target(
18+
name: "App",
19+
dependencies: [
20+
.product(name: "Fluent", package: "fluent"),
21+
.product(name: "FluentPostgresDriver", package: "fluent-postgres-driver"),
22+
.product(name: "Leaf", package: "leaf"),
23+
.product(name: "Vapor", package: "vapor")
24+
],
25+
swiftSettings: [
26+
// Enable better optimizations when building in Release configuration. Despite the use of
27+
// the `.unsafeFlags` construct required by SwiftPM, this flag is recommended for Release
28+
// builds. See <https://github.com/swift-server/guides/blob/main/docs/building.md#building-for-production> for details.
29+
.unsafeFlags(["-cross-module-optimization"], .when(configuration: .release))
30+
]
31+
),
32+
.executableTarget(name: "Run", dependencies: [.target(name: "App")]),
33+
.testTarget(name: "AppTests", dependencies: [
34+
.target(name: "App"),
35+
.product(name: "XCTVapor", package: "vapor"),
36+
])
37+
]
38+
)

Procfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
web: Run serve --env production --hostname 0.0.0.0 --port $PORT

Resources/Views/index.leaf

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
6+
<title>#(title)</title>
7+
</head>
8+
9+
<body>
10+
<h1>#(title)</h1>
11+
</body>
12+
</html>

Sources/App/Controllers/.gitkeep

Whitespace-only changes.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import Fluent
2+
import Vapor
3+
4+
//Todo Route
5+
struct TodoController: RouteCollection {
6+
func boot(routes: RoutesBuilder) throws {
7+
let todos = routes.grouped("todos")
8+
todos.get(use: index)
9+
todos.post(use: create)
10+
todos.delete(":todoID", use: delete(req:))
11+
todos.post(":todoID", use: update(req:))
12+
}
13+
// read all todos
14+
func index(req: Request) throws -> EventLoopFuture<[Todo]> {
15+
return Todo.query(on: req.db).all()
16+
}
17+
/// create or update the todo
18+
func create(req: Request) throws -> EventLoopFuture<Todo> {
19+
let todo = try req.content.decode(Todo.self)
20+
return todo.save(on: req.db).map { todo }
21+
}
22+
/// update the todo
23+
func update(req: Request) throws -> EventLoopFuture<Todo> {
24+
let update = try req.content.decode(Todo.self)
25+
return Todo.find(req.parameters.get("todoID"), on: req.db).unwrap(or: Abort(.notFound)).flatMap { todo in
26+
todo.isCompleted = update.isCompleted
27+
todo.title = update.title
28+
return todo.save(on: req.db).map({update})
29+
}
30+
}
31+
/// delete the todo
32+
func delete(req: Request) throws -> EventLoopFuture<Todo> {
33+
return Todo.find(req.parameters.get("todoID"), on: req.db)
34+
.unwrap(or: Abort(.notFound))
35+
.flatMap { todo in
36+
todo.delete(on: req.db).map {todo} }
37+
}
38+
}

0 commit comments

Comments
 (0)