Mohamed Taboubi
Mohamed Taboubi

Reputation: 7011

Date and Json in type definition for graphql

Is it possible to have a define a field as Date or JSON in my graphql schema ?

type Individual {
    id: Int
    name: String
    birthDate: Date
    token: JSON
}

actually the server is returning me an error saying :

Type "Date" not found in document.
at ASTDefinitionBuilder._resolveType (****node_modules\graphql\utilities\buildASTSchema.js:134:11)

And same error for JSON...

Any idea ?

Upvotes: 60

Views: 82857

Answers (3)

Yis Yak
Yis Yak

Reputation: 41

I think that the easiest way today is to use the popular graphql-scalars npm package. You can follow the quick-start documentation on the guild for the package.

Basically, after installing the package, you can add to your graphql schema (your "typeDefs") the following line:

scalar DateTime

Then, just add one line into your resolvers (plus of course you need the import statement):

import { DateTimeResolver} from 'graphql-scalars'

export const resolvers = {
    DateTime: DateTimeResolver,

    Query: {
     ...
    },
    ...
};

After that, you can just use DateTime as any other scalar, e.g.

type Post {
    id: ID!
    title: String!
    content: String!
    createdAt: DateTime!
    updatedAt: DateTime!
}

Note that this is exactly the DateTime type used in Prisma.

Upvotes: 1

Andreas Köberle
Andreas Köberle

Reputation: 110892

Have a look at custom scalars: https://www.apollographql.com/docs/graphql-tools/scalars.html

create a new scalar in your schema:

scalar Date
    
type MyType {
    created: Date
}

and create a new resolver:

import { GraphQLScalarType } from 'graphql';
import { Kind } from 'graphql/language';

const resolverMap = {
    Date: new GraphQLScalarType({
        name: 'Date',
        description: 'Date custom scalar type',
        parseValue(value) {
            return new Date(value); // value from the client
        },
        serialize(value) {
            return value.getTime(); // value sent to the client
        },
        parseLiteral(ast) {
            if (ast.kind === Kind.INT) {
            return parseInt(ast.value, 10); // ast value is always in string format
            }
            return null;
        },
    })
};

Upvotes: 82

Martín De la Fuente
Martín De la Fuente

Reputation: 6716

Primitive scalar types in GraphQL are Int, Float, String, Boolean and ID. For JSON and Date you need to define your own custom scalar types, the documentation is pretty clear on how to do this.

In your schema you have to add:

scalar Date

type MyType {
   created: Date
}

Then, in your code you have to add the type implementation:

import { GraphQLScalarType } from 'graphql';

const dateScalar = new GraphQLScalarType({
  name: 'Date',
  parseValue(value) {
    return new Date(value);
  },
  serialize(value) {
    return value.toISOString();
  },
})

Finally, you have to include this custom scalar type in your resolvers:

const server = new ApolloServer({
  typeDefs,
  resolvers: {
    Date: dateScalar,
    // Remaining resolvers..
  },
});

This Date implementation will parse any string accepted by the Date constructor, and will return the date as a string in ISO format.

For JSON you might use graphql-type-json and import it as shown here.

Upvotes: 24

Related Questions