使用 Swift KeyPaths 的模式和投影
Schemata 使你能够使用 KeyPath
为 Swift 类型构建模式和投影。通过提供 Schema
或 Projection
,符合 Model
或 ModelProjection
的类型具有一些基本内省能力。这可以用于诸如 投影 GraphQL 类型。
// These are classes so that they can refer to each other in a one-to-one
// relationship. If they were structs, then Swift wouldn't be able to construct
// a memory layout for them. But since they're not meant to be instantiated,
// the reference semantics are irrelevant.
final class Book {
let id: ISBN
let title: String
let author: Author
fileprivate init(id: ISBN, title: String, author: Author) {
// This code should never run. But instantiating the properties lets
// the compiler guarantee that all the necessary parameters have been
// added to the `init`.
self.id = id
self.title = title
self.author = author
}
}
final class Author {
let id: Author.ID
let name: String
let books: Set<Book>
}
extension Book: Model {
// This `Schema` can be used to:
// 1. Get a list of the `KeyPath`s in the object
// 2. Get the name for a given `KeyPath`
// 3. Break up a `KeyPath` into its individual properties
static let schema = Schema<Book>(
Book.init,
\.id ~ "id", // The strings here define names for these
\.title ~ "title", // properties that can be used for GraphQL fields
\.author ~ "author" // or database columns.
)
}
extension Author: Model {
static let schema = Schema<Author>(
Author.init ~ "Authors", // You can choose to name for the schema
\.id ~ "id",
\.name ~ "name",
\.books ~ \Book.author
)
}
struct BookViewModel {
let title: String
let authorName: String
}
extension BookViewModel: ModelProjection {
// This `Projection` can be used to:
// 1. Get a list of `Book` `KeyPath`s that are required to create a
// `BookViewModel`
// 2. Create a `BookViewModel` from a `[PartialKeyPath<Book>: Any]`.
static let projection = Projection<Book, BookViewModel>(
BookViewModel.init,
\.title,
\.author.name
)
}
Schemata 存在是为了提供用于数据投影的类型安全的基礎。
由于 Swift 自身的局限性,Schemata 在某种程度上受到限制。这些局限性有望在未来版本的 Swift 中得到解决。
无法 获取具有 Optional
或 Array
的 KeyPath
的各个属性。
理想情况下,Schemata 应该能够使用 Swift 的 Codable
功能。不幸的是,没有办法将 KeyPath
与 CodingKey
关联起来。
Schemata 使用 MIT 许可。