Files
vapor-po/Sources/DatabaseClient/Vendors.swift

145 lines
4.1 KiB
Swift

import Dependencies
import DependenciesMacros
import SharedModels
import Vapor
public extension DatabaseClient {
@DependencyClient
struct Vendors: Sendable {
public var create: @Sendable (Vendor.Create) async throws -> Vendor
public var delete: @Sendable (Vendor.ID) async throws -> Void
public var fetchAll: @Sendable (FetchRequest) async throws -> [Vendor]
public var get: @Sendable (Vendor.ID, GetRequest?) async throws -> Vendor?
public var update: @Sendable (Vendor.ID, Vendor.Update, GetRequest?) async throws -> Vendor
public enum FetchRequest: Sendable {
case all
case withBranches
}
public enum GetRequest: Sendable {
case withBranches
}
@Sendable
public func fetchAll() async throws -> [Vendor] {
try await fetchAll(.all)
}
@Sendable
public func get(_ id: Vendor.ID) async throws -> Vendor? {
try await get(id, nil)
}
@Sendable
public func update(
_ id: Vendor.ID,
with updates: Vendor.Update,
returnWithBranches: Bool = false
) async throws -> Vendor {
try await update(id, updates, returnWithBranches ? GetRequest.withBranches : nil)
}
}
}
extension Vendor: Content {}
extension Vendor.Create: Content {}
extension Vendor.Update: Content {}
extension DatabaseClient.Vendors.FetchRequest: Content {}
extension DatabaseClient.Vendors.GetRequest: Content {}
extension DatabaseClient.Vendors: TestDependencyKey {
public static let testValue: DatabaseClient.Vendors = Self()
}
#if DEBUG
typealias VendorMockStorage = MockStorage<
Vendor,
Vendor.Create,
DatabaseClient.Vendors.FetchRequest,
DatabaseClient.Vendors.GetRequest,
Vendor.Update
>
private extension VendorMockStorage {
// swiftlint:disable function_body_length
static func vendors(_ mocks: [Vendor]) -> Self {
@Dependency(\.date.now) var now
@Dependency(\.uuid) var uuid
@Dependency(\.database.vendorBranches) var vendorBranches
return .init(
mocks,
create: {
Vendor(
id: uuid(),
name: $0.name,
createdAt: now,
updatedAt: now
)
},
fetch: { _ in
{ _ in true }
},
fetchExtras: { request, models in
guard request == .withBranches else { return models }
let branches = try await vendorBranches.fetchAll()
return models.map { model in
Vendor(
id: model.id,
name: model.name,
branches: Array(branches.filter { $0.vendorID == model.id }),
createdAt: model.createdAt,
updatedAt: model.updatedAt
)
}
},
get: { req, model in
guard req == .withBranches else { return model }
let branches = try await vendorBranches.fetchAll(.for(vendorID: model.id))
return Vendor(
id: model.id,
name: model.name,
branches: branches,
createdAt: model.createdAt,
updatedAt: model.updatedAt
)
},
update: { model, updates, get in
var branches: [VendorBranch]?
if get == .withBranches {
branches = try await vendorBranches.fetchAll(.for(vendorID: model.id))
}
let vendor = Vendor(
id: model.id,
name: updates.name ?? model.name,
branches: branches ?? model.branches,
createdAt: model.createdAt,
updatedAt: now
)
model = vendor
}
)
}
// swiftlint:enable function_body_length
}
public extension DatabaseClient.Vendors {
static func mock(_ mocks: [Vendor]) -> Self {
let storage = VendorMockStorage.vendors(mocks)
return .init(
create: { try await storage.create($0) },
delete: { try await storage.delete($0) },
fetchAll: { try await storage.fetchAll($0) },
get: { try await storage.get($0, $1) },
update: { req, updates, get in try await storage.update(req, updates, get) }
)
}
}
#endif