diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..eae830c
Binary files /dev/null and b/.DS_Store differ
diff --git a/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..919434a
--- /dev/null
+++ b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/.swiftpm/xcode/package.xcworkspace/xcuserdata/michielcarman.xcuserdatad/UserInterfaceState.xcuserstate b/.swiftpm/xcode/package.xcworkspace/xcuserdata/michielcarman.xcuserdatad/UserInterfaceState.xcuserstate
new file mode 100644
index 0000000..f5ed618
Binary files /dev/null and b/.swiftpm/xcode/package.xcworkspace/xcuserdata/michielcarman.xcuserdatad/UserInterfaceState.xcuserstate differ
diff --git a/.swiftpm/xcode/xcuserdata/michielcarman.xcuserdatad/xcschemes/xcschememanagement.plist b/.swiftpm/xcode/xcuserdata/michielcarman.xcuserdatad/xcschemes/xcschememanagement.plist
new file mode 100644
index 0000000..f5003f8
--- /dev/null
+++ b/.swiftpm/xcode/xcuserdata/michielcarman.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -0,0 +1,14 @@
+
+
+
+
+ SchemeUserState
+
+ Fueling.xcscheme_^#shared#^_
+
+ orderHint
+ 0
+
+
+
+
diff --git a/Dockerfile b/Dockerfile
new file mode 100755
index 0000000..e3bde89
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,77 @@
+# ================================
+# Build image
+# ================================
+FROM swift:5.8-jammy as build
+
+# Install OS updates and, if needed, sqlite3
+RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \
+ && apt-get -q update \
+ && apt-get -q dist-upgrade -y\
+ && rm -rf /var/lib/apt/lists/*
+
+# Set up a build area
+WORKDIR /build
+
+# First just resolve dependencies.
+# This creates a cached layer that can be reused
+# as long as your Package.swift/Package.resolved
+# files do not change.
+COPY ./Package.* ./
+RUN swift package resolve
+
+# Copy entire repo into container
+COPY . .
+
+# Build everything, with optimizations
+RUN swift build -c release --static-swift-stdlib
+
+# Switch to the staging area
+WORKDIR /staging
+
+# Copy main executable to staging area
+RUN cp "$(swift build --package-path /build -c release --show-bin-path)/App" ./
+
+# Copy resources bundled by SPM to staging area
+RUN find -L "$(swift build --package-path /build -c release --show-bin-path)/" -regex '.*\.resources$' -exec cp -Ra {} ./ \;
+
+# Copy any resources from the public directory and views directory if the directories exist
+# Ensure that by default, neither the directory nor any of its contents are writable.
+RUN [ -d /build/Public ] && { mv /build/Public ./Public && chmod -R a-w ./Public; } || true
+RUN [ -d /build/Resources ] && { mv /build/Resources ./Resources && chmod -R a-w ./Resources; } || true
+
+# ================================
+# Run image
+# ================================
+FROM ubuntu:jammy
+
+# Make sure all system packages are up to date, and install only essential packages.
+RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \
+ && apt-get -q update \
+ && apt-get -q dist-upgrade -y \
+ && apt-get -q install -y \
+ ca-certificates \
+ tzdata \
+# If your app or its dependencies import FoundationNetworking, also install `libcurl4`.
+ # libcurl4 \
+# If your app or its dependencies import FoundationXML, also install `libxml2`.
+ # libxml2 \
+ && rm -r /var/lib/apt/lists/*
+
+# Create a vapor user and group with /app as its home directory
+RUN useradd --user-group --create-home --system --skel /dev/null --home-dir /app vapor
+
+# Switch to the new home directory
+WORKDIR /app
+
+# Copy built executable and any staged resources from builder
+COPY --from=build --chown=vapor:vapor /staging /app
+
+# Ensure all further commands run as the vapor user
+USER vapor:vapor
+
+# Let Docker bind to port 8080
+EXPOSE 8080
+
+# Start the Vapor service when the image is run, default to listening on 8080 in production environment
+ENTRYPOINT ["./App"]
+CMD ["serve", "--env", "production", "--hostname", "0.0.0.0", "--port", "8080"]
diff --git a/Package.resolved b/Package.resolved
new file mode 100755
index 0000000..8b97df4
--- /dev/null
+++ b/Package.resolved
@@ -0,0 +1,239 @@
+{
+ "pins" : [
+ {
+ "identity" : "async-http-client",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/swift-server/async-http-client.git",
+ "state" : {
+ "revision" : "333e60cc90f52973f7ee29cd8e3a7f6adfe79f4e",
+ "version" : "1.17.0"
+ }
+ },
+ {
+ "identity" : "async-kit",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/vapor/async-kit.git",
+ "state" : {
+ "revision" : "a61da00d404ec91d12766f1b9aac7d90777b484d",
+ "version" : "1.17.0"
+ }
+ },
+ {
+ "identity" : "console-kit",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/vapor/console-kit.git",
+ "state" : {
+ "revision" : "447f1046fb4e9df40973fe426ecb24a6f0e8d3b4",
+ "version" : "4.6.0"
+ }
+ },
+ {
+ "identity" : "fluent",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/vapor/fluent.git",
+ "state" : {
+ "revision" : "4b4d8bf15a06fd60137e9c543e5503c4b842654e",
+ "version" : "4.8.0"
+ }
+ },
+ {
+ "identity" : "fluent-kit",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/vapor/fluent-kit.git",
+ "state" : {
+ "revision" : "559dc9c730cde77cc9dac76fba73d6e0855f0220",
+ "version" : "1.42.0"
+ }
+ },
+ {
+ "identity" : "fluent-postgres-driver",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/vapor/fluent-postgres-driver.git",
+ "state" : {
+ "revision" : "afc07463fc5589f5bf95f98ae2719d13ad9fbbcf",
+ "version" : "2.6.0"
+ }
+ },
+ {
+ "identity" : "multipart-kit",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/vapor/multipart-kit.git",
+ "state" : {
+ "revision" : "1adfd69df2da08f7931d4281b257475e32c96734",
+ "version" : "4.5.4"
+ }
+ },
+ {
+ "identity" : "postgres-kit",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/vapor/postgres-kit.git",
+ "state" : {
+ "revision" : "3ad08265aade48fff5f2ec772e96ecf51b7900a2",
+ "version" : "2.10.0"
+ }
+ },
+ {
+ "identity" : "postgres-nio",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/vapor/postgres-nio.git",
+ "state" : {
+ "revision" : "98b8e1b1488c706f8bff9eb07560745630a64679",
+ "version" : "1.14.0"
+ }
+ },
+ {
+ "identity" : "routing-kit",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/vapor/routing-kit.git",
+ "state" : {
+ "revision" : "611bc45c5dfb1f54b84d99b89d1f72191fb6b71b",
+ "version" : "4.7.2"
+ }
+ },
+ {
+ "identity" : "sql-kit",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/vapor/sql-kit.git",
+ "state" : {
+ "revision" : "d547122756534d8224d4599739da0e82e4695623",
+ "version" : "3.25.0"
+ }
+ },
+ {
+ "identity" : "swift-algorithms",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/apple/swift-algorithms.git",
+ "state" : {
+ "revision" : "b14b7f4c528c942f121c8b860b9410b2bf57825e",
+ "version" : "1.0.0"
+ }
+ },
+ {
+ "identity" : "swift-atomics",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/apple/swift-atomics.git",
+ "state" : {
+ "revision" : "6c89474e62719ddcc1e9614989fff2f68208fe10",
+ "version" : "1.1.0"
+ }
+ },
+ {
+ "identity" : "swift-backtrace",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/swift-server/swift-backtrace.git",
+ "state" : {
+ "revision" : "f25620d5d05e2f1ba27154b40cafea2b67566956",
+ "version" : "1.3.3"
+ }
+ },
+ {
+ "identity" : "swift-collections",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/apple/swift-collections.git",
+ "state" : {
+ "revision" : "937e904258d22af6e447a0b72c0bc67583ef64a2",
+ "version" : "1.0.4"
+ }
+ },
+ {
+ "identity" : "swift-crypto",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/apple/swift-crypto.git",
+ "state" : {
+ "revision" : "33a20e650c33f6d72d822d558333f2085effa3dc",
+ "version" : "2.5.0"
+ }
+ },
+ {
+ "identity" : "swift-log",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/apple/swift-log.git",
+ "state" : {
+ "revision" : "32e8d724467f8fe623624570367e3d50c5638e46",
+ "version" : "1.5.2"
+ }
+ },
+ {
+ "identity" : "swift-metrics",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/apple/swift-metrics.git",
+ "state" : {
+ "revision" : "e8bced74bc6d747745935e469f45d03f048d6cbd",
+ "version" : "2.3.4"
+ }
+ },
+ {
+ "identity" : "swift-nio",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/apple/swift-nio.git",
+ "state" : {
+ "revision" : "f7c46552983b06b0958a1a4c8bc5199406ae4c8a",
+ "version" : "2.51.0"
+ }
+ },
+ {
+ "identity" : "swift-nio-extras",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/apple/swift-nio-extras.git",
+ "state" : {
+ "revision" : "0e0d0aab665ff1a0659ce75ac003081f2b1c8997",
+ "version" : "1.19.0"
+ }
+ },
+ {
+ "identity" : "swift-nio-http2",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/apple/swift-nio-http2.git",
+ "state" : {
+ "revision" : "6d021a48483dbb273a9be43f65234bdc9185b364",
+ "version" : "1.26.0"
+ }
+ },
+ {
+ "identity" : "swift-nio-ssl",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/apple/swift-nio-ssl.git",
+ "state" : {
+ "revision" : "9d0d5d8798a576fbf674a823734e65e15ca5f2ec",
+ "version" : "2.23.1"
+ }
+ },
+ {
+ "identity" : "swift-nio-transport-services",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/apple/swift-nio-transport-services.git",
+ "state" : {
+ "revision" : "59b966415dd336db6f388bbfe3fb43cfa549b981",
+ "version" : "1.16.0"
+ }
+ },
+ {
+ "identity" : "swift-numerics",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/apple/swift-numerics",
+ "state" : {
+ "revision" : "0a5bc04095a675662cf24757cc0640aa2204253b",
+ "version" : "1.0.2"
+ }
+ },
+ {
+ "identity" : "vapor",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/vapor/vapor.git",
+ "state" : {
+ "revision" : "f4b00a5350238fe896d865d96d64f12fcbbeda95",
+ "version" : "4.76.0"
+ }
+ },
+ {
+ "identity" : "websocket-kit",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/vapor/websocket-kit.git",
+ "state" : {
+ "revision" : "2166cbe932b29b6419f9cd751e8b27c647e1238e",
+ "version" : "2.8.0"
+ }
+ }
+ ],
+ "version" : 2
+}
diff --git a/Package.swift b/Package.swift
new file mode 100755
index 0000000..732222e
--- /dev/null
+++ b/Package.swift
@@ -0,0 +1,35 @@
+// swift-tools-version:5.8
+import PackageDescription
+
+let package = Package(
+ name: "Fueling",
+ platforms: [
+ .macOS(.v12)
+ ],
+ dependencies: [
+ // 💧 A server-side Swift web framework.
+ .package(url: "https://github.com/vapor/vapor.git", from: "4.76.0"),
+ .package(url: "https://github.com/vapor/fluent.git", from: "4.8.0"),
+ .package(url: "https://github.com/vapor/fluent-postgres-driver.git", from: "2.0.0"),
+ ],
+ targets: [
+ .executableTarget(
+ name: "App",
+ dependencies: [
+ .product(name: "Fluent", package: "fluent"),
+ .product(name: "FluentPostgresDriver", package: "fluent-postgres-driver"),
+ .product(name: "Vapor", package: "vapor")
+ ],
+ swiftSettings: [
+ // Enable better optimizations when building in Release configuration. Despite the use of
+ // the `.unsafeFlags` construct required by SwiftPM, this flag is recommended for Release
+ // builds. See for details.
+ .unsafeFlags(["-cross-module-optimization"], .when(configuration: .release))
+ ]
+ ),
+ .testTarget(name: "AppTests", dependencies: [
+ .target(name: "App"),
+ .product(name: "XCTVapor", package: "vapor"),
+ ])
+ ]
+)
diff --git a/Public/.gitkeep b/Public/.gitkeep
new file mode 100755
index 0000000..e69de29
diff --git a/Sources/.DS_Store b/Sources/.DS_Store
new file mode 100755
index 0000000..d424cbc
Binary files /dev/null and b/Sources/.DS_Store differ
diff --git a/Sources/App/.DS_Store b/Sources/App/.DS_Store
new file mode 100755
index 0000000..a1c20a6
Binary files /dev/null and b/Sources/App/.DS_Store differ
diff --git a/Sources/App/Controllers/.gitkeep b/Sources/App/Controllers/.gitkeep
new file mode 100755
index 0000000..e69de29
diff --git a/Sources/App/Controllers/FuelEntryController.swift b/Sources/App/Controllers/FuelEntryController.swift
new file mode 100755
index 0000000..fa8e6b9
--- /dev/null
+++ b/Sources/App/Controllers/FuelEntryController.swift
@@ -0,0 +1,41 @@
+//
+// FuelEntryController.swift
+//
+//
+// Created by Bill Ryckman on 4/24/23.
+//
+
+import Vapor
+
+struct FuelEntryController: RouteCollection {
+ func boot(routes: RoutesBuilder) throws {
+ let fuelEntries = routes.grouped("fuel_entries")
+ fuelEntries.get(use: index)
+ fuelEntries.post(use: create)
+ fuelEntries.group(":fuelEntryID") { fuelEntry in
+ fuelEntry.delete(use: delete)
+ }
+ }
+
+ func index(req: Request) async throws -> [FuelEntry] {
+ try await FuelEntry.query(on: req.db).all()
+ }
+
+ func create(req: Request) async throws -> FuelEntry {
+ let fuelEntry = try req.content.decode(FuelEntry.self)
+ try await fuelEntry.save(on: req.db)
+ return fuelEntry
+ }
+
+ func delete(req: Request) async throws -> HTTPStatus {
+ guard let fuelEntry = try await FuelEntry.find(req.parameters.get("fuelEntryID"), on: req.db) else {
+ throw Abort(.notFound)
+ }
+ try await fuelEntry.delete(on: req.db)
+ return .noContent
+ }
+}
+
+
+
+
diff --git a/Sources/App/Controllers/TodoController.swift b/Sources/App/Controllers/TodoController.swift
new file mode 100755
index 0000000..265228d
--- /dev/null
+++ b/Sources/App/Controllers/TodoController.swift
@@ -0,0 +1,31 @@
+import Fluent
+import Vapor
+
+struct TodoController: RouteCollection {
+ func boot(routes: RoutesBuilder) throws {
+ let todos = routes.grouped("todos")
+ todos.get(use: index)
+ todos.post(use: create)
+ todos.group(":todoID") { todo in
+ todo.delete(use: delete)
+ }
+ }
+
+ func index(req: Request) async throws -> [Todo] {
+ try await Todo.query(on: req.db).all()
+ }
+
+ func create(req: Request) async throws -> Todo {
+ let todo = try req.content.decode(Todo.self)
+ try await todo.save(on: req.db)
+ return todo
+ }
+
+ func delete(req: Request) async throws -> HTTPStatus {
+ guard let todo = try await Todo.find(req.parameters.get("todoID"), on: req.db) else {
+ throw Abort(.notFound)
+ }
+ try await todo.delete(on: req.db)
+ return .noContent
+ }
+}
diff --git a/Sources/App/Migrations/CreateFuelEntry.swift b/Sources/App/Migrations/CreateFuelEntry.swift
new file mode 100755
index 0000000..1b61d55
--- /dev/null
+++ b/Sources/App/Migrations/CreateFuelEntry.swift
@@ -0,0 +1,34 @@
+//
+// File.swift
+//
+//
+// Created by Bill Ryckman on 4/26/23.
+//
+
+import Vapor
+import Fluent
+
+struct CreateFuelEntry: AsyncMigration {
+ func prepare(on database: Database) async throws {
+ try await database.schema("fuel_entries")
+ .id()
+ .field("timestamp", .datetime)
+ .field("user_id", .string)
+ .field("gps_location", .string)
+ .field("image", .string)
+ .field("product", .string)
+ .field("make", .string)
+ .field("model", .string)
+ .field("serial_number", .string)
+ .field("tank_id", .string)
+ .field("fuel_amount", .double)
+ .field("fuel_type", .string)
+ .field("is_override", .bool)
+ .create()
+ }
+
+ func revert(on database: Database) async throws {
+ try await database.schema("fuel_entries").delete()
+ }
+}
+
diff --git a/Sources/App/Migrations/CreateTodo.swift b/Sources/App/Migrations/CreateTodo.swift
new file mode 100755
index 0000000..bf6d945
--- /dev/null
+++ b/Sources/App/Migrations/CreateTodo.swift
@@ -0,0 +1,14 @@
+import Fluent
+
+struct CreateTodo: AsyncMigration {
+ func prepare(on database: Database) async throws {
+ try await database.schema("todos")
+ .id()
+ .field("title", .string, .required)
+ .create()
+ }
+
+ func revert(on database: Database) async throws {
+ try await database.schema("todos").delete()
+ }
+}
diff --git a/Sources/App/Models/FuelEntry.swift b/Sources/App/Models/FuelEntry.swift
new file mode 100755
index 0000000..073d0ef
--- /dev/null
+++ b/Sources/App/Models/FuelEntry.swift
@@ -0,0 +1,105 @@
+//
+// FuelEntry.swift
+//
+//
+// Created by Bill Ryckman on 4/24/23.
+//
+
+import Fluent
+import Vapor
+
+final class FuelEntry: Model, Content {
+ static let schema = "fuel_entries"
+
+ @ID(key: .id)
+ var id: UUID?
+
+ @Field(key: "timestamp")
+ var timestamp: Date
+
+ @Field(key: "user_id")
+ var userID: String
+
+ @Field(key: "gps_location")
+ var gpsLocation: String
+
+ @Field(key: "image")
+ var image: String
+
+ @Field(key: "product")
+ var product: String
+
+ @Field(key: "make")
+ var make: String
+
+ @Field(key: "model")
+ var model: String
+
+ @Field(key: "serial_number")
+ var serialNumber: String
+
+ @Field(key: "tank_id")
+ var tankID: String
+
+ @Field(key: "fuel_amount")
+ var fuelAmount: Double
+
+ @Field(key: "fuel_type")
+ var fuelType: String
+
+ @Field(key: "is_override")
+ var isOverride: Bool
+
+ init() {}
+
+ init(id: UUID? = nil, timestamp: Date, userID: String, gpsLocation: String, image: String, product: String, make: String, model: String, serialNumber: String, tankID: String, fuelAmount: Double, fuelType: String, isOverride: Bool) {
+ self.id = id
+ self.timestamp = timestamp
+ self.userID = userID
+ self.gpsLocation = gpsLocation
+ self.image = image
+ self.product = product
+ self.make = make
+ self.model = model
+ self.serialNumber = serialNumber
+ self.tankID = tankID
+ self.fuelAmount = fuelAmount
+ self.fuelType = fuelType
+ self.isOverride = isOverride
+ }
+}
+
+
+//extension FuelEntry: Content {}
+//extension FuelEntry: Migration {
+// func prepare(on database: FluentKit.Database) -> NIOCore.EventLoopFuture {
+// <#code#>
+// }
+//
+// func revert(on database: FluentKit.Database) -> NIOCore.EventLoopFuture {
+// <#code#>
+// }
+// func prepare(on database: Database) -> EventLoopFuture {
+// return database.schema("fuel_entries")
+// .id()
+// .field("timestamp", .datetime)
+// .field("user_id", .string)
+// .field("gps_location", .string)
+// .field("image", .string)
+// .field("product", .string)
+// .field("make", .string)
+// .field("model", .string)
+// .field("serial_number", .string)
+// .field("tank_id", .string)
+// .field("fuel_amount", .double)
+// .field("fuel_type", .string)
+// .field("is_override", .bool)
+// .create()
+// }
+//
+// func revert(on database: Database) -> EventLoopFuture {
+// return database.schema("fuel_entries").delete()
+// }
+//}
+//extension FuelEntry: Parameter {}
+
diff --git a/Sources/App/Models/Todo.swift b/Sources/App/Models/Todo.swift
new file mode 100755
index 0000000..c3c9eac
--- /dev/null
+++ b/Sources/App/Models/Todo.swift
@@ -0,0 +1,19 @@
+import Fluent
+import Vapor
+
+final class Todo: Model, Content {
+ static let schema = "todos"
+
+ @ID(key: .id)
+ var id: UUID?
+
+ @Field(key: "title")
+ var title: String
+
+ init() { }
+
+ init(id: UUID? = nil, title: String) {
+ self.id = id
+ self.title = title
+ }
+}
diff --git a/Sources/App/configure.swift b/Sources/App/configure.swift
new file mode 100755
index 0000000..63e3a31
--- /dev/null
+++ b/Sources/App/configure.swift
@@ -0,0 +1,29 @@
+import Fluent
+import FluentPostgresDriver
+import Vapor
+
+// configures your application
+public func configure(_ app: Application) async throws {
+ // uncomment to serve files from /Public folder
+ // app.middleware.use(FileMiddleware(publicDirectory: app.directory.publicDirectory))
+
+ app.databases.use(.postgres(hostname: "localhost", username: "mcarman", password: "@ng31F@rm0823262", database: "fueling"), as: .psql)
+
+// app.databases.use(.postgres(
+// hostname: Environment.get("localhost") ?? "localhost",
+// port: Environment.get("5432").flatMap(Int.init(_:)) ?? PostgresConfiguration.ianaPortNumber,
+// username: Environment.get("mcarman") ?? "vapor_username",
+// //username: Environment.get("bryckman") ?? "vapor_username",
+// password: Environment.get("@ng31F@rm0823262" ?? "vapor_password"),
+// //password: Environment.get("55H1ck0ry1669") ?? "vapor_password",
+// database: Environment.get("fueling") ?? "vapor_database"
+// ), as: .psql)
+ app.http.server.configuration.port = 3001
+
+// app.migrations.add(CreateTodo())
+ app.migrations.add(CreateFuelEntry())
+ try await app.autoMigrate().get()
+
+ // register routes
+ try routes(app)
+}
diff --git a/Sources/App/entrypoint.swift b/Sources/App/entrypoint.swift
new file mode 100755
index 0000000..cae6165
--- /dev/null
+++ b/Sources/App/entrypoint.swift
@@ -0,0 +1,35 @@
+import Vapor
+import Dispatch
+import Logging
+
+/// This extension is temporary and can be removed once Vapor gets this support.
+private extension Vapor.Application {
+ static let baseExecutionQueue = DispatchQueue(label: "vapor.codes.entrypoint")
+
+ func runFromAsyncMainEntrypoint() async throws {
+ try await withCheckedThrowingContinuation { continuation in
+ Vapor.Application.baseExecutionQueue.async { [self] in
+ do {
+ try self.run()
+ continuation.resume()
+ } catch {
+ continuation.resume(throwing: error)
+ }
+ }
+ }
+ }
+}
+
+@main
+enum Entrypoint {
+ static func main() async throws {
+ var env = try Environment.detect()
+ try LoggingSystem.bootstrap(from: &env)
+
+ let app = Application(env)
+ defer { app.shutdown() }
+
+ try await configure(app)
+ try await app.runFromAsyncMainEntrypoint()
+ }
+}
diff --git a/Sources/App/routes.swift b/Sources/App/routes.swift
new file mode 100755
index 0000000..be06662
--- /dev/null
+++ b/Sources/App/routes.swift
@@ -0,0 +1,34 @@
+//import Fluent
+//import Vapor
+//
+//func routes(_ app: Application) throws {
+// app.get { req async in
+// "It works!"
+// }
+//
+// app.get("hello") { req async -> String in
+// "Hello, world!"
+// }
+//
+// try app.register(collection: TodoController())
+//}
+
+import Vapor
+
+func routes(_ app: Application) throws {
+ let fuelEntryController = FuelEntryController()
+
+ app.get("fuel-entries") { req in
+ try await fuelEntryController.index(req: req)
+ }
+
+ app.post("fuel-entries") { req in
+ try await fuelEntryController.create(req: req)
+ }
+
+ app.delete("fuel-entries", ":fuelEntryID") { req in
+ try await fuelEntryController.delete(req: req)
+ }
+}
+
+
diff --git a/Tests/AppTests/AppTests.swift b/Tests/AppTests/AppTests.swift
new file mode 100755
index 0000000..8cfd310
--- /dev/null
+++ b/Tests/AppTests/AppTests.swift
@@ -0,0 +1,15 @@
+@testable import App
+import XCTVapor
+
+final class AppTests: XCTestCase {
+ func testHelloWorld() async throws {
+ let app = Application(.testing)
+ defer { app.shutdown() }
+ try await configure(app)
+
+ try app.test(.GET, "hello", afterResponse: { res in
+ XCTAssertEqual(res.status, .ok)
+ XCTAssertEqual(res.body.string, "Hello, world!")
+ })
+ }
+}
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100755
index 0000000..ab5ac60
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,74 @@
+# Docker Compose file for Vapor
+#
+# Install Docker on your system to run and test
+# your Vapor app in a production-like environment.
+#
+# Note: This file is intended for testing and does not
+# implement best practices for a production deployment.
+#
+# Learn more: https://docs.docker.com/compose/reference/
+#
+# Build images: docker-compose build
+# Start app: docker-compose up app
+# Start database: docker-compose up db
+# Run migrations: docker-compose run migrate
+# Stop all: docker-compose down (add -v to wipe db)
+#
+version: '3.7'
+
+volumes:
+ db_data:
+
+x-shared_environment: &shared_environment
+ LOG_LEVEL: ${LOG_LEVEL:-debug}
+ DATABASE_HOST: db
+ DATABASE_NAME: vapor_database
+ DATABASE_USERNAME: vapor_username
+ DATABASE_PASSWORD: vapor_password
+
+services:
+ app:
+ image: fueling:latest
+ build:
+ context: .
+ environment:
+ <<: *shared_environment
+ depends_on:
+ - db
+ ports:
+ - '8080:8080'
+ # user: '0' # uncomment to run as root for testing purposes even though Dockerfile defines 'vapor' user.
+ command: ["serve", "--env", "production", "--hostname", "0.0.0.0", "--port", "8080"]
+ migrate:
+ image: fueling:latest
+ build:
+ context: .
+ environment:
+ <<: *shared_environment
+ depends_on:
+ - db
+ command: ["migrate", "--yes"]
+ deploy:
+ replicas: 0
+ revert:
+ image: fueling:latest
+ build:
+ context: .
+ environment:
+ <<: *shared_environment
+ depends_on:
+ - db
+ command: ["migrate", "--revert", "--yes"]
+ deploy:
+ replicas: 0
+ db:
+ image: postgres:15-alpine
+ volumes:
+ - db_data:/var/lib/postgresql/data/pgdata
+ environment:
+ PGDATA: /var/lib/postgresql/data/pgdata
+ POSTGRES_USER: vapor_username
+ POSTGRES_PASSWORD: vapor_password
+ POSTGRES_DB: vapor_database
+ ports:
+ - '5432:5432'