import Dependencies import DependenciesMacros import Fluent import Vapor public extension DependencyValues { var vendors: VendorDB { get { self[VendorDB.self] } set { self[VendorDB.self] = newValue } } } @DependencyClient public struct VendorDB: Sendable { var create: @Sendable (Vendor.Create) async throws -> Vendor.DTO var delete: @Sendable (Vendor.IDValue) async throws -> Void var fetchAll: @Sendable (FetchRequest) async throws -> [Vendor.DTO] var get: @Sendable (Vendor.IDValue, GetRequest) async throws -> Vendor.DTO? var update: @Sendable (Vendor.IDValue, Vendor.Update) async throws -> Vendor.DTO enum FetchRequest { case `default` case withBranches } enum GetRequest { case `default` case withBranches } func fetchAll() async throws -> [Vendor.DTO] { try await fetchAll(.default) } func get(_ id: Vendor.IDValue) async throws -> Vendor.DTO? { try await get(id, .default) } } extension VendorDB: TestDependencyKey { public static let testValue: VendorDB = Self() static func live(database db: any Database) -> Self { .init( create: { model in let model = model.toModel() try await model.save(on: db) return model.toDTO() }, delete: { id in guard let vendor = try await Vendor.find(id, on: db) else { throw Abort(.notFound) } try await vendor.delete(on: db) }, fetchAll: { request in var query = Vendor.query(on: db).sort(\.$name, .ascending) let withBranches = request == .withBranches if withBranches { query = query.with(\.$branches) } return try await query.all().map { $0.toDTO(includeBranches: withBranches) } }, get: { id, request in var query = Vendor.query(on: db).filter(\.$id == id) let withBranches = request == .withBranches if withBranches { query = query.with(\.$branches) } return try await query.first().map { $0.toDTO(includeBranches: withBranches) } }, update: { id, updates in guard let vendor = try await Vendor.find(id, on: db) else { throw Abort(.notFound) } vendor.applyUpdates(updates) return vendor.toDTO() } ) } }