olange
olange

Reputation: 175

How to use the names in a GraphQLEnumType as the defaultValue of a GraphQL query argument?

When defining a query in a schema, how do I refer to a value of an GraphQLEnumType declared previously, to use it as the default value of an argument?

Let's say I've defined following ObservationPeriod GraphQLEnumType:

observationPeriodEnum = new GraphQLEnumType {
  name: "ObservationPeriod"
  description: "One of the performance metrics observation periods"
  values:
    Daily:
      value: '1D'
      description: "Daily"
    […]
}

and use it as the type of query argument period:

queryRootType = new GraphQLObjectType {
  name: "QueryRoot"
  description: "Query entry points to the DWH."
  fields:
    performance:
      type: performanceType
      description: "Given a portfolio EID, an observation period (defaults to YTD)
                    and as-of date, as well as the source performance engine,
                    return the matching performance metrics."
      args:
        period:
          type: observationPeriodEnum 
          defaultValue: observationPeriodEnum.Daily ← how to achieve this?
      […]
}

Currently I'm using the actual '1D' string value as the default value; this works:

        period:
          type: observationPeriodEnum 
          defaultValue: '1D'

But is there a way I could use the Daily symbolic name instead? I couldn't find a way to use the names within the schema itself. Is there something I overlooked?

I'm asking, because I was expecting an enum type to behave as a set of constants also, and to be able to use them like this in the schema definition:

        period:
          type: observationPeriodEnum 
          defaultValue: observationPeriodEnum.Daily

Naïve workaround:

##
# Given a GraphQLEnumType instance, this macro function injects the names 
# of its enum values as keys the instance itself and returns the modified
# GraphQLEnumType instance.
#
modifiedWithNameKeys = (enumType) ->
  for ev in enumType.getValues()
    unless enumType[ ev.name]?
      enumType[ ev.name] = ev.value
    else
      console.warn "SCHEMA> Enum name #{ev.name} conflicts with key of same
        name on GraphQLEnumType object; it won't be injected for value lookup"
  enumType

observationPeriodEnum = modifiedWithNameKeys new GraphQLEnumType {
  name: "description: "Daily""
  values:
    […]

which allows to use it as desired in schema definition:

        period:
          type: observationPeriodEnum 
          defaultValue: observationPeriodEnum.Daily

Of course, this modifier fullfils its promise, only as long as the enum names do not interfere with GraphQLEnumType existing method and variable names (which are currently: name, description, _values, _enumConfig, _valueLookup, _nameLookup, getValues, serialize, parseValue, _getValueLookup, _getNameLookup and toString — see definition of GraphQLEnumType class around line 687 in https://github.com/graphql/graphql-js/blob/master/src/type/definition.js#L687)

Upvotes: 6

Views: 4519

Answers (3)

silvenon
silvenon

Reputation: 2197

I found a pull request adding a method .getValue() to enum types, which returns name and value. In your case this call:

observationPeriodEnum.getValue('Daily');

would return:

{
  name: 'Daily',
  value: '1D'
}

Upvotes: 0

Justin Mandzik
Justin Mandzik

Reputation: 255

It's possible to declare enum values as default inputs via the schema definition language, but it looks like you are only using the JS library APIs. You might be able to get to a solution by taking a look at the ASTs for the working example and comparing that with the AST from what your JS code is producing.

Sorry not a solution, but hope that helps!

Upvotes: 0

Matthew Herbst
Matthew Herbst

Reputation: 31973

I just ran into this. My enum:

const contributorArgs = Object.assign(
  {},
  connectionArgs, {
    sort: {
      type: new GraphQLEnumType({
        name: 'ContributorSort',
        values: {
          top: { value: 0 },
        },
      })
    },
  }
);

In my queries, I was doing:

... on Topic {
  id
  contributors(first: 10, sort: 'top') {
    ...
  }
}

Turns out you just don't quote the value (which after thinking about it makes sense; it's a value in the enum type, not an actual value:

... on Topic {
  id
  contributors(first: 10, sort: top) {
    ...
  }
}

Upvotes: 1

Related Questions