Skip to content

[RFC] "3.1.5 Enums" - requires additional consideration. Use complex objects with functions for enum values. #435

Closed
@nodkz

Description

@nodkz

In graphql-compose-connection I use Enum type for storing avaliable sortings for connections, so values represent complex objects with function, eg:

var ConnectionSortUserEnum = new GraphQLEnumType({
  name: 'ConnectionSortUserEnum',
  values: {
    AGE_ID_DESC: {
      uniqueFields: ['age', '_id'],
      sortValue: { age: -1, _id: 1 },
      directionFilter: (cursorData, filter, isBefore) => {
        // some code for extending filter with data obtained from `before` or `after` cursors 
        return filter;
      },
    },
    ...someOtherSorts
  }
});

With such Enum graphql server starts and works perfectly (example).

But throws error when I try to build introspection graphql(Schema, introspectionQuery) or run printSchema(Schema):

[11:33:10] Starting 'buildSchema'...
ERROR introspecting schema:  [
  {
    "path": [
      "__schema",
      "types",
      1,
      "fields",
      21,
      "args",
      5,

      "defaultValue"
    ],
    "originalError": {}
  }
]
Error
    at invariant (invariant.js:19:11)
    at astFromValue (astFromValue.js:112:3)
    at astFromValue.js:123:22
    at Array.forEach (native)
    at astFromValue (astFromValue.js:117:23)
    at printInputValue (schemaPrinter.js:180:44)
    at Array.map (native)
    at printArgs (schemaPrinter.js:174:39)
    at schemaPrinter.js:155:28
    at Array.map (native)
    at printFields (schemaPrinter.js:154:17)
    at printObject (schemaPrinter.js:121:65)
    at printType (schemaPrinter.js:100:12)
    at Array.map (native)
    at printFilteredSchema (schemaPrinter.js:72:87)
    at printSchema (schemaPrinter.js:37:10)

According to astFromValue.js#L116 it accepts only string values for Enums:

  // JavaScript strings can be Enum values or String values. Use the
  // GraphQLType to differentiate if possible.
  if (typeof _value === 'string') {
    if (type instanceof GraphQLEnumType &&
        /^[_a-zA-Z][_a-zA-Z0-9]*$/.test(_value)) {
      return ({ kind: ENUM, value: _value }: EnumValue);
    }
    // Use JSON stringify, which uses the same string encoding as GraphQL,
    // then remove the quotes.
    return ({
      kind: STRING,
      value: JSON.stringify(_value).slice(1, -1)
    }: StringValue);
  }
export type GraphQLEnumValueConfig/* <T> */ = {
  value?: any/* T */;
  deprecationReason?: ?string;
  description?: ?string;
}

So, according to concept of Enum ...

  • client gets only names from enum
  • enum values can be defined only on server (and client does not know anything about internal enum value)

... I think, that if developer define complex value for enum, so it expects that get it in args for resolve function. And astFromValue should not deeply extract AST for enum's value it should stops on enum's name.

I don't know enough FB internals requirements for ENUMs, so can not provide correct PR for this problem. @leebyron please consider this issue, as soon as possible, because it blocking me.

PS. Passing to enum's value arrow functions, provides for me awesome ability to customise logic in resolve methods - https://github.com/nodkz/graphql-compose-connection/blob/master/src/resolvers/connectionResolver.js#L207

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions