ra-data-graphql
Version:
A GraphQL data provider for react-admin
79 lines • 2.88 kB
JavaScript
import { getIntrospectionQuery, } from 'graphql';
import { gql } from '@apollo/client';
import { ALL_TYPES } from "./constants.js";
/**
* @param {ApolloClient} client The Apollo client
* @param {Object} options The introspection options
*/
export const introspectSchema = async (client, options) => {
const schema = options.schema ? options.schema : await fetchSchema(client);
const queries = getQueriesFromSchema(schema);
const types = getTypesFromSchema(schema);
const resources = getResources(types, queries, options);
return {
types,
queries,
resources,
schema,
};
};
const fetchSchema = (client) => client
.query({
fetchPolicy: 'network-only',
query: gql `
${getIntrospectionQuery()}
`,
})
.then(({ data: { __schema } }) => __schema);
const getQueriesFromSchema = (schema) => schema.types.reduce((acc, type) => {
if (type.name !== schema.queryType?.name &&
type.name !== schema.mutationType?.name &&
type.fields) {
return acc;
}
return [...acc, ...(type.fields || [])];
}, []);
const getTypesFromSchema = (schema) => schema.types.filter(type => type.name !== (schema.queryType && schema.queryType.name) &&
type.name !== (schema.mutationType && schema.mutationType.name));
const getResources = (types, queries, options) => {
const filteredResources = types.filter(type => isResource(type, queries, options));
return filteredResources.map(type => buildResource(type, queries, options));
};
const isResource = (type, queries, options) => {
if (isResourceIncluded(type, options))
return true;
if (isResourceExcluded(type, options))
return false;
const operations = Object.keys(options.operationNames).map(operation => options.operationNames[operation](type));
const hasAtLeastOneOperation = operations.some(operation => queries.find(({ name }) => name === operation));
return hasAtLeastOneOperation;
};
export const isResourceIncluded = (type, { include } = {}) => {
if (Array.isArray(include)) {
return include.includes(type.name);
}
if (typeof include === 'function') {
return include(type);
}
return false;
};
export const isResourceExcluded = (type, { exclude } = {}) => {
if (Array.isArray(exclude)) {
return exclude.includes(type.name);
}
if (typeof exclude === 'function') {
return exclude(type);
}
return false;
};
const buildResource = (type, queries, options) => ALL_TYPES.reduce((acc, raFetchMethod) => {
const query = queries.find(({ name }) => options.operationNames[raFetchMethod] &&
name === options.operationNames[raFetchMethod](type));
if (!query)
return acc;
return {
...acc,
[raFetchMethod]: query,
};
}, { type });
//# sourceMappingURL=introspection.js.map