-
-
Notifications
You must be signed in to change notification settings - Fork 5.3k
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
GraphQL Simple Data Provider Extensions Support #9403
GraphQL Simple Data Provider Extensions Support #9403
Conversation
Hi, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks really cool. I wonder whether the extension code should be in ra-data-graphql
directly
@djhi That's a great point. I think moving it down a level would be a good idea. That was definitely on my wishlist when integrating with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please explain what is currently preventing you from implementing such custom methods? Is it because we use a Proxy? Because we don't allow you to specify the DataProvider type? Something else?
All of our
As mentioned in #9392 (comment), |
# Conflicts: # packages/ra-data-graphql-simple/src/index.ts # packages/ra-data-graphql/src/index.ts
@djhi Sorry I missed your change requests. Just got those pushed up. Do you have any final thoughts on this proposal? |
After careful consideration, we believe this abstraction layer is unnecessary. You can already add those methods by extending the resulting dataProvider: const dataProvider = await buildGraphQLProvider({ clientOptions: { uri: 'http://localhost:4000' } });
return {
...dataProvider,
subscribe: async (topic: string, subscriptionCallback: any) => {
// The code you added for it
},
// etc
}; Besides, should you need to add custom queries generated from the schema, you would need to provide your own import { DataProvider } from 'ra-core';
import { BuildQueryFactory } from 'ra-data-graphql';
import buildDataProvider, { buildQuery } from 'ra-data-graphql-simple';
interface CustomDataProvider extends DataProvider {
subscribe: (resource: string, params: any) => void;
}
export const buildCustomDataProvider: Promise<CustomDataProvider> = async (
options: Parameters<typeof buildDataProvider>[0]
) => {
const dataProvider = await buildDataProvider({
...options,
buildQuery: buildCustomQuery,
});
return {
...dataProvider,
subscribe: (resource, params) => {
// takes introspectionResults but we don't have access to it here
buildCustomQuery()
},
};
};
const buildCustomQuery: BuildQueryFactory = introspectionResults => (
name: string,
resource: string,
params: any
) => {
if (name === 'subscribe') {
// Build the subscription query and return it
return null;
}
return buildQuery(introspectionResults)(name, resource, params);
}; I believe the solution is to add a import { DataProvider } from 'ra-core';
import { BuildQueryFactory } from 'ra-data-graphql';
import buildDataProvider, { buildQuery } from 'ra-data-graphql-simple';
interface CustomDataProvider extends DataProvider {
subscribe: (resource: string, params: any) => void;
}
export const buildCustomDataProvider: Promise<CustomDataProvider> = async (
options: Parameters<typeof buildDataProvider>[0]
) => {
const dataProvider = await buildDataProvider({
...options,
buildQuery: buildCustomQuery,
});
return {
...dataProvider,
subscribe: async (resource, params) => {
const introspection = await dataProvider.getIntrospection();
// Do what you want with it, including calling your buildCustomQuery but not necessarily.
},
};
};
const buildCustomQuery: BuildQueryFactory = introspectionResults => (
name: string,
resource: string,
params: any
) => {
if (name === 'subscribe') {
// Build the subscription query and return it
return null;
}
return buildQuery(introspectionResults)(name, resource, params);
}; |
Data Provider Extensions
A GraphQL backend may support functionality that extends beyond the default Data Provider methods. One such example of this would be implementing GraphQL subscriptions and integrating ra-realtime to power realtime updates in your React-Admin application. The extensions pattern allows you to easily expand the Data Provider methods to power this additional functionality. A Data Provider Extension is defined by the following type:
The
methodFactory
is a required function attribute that generates the additional Data Provider methods. It always receives the dataProvider as it's first argument. Arguments defined in the factoryArgs optional attribute will also be passed intomethodFactory
.introspectionOperationNames
is an optional object attribute that allows you to inform React-Admin hooks and UI components of how these methods map to the GraphQL schema.Realtime Extension
I've added an example Realtime Data Provider Extension that can be opted into. If your app uses ra-realtime, you can drop in the Realtime Extension and light up realtime events. Here is an example integration: