GraphQL

Swift SSWG License Codebeat

用于 GraphQL 的 Swift 实现,GraphQL 是 Facebook 创建的 API 查询语言。

需要帮助?请在社区寻找资源。

用法

Schema 定义

GraphQLSchema 对象可以用于定义 GraphQL Schema 和类型。 这些 schema 由类型、字段、参数和解析器函数组成。 下面是一个例子:

let schema = try GraphQLSchema(
    query: GraphQLObjectType(                   // Defines the special "query" type
        name: "Query",
        fields: [
            "hello": GraphQLField(              // Users may query 'hello'
                type: GraphQLString,            // The result is a string type
                resolve: { _, _, _, _ in
                    "world"                     // The result of querying 'hello' is "world"
                }
            )
        ]
    )
)

更多复杂的 schema 例子请参见测试文件。

此 repo 仅包含核心 GraphQL 实现,并不专注于简化 schema 的创建。 为了获得更好的 GraphQL schema 创建体验,请使用 Graphiti

执行

一旦 schema 被定义,就可以使用全局 graphql 函数对其执行查询

let result = try await graphql(
    schema: schema,
    request: "{ hello }",
    eventLoopGroup: eventLoopGroup
)

该查询的结果是一个 GraphQLResult,它编码为以下 JSON

{ "hello": "world" }

订阅

此包支持 GraphQL 订阅,但在 Swift 5.5 中集成 AsyncSequence 之前,标准的 Swift 库没有提供事件流结构。 出于历史原因和向后兼容性,此库使用 EventStream 协议来实现订阅,几乎每个异步流实现都可以遵循该协议。

要在 GraphQL schema 中创建订阅字段,请使用返回 EventStreamsubscribe 解析器。 你还必须提供一个 resolver,它定义了如何处理发生的每个事件,并且必须返回字段结果类型。 这是一个例子:

let schema = try GraphQLSchema(
    subscribe: GraphQLObjectType(
        name: "Subscribe",
        fields: [
            "hello": GraphQLField(              
                type: GraphQLString,
                resolve: { eventResult, _, _, _, _ in       // Defines how to transform each event when it occurs
                    return eventResult
                },
                subscribe: { _, _, _, _, _ in               // Defines how to construct the event stream
                    let asyncStream = AsyncThrowingStream<String, Error> { continuation in
                        let timer = Timer.scheduledTimer(
                            withTimeInterval: 3,
                            repeats: true,
                        ) {
                            continuation.yield("world")     // Emits "world" every 3 seconds
                        }
                    }
                    return ConcurrentEventStream<String>(asyncStream)
                }
            )
        ]
    )
)

要执行订阅,请使用 graphqlSubscribe 函数

let subscriptionResult = try await graphqlSubscribe(
    schema: schema,
)
// Must downcast from EventStream to concrete type to use in 'for await' loop below
let concurrentStream = subscriptionResult.stream! as! ConcurrentEventStream
for try await result in concurrentStream.stream {
    print(result)
}

上面的代码将每 3 秒打印以下 JSON

{ "hello": "world" }

上面的例子假设你的环境可以访问 Swift 并发。 如果不是这种情况,请尝试使用 GraphQLRxSwift

编码结果

如果你使用普通的 JSONEncoder 编码 GraphQLResult,则不能保证字段顺序与查询匹配,这违反了 GraphQL 规范。 为了保持此顺序,应该使用此包提供的 GraphQLJSONEncoder 来编码 GraphQLResult

支持

此包支持的 Swift 版本与 Swift NIO 的对齐

有关升级到新的主要版本的详细信息,请参见 MIGRATION

贡献

如果你认为你发现了安全漏洞,请遵循 安全指南

希望为此包做出贡献的人员应遵循 Swift 行为准则Swift API 设计指南SSWG 技术最佳实践

此 repo 使用 SwiftFormat,并包含 lint 检查来强制执行这些格式标准。 要格式化你的代码,请安装 swiftformat 并运行

swiftformat .

此 repo 的大部分结构都镜像了(用 Javascript/Typescript 编写的规范 GraphQL 实现)[https://github.com/graphql/graphql-js]。 如果缺少任何功能,查看原始代码并将其“翻译”为 Swift 大多数情况下是有效的。 例如:

Swift

/Sources/GraphQL/Language/AST.swift

Javascript/Typescript

/src/language/ast.js

许可证

本项目在 MIT 许可证下发布。 有关详细信息,请参见 LICENSE