feat: Adds script to generate database seeded values and removes old mock storage.
This commit is contained in:
@@ -32,70 +32,3 @@ extension Employee.Update: Content {}
|
||||
extension DatabaseClient.Employees: TestDependencyKey {
|
||||
public static let testValue = Self()
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
typealias EmployeeMockStorage = MockStorage<
|
||||
Employee,
|
||||
Employee.Create,
|
||||
DatabaseClient.Employees.FetchRequest,
|
||||
Void,
|
||||
Employee.Update
|
||||
>
|
||||
|
||||
private extension EmployeeMockStorage {
|
||||
|
||||
init(_ mocks: [Employee]) {
|
||||
@Dependency(\.date.now) var now
|
||||
@Dependency(\.uuid) var uuid
|
||||
self.init(
|
||||
mocks,
|
||||
create: { employee in
|
||||
Employee(
|
||||
id: uuid(),
|
||||
active: employee.active ?? true,
|
||||
createdAt: now,
|
||||
firstName: employee.firstName,
|
||||
lastName: employee.lastName,
|
||||
updatedAt: now
|
||||
)
|
||||
},
|
||||
fetch: { request in
|
||||
switch request {
|
||||
case .all:
|
||||
return { _ in true }
|
||||
case .active:
|
||||
return { $0.active == true }
|
||||
case .inactive:
|
||||
return { $0.active == false }
|
||||
}
|
||||
},
|
||||
update: { employee, updates in
|
||||
let model = Employee(
|
||||
id: employee.id,
|
||||
active: updates.active ?? employee.active,
|
||||
createdAt: employee.createdAt,
|
||||
firstName: updates.firstName ?? employee.firstName,
|
||||
lastName: updates.lastName ?? employee.lastName,
|
||||
updatedAt: now
|
||||
)
|
||||
|
||||
employee = model
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public extension DatabaseClient.Employees {
|
||||
static func mock(_ mocks: [Employee] = []) -> Self {
|
||||
let storage = EmployeeMockStorage(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) },
|
||||
update: { try await storage.update($0, $1) }
|
||||
)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
#if DEBUG
|
||||
import Dependencies
|
||||
import Vapor
|
||||
|
||||
actor MockStorage<
|
||||
Model: Identifiable,
|
||||
Create: Sendable,
|
||||
Fetch: Sendable,
|
||||
Get: Sendable,
|
||||
Update: Sendable
|
||||
> where Model: Sendable {
|
||||
@Dependency(\.date.now) var now
|
||||
@Dependency(\.uuid) var uuid
|
||||
|
||||
private var storage: [Model.ID: Model]
|
||||
|
||||
private let modelFromCreate: @Sendable (Create) async throws -> Model
|
||||
private let fetchToPredicate: @Sendable (Fetch) -> ((Model) -> Bool)
|
||||
private let fetchExtras: @Sendable (Fetch, [Model]) async throws -> [Model]
|
||||
private let applyUpdates: @Sendable (inout Model, Update, Get?) async throws -> Void
|
||||
private let getExtras: @Sendable (Get?, Model) async throws -> Model
|
||||
|
||||
init(
|
||||
_ mocks: [Model] = [],
|
||||
create modelFromCreate: @Sendable @escaping (Create) async throws -> Model,
|
||||
fetch fetchToPredicate: @Sendable @escaping (Fetch) -> ((Model) -> Bool),
|
||||
fetchExtras: @Sendable @escaping (Fetch, [Model]) async throws -> [Model] = { $1 },
|
||||
get getExtras: @Sendable @escaping (Get?, Model) async throws -> Model,
|
||||
update applyUpdates: @Sendable @escaping (inout Model, Update, Get?) async throws -> Void
|
||||
) {
|
||||
self.storage = mocks.reduce(into: [Model.ID: Model]()) { $0[$1.id] = $1 }
|
||||
self.modelFromCreate = modelFromCreate
|
||||
self.fetchToPredicate = fetchToPredicate
|
||||
self.fetchExtras = fetchExtras
|
||||
self.applyUpdates = applyUpdates
|
||||
self.getExtras = getExtras
|
||||
}
|
||||
|
||||
func count() async throws -> Int {
|
||||
storage.count
|
||||
}
|
||||
|
||||
func create(_ create: Create) async throws -> Model {
|
||||
let model = try await modelFromCreate(create)
|
||||
storage[model.id] = model
|
||||
return model
|
||||
}
|
||||
|
||||
func delete(_ id: Model.ID) async throws {
|
||||
storage[id] = nil
|
||||
}
|
||||
|
||||
func fetchAll(_ request: Fetch) async throws -> [Model] {
|
||||
let predicate = fetchToPredicate(request)
|
||||
return try await fetchExtras(request, Array(storage.values.filter { predicate($0) }))
|
||||
}
|
||||
|
||||
func get(_ id: Model.ID, _ request: Get?) async throws -> Model? {
|
||||
if let model = storage[id] {
|
||||
return try await getExtras(request, model)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func update(_ id: Model.ID, _ updates: Update, _ get: Get?) async throws -> Model {
|
||||
guard var model = storage[id] else {
|
||||
throw Abort(.badRequest, reason: "Model not found.")
|
||||
}
|
||||
try await applyUpdates(&model, updates, get)
|
||||
storage[id] = model
|
||||
return model
|
||||
}
|
||||
}
|
||||
|
||||
extension MockStorage where Get == Void {
|
||||
init(
|
||||
_ mocks: [Model] = [],
|
||||
create modelFromCreate: @Sendable @escaping (Create) async throws -> Model,
|
||||
fetch fetchToPredicate: @Sendable @escaping (Fetch) -> ((Model) -> Bool),
|
||||
fetchExtras: @Sendable @escaping (Fetch, [Model]) async throws -> [Model] = { $1 },
|
||||
update applyUpdates: @Sendable @escaping (inout Model, Update) async throws -> Void
|
||||
) {
|
||||
self.init(
|
||||
mocks,
|
||||
create: modelFromCreate,
|
||||
fetch: fetchToPredicate,
|
||||
fetchExtras: fetchExtras,
|
||||
get: { _, model in model },
|
||||
update: { model, updates, _ in try await applyUpdates(&model, updates) }
|
||||
)
|
||||
}
|
||||
|
||||
func get(_ id: Model.ID) async throws -> Model? {
|
||||
storage[id]
|
||||
}
|
||||
|
||||
func update(_ id: Model.ID, _ updates: Update) async throws -> Model {
|
||||
try await update(id, updates, ())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension MockStorage where Fetch == Void {
|
||||
init(
|
||||
_ mocks: [Model] = [],
|
||||
create modelFromCreate: @Sendable @escaping (Create) async throws -> Model,
|
||||
fetchExtras: @Sendable @escaping (Fetch, [Model]) async throws -> [Model] = { $1 },
|
||||
get getExtras: @Sendable @escaping (Get?, Model) async throws -> Model,
|
||||
update applyUpdates: @Sendable @escaping (inout Model, Update, Get?) async throws -> Void
|
||||
) {
|
||||
self.init(
|
||||
mocks,
|
||||
create: modelFromCreate,
|
||||
fetch: { _ in { _ in true } },
|
||||
fetchExtras: fetchExtras,
|
||||
get: getExtras,
|
||||
update: applyUpdates
|
||||
)
|
||||
}
|
||||
|
||||
func fetchAll() async throws -> [Model] {
|
||||
try await fetchAll(())
|
||||
}
|
||||
}
|
||||
|
||||
extension MockStorage where Fetch == Void, Get == Void {
|
||||
init(
|
||||
_ mocks: [Model] = [],
|
||||
create modelFromCreate: @Sendable @escaping (Create) async throws -> Model,
|
||||
fetchExtras: @Sendable @escaping (Fetch, [Model]) async throws -> [Model] = { $1 },
|
||||
update applyUpdates: @Sendable @escaping (inout Model, Update) async throws -> Void
|
||||
) {
|
||||
self.init(
|
||||
mocks,
|
||||
create: modelFromCreate,
|
||||
fetchExtras: fetchExtras,
|
||||
get: { _, model in model },
|
||||
update: { model, updates, _ in try await applyUpdates(&model, updates) }
|
||||
)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -22,74 +22,3 @@ extension PurchaseOrder.Create: Content {}
|
||||
extension DatabaseClient.PurchaseOrders: TestDependencyKey {
|
||||
public static let testValue: DatabaseClient.PurchaseOrders = Self()
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
typealias PurchaseOrderMockStorage = MockStorage<
|
||||
PurchaseOrder,
|
||||
PurchaseOrder.Create,
|
||||
Void,
|
||||
Void,
|
||||
Void
|
||||
>
|
||||
|
||||
public extension DependencyValues {
|
||||
var purchaseOrderID: PurchaseOrderIDGenerator {
|
||||
get { self[PurchaseOrderIDGenerator.self] }
|
||||
set { self[PurchaseOrderIDGenerator.self] = newValue }
|
||||
}
|
||||
}
|
||||
|
||||
@DependencyClient
|
||||
public struct PurchaseOrderIDGenerator: Sendable {
|
||||
var nextID: @Sendable () async throws -> Int
|
||||
}
|
||||
|
||||
extension PurchaseOrderIDGenerator: DependencyKey {
|
||||
public static let testValue: PurchaseOrderIDGenerator = .liveValue
|
||||
|
||||
public static var liveValue: Self {
|
||||
let counter = Counter()
|
||||
return .init(nextID: { await counter.nextID() })
|
||||
}
|
||||
|
||||
actor Counter {
|
||||
private var count: Int
|
||||
|
||||
init(starting: Int = 1) {
|
||||
self.count = starting
|
||||
}
|
||||
|
||||
func nextID() async -> Int {
|
||||
count += 1
|
||||
return count
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// private extension PurchaseOrderMockStorage {
|
||||
// static func make(_ mocks: [PurchaseOrder]) -> Self {
|
||||
// @Dependency(\.date.now) var now
|
||||
// @Dependency(\.purchaseOrderID) var purchaseOrderID
|
||||
//
|
||||
// return .init(
|
||||
// mocks,
|
||||
// create: { model in
|
||||
// try await PurchaseOrder(
|
||||
// id: purchaseOrderID.nextID(),
|
||||
// workOrder: model.workOrder,
|
||||
// materials: model.materials,
|
||||
// customer: model.customer,
|
||||
// truckStock: model.truckStock,
|
||||
// createdBy: model.createdForID,
|
||||
// createdFor: model.createdForID,
|
||||
// vendorBranch: .i
|
||||
//
|
||||
// )
|
||||
// },
|
||||
// update: { _, _ in
|
||||
// fatalError()
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
#endif
|
||||
|
||||
@@ -28,66 +28,3 @@ 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
|
||||
|
||||
@@ -31,61 +31,3 @@ extension DatabaseClient.VendorBranches.FetchRequest: Content {}
|
||||
extension DatabaseClient.VendorBranches: TestDependencyKey {
|
||||
public static let testValue: DatabaseClient.VendorBranches = Self()
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
typealias VendorBranchMockStorage = MockStorage<
|
||||
VendorBranch,
|
||||
VendorBranch.Create,
|
||||
DatabaseClient.VendorBranches.FetchRequest,
|
||||
Void,
|
||||
VendorBranch.Update
|
||||
>
|
||||
|
||||
private extension VendorBranchMockStorage {
|
||||
|
||||
init(_ mocks: [VendorBranch]) {
|
||||
@Dependency(\.date.now) var now
|
||||
@Dependency(\.uuid) var uuid
|
||||
|
||||
self.init(
|
||||
mocks,
|
||||
create: {
|
||||
VendorBranch(id: uuid(), name: $0.name, vendorID: $0.vendorID, createdAt: now, updatedAt: now)
|
||||
},
|
||||
fetch: { request in
|
||||
switch request {
|
||||
case .all:
|
||||
return { _ in true }
|
||||
case let .for(vendorID):
|
||||
return { $0.vendorID == vendorID }
|
||||
}
|
||||
},
|
||||
update: { branch, updates in
|
||||
let model = VendorBranch(
|
||||
id: branch.id,
|
||||
name: updates.name ?? branch.name,
|
||||
vendorID: branch.vendorID,
|
||||
createdAt: branch.createdAt,
|
||||
updatedAt: now
|
||||
)
|
||||
|
||||
branch = model
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public extension DatabaseClient.VendorBranches {
|
||||
static func mock(_ mocks: [VendorBranch] = []) -> Self {
|
||||
let storage = VendorBranchMockStorage(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) },
|
||||
update: { try await storage.update($0, $1) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -51,94 +51,3 @@ 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
|
||||
|
||||
Reference in New Issue
Block a user