ra-data-graphql-simple
Version:
A GraphQL simple data provider for react-admin
93 lines (82 loc) • 2.73 kB
text/typescript
import {
DELETE_MANY,
GET_LIST,
GET_MANY,
GET_MANY_REFERENCE,
UPDATE_MANY,
} from 'ra-core';
import { IntrospectionResult, IntrospectedResource } from 'ra-data-graphql';
import { IntrospectionField } from 'graphql';
import { ApolloQueryResult } from '@apollo/client';
export default (_introspectionResults: IntrospectionResult) =>
(
raFetchMethod: string,
_resource: IntrospectedResource,
_queryType: IntrospectionField
) =>
(response: ApolloQueryResult<any>) => {
const data = response.data;
if (
raFetchMethod === GET_LIST ||
raFetchMethod === GET_MANY ||
raFetchMethod === GET_MANY_REFERENCE
) {
return {
data: response.data.items.map(sanitizeResource),
total: response.data.total.count,
};
} else if (
raFetchMethod === DELETE_MANY ||
raFetchMethod === UPDATE_MANY
) {
return { data: sanitizeResource(data.data).ids };
}
return { data: sanitizeResource(data.data) };
};
const sanitizeResource = (data: any) => {
const result = Object.keys(data).reduce((acc, key) => {
if (key.startsWith('_')) {
return acc;
}
const dataForKey = data[key];
if (dataForKey === null || dataForKey === undefined) {
return acc;
}
if (Array.isArray(dataForKey)) {
if (
typeof dataForKey[0] === 'object' &&
dataForKey[0] != null &&
// If there is no id, it's not a reference but an embedded array
dataForKey[0].id != null
) {
return {
...acc,
[key]: dataForKey.map(sanitizeResource),
[`${key}Ids`]: dataForKey.map(d => d.id),
};
} else {
return { ...acc, [key]: dataForKey };
}
}
if (
typeof dataForKey === 'object' &&
dataForKey != null &&
// If there is no id, it's not a reference but an embedded object
dataForKey.id != null
) {
return {
...acc,
...(dataForKey &&
dataForKey.id && {
[`${key}.id`]: dataForKey.id,
}),
// We should only sanitize gql types, not objects
[key]: dataForKey.__typename
? sanitizeResource(dataForKey)
: dataForKey,
};
}
return { ...acc, [key]: dataForKey };
}, {});
return result;
};