{"action":"created","issue":{"url":"https://api.github.com/repos/facebook/relay/issues/112","labels_url":"https://api.github.com/repos/facebook/relay/issues/112/labels{/name}","comments_url":"https://api.github.com/repos/facebook/relay/issues/112/comments","events_url":"https://api.github.com/repos/facebook/relay/issues/112/events","html_url":"https://github.com/facebook/relay/issues/112","id":101726565,"number":112,"title":"Support Root Fields w/o Node Mapping","user":{"login":"yungsters","id":55161,"avatar_url":"https://avatars.githubusercontent.com/u/55161?v=3","gravatar_id":"","url":"https://api.github.com/users/yungsters","html_url":"https://github.com/yungsters","followers_url":"https://api.github.com/users/yungsters/followers","following_url":"https://api.github.com/users/yungsters/following{/other_user}","gists_url":"https://api.github.com/users/yungsters/gists{/gist_id}","starred_url":"https://api.github.com/users/yungsters/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yungsters/subscriptions","organizations_url":"https://api.github.com/users/yungsters/orgs","repos_url":"https://api.github.com/users/yungsters/repos","events_url":"https://api.github.com/users/yungsters/events{/privacy}","received_events_url":"https://api.github.com/users/yungsters/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/facebook/relay/labels/enhancement","name":"enhancement","color":"84b6eb"},{"url":"https://api.github.com/repos/facebook/relay/labels/inprogress","name":"inprogress","color":"5319e7"}],"state":"open","locked":false,"assignee":{"login":"steveluscher","id":13243,"avatar_url":"https://avatars.githubusercontent.com/u/13243?v=3","gravatar_id":"","url":"https://api.github.com/users/steveluscher","html_url":"https://github.com/steveluscher","followers_url":"https://api.github.com/users/steveluscher/followers","following_url":"https://api.github.com/users/steveluscher/following{/other_user}","gists_url":"https://api.github.com/users/steveluscher/gists{/gist_id}","starred_url":"https://api.github.com/users/steveluscher/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/steveluscher/subscriptions","organizations_url":"https://api.github.com/users/steveluscher/orgs","repos_url":"https://api.github.com/users/steveluscher/repos","events_url":"https://api.github.com/users/steveluscher/events{/privacy}","received_events_url":"https://api.github.com/users/steveluscher/received_events","type":"User","site_admin":false},"milestone":null,"comments":11,"created_at":"2015-08-18T18:58:55Z","updated_at":"2015-12-23T20:31:20Z","closed_at":null,"body":"## Problem\r\n\r\nRelay currently only knows how to handle these three types of root fields:\r\n\r\n- Root field with no arguments and queries a single node.\r\n - e.g. `empire` queries `{id: \"123\", ...}`\r\n- Root field with one argument and queries a single node.\r\n - e.g. `ship(id: \"456\")` queries `{id: \"456\", ...}`\r\n- Root field with one array argument and queries an array of nodes.\r\n - e.g. `ships(ids: [\"456\", \"789\"])` queries `[{id: \"456\", ...}, {id: \"789\", ...}]`\r\n\r\nHowever, it has become clear that Relay needs to support any kind of root field. For example:\r\n\r\n- Root field with multiple arguments.\r\n- Root field with no arguments and queries an array of nodes.\r\n- Root field that is a connection.\r\n\r\n## Workaround\r\n\r\nFor now, the unsupported use cases can be implemented by creating a \"global node\", commonly called the `viewer`. You can then add arbitrary fields to `viewer`.\r\n\r\n```\r\nstatic fragments = {\r\n  viewer: () => Relay.QL`\r\n    fragment on Viewer {\r\n      # Can return an array of users.\r\n      users\r\n    }\r\n  `\r\n};\r\n```\r\n\r\n## Rationale\r\n\r\nHistorically, GraphQL (as used internally at Facebook) did not have a root type or root fields. Instead, it had special \"root calls\" such as `node`, `nodes`, `me`, and `usernames`. Much of Relay was built on top of this assumption that the \"root calls\" return nodes.\r\n\r\nFor example, when we fetch `me` and get `{id: \"123\", ...}`, we record the association between the `me` root field and the node with ID of 123. Now, if we ever encounter another query for `me`, we can check our store for the node with ID of 123 and resolve the query without having to potentially re-fetch all of the fields we already have for `me`.\r\n\r\nAnother example, when we fetch `nodes(ids: [\"123\", \"456\"])`, we record the association between each argument and their respective response nodes. This allows us to fulfill queries for `node(id: \"123\")` and `node(id: \"456\")` even though we may never have independently queried for either before. (We would also be able to fulfill `me` if the association from above was established.)\r\n\r\n## Future Plans\r\n\r\nThe tentative plan is to figure out what it would take to treat the singleton root as a record (much like how we currently treat the workaround, `viewer`). The tricky parts are figuring out what metadata we will need in order to continue supporting the fulfillment optimizations described above, while also maintaining compatibility with the version of GraphQL used internally at Facebook."},"comment":{"url":"https://api.github.com/repos/facebook/relay/issues/comments/166985305","html_url":"https://github.com/facebook/relay/issues/112#issuecomment-166985305","issue_url":"https://api.github.com/repos/facebook/relay/issues/112","id":166985305,"user":{"login":"ForbesLindesay","id":1260646,"avatar_url":"https://avatars.githubusercontent.com/u/1260646?v=3","gravatar_id":"","url":"https://api.github.com/users/ForbesLindesay","html_url":"https://github.com/ForbesLindesay","followers_url":"https://api.github.com/users/ForbesLindesay/followers","following_url":"https://api.github.com/users/ForbesLindesay/following{/other_user}","gists_url":"https://api.github.com/users/ForbesLindesay/gists{/gist_id}","starred_url":"https://api.github.com/users/ForbesLindesay/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ForbesLindesay/subscriptions","organizations_url":"https://api.github.com/users/ForbesLindesay/orgs","repos_url":"https://api.github.com/users/ForbesLindesay/repos","events_url":"https://api.github.com/users/ForbesLindesay/events{/privacy}","received_events_url":"https://api.github.com/users/ForbesLindesay/received_events","type":"User","site_admin":false},"created_at":"2015-12-23T20:31:20Z","updated_at":"2015-12-23T20:31:20Z","body":"The right solution seems like it would be to fix this issue.  If you have pointers on what to do though I can try and produce a pull request.  I'm not really clear on the details of what code does what."}}