Skip to content

Instantly share code, notes, and snippets.

@xwlee
Created December 23, 2018 08:04
Show Gist options
  • Save xwlee/dc83825986c9d46490346b00353366e0 to your computer and use it in GitHub Desktop.
Save xwlee/dc83825986c9d46490346b00353366e0 to your computer and use it in GitHub Desktop.

Revisions

  1. xwlee created this gist Dec 23, 2018.
    78 changes: 78 additions & 0 deletions date-directive.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,78 @@
    const { ApolloServer, gql, SchemaDirectiveVisitor } = require('apollo-server');
    const { GraphQLScalarType, defaultFieldResolver, GraphQLString } = require('graphql');
    const { Kind } = require('graphql/language');
    const formatDate = require("dateformat");

    const typeDefs = gql`
    directive @date(
    defaultFormat: String = "mmmm d, yyyy"
    ) on FIELD_DEFINITION
    scalar Date
    type Query {
    today: Date @date
    }
    `;

    const resolvers = {
    Query: {
    today: () => {
    return new Date;
    }
    },
    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;
    },
    }),
    };

    class FormattableDateDirective extends SchemaDirectiveVisitor {
    visitFieldDefinition(field) {
    const { resolve = defaultFieldResolver } = field;
    const { defaultFormat } = this.args;

    field.args.push({
    name: 'format',
    type: GraphQLString
    });

    field.resolve = async function (
    source,
    { format, ...otherArgs },
    context,
    info
    ) {
    const date = await resolve.call(this, source, otherArgs, context, info);
    // If a format argument was not provided, default to the optional
    // defaultFormat argument take by the @date directive
    return formatDate(date, format || defaultFormat);
    };
    // The formatted Date becomes a String, so the field type must change:
    field.type = GraphQLString;
    }
    }

    const server = new ApolloServer({
    typeDefs,
    resolvers,
    schemaDirectives: {
    date: FormattableDateDirective
    }
    });

    server.listen().then(({ url }) => {
    console.log(`Server ready at ${url}`)
    });