Luis Maldonado
Luis Maldonado

Reputation: 378

Custom scalar on apollo server

Im trying to define a custom scalar on apollo server, so far here is what i've got

Custom scalar file (timestamp.js)

import { isRFC3339 } from 'validator';
import { GraphQLScalarType } from 'graphql';

export default new GraphQLScalarType({
  name: 'Timestamp',
  description: 'RFC3339 Timestamp format',
  serialize(value) {
    if (isRFC3339(value)) {
      return value;
    }
    throw new Error('Timestamp cannot represent an invalid RFC-3339 Timestamp string');
  },
  parseValue(value) {
    if (isRFC3339(value)) {
      return value;
    }
    throw new Error('Timestamp cannot represent an invalid RFC-3339 Timestamp string');
  },
  parseLiteral(ast) {
    if (isRFC3339(ast.value)) {
      return ast.value;
    }
    throw new Error('Timestamp cannot represent an invalid RFC-3339 Timestamp string');
  }
});

In my schema, my schema is in several files, but I join them together before passing them to makeExecutableSchema.

scalar Timestamp

On the file that has the makeExecutableSchema that later on is exported and user in my server constructor.

import timeStamp from './scalars/timeStamp';
.
.
.
.
const schema = {
  typeDefs: [
    myTypeDefs
  ],
  resolvers: merge(
    resolvers,
    timeStamp
  ),
};

export default makeExecutableSchema({
  typeDefs: schema.typeDefs,
  resolvers: schema.resolvers
});

I dont know what im missing because i have this error when trying to run my API

throw new _1.SchemaError("\"" + typeName + "\" defined in resolvers, but has invalid value \"" + resolverValue + "\". A resolver's value " +
            ^

Error: "name" defined in resolvers, but has invalid value "Timestamp". A resolver's value must be of type object or function.

Any help would be greatly appreciated. Thanks in advance!

Upvotes: 0

Views: 2418

Answers (1)

Daniel Rearden
Daniel Rearden

Reputation: 84807

When building a schema using apollo-server (or graphql-tools), the resolvers parameter must be an object whose properties are either

  • the name of an output object type in your schema
  • the name of a (custom) scalar type
  • the name of an enum type

In other words, the resulting object should look something like:

const resolvers = {
  Query: {
    // field resolvers here...
  },
  // Maybe some other object types here...
  Timestamp: timeStamp,
}

Note that for our custom scalars, the property name needs to match the name we've specified for the scalar. This is also the same name you include in your typeDefs. In this case, the property would be Timestamp and we would set it to the GraphQLScalarType we instantiated.

So, assuming your actual resolvers variable is correctly formatted, you need to do:

merge(
  resolvers,
  { Timestamp: timeStamp }
)

Alternatively, you can also change your timeStamp's default export...

export default { Timestamp: new GraphQLScalarType(...) }

or just forgo using merge altogether using spread syntax :)

resolvers: {
  ...resolvers,
  Timestamp: timeStamp,  
}

Upvotes: 4

Related Questions