Apollo-link-rest: [Aide recherchée] Une requête avec une réponse où les clés d'objet dynamiques sont

Créé le 3 juil. 2020  ·  4Commentaires  ·  Source: apollographql/apollo-link-rest

Je demande des données de schéma Salesforce. Il a un format

res = {
  Id: { name, type, label },
  IsDeleted: { type, name, label },
  MasterRecordId: { type, name, label },
 ...and so on
}

Ainsi, les champs sont dynamiques.

Dans queries.js, j'essaie de le décrire

export const GET_SALESFORCE_FIELDS = gql`
  query SalesforceFields {
    salesforceFields @rest(endpoint: "schemaservice", type: "SalesforceFields", path: "/fields") {
       // What should be here??
   }
  }
`;
`

Comment décrire la partie dynamique ? Je n'ai aucun fichier de schéma ni résolveur. Uniquement queries.js (pour d'autres requêtes avec useQuery) et client.js (où le nouvel ApolloClient est défini)

"@apollo/client": "^3.0.0-rc.10",
"apollo-link-rest": "^0.8.0-beta.0",

question❔

Tous les 4 commentaires

@ssuvorov -- Avez-vous vérifié que l'appel réseau est passé avec succès ?

Si c'est le cas, alors basé uniquement sur votre exemple de réponse : je ferais quelque chose comme :

export const GET_SALESFORCE_FIELDS = gql`
  query SalesforceFields {
    salesforceFields @rest(endpoint: "schemaservice", type: "SalesforceFields", path: "/fields") {
       Id {
         type, name, label
       }
       IsDeleted {
         type, name, label
       }
       # …remaining fields
   }
  }
`;

-- Maintenant, cela peut ne pas fonctionner car GraphQL s'attend à ce que chaque type ait un nom, donc à la place, vous devrez peut-être changer ceci :

export const GET_SALESFORCE_FIELDS = gql`
  query SalesforceFields {
    salesforceFields @rest(endpoint: "schemaservice", type: "SalesforceFields", path: "/fields") {
-      Id {
+      Id @type(name: "FieldDescriptor") {
         type, name, label
       }
-      IsDeleted {
+      IsDeleted @type(name: "FieldDescriptor") {
         type, name, label
       }
       # …remaining fields
   }
  }
`;

(Une autre façon de le faire est d'utiliser un TypePatcher - documenté dans la documentation)

Si chaque entrée correspond au même schéma d'objet, vous pouvez même utiliser un fragment pour vous aider :

export const GET_SALESFORCE_FIELDS = gql`
  query SalesforceFields {
    salesforceFields @rest(endpoint: "schemaservice", type: "SalesforceFields", path: "/fields") {
       Id @type(name: "FieldDescriptor") {
-          type, name, label
+          ...FieldFrag
       }
       IsDeleted @type(name: "FieldDescriptor") {
-          type, name, label
+          ...FieldFrag
       }
       # …remaining fields
   }
+ fragment FieldFrag on FieldDescriptor {
+    type
+    name
+    label
+ }
 }`;

Si vous utilisez Salesforce de manière générique et que vous ne savez pas combien de colonnes vous allez avoir, cela devient un peu plus compliqué et vous devez utiliser le correctif de type pour modifier la forme du API.

Je n'utilise pas Salesforce - mais si c'était moi, j'envisagerais de demander à mon représentant Salesforce s'il a une offre GraphQL officielle ou s'il a une offre tierce bénie pour l'obtenir en natif.

Une recherche rapide sur Google a montré que cela existait : https://appexchange.salesforce.com/appxListingDetail?listingId=a0N3A00000G0l6nUAB -- mais il n'y a qu'un seul avis, donc je ne sais pas si c'est bon.

@fbartho Merci beaucoup pour votre réponse. Malheureusement, c'est plus de 500 champs. Eh bien, j'essaierais de clarifier avec l'équipe SF.

Si vous avez besoin de traiter une réponse pour rendre cela un peu plus facile, vous pouvez utiliser un typenamePatcher, qui vous donnera un crochet pour remodeler complètement la réponse.

Un schéma meilleur/plus générique pourrait virtuellement ressembler à ceci :

type MyResponse (
  columns: [Column!]!
}
type Column {
  name: String!
  type: String!
  label: String!
}

@fbartho Merci pour votre aide. C'est comme ça que je l'ai résolu.

// queries.js
export const GET_SALESFORCE_FIELDS = gql`
  query SalesforceFields {
    salesforceFields @rest(endpoint: "schemaservice", type: "SalesforceFieldsPayload", path: "/fields") {
      items @type(name: "Salesforce")
    }
  }
`;

// client.js
const restLink = new RestLink({
  ...,
  typePatcher: {
    SalesforceFieldsPayload: (
      data,
      outerType,
      patchDeeper
    ) => {
      if (data != null) {
        data.items = Object.keys(data).map(field => ({ __typename: "Salesforce", ...data[field] }));
      }
      return data;
    }
  }
});
Cette page vous a été utile?
0 / 5 - 0 notes