{"action":"created","issue":{"url":"https://api.github.com/repos/graphql/graphql-js/issues/435","repository_url":"https://api.github.com/repos/graphql/graphql-js","labels_url":"https://api.github.com/repos/graphql/graphql-js/issues/435/labels{/name}","comments_url":"https://api.github.com/repos/graphql/graphql-js/issues/435/comments","events_url":"https://api.github.com/repos/graphql/graphql-js/issues/435/events","html_url":"https://github.com/graphql/graphql-js/issues/435","id":166031328,"number":435,"title":"[RFC] \"3.1.5 Enums\" - requires additional consideration. Use complex objects with functions for enum values.","user":{"login":"nodkz","id":1946920,"avatar_url":"https://avatars.githubusercontent.com/u/1946920?v=3","gravatar_id":"","url":"https://api.github.com/users/nodkz","html_url":"https://github.com/nodkz","followers_url":"https://api.github.com/users/nodkz/followers","following_url":"https://api.github.com/users/nodkz/following{/other_user}","gists_url":"https://api.github.com/users/nodkz/gists{/gist_id}","starred_url":"https://api.github.com/users/nodkz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nodkz/subscriptions","organizations_url":"https://api.github.com/users/nodkz/orgs","repos_url":"https://api.github.com/users/nodkz/repos","events_url":"https://api.github.com/users/nodkz/events{/privacy}","received_events_url":"https://api.github.com/users/nodkz/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2016-07-18T07:03:04Z","updated_at":"2016-07-18T10:45:42Z","closed_at":null,"body":"In [graphql-compose-connection](https://github.com/nodkz/graphql-compose-connection) I use `Enum type` for storing avaliable sortings for connections, so values represent complex objects with function, eg: \r\n```js\r\nvar ConnectionSortUserEnum = new GraphQLEnumType({\r\n  name: 'ConnectionSortUserEnum',\r\n  values: {\r\n    AGE_ID_DESC: {\r\n      uniqueFields: ['age', '_id'],\r\n      sortValue: { age: -1, _id: 1 },\r\n      directionFilter: (cursorData, filter, isBefore) => {\r\n        // some code for extending filter with data obtained from `before` or `after` cursors \r\n        return filter;\r\n      },\r\n    },\r\n    ...someOtherSorts\r\n  }\r\n});\r\n```\r\nWith such `Enum` graphql server starts and works perfectly ([example](https://graphql-compose-mongoose.herokuapp.com/mongoose-relay?query=%7B%0A%20%20userConnection(sort%3A%20_ID_DESC%2C%20first%3A%203)%20%7B%0A%20%20%20%20edges%20%7B%0A%20%20%20%20%20%20node%20%7B%0A%20%20%20%20%20%20%20%20name%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%2C%0A%20%20u2%3A%20userConnection(sort%3A%20_ID_ASC%2C%20first%3A%203)%20%7B%0A%20%20%20%20edges%20%7B%0A%20%20%20%20%20%20node%20%7B%0A%20%20%20%20%20%20%20%20name%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D)). \r\n\r\nBut throws error when I try to build introspection `graphql(Schema, introspectionQuery)` or run `printSchema(Schema)`:\r\n```\r\n[11:33:10] Starting 'buildSchema'...\r\nERROR introspecting schema:  [\r\n  {\r\n    \"path\": [\r\n      \"__schema\",\r\n      \"types\",\r\n      1,\r\n      \"fields\",\r\n      21,\r\n      \"args\",\r\n      5,\r\n\r\n      \"defaultValue\"\r\n    ],\r\n    \"originalError\": {}\r\n  }\r\n]\r\nError\r\n    at invariant (invariant.js:19:11)\r\n    at astFromValue (astFromValue.js:112:3)\r\n    at astFromValue.js:123:22\r\n    at Array.forEach (native)\r\n    at astFromValue (astFromValue.js:117:23)\r\n    at printInputValue (schemaPrinter.js:180:44)\r\n    at Array.map (native)\r\n    at printArgs (schemaPrinter.js:174:39)\r\n    at schemaPrinter.js:155:28\r\n    at Array.map (native)\r\n    at printFields (schemaPrinter.js:154:17)\r\n    at printObject (schemaPrinter.js:121:65)\r\n    at printType (schemaPrinter.js:100:12)\r\n    at Array.map (native)\r\n    at printFilteredSchema (schemaPrinter.js:72:87)\r\n    at printSchema (schemaPrinter.js:37:10)\r\n```\r\n\r\nAccording to [astFromValue.js#L116](https://github.com/graphql/graphql-js/blob/516dfb9674b4dbde1ee17f715e4c0b6bc24a9f92/src/utilities/astFromValue.js#L116) it accepts only `string` values for `Enums`:\r\n```js\r\n  // JavaScript strings can be Enum values or String values. Use the\r\n  // GraphQLType to differentiate if possible.\r\n  if (typeof _value === 'string') {\r\n    if (type instanceof GraphQLEnumType &&\r\n        /^[_a-zA-Z][_a-zA-Z0-9]*$/.test(_value)) {\r\n      return ({ kind: ENUM, value: _value }: EnumValue);\r\n    }\r\n    // Use JSON stringify, which uses the same string encoding as GraphQL,\r\n    // then remove the quotes.\r\n    return ({\r\n      kind: STRING,\r\n      value: JSON.stringify(_value).slice(1, -1)\r\n    }: StringValue);\r\n  }\r\n``` \r\n* But in graphql specification https://facebook.github.io/graphql/#sec-Enums I did not found explicit requirement that enum value must be `string`.\r\n* Also in `flow-type` [definitions](https://github.com/graphql/graphql-js/blob/master/src/type/definition.js#L838) value has `any` type:\r\n```js\r\nexport type GraphQLEnumValueConfig/* <T> */ = {\r\n  value?: any/* T */;\r\n  deprecationReason?: ?string;\r\n  description?: ?string;\r\n}\r\n```  \r\n\r\nSo, according to concept of Enum ...\r\n* client gets only `names` from enum\r\n* enum values can be defined only on server (and client does not know anything about internal enum value)\r\n\r\n... 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`.\r\n\r\nI 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.\r\n\r\nPS. 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\r\n"},"comment":{"url":"https://api.github.com/repos/graphql/graphql-js/issues/comments/233297537","html_url":"https://github.com/graphql/graphql-js/issues/435#issuecomment-233297537","issue_url":"https://api.github.com/repos/graphql/graphql-js/issues/435","id":233297537,"user":{"login":"nodkz","id":1946920,"avatar_url":"https://avatars.githubusercontent.com/u/1946920?v=3","gravatar_id":"","url":"https://api.github.com/users/nodkz","html_url":"https://github.com/nodkz","followers_url":"https://api.github.com/users/nodkz/followers","following_url":"https://api.github.com/users/nodkz/following{/other_user}","gists_url":"https://api.github.com/users/nodkz/gists{/gist_id}","starred_url":"https://api.github.com/users/nodkz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nodkz/subscriptions","organizations_url":"https://api.github.com/users/nodkz/orgs","repos_url":"https://api.github.com/users/nodkz/repos","events_url":"https://api.github.com/users/nodkz/events{/privacy}","received_events_url":"https://api.github.com/users/nodkz/received_events","type":"User","site_admin":false},"created_at":"2016-07-18T10:45:42Z","updated_at":"2016-07-18T10:45:42Z","body":"Deeper investigations shows that problem with `defaultValue` for input field with Enum type.\r\nEg.\r\n```js\r\nconst RootQuery = new GraphQLObjectType({\r\n  name: 'RootQuery',\r\n  fields: {\r\n    'userConnection': {\r\n      type: UserConnection,\r\n      args: {\r\n         first: { type: GraphQLInt },\r\n         after: { type: CursorType },\r\n         last: { type: GraphQLInt },\r\n         before: { type: CursorType},\r\n         ...additionalArgs,\r\n         sort: {\r\n           type: SortEnumType,\r\n           defaultValue: SortEnumType.getValues()[0].name, // <<<< problem here  <<<<<<<<<<<\r\n           description: 'Sort argument for data ordering',\r\n         },\r\n      },\r\n   },\r\n});\r\n```\r\n- If `sort` arg provided for query (eg. `{ userConnection(first: 5, sort: AGE_ID_DESC) { ... }`) then\r\n  - `astFromValue` works without errors 💚\r\n  - `resolve` functions gets **complex object** via `args.sort` 💚\r\n- If `sort` is not provided, then it takes `defaultValue` from config option:\r\n  - when `defaultValue` equals `SortEnumType.getValues()[0].name`, which equals to `AGE_ID_DESC`, then\r\n    - `astFromValue` works without errors 💚\r\n    - `resolve` function gets **string** name of sorting value in `args.sort` **(I think it should implicitly convert enum name to value)** 💔\r\n  - when `defaultValue` equals `SortEnumType.getValues()[0].value`, which equals to `{ age: -1, _id: 1 }`, then\r\n    - `astFromValue` throws error. **It was called such way `astFromValue(undefined, { age: -1, _id: 1 })`** 💔\r\n    - `resolve` function gets **complex object** in `args.sort` 💚\r\n\r\nSo what `defaultValue` should be provided for field with `Enum` type?"}}
{"actor":{"display_login":"nodkz"}}