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",
@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๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค)
๋ชจ๋ ํญ๋ชฉ์ด ๋์ผํ ๊ฐ์ฒด ์คํค๋ง ์ธ ๊ฒฝ์ฐ Fragment๋ฅผ ์ฌ์ฉํ์ฌ ๋ค์์ ์ํ ํ ์๋ ์์ต๋๋ค.
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๋ฅผ ์ผ๋ฐ์ ์ธ ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ๊ณ ์๊ณ ๋ช ๊ฐ์ ์ด ์ ๊ฐ์ง ์ง ๋ชจ๋ฅด๋ ๊ฒฝ์ฐ ์กฐ๊ธ ๋ ๋ณต์กํด์ง๊ณ type-patcher๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ์์ ๋ณ๊ฒฝํด์ผํฉ๋๋ค. API.
์ ๋ Salesforce๋ฅผ ์ฌ์ฉํ์ง ์์ต๋๋ค.ํ์ง๋ง ์ ๋ผ๋ฉด Salesforce ๋ด๋น์์๊ฒ ๊ณต์ GraphQL ์คํผ๋ง์ด ์๋์ง ๋๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณต๋๋ ์ 3 ์ ์คํผ๋ง์ด ์๋์ง ๋ฌธ์ํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
๋น ๋ฅธ 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;
}
}
});