Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is graphql's ID type necessary if I've set an unique identifier with dataIdFromObject in Apollo Client

I'm using graphql + mysql + react-apollo and here's one of the graphql type for User table:

type User {
  id: ID!
  name: String!
}

My issue with ID scalar type in graphql is that it is returned as a string when primary keys are int in mysql and it has created some type conflicts on the frontend with typescript.

Can I just simply not use ID scalar type at all, given that I have already set a unique identifier with dataIdFromObject for each object in Apollo Client:

import {InMemoryCache} from 'apollo-cache-inmemory';

const apolloMemoryCache = new InMemoryCache(
    {
        dataIdFromObject: ({id,__typename}) => {

          return __typename+id

        }
    }
);

const client = new ApolloClient({
   link: ApolloLink.from([authLink, httpLink]),
   cache: apolloMemoryCache,
 });

Would you keep the ID type or just ditch it?

like image 628
RedGiant Avatar asked Apr 25 '18 16:04

RedGiant


2 Answers

You asked

would you keep the ID type or just ditch it

I generally recommend keeping the ID type, and NOT exposing to the client the integer that you are using. If this is a new dataset, you're probably even going to be better off using uuids as the PK from the offset. It's going to be "safer" and "more secure", as you're less likely to accidentally give someone access to someone else's stuff.

Either way, I would recommend making the IDs "opaque", as per the Relay spec, so that you have the ability to change them later, if you change your datastore, without affecting your clients. Apps often do their own type-checking, so you want to make sure your stuff isn't going to ever change in that regard whenever possible.

like image 93
Dan Crews Avatar answered Oct 01 '22 00:10

Dan Crews


You should define a custom scalar for your resolver.

In your resolver you should add one for ID where you expect an int or you can do your conversion between int and string in your resolver.

import { GraphQLScalarType } from 'graphql';

const resolverMap = {
  ID: new GraphQLScalarType({
    name: 'ID',
    description: 'Numeric custom scalar type',
    parseValue(value) {
      let result;
      // Implement your own behavior here by setting the 'result' variable
      return result;
    },
    serialize(value) {
      let result;
      // Implement your own behavior here by setting the 'result' variable
      return result;
    },
    parseLiteral(ast) {
      switch (ast.kind) {
      // Implement your own behavior here by returning what suits your needs
      // depending on ast.kind
      }
    }
  }),
};

https://github.com/apollographql/graphql-tools/blob/master/docs/source/scalars.md#custom-graphqlscalartype-instance

like image 44
Kenneth Truong Avatar answered Oct 01 '22 02:10

Kenneth Truong