apollo-server: Custom scalars don't run when using modules

Hi! We are using Apollo Server modules to organize our code at OkCupid, and as I looked into adding custom scalars to our graph, it appears that they don’t quite work with modules.

I took this example from the Apollo Server docs, added a few console logs, and updated it to pass the typeDefs and resolvers in as a module instead of on the top level.

const { ApolloServer, gql } = require('apollo-server');
const { GraphQLScalarType, Kind } = require('graphql');

const myCustomScalarType = new GraphQLScalarType({
  name: 'MyCustomScalar',
  description: 'Description of my custom scalar type',
  serialize(value) {
    console.log("serialize");
    let result;
    // Implement custom behavior by setting the 'result' variable
    return result;
  },
  parseValue(value) {
    console.log("parse");
    let result;
    // Implement custom behavior here by setting the 'result' variable
    return result;
  },
  parseLiteral(ast) {
    console.log("literal");
    switch (ast.kind) {
      case Kind.Int:
      // return a literal value, such as 1 or 'static string'
    }
  }
});

const schemaString = gql`
  scalar MyCustomScalar

  type Foo {
    aField: MyCustomScalar
  }

  type Query {
    foo: Foo
  }
`;

const resolverFunctions = {
  MyCustomScalar: myCustomScalarType,
  Query: {
    foo: () => {
      return { aField: 1 };
    },
  },
};

const scalarModule = {
  typeDefs: schemaString,
  resolvers: resolverFunctions,
};

const server = new ApolloServer({
  modules: [ scalarModule ],
});

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

I expect the docs to reflect the new type, and for the serialize log on line 8 to run when a request is made in playground. But while I see the the MyCustomScalar type details, the description doesn’t come through. And when I execute a request, none of the myCustomScalarType functions run.

Thanks in advance for your time, and thanks for making a great tool! Please let me know if there’s anything else I can provide to help debug this. I’m also quite new to GraphQL, so let me know if I’ve misunderstood something here!

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 5
  • Comments: 15 (5 by maintainers)

Most upvoted comments

For what it’s worth, a solution that I found is to just… not use modules. The code in the server config becomes a little more complex, but you can do the following:

import { ApolloServer, makeExecutableSchema, gql } from "apollo-server-express";
import { merge } from "lodash";

// an example module
import user from "modules/user";

const schema = makeExecutableSchema({
	typeDefs: [
		user.typeDefs,
		// etc.
	],
	resolvers: merge(
		user.resolvers,
		// etc.
	),
});

const server = new ApolloServer({
	schema,
});

This also fixes another bug with modules — if you make a union type when using modules, Apollo doesn’t tell you about (or run) the __resolveType function for them. So I’d recommend moving to the method above, even though it’s more verbose.

So is this going to be fixed?

This seems crazy that it has been open for so long and is an extremely surprising limiting feature

Thank you for reporting this issue!

As you’ve both found here, this is currently a limitation of the modules implementation in Apollo Server which internally leverages @apollographql/apollo-tools’s buildServiceDefinition rather than graphql-tools’s makeExecutableSchema which supports custom scalars directly in the resolver map.

Longer-term, we suspect that we’ll land on a more effective module approach with buildServiceDefinition than that is currently possible with makeExecutableSchema, but the patterns you’ve adopted above may be better suited in for some scenarios (e.g. custom scalars) in the short-term.

This is all to say, it’s on our radar, particularly as we move to introduce further modularization for federation support.

@abernix thx and sorry for the noise, as I mentioned on the linked ticket, it turns out it was the interaction between a lib of mine graphql-validated-types which was extending GraphQLScalarType and graphql where the changed implementation in 14.x.x broke my implementation