Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve graphql dataProviders #6628

Merged
merged 3 commits into from
Sep 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 25 additions & 5 deletions examples/demo/src/dataProvider/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { ApolloQueryResult } from '@apollo/client';
import buildApolloClient, {
buildQuery as buildQueryFactory,
} from 'ra-data-graphql-simple';
import { DELETE, LegacyDataProvider } from 'react-admin';
import { BuildQuery } from 'ra-data-graphql';
import { DataProvider, DELETE } from 'react-admin';
import gql from 'graphql-tag';
import {
IntrospectionField,
Expand Down Expand Up @@ -48,7 +49,7 @@ interface IntrospectionResults {

const customBuildQuery = (
introspectionResults: IntrospectionResults
): LegacyDataProvider => {
): BuildQuery => {
const buildQuery = buildQueryFactory(introspectionResults);

return (type, resource, params) => {
Expand Down Expand Up @@ -88,7 +89,26 @@ export default async () => {
buildQuery: customBuildQuery,
});

return (type: string, resource: string, params: any) => {
return dataProvider(type, getGqlResource(resource), params);
};
return new Proxy<DataProvider>(defaultDataProvider, {
get: (target, name) => {
if (typeof name === 'symbol' || name === 'then') {
return;
}
return async (resource: string, params: any) => {
return dataProvider[name](getGqlResource(resource), params);
};
},
});
};
// Only used to initialize proxy
const defaultDataProvider: DataProvider = {
create: () => Promise.reject({ data: null }), // avoids adding a context in tests
delete: () => Promise.reject({ data: null }), // avoids adding a context in tests
deleteMany: () => Promise.resolve({ data: [] }), // avoids adding a context in tests
getList: () => Promise.resolve({ data: [], total: 0 }), // avoids adding a context in tests
getMany: () => Promise.resolve({ data: [] }), // avoids adding a context in tests
getManyReference: () => Promise.resolve({ data: [], total: 0 }), // avoids adding a context in tests
getOne: () => Promise.reject({ data: null }), // avoids adding a context in tests
update: () => Promise.reject({ data: null }), // avoids adding a context in tests
updateMany: () => Promise.resolve({ data: [] }), // avoids adding a context in tests
};
16 changes: 2 additions & 14 deletions examples/demo/src/dataProvider/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import {
convertLegacyDataProvider,
DataProvider,
LegacyDataProvider,
} from 'react-admin';
import { DataProvider } from 'react-admin';
import fakeServerFactory from '../fakeServer';

export default (type: string) => {
Expand All @@ -20,12 +16,6 @@ export default (type: string) => {
get(_, name) {
return (resource: string, params: any) => {
return dataProviderPromise.then(dataProvider => {
// We have to convert the dataProvider here otherwise the proxy would try to intercept the promise resolution
if (typeof dataProvider === 'function') {
return convertLegacyDataProvider(dataProvider)[
name.toString()
](resource, params);
}
return dataProvider[name.toString()](resource, params);
});
};
Expand All @@ -35,9 +25,7 @@ export default (type: string) => {
return dataProviderWithGeneratedData;
};

const getDataProvider = async (
type: string
): Promise<DataProvider | LegacyDataProvider> => {
const getDataProvider = async (type: string): Promise<DataProvider> => {
await fakeServerFactory(process.env.REACT_APP_DATA_PROVIDER || '');
/**
* This demo can work with either a fake REST server, or a fake GraphQL server.
Expand Down
2 changes: 1 addition & 1 deletion packages/ra-core/src/dataProvider/useDataProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ const useDataProvider = <
const dataProviderProxy = useMemo<DataProviderProxy<TDataProvider>>(() => {
return new Proxy(dataProvider, {
get: (target, name) => {
if (typeof name === 'symbol') {
if (typeof name === 'symbol' || name === 'then') {
return;
}
return (...args) => {
Expand Down
2 changes: 2 additions & 0 deletions packages/ra-data-graphql-simple/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
A GraphQL data provider for [react-admin](https://github.com/marmelab/react-admin/)
built with [Apollo](https://www.apollodata.com/) and tailored to target a simple GraphQL implementation.

**This is an example implementation to show how to build a graphql adapter using `ra-data-graphql`.**

- [Installation](#installation)
- [Usage](#installation)
- [Options](#options)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ describe('getArgType', () => {

describe('buildArgs', () => {
it('returns an empty array when query does not have any arguments', () => {
expect(buildArgs({ args: [] })).toEqual([]);
expect(buildArgs({ args: [] }, {})).toEqual([]);
});

it('returns an array of args correctly filtered when query has arguments', () => {
Expand All @@ -84,7 +84,7 @@ describe('buildArgs', () => {

describe('buildApolloArgs', () => {
it('returns an empty array when query does not have any arguments', () => {
expect(print(buildApolloArgs({ args: [] }))).toEqual([]);
expect(print(buildApolloArgs({ args: [] }, {}))).toEqual([]);
});

it('returns an array of args correctly filtered when query has arguments', () => {
Expand Down
Loading