import Dependencies import DependenciesMacros import Foundation import SharedModels import Vapor public extension DatabaseClient { @DependencyClient struct Users: Sendable { public var count: @Sendable () async throws -> Int public var create: @Sendable (User.Create) async throws -> User public var delete: @Sendable (User.ID) async throws -> Void public var fetchAll: @Sendable () async throws -> [User] public var get: @Sendable (User.ID) async throws -> User? public var login: @Sendable (User.Login) async throws -> User.Token public var logout: @Sendable (User.Token.ID) async throws -> Void public var token: @Sendable (User.ID) async throws -> User.Token public var update: @Sendable (User.ID, User.Update) async throws -> User } } extension User: Content {} extension User.Create: Content {} extension User.Token: Content {} extension User.Update: Content {} extension DatabaseClient.Users: TestDependencyKey { public static let testValue: DatabaseClient.Users = Self() } #if DEBUG typealias UserMockStorage = MockStorage< User, User.Create, Void, Void, User.Update > private extension UserMockStorage { static func make(_ mocks: [User]) -> Self { @Dependency(\.date.now) var now @Dependency(\.uuid) var uuid return .init( create: { model in User( id: uuid(), email: model.email, username: model.username, createdAt: now, updatedAt: now ) }, update: { model, updates in let user = User( id: model.id, email: updates.email ?? model.email, username: updates.username ?? model.username, createdAt: model.createdAt, updatedAt: now ) model = user } ) } } public extension User.Token { static func mock(id: User.ID) -> Self { .init(id: UUID(0), userID: id, value: "test") } } public extension DatabaseClient.Users { static func mock(_ mocks: [User]) -> Self { let storage = UserMockStorage.make(mocks) return .init( count: { try await storage.count() }, create: { try await storage.create($0) }, delete: { try await storage.delete($0) }, fetchAll: { try await storage.fetchAll() }, get: { try await storage.get($0) }, login: { _ in .mock(id: UUID(0)) }, logout: { _ in }, token: { .mock(id: $0) }, update: { try await storage.update($0, $1) } ) } } #endif