GraphQL 検証移行ガイド
Reading time: 13 min
まもなく「graph-node」は を 100% カバーします。
以前のバージョンの「graph-node」は、すべての検証をサポートしておらず、より適切な応答を提供していました。そのため、あいまいな場合、「graph-node」は無効な GraphQL 操作コンポーネントを無視していました。
GraphQL Validations サポートは、今後の新機能と The Graph Network の大規模なパフォーマンスの柱です。
また、The Graph Network の重要な要件であるクエリ応答の決定性も保証されます。
GraphQL Validations を有効にすると、The Graph API に送信された既存のクエリの一部が壊れます。
これらの検証に準拠するには、移行ガイドに従ってください。
⚠️ 検証がロールアウトされる前にクエリを移行しないと、エラーが返され、フロントエンド/クライアントが壊れる可能性があります。
CLI 移行ツールを使用して、GraphQL 操作の問題を見つけて修正できます。または、GraphQL クライアントのエンドポイントを更新して、https://api-next.thegraph.com/subgraphs/name/$GITHUB_USER/$SUBGRAPH_NAME
エンドポイントを使用することもできます。このエンドポイントに対してクエリをテストすると、クエリの問題を見つけるのに役立ちます。
GraphQL 操作エラーのほとんどは、事前にコードベースで見つけることができます。
このため、開発中または CI で GraphQL 操作を検証するためのスムーズなエクスペリエンスを提供します。
は、特定のスキーマに対して GraphQL 操作を検証するのに役立つシンプルな CLI ツールです。
ツールは次のように実行できます。
npx @graphql-validate/cli -s https://api-next.thegraph.com/subgraphs/name/$GITHUB_USER/$SUBGRAPH_NAME -o *.graphql
ノート:
- $GITHUB_USER、$SUBGRAPH_NAME を適切な値に設定または置き換えます。のように:
- 提供されているプレビュー スキーマ URL () は大幅にレート制限されており、すべてのユーザーが新しいバージョンに移行すると廃止されます。 本番環境では使用しないでください。
- 操作は、次の拡張子を持つファイルで識別されます (
-o
オプション)。
[@graphql-validate/cli](https://github.com/saihaj/graphql-validate)
CLI ツールは、GraphQL 操作エラーを次のように出力します。
エラーごとに、説明、ファイル パスと位置、および解決例へのリンクが表示されます (次のセクションを参照)。
検証がオンになっている「graph-node」バージョンを実行するエンドポイント「
クエリを次の宛先に送信して試すことができます。
https://api-next.thegraph.com/subgraphs/id/<Qm...>
または
https://api-next.thegraph.com/subgraphs/name/<GITHUB_USER>/<SUBGRAPH_NAME>
検証エラーがあるとフラグが立てられたクエリを処理するには、Altair や などの好きな GraphQL クエリ ツールを使用して、クエリを試してみてください。これらのツールは、実行前であっても、UI でこれらのエラーをマークします。
以下に、既存の GraphQL 操作で発生する可能性があるすべての GraphQL 検証エラーを示します。
操作に GraphQL 変数、操作、フラグメント、および引数の一意のセットが含まれるようにするためのルールを適用しました。
GraphQL 操作は、あいまいさが含まれていない場合にのみ有効です。
これを実現するには、GraphQL 操作の一部のコンポーネントが一意でなければならないことを確認する必要があります。
これらの規則に違反するいくつかの無効な操作の例を次に示します。
クエリ名が重複しています (#UniqueOperationNamesRule)
# The following operation violated the UniqueOperationName# rule, since we have a single operation with 2 queries# with the same namequery myData {id}query myData {name}
解決:
query myData {id}query myData2 {# rename the second queryname}
フラグメント名の重複 (#UniqueFragmentNamesRule)
# The following operation violated the UniqueFragmentName# rule.query myData {id...MyFields}fragment MyFields {metadata}fragment MyFields {name}
解決:
query myData {id...MyFieldsName...MyFieldsMetadata}fragment MyFieldsMetadata { # assign a unique name to fragmentmetadata}fragment MyFieldsName { # assign a unique name to fragmentname}
重複した変数名 (#UniqueVariableNamesRule)
# The following operation violates the UniqueVariablesquery myData($id: String, $id: Int) {id...MyFields}
解決:
query myData($id: String) {# keep the relevant variable (here: `$id: String`)id...MyFields}
引数名が重複しています (#UniqueArgument)
# The following operation violated the UniqueArgumentsquery myData($id: ID!) {userById(id: $id, id: "1") {id}}
解決:
query myData($id: ID!) {userById(id: $id) {id}}
重複した匿名クエリ (#LoneAnonymousOperationRule)
また、2 つの匿名操作を使用すると、応答構造の競合により、「LoneAnonymousOperation」ルールに違反します。
# This will fail if executed together in# a single operation with the following two queries:query {someField}query {otherField}
解決:
query {someFieldotherField}
または、2 つのクエリに名前を付けます。
query FirstQuery {someField}query SecondQuery {otherField}
GraphQL 選択セットは、最終的な結果セットを正しく解決する場合にのみ有効と見なされます。
特定の選択セットまたはフィールドが、選択されたフィールドまたは使用された引数のいずれかによってあいまいさを生み出す場合、GraphQL サービスは操作の検証に失敗します。
この規則に違反する無効な操作の例をいくつか示します。
競合するフィールド エイリアス (#OverlappingFieldsCanBeMergedRule)
# Aliasing fields might cause conflicts, either with# other aliases or other fields that exist on the# GraphQL schema.query {dogs {name: nicknamename}}
解決:
query {dogs {name: nicknameoriginalName: name # alias the original `name` field}}
引数を持つフィールドの競合 (#OverlappingFieldsCanBeMergedRule)
# Different arguments might lead to different data,# so we can't assume the fields will be the same.query {dogs {doesKnowCommand(dogCommand: SIT)doesKnowCommand(dogCommand: HEEL)}}
解決:
query {dogs {knowsHowToSit: doesKnowCommand(dogCommand: SIT)knowsHowToHeel: doesKnowCommand(dogCommand: HEEL)}}
また、より複雑なユースケースでは、最終的に予想されるセットで競合を引き起こす可能性のある 2 つのフラグメントを使用して、この規則に違反する可能性があります。
query {# Eventually, we have two "x" definitions, pointing# to different fields!...A...B}fragment A on Type {x: a}fragment B on Type {x: b}
それに加えて、@skip
や @include
などのクライアント側の GraphQL ディレクティブは、あいまいさにつながる可能性があります。次に例を示します。
fragment mergeSameFieldsWithSameDirectives on Dog {name @include(if: true)name @include(if: false)}
GraphQL 操作も、操作で定義されたすべてのコンポーネント (変数、フラグメント) が使用されている場合にのみ有効と見なされます。
これらのルールに違反する GraphQL 操作の例をいくつか示します:
未使用の変数 (#NoUnusedVariablesRule)
# Invalid, because $someVar is never used.query something($someVar: String) {someData}
解決:
query something {someData}
未使用のフラグメント (#NoUnusedFragmentsRule)
# Invalid, because fragment AllFields is never used.query something {someData}fragment AllFields { # unused :(nameage}
解決:
# Invalid, because fragment AllFields is never used.query something {someData}# remove the `AllFields` fragment
また、GraphQL フィールドの選択は、以下が検証された場合にのみ有効です:
- オブジェクト フィールドには選択セットが指定されている必要があります。
- エッジ フィールド (スカラー、列挙型) には、選択セットが指定されていてはなりません。
次のスキーマでこれらの規則に違反する例をいくつか示します:
type Image {url: String!}type User {id: ID!avatar: Image!}type Query {user: User!}
無効な選択セット
query {user {id { # Invalid, because "id" is of type ID and does not have sub-fields}}}
解決:
query {user {id}}
選択セットがありません
query {user {idimage # `image` requires a Selection-Set for sub-fields!}}
解決:
query {user {idimage {src}}}
ハードコーディングされた値を引数に渡す GraphQL 操作は、スキーマで定義された値に基づいて有効である必要があります。
これらの規則に違反する無効な操作の例をいくつか示します:
query purposes {# If "name" is defined as "String" in the schema,# this query will fail during validation.purpose(name: 1) {id}}# This might also happen when an incorrect variable is defined:query purposes($name: Int!) {# If "name" is defined as `String` in the schema,# this query will fail during validation, because the# variable used is of type `Int`purpose(name: $name) {id}}
不明なタイプ、変数、フラグメント、またはディレクティブが使用されている場合、GraphQL API はエラーを発生させます。
これらの不明な参照は修正する必要があります:
- タイプミスだった場合の名前の変更
- それ以外の場合は、削除します
無効なフラグメント スプレッド (#PossibleFragmentSpreadsRule)
Fragment は、適用できない型に展開できません。
たとえば、Cat
フラグメントを Dog
タイプに適用することはできません。
query {dog {...CatSimple}}fragment CatSimple on Cat {# ...}
無効なフラグメント定義 (#FragmentsOnCompositeTypesRule)
すべての Fragment は、(on ...
を使用して) 複合型、つまり、オブジェクト、インターフェイス、またはユニオンで定義する必要があります。
スカラーでのフラグメントの定義は無効であるため、次の例は無効です。
ragment fragOnScalar on Int {# we cannot define a fragment upon a scalar (`Int`)something}fragment inlineFragOnScalar on Dog {... on Boolean {# `Boolean` is not a subtype of `Dog`somethingElse}}
ディレクティブはこの場所では使用できません (#KnownDirectivesRule)
The Graph API でサポートされている GraphQL ディレクティブ (@...
) のみを使用できます。
以下は、GraphQL がサポートするディレクティブの例です:
query {dog {name @include(true)age @skip(true)}}
_注: @stream
、@live
、@defer
はサポートされていません。
ディレクティブは、この場所で 1 回だけ使用できます (#UniqueDirectivesPerLocationRule)
The Graph でサポートされているディレクティブは、場所ごとに 1 回だけ使用できます。
以下は無効です (そして冗長です):
query {dog {name @include(true) @include(true)}}