Apollo-link-rest: [Требуется помощь] Запрос с ответом, в котором указаны ключи динамических объектов.

Созданный на 3 июл. 2020  ·  4Комментарии  ·  Источник: apollographql/apollo-link-rest

Я запрашиваю данные схемы Salesforce. Имеет формат

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

Итак, поля динамические.

В query.js я пытаюсь описать это

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

Как я могу описать динамическую часть? У меня нет файлов схемы или преобразователей. Только query.js (для дальнейших запросов с useQuery) и client.js (где определен новый ApolloClient)

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

question❔

Все 4 Комментарий

@ssuvorov - Вы проверили, что сетевой вызов выполняется успешно?

Если это так, то, основываясь только на вашем примере ответа: я бы сделал что-то вроде:

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
   }
  }
`;

- Теперь это может не сработать, потому что GraphQL ожидает, что у каждого типа будет имя, поэтому вместо этого вам может потребоваться изменить это:

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
   }
  }
`;

(Альтернативный способ сделать это - с помощью TypePatcher - задокументировано в документации)

Если каждая запись представляет собой одну и ту же схему объекта, вы даже можете использовать фрагмент, чтобы помочь вам:

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
+ }
 }`;

Если вы используете Salesforce обычным образом и не знаете, сколько столбцов у вас будет, тогда все становится немного сложнее, и вам нужно использовать патчер типов, чтобы изменить форму API.

Я не использую Salesforce, но если бы это был я, я бы подумал о том, чтобы спросить моего представителя Salesforce, есть ли у них официальное предложение GraphQL или есть ли у них благословенное стороннее предложение, чтобы получить его изначально.

Быстрый поиск в Google показал, что это существует: https://appexchange.salesforce.com/appxListingDetail?listingId=a0N3A00000G0l6nUAB - но у него только один обзор, поэтому я понятия не имею, насколько он хорош.

@fbartho Большое спасибо за ваш ответ. К сожалению, это более 500 полей. Что ж, я попробую уточнить у команды SF.

Если вам нужно обработать ответ, чтобы сделать это немного проще, вы можете использовать typenamePatcher, который даст вам возможность полностью изменить форму ответа.

Лучшая / более общая схема может выглядеть примерно так:

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

@fbartho Спасибо за вашу помощь. Вот как я это решил.

// 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;
    }
  }
});
Была ли эта страница полезной?
0 / 5 - 0 рейтинги