import Dependencies import DependenciesMacros import Fluent import Vapor extension DependencyValues { var users: UserDB { get { self[UserDB.self] } set { self[UserDB.self] = newValue } } } @DependencyClient struct UserDB: Sendable { var create: @Sendable (User.Create) async throws -> User.DTO var delete: @Sendable (User.IDValue) async throws -> Void var fetchAll: @Sendable () async throws -> [User.DTO] var login: @Sendable (User) async throws -> UserToken } extension UserDB: TestDependencyKey { static let testValue: UserDB = Self() static func live(database db: any Database) -> Self { self.init( create: { model in guard model.password == model.confirmPassword else { throw Abort(.badRequest, reason: "Passwords did not match.") } let user = try User( username: model.username, email: model.email, passwordHash: Bcrypt.hash(model.password) ) try await user.save(on: db) return user.toDTO() }, delete: { id in guard let user = try await User.find(id, on: db) else { throw Abort(.notFound) } try await user.delete(on: db) }, fetchAll: { try await User.query(on: db).all().map { $0.toDTO() } }, login: { user in let token = try user.generateToken() try await token.save(on: db) return token } ) } }