试试Elixir: graphql-elixir
简而言之
根据 awesome-graphql,Elixir 有三个用于 GraphQL 的解析器。
-
- asonge/graphql
-
- joshprice/graphql-elixir
-
- peburrows/plot
asonge/graphql -> asonge/graphql
joshprice/graphql-elixir -> joshprice/graphql-elixir
peburrows/plot -> peburrows/plot
我调查了这些选项中最活跃的 graphql-elixir 开发。
解析查询
在中国,GraphQL 的解析如下所示。
GraphQL.parse "{ hello }"
首先,让我们尝试解析之前在文章中试过的简单查询。
{game {
id
}}
将其分解为按照规范定义的元素。
[kind: :Document, loc: [start: 0],
definitions: [[kind: :OperationDefinition, loc: [start: 0], operation: :query,
selectionSet: [kind: :SelectionSet, loc: [start: 0],
selections: [[kind: :Field, loc: [start: 0], name: 'game',
selectionSet: [kind: :SelectionSet, loc: [start: 0],
selections: [[kind: :Field, loc: [start: 0], name: 'id']]]]]]]]]
突变也可以正确解析。
mutation Mutation($input:CheckHidingSpotForTreasureInput!) {
checkHidingSpotForTreasure(input:$input) {
clientMutationId
}
}
[kind: :Document, loc: [start: 0],
definitions: [[kind: :OperationDefinition, loc: [start: 0],
operation: :mutation, name: 'Mutation',
variableDefinitions: [[kind: :VariableDefinition, loc: [start: 0],
variable: [kind: :Variable, loc: [start: 0], name: 'input'],
type: [kind: :NonNullType, loc: [start: 0],
type: [kind: :NamedType, loc: [start: 0],
name: 'CheckHidingSpotForTreasureInput']]]],
selectionSet: [kind: :SelectionSet, loc: [start: 0],
selections: [[kind: :Field, loc: [start: 0],
name: 'checkHidingSpotForTreasure',
arguments: [[kind: :Argument, loc: [start: 0], name: 'input',
value: [kind: :Variable, loc: [start: 0], name: 'input']]],
selectionSet: [kind: :SelectionSet, loc: [start: 0],
selections: [[kind: :Field, loc: [start: 0],
name: 'clientMutationId']]]]]]]]]
变量$input可以解析为kind: :Variable。
变量的赋值可能被实现在后面提及的执行器中。
你可以在graphql-elixir的test/graphql_parser_test.exs中找到其他模式的确认。
模式的解析
对于模式的解析也是支持的,并且在这里运行 npm run update-schema 生成的 data/schema.graphql 示例中,它将如下所示。
input CheckHidingSpotForTreasureInput {
id: ID!
clientMutationId: String!
}
type CheckHidingSpotForTreasurePayload {
hidingSpot: HidingSpot
game: Game
clientMutationId: String!
}
<中略>
type Query {
node(id: ID!): Node
game: Game
}
[kind: :Document, loc: [start: 0],
definitions: [[kind: :InputObjectTypeDefinition, loc: [start: 0],
name: 'CheckHidingSpotForTreasureInput',
fields: [[kind: :InputValueDefinition, loc: [start: 0], name: 'id',
type: [kind: :NonNullType, loc: [start: 0],
type: [kind: :NamedType, loc: [start: 0], name: 'ID']]],
[kind: :InputValueDefinition, loc: [start: 0], name: 'clientMutationId',
type: [kind: :NonNullType, loc: [start: 0],
type: [kind: :NamedType, loc: [start: 0], name: 'String']]]]],
[kind: :ObjectTypeDefinition, loc: [start: 0],
name: 'CheckHidingSpotForTreasurePayload',
fields: [[kind: :FieldDefinition, loc: [start: 0], name: 'hidingSpot',
type: [kind: :NamedType, loc: [start: 0], name: 'HidingSpot']],
[kind: :FieldDefinition, loc: [start: 0], name: 'game',
type: [kind: :NamedType, loc: [start: 0], name: 'Game']],
[kind: :FieldDefinition, loc: [start: 0], name: 'clientMutationId',
type: [kind: :NonNullType, loc: [start: 0],
type: [kind: :NamedType, loc: [start: 0], name: 'String']]]]],
<中略>
[kind: :ObjectTypeDefinition, loc: [start: 0], name: 'Query',
fields: [[kind: :FieldDefinition, loc: [start: 0], name: 'node',
arguments: [[kind: :InputValueDefinition, loc: [start: 0], name: 'id',
type: [kind: :NonNullType, loc: [start: 0],
type: [kind: :NamedType, loc: [start: 0], name: 'ID']]]],
type: [kind: :NamedType, loc: [start: 0], name: 'Node']],
[kind: :FieldDefinition, loc: [start: 0], name: 'game',
type: [kind: :NamedType, loc: [start: 0], name: 'Game']]]]]]
目前似乎没有查询和模式的一致性检查功能。
执行者 zhě)
通过在模式(schema)中设定Elixir函数,可以将查询中指定的变量传递给函数进行处理。
※由于最新的版本0.0.2和主分支的规范已经发生了变化,因此可能会有较大改动。
defmodule TestSchema do
def schema do
%GraphQL.Schema{
query: %GraphQL.ObjectType{
name: "RootQueryType",
fields: [
%GraphQL.FieldDefinition{
name: "greeting",
type: "String",
resolve: &greeting/1,
}
]
}
}
end
def greeting(name: name), do: "Hello, #{name}!"
def greeting(_), do: greeting(name: "world")
end
test "query arguments" do
query = "{ greeting }"
assert GraphQL.execute(TestSchema.schema, query) == [data: [greeting: "Hello, world!"]]
query = "{ greeting(name: \"Elixir\") }"
assert GraphQL.execute(TestSchema.schema, query) == [data: [greeting: "Hello, Elixir!"]]
end
最后
与其他两个相比,它的提交数量较多,最近也在进行开发,但要使其易于使用,似乎还需要一些时间。
尽管我轻轻地触及了情节,但出现了以下问题。
-
- variables があるとエラーになる
-
- schema のパースでエラー
- パラメータにオブジェクトを渡すとエラー (文字と数字はok)
这个可能需要更多的时间。
样本代码在这里。
-
- sample_elixir_graphql-elixir
- sample_elixir_plot