AutoGraph

CocoaPods Compatible CircleCI

GraphQL 最快捷的方式

特性

AutoGraph 是一个 Swift 客户端框架,用于发起 GraphQL 请求并将响应映射到强类型模型。模型可以由任何 Decodable 类型表示。AutoGraph 很大程度上依赖于 Swift 的类型安全来驱动它,从而实现更安全、编译时检查的代码。

要求

Swift 5.9

平台

安装

CocoaPods

platform :ios, '13.0'
use_frameworks!

pod 'AutoGraph'

Swift Package Manager (SPM)

dependencies: [
.package(url: "https://github.com/remind101/AutoGraph.git", .upToNextMinor(from: "0.16.0"))
]

代码生成

请参阅 https://github.com/remind101/AutoGraphCodeGen 以了解代码生成。

存储和缓存

AutoGraph 当前的理念是自带存储/缓存层。用户可能希望存储或缓存数据的方式种类繁多,因此我们不包含任何特定的方法。只需使用 AutoGraph 来处理代码生成和网络,然后使用任何所需的存储即可。

这并不妨碍我们在未来探索存储/缓存,但如果这样做,它将作为一个单独的库出现,AutoGraph 作为依赖项。

查询构建器

AutoGraph 包含一个 GraphQL 查询构建器,用于以类型安全的方式构建查询。但是,不强制使用查询构建器;任何继承 GraphQLQuery 的对象都可以充当查询。String 默认继承此特性。

查询示例

Raw GraphQL         AutoGraph
-----------         ---------
query MyCoolQuery {         AutoGraphQL.Operation(type: .query, name: "MyCoolQuery", fields: [
  user {                        Object(name: "user", fields: [
    favorite_authors {              Object(name: "favorite_authors", fields: [,
      uuid                              "uuid",
      name                              "name"
    }                               ]),
    uuid                            "uuid",
    signature                       "signature"
  }                             ])
}

Mutation 示例

Raw GraphQL
-----------
mutation MyCoolMutation {
  updateFavoriteAuthor(uuid: "long_id", input: { name: "My Cool Name" })
  {
    favorite_author {
      uuid
      name
    }
  }
}

AutoGraph
---------
AutoGraphQL.Operation(type: .mutation, name: "MyCoolMutation", fields: [
                            Object(
                            name: "updateFavoriteAuthor",
                            arguments: [ // Continues "updateFavoriteAuthor".
                                "uuid" : "long_id",
                                "input" : [
                                   "name" : "My Cool Class"
                                ]
                            ],
                            fields: [
                                Object(
                                name: "favorite_author",
                                fields: [
                                    "uuid",
                                    "name"
                                    ])
                                ]
                        ])

支持

订阅

AutoGraph 现在支持使用 graphql-ws 协议的订阅。这与 Apollo GraphQL 服务器使用的协议相同,这意味着订阅将与 Apollo 服务器一起工作。

let url = URL(string: "wss.mygraphql.com/subscriptions")!
let webSocketClient = try WebSocketClient(url: url)
webSocketClient.delegate = self   // Allows the user to inspect errors and events as they arrive.

let client = try AlamofireClient(url: AutoGraph.localHost,
                                 session: Session(configuration: MockURLProtocol.sessionConfiguration(),
                                                  interceptor: AuthHandler()))
let autoGraph = AutoGraph(client: client, webSocketClient: webSocketClient)

let request = FilmSubscriptionRequest()
let subscriber = self.subject.subscribe(request) { (result) in
    switch result {
    case .success(let object): // Handle new object.
    case .failure(let error):  // Handle error
    }
}

// Sometime later...
try autoGraph.unsubscribe(subscriber: subscriber!)

类型安全模型的可解码

AutoGraph 完全依赖 Decodable 来将 GraphQL JSON 响应映射到数据模型。就像使模型符合 Decodable 一样简单!

类型安全 JSON 的 JSONValue

在幕后,AutoGraph 使用 JSONValue 来实现类型安全 JSON。请随意导入它以满足您自己的需求。

线程

AutoGraph 在主线程之外执行所有网络请求和映射。由于 Request 最终会将完整的模型返回给主线程上的调用者,因此考虑正在使用的模型类型的线程安全性非常重要。因此,建议使用不可变的 struct 类型作为模型。

网络库

AutoGraph 目前依赖 Alamofire 进行网络连接。但这并不是硬性要求。欢迎为此提交 Pull Request!

用法

Request 协议

  1. 创建一个符合 Request 协议的类。您还可以扩展现有类以符合此协议。Request 是用于通过 AutoGraph 发送的 GraphQL 请求的基本协议。它提供以下参数。
    1. queryDocument - 要发送的查询。您可以使用查询构建器或字符串。
    2. variables - 要与查询一起发送的变量。接受 Dictionary
    3. rootKeyPath - 定义从何处开始映射数据。空字符串 ("") 将从 JSON 的根目录开始映射。
    4. 必须提供一个 associatedtype SerializedObject: Decodable,以告知 AutoGraph 要解码到的数据模型。
    5. 许多方法用于通知 Request 其在生命周期中的位置。
class FilmRequest: Request {
    /*
     query film {
        film(id: "ZmlsbXM6MQ==") {
            id
            title
            episodeID
            director
            openingCrawl
        }
     }
     */

    let query = Operation(type: .query,
                          name: "film",
                          fields: [
                            Object(name: "film",
                                   alias: nil,
                                   arguments: ["id" : "ZmlsbXM6MQ=="],
                                   fields: [
                                    "id",  // May use string literal or Scalar.
                                    Scalar(name: "title", alias: nil),
                                    Scalar(name: "episodeID", alias: nil),
                                    Scalar(name: "director", alias: nil),
                                    Scalar(name: "openingCrawl", alias: nil)])
                            ])

    let variables: [AnyHashable : Any]? = nil

    let rootKeyPath: String = "data.film"

    public func willSend() throws { }
    public func didFinishRequest(response: HTTPURLResponse?, json: JSONValue) throws { }
    public func didFinish(result: Result<Film, Error>) throws { }
}

发送

Swift

  1. 在 AutoGraph 上调用 send
    1. autoGraph.send(request, completion: { [weak self] result in ... }
  2. 处理响应
    1. result 是一个泛型 Result<SerializedObject, Error> 枚举,具有成功和失败情况。

Objective-C

由于 AutoGraph 使用 associatedtype 和泛型,因此无法直接通过 Objective-C 发送。可以构建从 Swift 到 Objective-C 的桥接来发送请求。

贡献

欢迎提交 Pull Request!

许可证

MIT 许可证 (MIT)

版权所有 (c) 2017-Present Remind101

特此授予许可,免费授予任何人获得本软件及相关文档文件(“软件”)副本的权利,以处理本软件,不受限制,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件副本的权利,并允许向其提供软件的人员这样做,但须符合以下条件

上述版权声明和本许可声明应包含在软件的所有副本或主要部分中。

本软件按“原样”提供,不提供任何形式的明示或暗示的保证,包括但不限于适销性、特定用途的适用性和不侵权的保证。在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任负责,无论是在合同诉讼、侵权诉讼或其他诉讼中,由软件或软件的使用或其他交易引起、产生或与之相关。