📢 Graphqlにおける埋め込み可能なフィールドの提案


もとはpublished in my blog leoloso.com
GraphSQLの新機能の提案をしたいのですが、official spec , しかし、オプションの機能として、GraphSQLサーバーはGraphQL Cursor Connections spec ).
このポストは、GraphSQLコミュニティ内でこの機能のサポートがあるかどうかを調べるための基礎資料の一部です.そこにあるならば、私はそれに新しい問題としてそれを提出しますGraphQL spec repo 徹底的な議論のために、そして、そのチャンピオンになることを申し出てください.

Note: This feature is already supported by GraphQL by PoP. Click on the "Run" button on the GraphiQL clients linked to throughout this post, to execute the query and see the expected response.



新機能:“埋め込み可能なフィールド”
埋め込み可能なフィールドは、構文を構成する構文ですmustache 構文{{field}} .

Note: To make it convenient to use, field echoStr(value: String): String can be added to the schema, as in the examples shown throughout this post.


This query 組み込みフィールド{{title}} and {{date}} :
query {
  posts {
    description: echoStr(value: "Post {{title}} was published on {{date}}")
  }
}
構文は、フィールドの周りに空白を含めることができます.{{ field }} .
This query 組み込みフィールド{{ title }} and {{ date }} :
query {
  posts {
    description: echoStr(value: "Post {{ title }} was published on {{ date }}")
  }
}
埋め込みフィールドには引数を含めることもできます.
  • {{ fieldName }}
  • {{ fieldName(fieldArgs) }}
  • This query 日付をフォーマットします:date(format: \"d/m/Y\") :
    query {
      posts {
        description: echoStr(value: "Post {{ title }} was published on {{ date(format: \"d/m/Y\") }}")
      }
    }
    

    Note: The string quotes must be escaped: \"


    埋め込みフィールドもディレクティブ引数内で動作します.
    This query フィールドを解決するtitle 同じ投稿がコメントを持っている場合に限ります.
    query {
      posts {
          id
        title @skip(if: "{{ hasComments }}")
      }
    }
    

    Note: Using embeddable fields together with directives @skip and @include is an interesting use case. However, condition if expects a Boolean, not a String; even though the query can be resolved properly in the server, there is type mismatch in the client.

    This proposal may suggest to accept embedded fields also on their own, and not only within a string, so they can be casted to their own type: @skip(if: {{ hasComments }}). More on this below.


    This query フィールドを解決するtitle 2つの異なった方法で、コメントがあるかどうかに関係なく:
    query {
      posts {
        title: echoStr(value: "({{ commentCount }}) {{ title }} - posted on {{ date }}") @include(if: "{{ hasComments }}")
        title @skip(if: "{{ hasComments }}")
      }
    }
    

    この新機能の利点
    なぜ我々は、GraphSQLクエリを埋め込み可能なフィールドをサポートしたいですか?以下は私がこれまでに確認した利点です.

    クライアントが応答を処理する必要性を軽減する
    ほとんどの場合、GraphSQLサーバーからデータを要求し、必要な形式に変換するクライアントがあります.
    たとえば、クライアント側のウェブサイトはJavaScriptを使ってデータを処理することができますtitle and date 説明する
    const desc = `Post ${ response.data.title } was published on ${ response.data.date }`
    
    しかし、いくつかの状況では、制御しないサービスのデータを取得する必要があります.
    例えば、ニュースレターサービス(mailchimpのような)はニュースレターのためにデータを検索する終点を定義するのを受け入れるかもしれません.エンドポイントによって返されるデータはすべて、それはニュースレターに注入される前に操作できません.
    これらの状況では、クエリは、必要な形式に応答を操作するために埋め込み可能なフィールドを使用することができます.これは特にアクセスするときに便利ですGraphQL over HTTP .

    これは、スキーマの整理を助ける
    上記のユースケースは、余分なフィールドを追加することによっても満足できるPost.descriptionForNewsletter スキーマに.しかし、この解決策は、スキーマを整理し、埋め込み可能なフィールドは、よりエレガントな解決策と見なされる可能性があります.

    開発経験を改善
    埋め込み可能なフィールドをarrow functions JavaScriptでは、言語で既に利用可能な機能の構文上の砂糖です.
    矢印関数は本当に必要ではありません.
  • 何かを達成するために必要なコードの量を短くする
  • 構文を簡素化する
  • そのように、機能はより良い開発経験を生産して、言語を持っている歓迎です.

    The if コンディション@skip and @include ダイナミックになる
    現在引数"if" のために@skip and @include ディレクティブは、実際のブール値のみですtrue or false ) またはboolean値を持つ変数.この動作はかなり静的です.
    埋め込み可能なフィールドは、オブジェクト自身からの何らかのプロパティの条件を評価することによって、この振舞いをよりダイナミックにするのを可能にするでしょう.
    対処する問題があります.ifBoolean , ないString , したがって、型競合を避けるために、GraphSQL構文も埋め込まれたフィールドを独自に受け入れる必要があります.
    query {
      posts {
          id
        title @skip(if: {{ hasComments }})
      }
    }
    
    ラップの必要性を取り除く{{ }} 引用の間に" " 以外のすべてのスカラー型でこの問題を解決しますString , だけでなくBoolean (下記の例を確認するdroid , 解決可能な埋め込み可能フィールドの使用ID ).

    GraphSQLクエリ内のテンプレートをコード化することができます
    埋め込み可能なフィールドは、GraphSQLのクエリ自体の中でテンプレートを埋め込むことができます.これは、GraphSQLサービスをより柔軟に設定できるようになります.
    例えば、flat chain syntax and nested mutations (他の2つの特徴も提案されている)、以下の質問を生成することができた.この質問は、彼のコメントが返信されたことを通知するためのメールをユーザに送ることができた.
    mutation {
      comment(id: 1) {
        replyToComment(data: data) {
          id @sendEmail(
            to: "{{ parentComment.author.email }}",
            subject: "{{ author.name }} has replied to your comment",
            content: "
              <p>On {{ comment.date(format: \"d/m/Y\") }}, {{ author.name }} says:</p>
              <blockquote>{{ comment.content }}</blockquote>
              <p>Read online: {{ comment.url }}</p>
            "
          )
        }
      }
    }
    

    クエリ間の変数のエクスポート
    提案機能[RFC] exporting variables between queries 試み@export フィールドの値を返し、同じクエリ内の別のフィールドに入力します.
    query A {
      hero {
        id @export(as: "droidId") 
      }
    }
    
    query B($droidId: String!) {
      droid (id: $droidId) {
        name
      }
    }
    
    埋め込み可能なフィールドとフラットチェーンの構文で、このユースケースは以下のように満足することができます.
    query {
      droid (id: {{ hero.id }} ) {
        name
      }
    }
    

    後方互換性
    この機能は後方互換性を破る.From the spec :

    Once a query is written, it should always mean the same thing and return the same shaped result. Future changes should not change the meaning of existing schema or queries or in any other way cause an existing compliant GraphQL service to become non-compliant for prior versions of the spec.


    現在のクエリでは、現在のクエリには次のような形があります.
    query {
      foo: echoStr(value: "Hello {{ world }}!")
    }
    
    ...応答は以下のようになります.
    {
      "data": {
        "foo": "Hello {{ world }}!"
      }
    }
    
    埋め込み可能なフィールドを使用すると、上記のクエリは異なる応答を生成します.また、フィールドがないときのエラーメッセージも生成することがありますRoot.world .
    また、包装しない場合を考える{{ }} 文字列間の引用" " , 下記のクエリのように.
    query {
      posts {
          id
        title @skip(if: {{ hasComments }})
      }
    }
    
    現在、このクエリは、文法エラーを生成します.これは、GraphSQLクライアントに表示され、サーバーによって解析されない可能性があります.この動作は変更される.
    後方互換性がないので、埋め込み可能なフィールドをopt - in機能にすることが提案されています.これにより、ユーザはそれを有効にする前に、結果を十分に意識するように促します.

    更なる研究
    埋め込み可能なフィールドは、GraphSQLワークフローからいくつかのコンポーネントに影響します.これらはどう対処すべきか

    Graphqlの統合
    The GraphiQL client フィールドが存在しない場合、またはフィールド引数がスキーマ内で宣言されている型と異なる型の値を受け取る場合、エラーメッセージが表示されます.この情報は埋め込み可能なフィールドのためにも運ぶことができますか?
    このために、GraphSQLはフィールド引数入力を解析して、すべてを特定する必要があるでしょう{{ fieldName(fieldArgs) }} インスタンスは、妥当性検査を行い、エラーメッセージを表示します.

    フィールドが見つからないときの動作
    埋め込まれたフィールドが存在しない場合はどうなりますか?たとえば、下記のクエリでフィールド{{ name }} 現存するが{{ surname }} ではありません:
    {
      users {
        fullName: echoStr(value: "{{ name }} {{ surname }}")
      }
    }
    
    応答がエラーメッセージを生成し、フィールドの処理をスキップするか?EG :
    {
      "errors": [
        "Field 'surname' does not exist, so 'echoStr(value: \"{{ name }} {{ surname }}\")' cannot be resolved"
      ]
    }
    
    または不足しているフィールドをスキップするが、まだフィールドを解決し、おそらく警告を表示する必要がありますか?EG :
    {
      "warnings": [
        "Field 'surname' does not exist"
      ],
      "data": {
        "users": [
          {
            "fullName": "Juan {{ surname }}"
          },
          {
            "fullName": "Pedro {{ surname }}"
          },
          {
            "fullName": "Manuel {{ surname }}"
          }
        ]
      }
    }
    
    または失敗したフィールドを完全に削除する必要がありますか?(各解決値の最後にまだスペースがあることに注意してください):
    {
      "warnings": [
        "Field 'surname' does not exist"
      ],
      "data": {
        "users": [
          {
            "fullName": "Juan "
          },
          {
            "fullName": "Pedro "
          },
          {
            "fullName": "Manuel "
          }
        ]
      }
    }
    

    エスケープ{{ field }}実際に文字列を出力したい場合"{{ field }}" 応答では、解決せずに、どのように行う必要がありますか?

    前文学
    この機能は以下の野心的なバージョンですcomposable fields , これらの面で異なる
  • これはGraphSQL仕様の一部ではなく、付属のオプション仕様として、また、GraphSQL Server
  • 文字列内でのみ解決された場合、埋め込み可能なフィールドはGraphSQL構文への変更を必要としません
  • 他のフィールドの値はフィールドレベルで1レベルダウンし、複数のレベルではなく、

  • 現在の実装
    埋め込み可能なフィールドはGraphQL by PoP , とWordPressの実装GraphQL API for WordPress , 両方ともoptイン機能として.

    参加討論!
    この機能に十分なサポートがあれば、GraphSQLの仕様にRFC問題を追加します.
  • GraphSQLの埋め込み可能なフィールドをサポートしていますか?あなたはそれから恩恵を受けますか.どうやって?
  • あなたは埋込み可能なフィールドに反対ですか?なぜ?