Graphiti 是一个 Swift 库,用于快速、安全且轻松地构建 GraphQL schema。
需要帮助吗?请在社区中查找资源。
关于 GraphQL 的总体概述,请参阅 README,它是 GraphQL 规范的一部分。该概述描述了一组简单的 GraphQL 示例,这些示例以测试的形式存在于此仓库中。开始使用此仓库的一个好方法是并行阅读该 README 文档和相应的测试。
将 Graphiti 添加到您的 Package.swift
文件中
import PackageDescription
let package = Package(
dependencies: [
.package(url: "https://github.com/GraphQLSwift/Graphiti.git", .upToNextMinor(from: "0.20.1")),
]
)
Graphiti 提供两个重要的功能:构建类型 schema,以及针对该类型 schema 提供查询服务。
首先,我们声明常规的 Swift 实体。
struct Message : Codable {
let content: String
}
⭐️ Graphiti 背后的主要设计决策之一是不污染您的实体声明。 这样您就可以轻松地将您的实体引入任何其他解决方案。
第二步是创建应用程序的上下文。上下文将传递给您的所有字段解析器函数。 这允许您将依赖注入应用于您的 API。 您可以在此处放置与数据库或其他服务通信的代码。
struct Context {
func message() -> Message {
Message(content: "Hello, world!")
}
}
⭐️ 再次注意,此步骤不需要 Graphiti。 这纯粹是业务逻辑。
现在我们有了实体和上下文,我们可以创建 GraphQL API 解析器。
import Graphiti
struct Resolver {
func message(context: Context, arguments: NoArguments) -> Message {
context.message()
}
}
现在我们终于可以使用其 schema 定义 GraphQL API 了。
struct MessageAPI : API {
let resolver: Resolver
let schema: Schema<Resolver, Context>
}
let api = MessageAPI(
resolver: Resolver()
schema: try! Schema<Resolver, Context> {
Type(Message.self) {
Field("content", at: \.content)
}
Query {
Field("message", at: Resolver.message)
}
}
)
Schema 也可以使用 SchemaBuilder
以模块化方式创建
SchemaBuilder API
let builder = SchemaBuilder(Resolver.self, Context.self) builder.add( Type(Message.self) { Field("content", at: \.content) } ) builder.query.add( Field("message", at: Resolver.message) ) let schema = try builder.build() let api = MessageAPI( resolver: Resolver() schema: schema )PartialSchema 实现
final class ChatSchema: PartialSchema<Resolver, Context> { @TypeDefinitions public override var types: Types { Type(Message.self) { Field("content", at: \.content) } } @FieldDefinitions public override var query: Fields { Field("message", at: Resolver.message) } } let schema = try SchemaBuilder(Resolver.self, Context.self) .use(partials: [ChatSchema(), ...]) .build() let api = MessageAPI( resolver: Resolver() schema: schema )PartialSchema 实例
let chatSchema = PartialSchema<Resolver, Context>( types: { Type(Message.self) { Field("content", at: \.content) } }, query: { Field("message", at: Resolver.message) } ) let schema = try SchemaBuilder(Resolver.self, Context.self) .use(partials: [chatSchema, ...]) .build() let api = MessageAPI( resolver: Resolver() schema: schema )
⭐️ 请注意,API
允许依赖注入。 例如,在测试时,您可以传递 resolver
和 context
的 mock 对象。
要查询 schema,我们需要传入一个 NIO EventLoopGroup,以便将 execute 函数与查询本身一起提供。
import NIO
let group = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount)
defer {
try? group.syncShutdownGracefully()
}
let result = try await api.execute(
request: "{ message { content } }",
context: Context(),
on: group
)
print(result)
输出将是
{"data":{"message":{"content":"Hello, world!"}}}
API.execute
返回一个 GraphQLResult
,它采用了 Encodable
协议。 您可以将其与 JSONEncoder
一起使用,以使用 JSON 将响应发送回客户端。
解析器函数也可以是 async
的
struct Resolver {
func message(context: Context, arguments: NoArguments) async -> Message {
await someAsyncMethodToGetMessage()
}
}
解析器函数也支持 NIO
风格的并发。 为此,只需在解析器函数中添加一个类型为 EventLoopGroup
的参数,并将返回类型更改为 EventLoopFuture<YouReturnType>
。 不要忘记导入 NIO。
import NIO
struct Resolver {
func message(context: Context, arguments: NoArguments, group: EventLoopGroup) -> EventLoopFuture<Message> {
group.next().makeSucceededFuture(context.message())
}
}
此库支持 GraphQL 订阅,并通过 Swift Concurrency AsyncThrowingStream
类型支持它们。 有关详细信息,请参阅使用指南。
如果您无法使用 Swift Concurrency,则必须创建 EventStream
类的具体子类来实现事件流功能。 如果您不想自己创建子类,则可以使用 GraphQLRxSwift 仓库来开箱即用地集成 RxSwift observables。 或者,您可以将该仓库用作参考,以连接不同的流库,例如 ReactiveSwift、OpenCombine,或者您自己创建的库。
有关渐进式演练,请参阅使用指南。星球大战 API 提供了一个相当完整的示例。
此软件包支持与 Swift NIO 对齐的 Swift 版本。
此仓库使用 SwiftFormat,并包含 lint 检查以强制执行这些格式标准。 要格式化您的代码,请安装 swiftformat
并运行
swiftformat .
本项目根据 MIT 许可证发布。 有关详细信息,请参阅 LICENSE。