加入我们,于10月8日至10日在纽约市学习关于GraphQL联邦和API平台工程的最新技巧、趋势和新闻。加入我们参加2024年的纽约市GraphQL峰会
文档
免费开始

Apollo AST


要生成客户端代码, 解析您的 每一个 成为一个 抽象语法树AST). 一个 AST 表示了一个 以类型安全的、机器可读的格式。

Apollo Kotlin 解析器有其自己的工件(apollo-ast),你可以独立于 apollo-runtimeapollo-api 使用。

Apollo-ast 的特性包括:

安装

apollo-ast 依赖项添加到你的项目中:

build.gradle[.kts]
dependencies {
// ...
implementation("com.apollographql.apollo:apollo-ast:4.0.0")
}

解析文档

使用 parseAsGQLDocument 方法从 FileString 或 Okio BufferedSource 解析文档。

val graphQLText = """
query HeroForEpisode(${"$"}ep: Episode) {
hero(episode: ${"$"}ep) {
name
friends {
height
}
foobar
}
}
""".trimIndent()
val parseResult = graphQLText.parseAsGQLDocument()

此方法返回一个 GQLResult<GQLDocument>,其中包含 document 和/或解析问题,每个问题都可以有 WARNINGERROR的严重程度。因为可能存在警告,所以可能同时存在一个有效的 document 和问题。

要获取 document 并在出现错误时抛出异常,请使用 getOrThrow():

val queryGqlDocument = parseResult.getOrThrow()

GQLDocument 是 AST 的根。它包含一个 GQLDefinition 的列表,这些定义共同表示 GraphQL document

AST 中的所有节点都是 GQLNode 的子类(所有名称都以 GQL 前缀开头)。每个子类都公开与相应节点类型相关的特定属性和方法。

以下是 AST 结构的示例

在上面的 HeroForEpisode 示例 ,以下是由解析器返回的 AST 结构:

GQLDocument
└─GQLOperationDefinition query "HeroForEpisode"
├─GQLVariableDefinition "ep": "Episode"
└─GQLSelectionSet
└─GQLField "hero"
├─GQLSelectionSet
│ ├─GQLField "name"
│ ├─GQLField "friends"
│ │ └─GQLSelectionSet
│ │ └─GQLField "height"
│ └─GQLField "foobar"
└─GQLArguments
└─GQLArgument "episode"
└─GQLVariableValue "ep"

请注意,此结构与节点名称紧密遵循 GraphQL 规范

验证输入

除了解析之外,apollo-ast 库还提供了用于执行 GraphQL 文档的高级验证的方法。

要验证解析后的 GQLDocument:

  • 如果文档表示一个模式(schema),请调用 validateAsSchema方法。
  • 如果文档表示一个或多个操作(operations),请调用 validateAsExecutable方法。

validateAsSchema

validateAsSchema返回一个 GQLResult<Schema>。以下代码段解析并验证一个使用未定义指令()(@private)的无效模式:

val schemaText = """
type Query {
hero(episode: Episode): Character
}
enum Episode {
NEWHOPE
EMPIRE
}
type Character @private {
name: String
height: Int @deprecated
friends: [Character]
}
""".trimIndent()
val schemaGQLDocument = schemaText.parseAsGQLDocument().getOrThrow()
val schemaResult = schemaGQLDocument.validateAsSchema()
println(schemaResult.issues.map { it.severity.name + ": " + it.message })

在执行时,此代码段将打印 [WARNING: Unknown directive 'private']

因为这个是警告而不是错误,您仍然可以使用返回的 schemaResult.getOrThrow()

validateAsExecutable

validateAsExecutable 方法检查一个 document 的定义操作是否与提供的特定 有效。您可以通过调用代表 sch...

val schema = schemaGQLDocument.validateAsSchema().getOrThrow()
val executableIssues = queryGqlDocument.validateAsExecutable(schema)
println(executableIssues.map { it.severity.name + ": " + it.message })

如果queryGqlDocument查询了一个过时的并且拼写错误了另一个,这个片段可能打印以下内容:

[WARNING: Use of deprecated field 'height', ERROR: Can't query 'frends' on type 'Character']

输出SDL

您可以使用GQLDocumentstandard GraphQL语法输出,使用toUtf8

// Returns a string
println(queryGqlDocument.toUtf8())
// Output to a File
queryGqlDocument.toUtf8(file)

转换AST

您可以使用GQLDocumenttransform方法修改现有的AST。

您传递一个接受GQLNode的lambda,并返回用于操作AST的指令的transform

  • Continue:保留节点并继续访问子节点
  • Delete:删除节点
  • Replace(GQLNode):用指定的节点替换节点

transform方法遍历AST,并对每个节点执行lambda,然后根据lambda的返回值在AST上执行操作。

注意,DeleteReplace,节点的不自动访问子节点,因此如果需要,您应该递归地调用transform

例如,此代码片段从中移除所有restrictedField定义在queryGqlDocument中的操作,并打印结果:

val transformedQuery = queryGqlDocument.transform{ node ->
if (node is GQLField && node.name == "restrictedField") {
TransformResult.Delete
} else {
TransformResult.Continue
}
}
println(transformedQuery!!.toUtf8())
上一页
使用Java
下一页
编译器插件
评价文章评价在GitHub上编辑Edit论坛Discord

©2024Apollo Graph Inc.,商号Apollo GraphQL。

隐私政策

公司