web-dev-qa-db-ja.com

引数に基づく動的フィールドを持つGraphQL ObjectType

GraphQLクエリの応答がオブジェクトの動的プロパティを返す必要がある状況にあります。私たちの場合、すべての可能なプロパティを事前に定義することはできません。そのため、動的でなければなりません。

私たちが考えるには、それを解決するための2つのオプションがあります。

const MyType = new GraphQLObjectType({
  name: 'SomeType',
  fields: {
    name: {
      type: GraphQLString,
    },
    elements: {
      /*
      THIS is our special field which needs to return a dynamic object 
      */
    },
    // ...
  },
});

例のコードでわかるように、要素はオブジェクトを返す必要があるプロパティです。これを解決するときの応答は次のとおりです。

{
  name: 'some name',
  elements: {
    an_unkonwn_key: {
      some_nested_field: {
        some_other: true,
      },
    },
    another_unknown_prop: 'foo',
  },
}

1)「任意のオブジェクト」を返す

オブジェクトを返すだけでよいので、GraphQLはオブジェクトがどのフィールドを持っているかを知る必要はありません。フィールドがGraphQlObjectType型であることをGraphQLに通知する場合、フィールドを定義する必要があります。このため、誰かが単なるオブジェクトであることをGraphQLに伝えることはできないようです。

このため、次のように変更しました。

elements: {
      type: new GraphQLObjectType({ name: 'elements' });
    },

2)関数内にあるため、動的フィールドプロパティを定義できます

フィールドを関数として定義すると、オブジェクトを動的に定義できます。しかし、フィールド関数にはいくつかの情報(この場合は要素に渡される情報)が必要であり、フィールドオブジェクトを作成するにはそれらにアクセスする必要があります。

例:

const MyType = new GraphQLObjectType({
  name: 'SomeType',
  fields: {
    name: {
      type: GraphQLString,
    },
    elements: {
      type: new GraphQLObjectType({
        name: 'elements',
        fields: (argsFromElements) => {
          // here we can now access keys from "args"
          const fields = {};
          argsFromElements.keys.forEach((key) => {
            // some logic here ..
            fields[someGeneratedProperty] = someGeneratedGraphQLType;
          });
          return fields;
        },
      }),
      args: {
        keys: {
          type: new GraphQLList(GraphQLString),
        },
      },
    },
    // ...
  },
});

これはうまくいくかもしれませんが、問題は、引数を渡す方法やオブジェクトをフィールドに解決する方法があるかどうかです。

質問したがって、私たちの質問は次のとおりです。GraphQLの場合、どちらの方法が推奨され、ソリューション1または2が可能ですか?多分別の解決策がありますか?

編集 ScalarTypeを使用すると、ソリューション1が機能します。例:

type: new GraphQLScalarType({
        name: 'elements',
        serialize(value) {
          return value;
        },
      }),

これが私たちの状況を解決するための推奨される方法かどうかはわかりません。

16
TJR

考えられるもう1つの解決策は、そのような動的オブジェクトを文字列として宣言することです。そして、オブジェクトの文字列化されたバージョンをリゾルバ関数からそのオブジェクトに値として渡します。そして最終的に、その文字列をもう一度JSONに解析して、クライアント側のオブジェクトにすることができます。

推奨される方法かどうかはわかりませんが、このアプローチで機能させようとしたところ、スムーズに機能したため、ここで共有します。

0
Point Networks