64 lines
2.2 KiB
Swift
64 lines
2.2 KiB
Swift
import FluentKit
|
|
import Foundation
|
|
import HummingbirdFluent
|
|
|
|
/// A `Sendable` snapshot of an ``ExampleRecord``, safe to return across concurrency boundaries.
|
|
///
|
|
/// Repositories return these value-type snapshots rather than FluentKit models, which are mutable reference
|
|
/// types that must not escape the database's execution context.
|
|
public struct Example: Sendable, Equatable {
|
|
|
|
// MARK: Properties
|
|
|
|
/// The record's primary key, or `nil` if it has never been saved.
|
|
public let id: UUID?
|
|
/// The record's name.
|
|
public let name: String
|
|
|
|
}
|
|
|
|
/// Reads and writes ``ExampleRecord`` rows through the default database.
|
|
///
|
|
/// This is the shape every real repository takes: it holds the `Sendable` `Fluent` service, resolves the
|
|
/// default database per call, and maps FluentKit models to `Sendable` snapshots before returning — so no
|
|
/// model ever escapes across an async boundary. It is reference scaffolding paired with ``ExampleRecord``;
|
|
/// replace it with the first real repository once a domain model is defined.
|
|
public struct ExampleRepository: Sendable {
|
|
|
|
// MARK: Properties
|
|
|
|
/// The service providing the default database the repository reads and writes through.
|
|
private let fluent: Fluent
|
|
|
|
// MARK: Initializers
|
|
|
|
/// Creates a repository backed by the given `Fluent` service.
|
|
/// - Parameter fluent: the service whose default database the repository operates on.
|
|
public init(fluent: Fluent) {
|
|
self.fluent = fluent
|
|
}
|
|
|
|
// MARK: Methods
|
|
|
|
/// Inserts a record with the given name.
|
|
/// - Parameter name: the name of the record to insert.
|
|
/// - Returns: a `Sendable` snapshot of the inserted record, including its assigned identifier.
|
|
public func create(name: String) async throws -> Example {
|
|
let record = ExampleRecord(name: name)
|
|
|
|
try await record.save(on: fluent.db())
|
|
|
|
return Example(id: record.id, name: record.name)
|
|
}
|
|
|
|
/// Fetches every record, ordered by name.
|
|
/// - Returns: a `Sendable` snapshot of each record, sorted by name.
|
|
public func all() async throws -> [Example] {
|
|
try await ExampleRecord.query(on: fluent.db())
|
|
.sort(\.$name)
|
|
.all()
|
|
.map { Example(id: $0.id, name: $0.name) }
|
|
}
|
|
|
|
}
|