web-dev-qa-db-fra.com

GraphQL ObjectType avec des champs dynamiques basés sur des arguments

Nous sommes dans la situation où la réponse de notre requête GraphQL doit renvoyer certaines propriétés dynamiques d'un objet. Dans notre cas, nous ne sommes pas en mesure de prédéfinir toutes les propriétés possibles - il doit donc être dynamique.

Comme nous le pensons, il existe deux options pour le résoudre.

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

Comme vous pouvez le voir dans l'exemple de code, l'élément est la propriété qui doit renvoyer un objet. Une réponse lorsque résoudre ce problème pourrait être:

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

1) Retourne un "Any-Object"

Nous pourrions simplement renvoyer n'importe quel objet - afin que GraphQL n'ait pas besoin de savoir quels champs contient l'objet. Lorsque nous disons à GraphQL que le champ est le type GraphQlObjectType dont il a besoin pour définir les champs. Pour cette raison, il ne semble pas possible de dire à GraphQL que quelqu'un n'est qu'un objet.

Pour cela, nous l'avons changé comme ceci:

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

2) Nous pourrions définir des propriétés de champ dynamique parce que c'est dans une fonction

Lorsque nous définissons des champs comme une fonction, nous pourrions définir notre objet de manière dynamique. Mais la fonction de champ aurait besoin de certaines informations (dans notre cas, des informations qui seraient transmises aux éléments) et nous aurions besoin d'y accéder pour construire l'objet champ.

Exemple:

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),
        },
      },
    },
    // ...
  },
});

Cela pourrait fonctionner mais la question serait de savoir s'il existe un moyen de passer les arguments et/ou de résoudre l'objet aux champs.

Question Donc notre question est maintenant: quelle voie serait recommandée dans notre cas dans GraphQL et la solution 1 ou 2 est-elle possible? Peut-être existe-t-il une autre solution?

Edit La solution 1 fonctionnerait lors de l'utilisation de ScalarType. Exemple:

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

Je ne sais pas si c'est une façon recommandée de résoudre notre situation.

16
TJR

Une autre solution possible pourrait être de déclarer un tel objet dynamique sous forme de chaîne. Et puis passez une version chaîne de l'objet en tant que valeur à cet objet à partir de vos fonctions de résolution. Et finalement, vous pouvez à nouveau analyser cette chaîne en JSON pour en faire à nouveau un objet côté client.

Je ne sais pas si c'est recommandé ou non, mais j'ai essayé de le faire fonctionner avec cette approche et cela a fonctionné sans problème, donc je le partage ici.

0
Point Networks