Schemata

使用 Swift KeyPaths 的模式和投影

概述

Schemata 使你能够使用 KeyPath 为 Swift 类型构建模式投影。通过提供 SchemaProjection,符合 ModelModelProjection 的类型具有一些基本内省能力。这可以用于诸如 投影 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 中得到解决。

许可

Schemata 使用 MIT 许可