试试Elixir: graphql-elixir

简而言之

根据 awesome-graphql,Elixir 有三个用于 GraphQL 的解析器。

    1. asonge/graphql

 

    1. joshprice/graphql-elixir

 

    1. 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
广告
将在 10 秒后关闭
bannerAds