hasura / ra-data-hasura

react-admin data provider for Hasura GraphQL Engine
MIT License
336 stars 70 forks source link

Support for new hasura naming convention (graphql-default) #130

Open spion opened 1 year ago

spion commented 1 year ago

I tried to do this by modifying the operation template

function decapitalize(s: string) {
  if (s.length < 1) return s;
  return s.charAt(0).toLowerCase() + s.substring(1);
}
const operationTemplate = {
  GET_LIST: (resource: { name: string }) => `${decapitalize(resource.name)}`,
  GET_ONE: (resource: { name: string }) => `${decapitalize(resource.name)}`,
  GET_MANY: (resource: { name: string }) => `${decapitalize(resource.name)}`,
  GET_MANY_REFERENCE: (resource: { name: string }) => {
    console.log("Getting reference for", resource);
    return `${decapitalize(resource.name)}`;
  },
  CREATE: (resource: { name: string }) => `insert${resource.name}`,
  UPDATE: (resource: { name: string }) => `update${resource.name}`,
  UPDATE_MANY: (resource: { name: string }) => `update${resource.name}`,
  DELETE: (resource: { name: string }) => `delete${resource.name}`,
  DELETE_MANY: (resource: { name: string }) => `delete${resource.name}`,
};

However this is insufficient as relationships such as e.g. otherEntity cannot be found

Unknown resource otherEntities. Make sure it has been declared on your server side schema. Known resources are OtherEntity, ...
arjunyel commented 1 year ago

Do you by chance have any repo I can test out?

cassus commented 1 year ago

I found a way to make it work:

function lowerFirst(s: string) {
  if (s.length < 1) return s
  return s.charAt(0).toLowerCase() + s.substring(1)
}
type Resource = { name: string }
const introspectionOptions = {
  include: ["Surveys", "SurveyAccess", "Users"],
  operationNames: {
    [GET_LIST]: (resource: Resource) => `${lowerFirst(resource.name)}`,
    [GET_ONE]: (resource: Resource) => `${lowerFirst(resource.name)}`,
    [GET_MANY]: (resource: Resource) => `${lowerFirst(resource.name)}`,
    [GET_MANY_REFERENCE]: (resource: Resource) =>
      `${lowerFirst(resource.name)}`,
    [CREATE]: (resource: Resource) => `insert${resource.name}`,
    [UPDATE]: (resource: Resource) => `update${resource.name}`,
    [UPDATE_MANY]: (resource: Resource) => `update${resource.name}`,
    [DELETE]: (resource: Resource) => `delete${resource.name}`,
    [DELETE_MANY]: (resource: Resource) => `delete${resource.name}`,
  },
}

useEffect(() => {
    if (!client) return

    const buildDataProvider = async () => {
      const _dataProvider = await buildHasuraProvider(
        {
          client,
          introspection: introspectionOptions,
        },
        {
          aggregateFieldName(resourceName) {
            return `${lowerFirst(resourceName)}Aggregate`
          },
        },
      )
      setDataProvider(() => _dataProvider)
    }
    void buildDataProvider()
  }, [client])
gregorojstersek commented 1 year ago

Thanks @cassus that works great!