import Dependencies import DependenciesMacros import Fluent import Vapor public extension DependencyValues { var vendorBranches: VendorBranchDB { get { self[VendorBranchDB.self] } set { self[VendorBranchDB.self] = newValue } } } @DependencyClient public struct VendorBranchDB: Sendable { var create: @Sendable (VendorBranch.Create, Vendor.IDValue) async throws -> VendorBranch.DTO var delete: @Sendable (VendorBranch.IDValue) async throws -> Void var fetchAll: @Sendable (FetchRequest) async throws -> [VendorBranch.DTO] var get: @Sendable (VendorBranch.IDValue) async throws -> VendorBranch.DTO? var update: @Sendable (VendorBranch.IDValue, VendorBranch.Update) async throws -> VendorBranch.DTO enum FetchRequest: Equatable { case `default` case `for`(vendorID: Vendor.IDValue) case withVendor } func fetchAll() async throws -> [VendorBranch.DTO] { try await fetchAll(.default) } } extension VendorBranchDB: TestDependencyKey { public static let testValue: VendorBranchDB = Self() static func live(database db: any Database) -> Self { .init( create: { model, vendorID in let branch = model.toModel() guard let vendor = try await Vendor.find(vendorID, on: db) else { throw Abort(.badRequest, reason: "Vendor does not exist.") } try await vendor.$branches.create(branch, on: db) return branch.toDTO() }, delete: { id in guard let branch = try await VendorBranch.find(id, on: db) else { throw Abort(.notFound) } try await branch.delete(on: db) }, fetchAll: { request in var query = VendorBranch.query(on: db) switch request { case .withVendor: query = query.with(\.$vendor) case let .for(vendorID: vendorID): let branches = try await Vendor.query(on: db) .filter(\.$id == vendorID) .with(\.$branches) .first()? .branches .map { $0.toDTO() } guard let branches else { throw Abort(.badGateway, reason: "Vendor id not found.") } return branches case .default: break } return try await query.all().map { $0.toDTO() } }, get: { id in try await VendorBranch.find(id, on: db).map { $0.toDTO() } }, update: { id, updates in guard let branch = try await VendorBranch.find(id, on: db) else { throw Abort(.notFound) } branch.applyUpdates(updates) try await branch.save(on: db) return branch.toDTO() } ) } }