graphql-spec icon indicating copy to clipboard operation
graphql-spec copied to clipboard

GraphQL is a query language and execution engine tied to any backend service.

Results 202 graphql-spec issues
Sort by recently updated
recently updated
newest added

Fix wording on Leaf Field Selections

[{"_id":"6351cb9a3056137e265821ca","body":"<a href=\"https:\/\/easycla.lfx.linuxfoundation.org\/#\/?version=2\"><img src=\"https:\/\/s3.amazonaws.com\/cla-project-logo-prod\/cla-signed.svg\" alt=\"CLA Signed\" align=\"left\" height=\"28\" width=\"328\" ><\/a><br\/><br \/>The committers listed above are authorized under a signed CLA.<ul><li>:white_check_mark: login: iglosiggio \/ name: Ignacio Losiggio (315c94efe7add16a478faf78d04eec6e18d805ab)<\/li><\/ul>","issue_id":1660651461828,"origin_id":1105694994,"user_origin_id":43480880,"create_time":1650570927,"update_time":1650571130,"id":1666304922940,"updated_at":"2022-10-20T22:28:42.940000Z","created_at":"2022-10-20T22:28:42.940000Z"},{"_id":"6351cb9a3056137e265821cb","body":"### <span aria-hidden=\"true\">\u2705<\/span> Deploy Preview for *graphql-spec-draft* ready!\n\n\n| Name | Link |\n|---------------------------------|------------------------|\n|<span aria-hidden=\"true\">\ud83d\udd28<\/span> Latest commit | 315c94efe7add16a478faf78d04eec6e18d805ab |\n|<span aria-hidden=\"true\">\ud83d\udd0d<\/span> Latest deploy log | https:\/\/app.netlify.com\/sites\/graphql-spec-draft\/deploys\/6261b6ad24592800086113c4 |\n|<span aria-hidden=\"true\">\ud83d\ude0e<\/span> Deploy Preview | https:\/\/deploy-preview-940--graphql-spec-draft.netlify.app |\n|<span aria-hidden=\"true\">\ud83d\udcf1<\/span> Preview on mobile | <details><summary> Toggle QR Code... <\/summary><br \/><br \/>![QR Code](https:\/\/app.netlify.com\/qr-code\/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1cmwiOiJodHRwczovL2RlcGxveS1wcmV2aWV3LTk0MC0tZ3JhcGhxbC1zcGVjLWRyYWZ0Lm5ldGxpZnkuYXBwIn0.8jpyq4tLjjT8pv7_yrsO9-PjUHeb67-EuKjf0b0HhXg)<br \/><br \/>_Use your smartphone camera to open QR code link._<\/details> |\n---\n\n_To edit notification comments on pull requests, go to your [Netlify site settings](https:\/\/app.netlify.com\/sites\/graphql-spec-draft\/settings\/deploys#deploy-notifications)._","issue_id":1660651461828,"origin_id":1105695031,"user_origin_id":40209326,"create_time":1650570930,"update_time":1650570949,"id":1666304922944,"updated_at":"2022-10-20T22:28:42.943000Z","created_at":"2022-10-20T22:28:42.943000Z"},{"_id":"6351cb9a3056137e265821cc","body":"Also, this change might be completely wrong if the idea is that the _result type_ of something that has `[Thing]` or `Thing!` as it's _return type_ is `Thing`.\r\n\r\nIf that's the case it would be nice to write this distinction explicitly in the spec.","issue_id":1660651461828,"origin_id":1105706081,"user_origin_id":1154680,"create_time":1650571609,"update_time":1650572277,"id":1666304922947,"updated_at":"2022-10-20T22:28:42.947000Z","created_at":"2022-10-20T22:28:42.947000Z"},{"_id":"6351cb9a3056137e265821cd","body":"I can see why \"result type\" was used here - \"return type\" is used for fields to dictate what can be selected on them, the \"type\" of the selection set is a related but separate concept. \r\n\r\nIf we look at the [\"CompleteValue()\" algorithm](https:\/\/spec.graphql.org\/draft\/#CompleteValue()) we can see that it removes all the wrapping types before deferring to `ExecuteSelectionSet()`. Inside `ExecuteSelectionSet()` itself, the type is referred to as `objectType` - and we can see that `CompleteValue` handled the resolution of the abstract type (interface\/union). The part of the spec you've highlighted seems to be referencing the unwrapped, but not abstract-resolved, type on which the selection set is valid. From a quick scan over the relevant parts of the spec, I cannot see that a name was ever attributed to this concept (except where you highlight, implicitly). Using \"return type\" or \"field type\" doesn't feel right because selection sets can also be defined by named fragments which have a \"type condition\", or by inline fragments which optionally can have a \"type condition\" too. Using \"type condition\" directly doesn't feel right because inline fragments don't need a type condition (they have the implicit type they inherit from the parent selection set, or field).\r\n\r\nAnyway, this is a bit of a ramble without a conclusion. I agree some attention should be paid here; probably, as you say, a definition of the term \"result type\" is all that's needed.","issue_id":1660651461828,"origin_id":1106196859,"user_origin_id":129910,"create_time":1650616848,"update_time":1650616848,"id":1666304922951,"updated_at":"2022-10-20T22:28:42.950000Z","created_at":"2022-10-20T22:28:42.950000Z"}] comment

There's no other reference to "result types" on the specification and the same idea is given the name "return type" on IsValidImplementation, SameResponseShape and ExecuteSelectionSet. As an aside: Should this...

✏️ Editorial

Discussion: Generic error codes in the spec

[{"_id":"6351c948d297b621322ebb57","body":"OK. My thoughts:\r\n1. No breaking changes. Good.\r\n2. Easy to implement.\r\n3. It should be explicitly stated in spec (if we decide to supplement the spec) that attaching the error information about code is optional for the server.\r\n4. I propose to use `__graphqlspec` as a conventional prefix for all such things and not as full property name. Full property name for error code may be `__graphqlspecErrorCode`","issue_id":1660651461831,"origin_id":602182948,"user_origin_id":21261007,"create_time":1584875668,"update_time":1584875668,"id":1666304328637,"updated_at":"2022-10-20T22:18:48.637000Z","created_at":"2022-10-20T22:18:48.637000Z"},{"_id":"6351c948d297b621322ebb58","body":"Well @sungam3r IMO the whole point of adding such error codes is to enforce \/ streamline error codes across implementations. Having it optional would defeat the whole purpose. What are your thoughts on this. What effort do you think would go in this route?","issue_id":1660651461831,"origin_id":602184118,"user_origin_id":4711855,"create_time":1584876211,"update_time":1584876211,"id":1666304328641,"updated_at":"2022-10-20T22:18:48.640000Z","created_at":"2022-10-20T22:18:48.640000Z"},{"_id":"6351c948d297b621322ebb59","body":"That is simple. It is **impossible** to do such error codes as required properties since\r\n1. Breaking changes to existing implementations.\r\n2. Extensions property by design has no structure defined.","issue_id":1660651461831,"origin_id":602184867,"user_origin_id":21261007,"create_time":1584876605,"update_time":1584876605,"id":1666304328644,"updated_at":"2022-10-20T22:18:48.643000Z","created_at":"2022-10-20T22:18:48.643000Z"},{"_id":"6351c948d297b621322ebb5a","body":"See https:\/\/github.com\/graphql\/graphql-spec\/blob\/master\/CONTRIBUTING.md#guiding-principles\r\n\r\n> Future changes should not change the meaning of existing schema or queries or in any other way cause an existing compliant GraphQL service to become non-compliant for prior versions of the spec.","issue_id":1660651461831,"origin_id":602185209,"user_origin_id":21261007,"create_time":1584876785,"update_time":1584876785,"id":1666304328646,"updated_at":"2022-10-20T22:18:48.646000Z","created_at":"2022-10-20T22:18:48.646000Z"},{"_id":"6351c948d297b621322ebb5b","body":"How about a optional \"catagory\" key, so clients can make broad decision and servers are testable whether right check triggered?\r\n\r\nEnumerating individual errors seems lot of work, for dubious benefit.\r\n\r\nMain disadvantage would be that some implementations opt out from it if it's too bothersome.","issue_id":1660651461831,"origin_id":602185689,"user_origin_id":49397,"create_time":1584877035,"update_time":1584877035,"id":1666304328649,"updated_at":"2022-10-20T22:18:48.648000Z","created_at":"2022-10-20T22:18:48.648000Z"},{"_id":"6351c948d297b621322ebb5c","body":"Well, `category` or `code` are the same things. GraphQL-dotnet for example already has error codes in response https:\/\/github.com\/graphql-dotnet\/graphql-dotnet\/blob\/master\/src\/GraphQL.NewtonsoftJson\/ExecutionResultJsonConverter.cs#L98","issue_id":1660651461831,"origin_id":602186258,"user_origin_id":21261007,"create_time":1584877313,"update_time":1584877313,"id":1666304328652,"updated_at":"2022-10-20T22:18:48.651000Z","created_at":"2022-10-20T22:18:48.651000Z"},{"_id":"6351c948d297b621322ebb5d","body":"``code`` is fine as a key. The question is can other implementations reproduce them.\r\n\r\nMain goal is spec regression tests that can be run over several implementations.\r\n\r\nIt's fine to say that this testsuite requires support for ``code``. ","issue_id":1660651461831,"origin_id":602188103,"user_origin_id":49397,"create_time":1584878247,"update_time":1584878247,"id":1666304328654,"updated_at":"2022-10-20T22:18:48.654000Z","created_at":"2022-10-20T22:18:48.654000Z"},{"_id":"6351c948d297b621322ebb5e","body":"> Well, `category` or `code` are the same things. GraphQL-dotnet for example already has error codes in response https:\/\/github.com\/graphql-dotnet\/graphql-dotnet\/blob\/master\/src\/GraphQL.NewtonsoftJson\/ExecutionResultJsonConverter.cs#L98\r\n\r\nThat looks interesting, can you point me to the exact listing of these error codes.","issue_id":1660651461831,"origin_id":602188135,"user_origin_id":32242596,"create_time":1584878264,"update_time":1584878264,"id":1666304328662,"updated_at":"2022-10-20T22:18:48.662000Z","created_at":"2022-10-20T22:18:48.662000Z"},{"_id":"6351c948d297b621322ebb5f","body":"`Code` is already used in many implementations so I would go with that. We also use `code` in Hot Chocolate. The more important issue is to specify error codes for spec errors.","issue_id":1660651461831,"origin_id":602199270,"user_origin_id":9714350,"create_time":1584883115,"update_time":1584883115,"id":1666304328665,"updated_at":"2022-10-20T22:18:48.665000Z","created_at":"2022-10-20T22:18:48.665000Z"},{"_id":"6351c948d297b621322ebb60","body":"> That looks interesting, can you point me to the exact listing of these error codes.\r\n\r\nErrors codes are aligned with paragraph numbers from the spec. 5.4.2.1 for http:\/\/spec.graphql.org\/June2018\/#sec-Required-Arguments for example.","issue_id":1660651461831,"origin_id":602217404,"user_origin_id":21261007,"create_time":1584887750,"update_time":1584887750,"id":1666304328668,"updated_at":"2022-10-20T22:18:48.667000Z","created_at":"2022-10-20T22:18:48.667000Z"},{"_id":"6351c948d297b621322ebb61","body":"Hardwiring chapter numbers as errors seems wrong, both implementations side and also spec side: one-chapter-per-error may be annoying to maintain, especially if you are not allowed to refactor.\r\n\r\nNamed errors seems good enough, or if you really want numbers, then OID-like tree maintained in spec.","issue_id":1660651461831,"origin_id":602221146,"user_origin_id":49397,"create_time":1584889127,"update_time":1584889127,"id":1666304328670,"updated_at":"2022-10-20T22:18:48.670000Z","created_at":"2022-10-20T22:18:48.670000Z"},{"_id":"6351c948d297b621322ebb62","body":"I also would not bind them to the chapters. I personally also prefer named errors. But that might be a personal preference I would also be fine with something else. ","issue_id":1660651461831,"origin_id":602229143,"user_origin_id":9714350,"create_time":1584892058,"update_time":1584892058,"id":1666304328672,"updated_at":"2022-10-20T22:18:48.672000Z","created_at":"2022-10-20T22:18:48.672000Z"},{"_id":"6351c948d297b621322ebb63","body":"Similar to \"error code\", we are using system events for all our exception handling but we expose it in error extension block (as per spec). \r\n\r\nWhen following code first approach, schema generation process should not allow generation of invalid schema. Your runtime should already run valid schema that produces correct responses so I am unsure how often you would end up with something non-compliant with the spec. I believe you need this sort of validation when creating the schema but if that is the case then I am unsure why you would need this error information in GraphQL response as the server should not start with invalid schema.","issue_id":1660651461831,"origin_id":602236848,"user_origin_id":9501705,"create_time":1584895224,"update_time":1584895224,"id":1666304328676,"updated_at":"2022-10-20T22:18:48.675000Z","created_at":"2022-10-20T22:18:48.675000Z"},{"_id":"6351c948d297b621322ebb64","body":"@dariuszkuc The talk is about **query** validation errors as well.","issue_id":1660651461831,"origin_id":602239845,"user_origin_id":21261007,"create_time":1584896549,"update_time":1584896549,"id":1666304328679,"updated_at":"2022-10-20T22:18:48.679000Z","created_at":"2022-10-20T22:18:48.679000Z"},{"_id":"6351c948d297b621322ebb65","body":"@markokr We can use different properties together- `code` like `UNIQUE_ARGUMENT`, `number` like `1.2.3.4` , even `helpUrl` to spec like `http:\/\/spec.graphql.org\/June2018\/#sec-Argument-Names`","issue_id":1660651461831,"origin_id":602240220,"user_origin_id":21261007,"create_time":1584896725,"update_time":1584896725,"id":1666304328681,"updated_at":"2022-10-20T22:18:48.681000Z","created_at":"2022-10-20T22:18:48.681000Z"},{"_id":"6351c948d297b621322ebb66","body":"URLs convenient because paragraph numbers can vary from version to version of specification.","issue_id":1660651461831,"origin_id":602240521,"user_origin_id":21261007,"create_time":1584896860,"update_time":1584896860,"id":1666304328683,"updated_at":"2022-10-20T22:18:48.683000Z","created_at":"2022-10-20T22:18:48.683000Z"},{"_id":"6351c948d297b621322ebb67","body":"@pranshuchittora From my comment it follows that separate test suites are required for each version of the specification.","issue_id":1660651461831,"origin_id":602240873,"user_origin_id":21261007,"create_time":1584896993,"update_time":1584896993,"id":1666304328686,"updated_at":"2022-10-20T22:18:48.685000Z","created_at":"2022-10-20T22:18:48.685000Z"},{"_id":"6351c948d297b621322ebb68","body":"The testsuite itself would indeed be tied to specific spec version, so instead it makes sense for tests to contain spec section numbers and even links to spec.\r\n\r\nI still cannot see how making implementation organize code around spec layout is useful - it may be natural to share some error handling code, so why force it track spec layout?","issue_id":1660651461831,"origin_id":602242275,"user_origin_id":49397,"create_time":1584897599,"update_time":1584897599,"id":1666304328688,"updated_at":"2022-10-20T22:18:48.688000Z","created_at":"2022-10-20T22:18:48.688000Z"},{"_id":"6351c948d297b621322ebb69","body":"@sungam3r I think creating a separate section for the error spec can be one of the approaches. \r\nThe section will contain a whole bunch of error code like `GQ0001` (inspired from `rust-lang`), and these codes can internally reference their corresponding section i.e. `1.2.3.4`.\r\n\r\nThis approach can be fruitful in the long run as it is decoupled with the entire structure of the spec.\r\n\r\n\r\n\r\n\r\n","issue_id":1660651461831,"origin_id":602242983,"user_origin_id":32242596,"create_time":1584897887,"update_time":1584897887,"id":1666304328690,"updated_at":"2022-10-20T22:18:48.690000Z","created_at":"2022-10-20T22:18:48.690000Z"},{"_id":"6351c948d297b621322ebb6a","body":"@pranshuchittora this sounds quite good.","issue_id":1660651461831,"origin_id":602245222,"user_origin_id":9714350,"create_time":1584898821,"update_time":1584898821,"id":1666304328693,"updated_at":"2022-10-20T22:18:48.692000Z","created_at":"2022-10-20T22:18:48.692000Z"},{"_id":"6351c948d297b621322ebb6b","body":"@markokr @sungam3r \r\n\r\nWe implement features once they hit draft. Meaning organizing a test suite around a specific spec version can be count-productive. I like the approaches that web browser suites go where you can see what is implemented and what not.\r\n\r\n@pranshuchittora when I talked with @IvanGoncharov about building a replacement for GraphQL-CATS we first wanted to focus on parser tests. What is now the general idea.\r\n\r\nWe had CATS already implemented for [Hot Chocolate](https:\/\/github.com\/ChilliCream\/hotchocolate) but it was quite difficult back then. One of the issues were error codes. But there are other problems to solve. Do you already have a broader idea how to go about it?","issue_id":1660651461831,"origin_id":602246258,"user_origin_id":9714350,"create_time":1584899255,"update_time":1584899255,"id":1666304328695,"updated_at":"2022-10-20T22:18:48.695000Z","created_at":"2022-10-20T22:18:48.695000Z"},{"_id":"6351c948d297b621322ebb6c","body":"@michaelstaib I am in the process of writing the proposal and I would love to get it reviewed by you, once it gets completed.\r\n\r\nAs of now, we can only test the implementations for basic input-output, hence not covering the edge case. The idea of standardising the `error codes` is one of the effort for testing the implementations more deeply. We can improve the proposal prioritizing the aspects of the spec which seem most valuable to be covered with centralized tests.","issue_id":1660651461831,"origin_id":602250600,"user_origin_id":32242596,"create_time":1584901259,"update_time":1584901259,"id":1666304328697,"updated_at":"2022-10-20T22:18:48.697000Z","created_at":"2022-10-20T22:18:48.697000Z"},{"_id":"6351c948d297b621322ebb6d","body":"@pranshuchittora excellent... love that this finally gets some traction.","issue_id":1660651461831,"origin_id":602265509,"user_origin_id":9714350,"create_time":1584908009,"update_time":1584908009,"id":1666304328700,"updated_at":"2022-10-20T22:18:48.699000Z","created_at":"2022-10-20T22:18:48.699000Z"},{"_id":"6351c948d297b621322ebb6e","body":"Hello there,\r\nWith several iterations in the design, and the help of @michaelstaib. I have created a rough architecture for the compliance test suite.\r\n\r\n---\r\n\r\n#### Design of the App Server and the test runner. (Docker Approach)\r\n<img\r\n src=\"https:\/\/user-images.githubusercontent.com\/32242596\/78066964-82432480-73b3-11ea-8a71-3143f420a57b.png\" height=\"600\" >\r\n\r\n---\r\n\r\n#### Events and lifecycle\r\n<img src=\"https:\/\/user-images.githubusercontent.com\/32242596\/78067431-583e3200-73b4-11ea-80b2-5526e73d936e.png\" height=\"600\">\r\n\r\n\r\nFor detailed info, you can read my GSoC proposal -> https:\/\/docs.google.com\/document\/d\/1D0PD2nwU97aL-hTc_XLL8H5MYNqBzkIBJeDeh_UJ0yo\/edit?usp=sharing\r\n\r\n","issue_id":1660651461831,"origin_id":606832246,"user_origin_id":32242596,"create_time":1585683520,"update_time":1585683520,"id":1666304328702,"updated_at":"2022-10-20T22:18:48.702000Z","created_at":"2022-10-20T22:18:48.702000Z"},{"_id":"6351c948d297b621322ebb6f","body":"@michaelstaib , @sungam3r \r\nThe above sounds quite good. Wanted to also check on the suggestions around Error spec for gql - https:\/\/github.com\/graphql\/graphql-spec\/issues\/698#issuecomment-602242983\r\n\r\n\r\n\r\n> @sungam3r I think creating a separate section for the error spec can be one of the approaches.\r\n> The section will contain a whole bunch of error code like `GQ0001` (inspired from `rust-lang`), and these codes can internally reference their corresponding section i.e. `1.2.3.4`.\r\n> \r\n> This approach can be fruitful in the long run as it is decoupled with the entire structure of the spec.\r\n\r\nLet me know if we can start some discussion around this, and write an initial spec \/ RFC around this.","issue_id":1660651461831,"origin_id":609069549,"user_origin_id":4711855,"create_time":1586024584,"update_time":1586024584,"id":1666304328705,"updated_at":"2022-10-20T22:18:48.704000Z","created_at":"2022-10-20T22:18:48.704000Z"},{"_id":"6351c948d297b621322ebb70","body":"I'm doing other things now, I can help with wordings and review.","issue_id":1660651461831,"origin_id":609096443,"user_origin_id":21261007,"create_time":1586038654,"update_time":1586038654,"id":1666304328707,"updated_at":"2022-10-20T22:18:48.707000Z","created_at":"2022-10-20T22:18:48.707000Z"},{"_id":"6351c948d297b621322ebb71","body":"@shobhitchittora I\u2019m happy to hop in and start some discussion on this. Currently building a GraphQL server in Go and would love to add these generic error codes as early as possible, would make testing much easier later.\r\n\r\n@pranshuchittora Awesome work, nice proposal. ","issue_id":1660651461831,"origin_id":609464660,"user_origin_id":11632400,"create_time":1586112959,"update_time":1586112959,"id":1666304328711,"updated_at":"2022-10-20T22:18:48.710000Z","created_at":"2022-10-20T22:18:48.710000Z"},{"_id":"6351c948d297b621322ebb72","body":"@shobhitchittora I would really like to get this going since it would at a lot of value. So, I am in.","issue_id":1660651461831,"origin_id":609630771,"user_origin_id":9714350,"create_time":1586159111,"update_time":1586159111,"id":1666304328713,"updated_at":"2022-10-20T22:18:48.713000Z","created_at":"2022-10-20T22:18:48.713000Z"},{"_id":"6351c948d297b621322ebb73","body":"Thanks for the positive vibe here. Let me take some time and start a RFC around this.\n\nThanks all. ","issue_id":1660651461831,"origin_id":609768688,"user_origin_id":4711855,"create_time":1586176727,"update_time":1586176727,"id":1666304328716,"updated_at":"2022-10-20T22:18:48.715000Z","created_at":"2022-10-20T22:18:48.715000Z"},{"_id":"6351c948d297b621322ebb74","body":"@michaelstaib @Fontinalis @sungam3r @markokr @pranshuchittora @IvanGoncharov \r\nHope you're all safe and well. Please check out #708. \r\nWould love all suggestions and feedback for improvements.","issue_id":1660651461831,"origin_id":612535367,"user_origin_id":4711855,"create_time":1586648019,"update_time":1586649533,"id":1666304328718,"updated_at":"2022-10-20T22:18:48.718000Z","created_at":"2022-10-20T22:18:48.718000Z"}] comment

**Abstract** I am researching and planning to build a generic test suite to check the compliance of the various GraphQL libraries The [project idea](https://github.com/graphql/foundation/tree/master/mentorship/2020/gsoc#1-graphql-compatibility-acceptance-tests-medium) is given by the GraphQL Foundation...

Consider allowing use of '-' & '/' characters in names, enums if possible

[{"_id":"6351c129d297b621322eb525","body":"> Names in GraphQL are limited to this ASCII subset of possible characters to support interoperation with as many other systems as possible.\r\n\r\n\u2013 https:\/\/spec.graphql.org\/June2018\/#sec-Names\r\n\r\nA really nice property of GraphQL names is that they're also valid variable names for virtually all major programming languages. I'd hate to see that go.","issue_id":1660651461834,"origin_id":701891496,"user_origin_id":1731074,"create_time":1601529517,"update_time":1601529517,"id":1666302249338,"updated_at":"2022-10-20T21:44:09.338000Z","created_at":"2022-10-20T21:44:09.338000Z"},{"_id":"6351c129d297b621322eb526","body":"IMHO the character set constraint is unnecessarily onerous. Many JSON APIs out there already use all kinds of special characters - it's really common to see field names starting with $ or \/ which mark a field as having some special significance - for example the IPLD DAG for JSON uses '\/' as a field name for links. Far from supporting interoperation, limiting the set of characters makes it harder to add graphQL any *existing* API. If interoperability is a design requirement for a new API, there is nothing that forces the developer to use these special characters. Recommend instead following the JSON rules for property names, and where issues exist in a given target language simply following whatever workarounds have already been developed for mapping in JSON.","issue_id":1660651461834,"origin_id":915347365,"user_origin_id":25228003,"create_time":1631115384,"update_time":1631115384,"id":1666302249344,"updated_at":"2022-10-20T21:44:09.343000Z","created_at":"2022-10-20T21:44:09.343000Z"},{"_id":"6351c129d297b621322eb527","body":"I'd also like to see additional characters allowed specifically in enum members, e.g. `+` (as well as `-` and `\/`). (I'm less concerned with type names, but maybe someone else has a need for that.)\r\n\r\nAs an example, I need to represent letter grades (e.g. `A+`, `A`, `A-`, etc.), which seems like a natural fit for an enum, since letter grades are usually a fixed set of unique elements. What I'd like is to be able to write the obvious enum, i.e.\r\n```\r\nenum LetterGrade {\r\n A+\r\n A\r\n A-\r\n B+\r\n B\r\n B-\r\n C+\r\n etc...\r\n}\r\n```\r\nI can't, however, because GraphQL doesn't allow `+` or `-` in enum members. Instead, I'd have to do something like this:\r\n```\r\nenum LetterGrade {\r\n A_PLUS\r\n A\r\n A_MINUS\r\n B_PLUS\r\n etc...\r\n}\r\n```\r\nThis is mildly annoying because now I need a client-side transform to change the enum value into the more common letter grade format (`A+`, `A-`, etc.). \r\n\r\nLibraries like `graphql-tools` do let you specify resolvers for your enum values (see [https:\/\/www.graphql-tools.com\/docs\/scalars#internal-values](https:\/\/www.graphql-tools.com\/docs\/scalars#internal-values)), but crucially the docs note that \"_These don't change the public API at all_\" (emphasis mine). This solves the internal side, because the letter grades will ultimately be stored in their common format, but it still leaves the public-facing side of the API with enum members that have to be manipulated for display to the user, even though they don't differ from how they will be stored.","issue_id":1660651461834,"origin_id":1084990903,"user_origin_id":13541242,"create_time":1648753243,"update_time":1648753243,"id":1666302249354,"updated_at":"2022-10-20T21:44:09.354000Z","created_at":"2022-10-20T21:44:09.354000Z"},{"_id":"6351c129d297b621322eb528","body":"> This is mildly annoying because now I need a client-side transform to change the enum value into the more common letter grade format (A+, A-, etc.).\r\n\r\nThere is a generic principle that should be followed: internal 'code' names and user visible labels are completely different set of tokens, and live in separate universes, and should never be mixed up. I think most devs out there will agree. \r\n\r\nThere is a temptation sometimes to directly use the enum value (or some other internal code name) as a user-visible label\/token in UI - why not, they are the same. But it is dangerous path; for one thing it never works with localization (when app supports multiple UI languages); the other example is when you need to add a two-word enum value to already existing enum. \r\n\r\nYour case with grades, although seems reasonable, is a rare corner case. I do not think it's worth changing GraphQL syntax for this rare case. By the way, what if there are countries\/colleges that use some other extra chars in grades? like A* ? should we then change syntax again?\r\n ","issue_id":1660651461834,"origin_id":1085120345,"user_origin_id":594969,"create_time":1648761052,"update_time":1648761101,"id":1666302249358,"updated_at":"2022-10-20T21:44:09.358000Z","created_at":"2022-10-20T21:44:09.358000Z"},{"_id":"6351c129d297b621322eb529","body":"> There is a generic principle that should be followed: internal 'code' names and user visible labels are completely different set of tokens, and live in separate universes, and should never be mixed up. I think most devs out there will agree.\r\n\r\nYes, I am completely aware of this, and I practice this elsewhere in my schema and my back-end code. I was going to mention something about that in my original comment but left it out because it didn't seem necessary. I was giving an example of a natural, and fairly common in real life, set of enumerated values, and how a slightly less restrictive character set for enum members would be helpful.\r\n\r\n**To be clear**, I can accomplish what I need to do with GraphQL as it exists right now, just in a way that is more verbose.","issue_id":1660651461834,"origin_id":1085979893,"user_origin_id":13541242,"create_time":1648823682,"update_time":1648823682,"id":1666302249372,"updated_at":"2022-10-20T21:44:09.372000Z","created_at":"2022-10-20T21:44:09.372000Z"},{"_id":"6351c129d297b621322eb52a","body":"I think we should not do this, but regarding letter grades:\r\n\r\n> This is mildly annoying because now I need a client-side transform to change the enum value into the more common letter grade format (A+, A-, etc.).\r\n\r\nYou **could** do this:\r\n```graphql\r\ntype LetterGrade {\r\n normalized: NormalizedLetterGrade\r\n textRepresentation: String\r\n}\r\n\r\nenum NormalizedLetterGrade {\r\n A_PLUS\r\n A\r\n A_MINUS\r\n B_PLUS\r\n etc...\r\n}\r\n```\r\n\r\nYou can even add something like a `hexColor: String` to give even more control to your backend.\r\nWhen adding something like themes this can then be transformed to `hexColor(theme: MyTheme = LIGHT): String` - it will still be backwards-compatible\r\n\r\nGraphQL is really expressive this way, just carefully consider what you want on the frontend, and what you want on the backend.","issue_id":1660651461834,"origin_id":1093998352,"user_origin_id":30464310,"create_time":1649508934,"update_time":1649508934,"id":1666302249376,"updated_at":"2022-10-20T21:44:09.376000Z","created_at":"2022-10-20T21:44:09.376000Z"}] comment

Currently name regex only allows limited characters, it would be good if it can add support for `-` & `/` characters. ```gql data { "application/json": "test", "en-GB": "test", "C-AR/A": "test...

Literal types support

[{"_id":"6351c8d28041c95dfb0ff226","body":"You could model those literal types using interfaces:\r\n\r\n```graphql\r\ninterface MagicalItem {\r\n magic: Boolean!\r\n}\r\ninterface RangedItem {\r\n ranged: Boolean!\r\n}\r\ninterface MeeleItem {\r\n meele: Boolean!\r\n}\r\ninterface NeutralItemAptitude {\r\n neutral: Boolean!\r\n}\r\ninterface TechnologicalItemAptitude {\r\n technological: Boolean!\r\n}\r\ninterface MagicalItemAptitute {\r\n magical: Boolean!\r\n}\r\n\r\ntype Sword implements MeeleItem, NeutralItemAptitude {\r\n meele: Boolean!\r\n neutral: Boolean!\r\n damage: Float!\r\n}\r\ntype Rifle implements RangedItem, TechnologicalItemAptitude {\r\n ranged: Boolean!\r\n technological: Boolean!\r\n damage: Float!\r\n}\r\ntype Spellbook implements MagicItem, MagicalItemAptitude {\r\n magic: Boolean!\r\n magical: Boolean!\r\n}\r\nunion Weapon = Sword | Rifle | Spellbook\r\n```\r\n\r\nThat would allow discriminating a generated union types with a `property in object` check in TypeScript.\r\n\r\n```ts\r\nif ('ranged' in item) {\r\n \/\/ thing must implement the RangedItem interface \u2611\ufe0f\r\n}\r\nif ('magic' in item || 'technological' in item) {\r\n \/\/ thing must implement either MagicItem or TechnologicalAptitude interface \u2611\ufe0f\r\n}\r\n```","issue_id":1660651461837,"origin_id":882051729,"user_origin_id":14338007,"create_time":1626612642,"update_time":1626612642,"id":1666304210427,"updated_at":"2022-10-20T22:16:50.426000Z","created_at":"2022-10-20T22:16:50.426000Z"},{"_id":"6351c8d28041c95dfb0ff227","body":"@n1ru4l that's not a solution, because it doesn't allow us to use exhaustive type check === solution is not type-safe, and even less type-safe than creating the types manually and casting them manually on API level. Consider a case, when devs will need to add a new `weaponType`. In that case, all of the checks I did with using `switch` will trigger an error for them, so they will see all of the places they need to change. Same with removal of a particular `weaponType` - devs will see all of the places to fix, without even running a single test. An exhaustive type check forces you to cover all of the cases, so you won't accidentally forget it. Having multiple boolean flags gives nothing. It's more safe to create all of the types manually and cast graphql results to these types on API level, so only API part will be our point of failure. Using boolean flags will make the entire codebase unsafe, so it will be much harder to spot the bug then with type casts in a single place.","issue_id":1660651461837,"origin_id":882054262,"user_origin_id":1625500,"create_time":1626613798,"update_time":1626613798,"id":1666304210431,"updated_at":"2022-10-20T22:16:50.430000Z","created_at":"2022-10-20T22:16:50.430000Z"},{"_id":"6351c8d28041c95dfb0ff228","body":"Example code and \"switch\" alternative using if statements:\r\n\r\nhttps:\/\/www.typescriptlang.org\/play?#code\/C4TwDgpgBAyg7gewE4BMoF4oG8BQUoC2EEANhAFxQBGCCZAhgHZ5SMQCuwS9JlNdEJixT0C9AOYVW7AlQhIcAXxyhIUAEoBLAGZl8mXPm6NJKPrQbN8wCAGMAFozoJxm2z3MCh+EWMmVGGTkFZVVoGEgSEn4AawxsFj83T0tEiTcPagtBKyhfCSlA2XkWB3okSQBnABkIbWAAoJLlFXBoAHVBMARGePhkNAAfDR09YYjSaNoYnBxbHsrgKCQIRhR5AFliMk76bt7MAAoiUghd-cp+1ABKDAA+BKMIYHYkXsCopVn5xkXl1fWSHUTFM5x68UOxlBXR6lC0uggt3QD0M-xeb2knxaPz+KzWm3StjBBygx0JxMukSmCBiSJRLBW6Pe7Cx3wWS0kwAAIqIChC4DDGJRiddGlF7o8oDpSQAiE5kGVS3oCvY9W6op5M-74pBbU7Ew4q-bXFjKfDSw4yqEQFCKzTKwXqlia169PGA4EmG0Go1q01QBnPV3awEbcmCw2OpRAA\r\n\r\nYour described case where a new weapon type is introduced:\r\n\r\nhttps:\/\/www.typescriptlang.org\/play?ssl=44&ssc=2&pln=1&pc=1#code\/C4TwDgpgBAyg7gewE4BMoF4oG8BQUoC2EEANhAFxQBGCCZAhgHZ5SMQCuwS9JlNdEJixT0C9AOYVW7AlQhIcAXxyhIUAEoBLAGZl8mXPm6NJKPrQbN8wCAGMAFozoJxm2z3MCh+EWMmVGGTkFZVVoGEgSEn4AawxsFj83T0tEiTcPagtBKyhfCSlA2XkWB3okSQBnABkIbWAAoJLQ8GgAUQAPMBIESs0AN2gDFggunr7BlJzhUQLG4pCcFVaoAHVBMARGePhkNAAfDR09Q4jSaNo4w87u3oGIJdstyuAoJAhGFHkAWWIydfom22mAAFERSBAAUDKLtUABKDAAPgSRggwHYSG2gSiSkez1e70+8nUTFMUK28RBxjJGy2lC0uggCPQyMMbzRGKx7BxyhwT0YL3ZRKQ33StnJwKgYLFEphkQuCBizNZLHe6Mx0h5eIFr0kwAAIrNJJS4LTGJQJXDGlEkSioDopQAicFkR327amwFbBFs1Hq7aEr4iv6Qs0gz1AuEsZT4B0gx3UiAoN2aD1mn0sP2coVBkkmJMS8Pp6NQVUcjWBn4ysMR71KIA\r\n\r\nAs you can see the introduction of a new type results in a TypeScript error.\r\n\r\nPlease also differentiate between \"not the optimal solution that you desire\" and \"not a solution\".\r\n\r\nAs mentioned on Discord before, there is definitely some room for improvement here and literal types might be a possible solution for making this more convenient.\r\n","issue_id":1660651461837,"origin_id":882308719,"user_origin_id":14338007,"create_time":1626679421,"update_time":1626679421,"id":1666304210434,"updated_at":"2022-10-20T22:16:50.434000Z","created_at":"2022-10-20T22:16:50.434000Z"},{"_id":"6351c8d28041c95dfb0ff229","body":"now open your second link and change the union to `type Weapon = Sword | Spellbook`. type check will pass, while it clearly should trigger an error. exhaustive type check should work in both directions, not only \"when things are right\".\r\n\r\nif the solution requires to change the data model, introduce lots of unnecessary fields, throws away standard TS way to iterate over union but fails to detect the error anyway - that's not \"not the optimal solution\", that's just \"not a solution\"","issue_id":1660651461837,"origin_id":882320502,"user_origin_id":1625500,"create_time":1626680596,"update_time":1626680596,"id":1666304210437,"updated_at":"2022-10-20T22:16:50.436000Z","created_at":"2022-10-20T22:16:50.436000Z"},{"_id":"6351c8d28041c95dfb0ff22a","body":"@PinkaminaDianePie This can be used as a workaround:\r\n\r\nhttps:\/\/www.typescriptlang.org\/play?#code\/C4TwDgpgBAyg7gewE4BMoF4oG8BQUoC2EEANhAFxQBGCCZAhgHZ5SMQCuwS9JlNdEJixT0C9AOYVW7AlQhIcAXxyhIUAEoBLAGZl8mXPm6NJKPrQbN8wCAGMAFozoJxm2z3MCh+EWMmVGGTkFZVVoGEgSEn4AawxsFj83T0tEiTcPagtBKyhfCSlA2XkWB3okSQBnABkIbWAAoJLQ8GgAUQAPMBIESs0AN2gDFggunr7BlJzhUQLG4pCcFVaoAHVBMARGePhkNAAfDR09Q4jSaNo4w87u3oGIJdstyuAoJAhGFHkAWWIydfom22mAAFERSBAAUDKLtUABKDAAPgSRggwHYSG2gSiSkez1e70+8nUTFMUK28RBxjJGy2lC0uggCPQyMMbzRGKx7BxyhwT0YL3ZRKQ33StnJwKgYLFEphkQuCBizNZLHe6Mx0h5eIFr0kwAAIrNJJS4LTGJQJXDGlEkSioDopQAicFkR327amwEUgBk3qgnqBADoXUy7aj1dtCV8RX9IWaQQGtnCWMp8A6QY7qRAUG7NB6zVBff6zYGsygEWzw5yhdGSSZsxKE2bk-hFFBVRyNVGfjL44nGMnFEA\r\n\r\n---->\r\n\r\n\r\nhttps:\/\/www.typescriptlang.org\/play?#code\/C4TwDgpgBAyg7gewE4BMoF4oG8BQUoC2EEANhAFxQBGCCZAhgHZ5SMQCuwS9JlNdEJixT0C9AOYVW7AlQhIcAXxyhIUAEoBLAGZl8mXPm6NJKPrQbN8wCAGMAFozoJxm2z3MCh+EWMmVGGTkFZVVoGEgSEn4AawxsFj83T0tEiTcPagtBKyhfCSlA2XkWB3okSQBnABkIbWAAoJLQ8GgAUQAPMBIESs0AN2gDFggunr7BlJzhUQLG4pCcFVaoAHVBMARGePhkNAAfWEjo2jjDzu7egYgl2y3K4CgkCEYUeQBZYjJ1+k3tzAAFERSBAfn9KLtUABKDAAPgSRggwHYSG2gSiSlu90ez1e8nUTFMYK28QBxiJGy2lC0uggMPQ8MMTyRKLR7Axyhwd0YD2ZeKQ73StmJ-ygQKFIohx1i9MZLGeyNR0g5WJ5j0kwAAIrNJKS4JTGJQRVDGlE4QioDoxQAiYFka2W7b634kgBkrqgzr+ADo7XSLYjFdtcW8BV9QQaAV6tlCWMp8FaAdbyRAUA7NE6DVB3Z6Dd6UygYUzA6y+aGCSZUyKowbY-hFFB5SylSGPhLI9HGLHFEA\r\n","issue_id":1660651461837,"origin_id":882351296,"user_origin_id":14338007,"create_time":1626683097,"update_time":1626683097,"id":1666304210439,"updated_at":"2022-10-20T22:16:50.439000Z","created_at":"2022-10-20T22:16:50.439000Z"},{"_id":"6351c8d28041c95dfb0ff22b","body":"Regarding the proposal, could the introduction of exact enum field types be a possible solution?\r\n\r\n```graphql\r\nenum WeaponType {\r\n melee\r\n ranged\r\n magic\r\n}\r\n\r\nenum ItemAptitude {\r\n neutral\r\n technological\r\n magical\r\n}\r\n\r\ntype Sword {\r\n weaponType: WeaponType.melee!\r\n aptitude: ItemAptitude.neutral!\r\n damage: Float!\r\n}\r\n\r\ntype Rifle {\r\n weaponType: WeaponType.ranged!\r\n aptitude: ItemAptitude.technological!\r\n damage: Float!\r\n}\r\n\r\ntype Spellbook {\r\n weaponType: WeaponType.magic!\r\n aptitude: ItemAptitude.magical!\r\n damage: Float!\r\n chargesLeft: Int!\r\n}\r\n```","issue_id":1660651461837,"origin_id":882352736,"user_origin_id":14338007,"create_time":1626683217,"update_time":1626683238,"id":1666304210441,"updated_at":"2022-10-20T22:16:50.441000Z","created_at":"2022-10-20T22:16:50.441000Z"},{"_id":"6351c8d28041c95dfb0ff22c","body":"In my particular case, exact enums would solve all the issues I have. The only problem is that it works only with strings, but I saw some cases where people used number\/boolean literals as discriminators. Not sure how common is this case, but that's probably a separate topic - allowing enum to have boolean\/numeric values is a nice thing to have, but not mandatory to solve the issue we talk about. I'd be happy to see either solution","issue_id":1660651461837,"origin_id":882361058,"user_origin_id":1625500,"create_time":1626683929,"update_time":1626683929,"id":1666304210444,"updated_at":"2022-10-20T22:16:50.443000Z","created_at":"2022-10-20T22:16:50.443000Z"},{"_id":"6351c8d28041c95dfb0ff22d","body":"+1 Exact enums would be a useful construct, particularly in the absence of generics.","issue_id":1660651461837,"origin_id":1084920973,"user_origin_id":13541242,"create_time":1648748913,"update_time":1648748913,"id":1666304210448,"updated_at":"2022-10-20T22:16:50.447000Z","created_at":"2022-10-20T22:16:50.447000Z"},{"_id":"6351c8d28041c95dfb0ff22e","body":"I created this branch where I added parser and printer support for exact enums, it was a fun experience diving into the parser and lexer: https:\/\/github.com\/graphql\/graphql-js\/compare\/main...n1ru4l:feat-exact-named-type-node?expand=1\r\n\r\nThis is still far from an RFC, but I am just experimenting a bit with it for now!","issue_id":1660651461837,"origin_id":1085131412,"user_origin_id":14338007,"create_time":1648761752,"update_time":1648761752,"id":1666304210450,"updated_at":"2022-10-20T22:16:50.450000Z","created_at":"2022-10-20T22:16:50.450000Z"},{"_id":"6351c8d28041c95dfb0ff22f","body":"Would a Union of Interfaces help? You can use the schema to automatically generate type predicates that check whether a received concrete type satisfies an interface based simply on the type name. This is similar to suggestion above, but avoids booleans","issue_id":1660651461837,"origin_id":1085717520,"user_origin_id":4108384,"create_time":1648808113,"update_time":1648808113,"id":1666304210454,"updated_at":"2022-10-20T22:16:50.453000Z","created_at":"2022-10-20T22:16:50.453000Z"},{"_id":"6351c8d28041c95dfb0ff230","body":"@yaacovCR One drawback of that solution is that the functions can become quite large if there are a lot of types within the schema.\r\n\r\nThis solution would also work with the boolean solution (but less verbose as type names tend to be longer).\r\n\r\nIn contrast, the exact enums approach would not require generating any function code.","issue_id":1660651461837,"origin_id":1085722871,"user_origin_id":14338007,"create_time":1648808499,"update_time":1648808550,"id":1666304210456,"updated_at":"2022-10-20T22:16:50.456000Z","created_at":"2022-10-20T22:16:50.456000Z"},{"_id":"6351c8d28041c95dfb0ff231","body":"Although I am in favor of literals in general mostly because of why not","issue_id":1660651461837,"origin_id":1085727579,"user_origin_id":4108384,"create_time":1648808829,"update_time":1648808829,"id":1666304210459,"updated_at":"2022-10-20T22:16:50.458000Z","created_at":"2022-10-20T22:16:50.458000Z"},{"_id":"6351c8d28041c95dfb0ff232","body":"> @yaacovCR One drawback of that solution is that the functions can become quite large if there are a lot of types within the schema.\n> \n> \n> \n> This solution would also work with the boolean solution (but less verbose as type names tend to be longer).\n> \n> \n> \n> In contrast, the exact enums approach would not require generating any function code.\n\nTrue. To clarify, you would need a generated predicate per interface, not per concrete implementation.\n\nThe good news is that you would have symmetry between your runtime types and the graphql types instead of so that could be an organizational plus.\n\nThose predicates might be handy anyway. Imagine if you already had such an interface setup, for example. We are talking about introducing it to solve this problem, but I bet a lot of schemas already use interfaces, and such predicates would also help them.\n\nMaybe TypedDocumentNode would already solve this problem also...","issue_id":1660651461837,"origin_id":1087324378,"user_origin_id":4108384,"create_time":1649064468,"update_time":1649064468,"id":1666304210461,"updated_at":"2022-10-20T22:16:50.461000Z","created_at":"2022-10-20T22:16:50.461000Z"},{"_id":"6351c8d28041c95dfb0ff233","body":"I don't understand how the union of interfaces would help. I want to specify that some particular interface has a field with literal type as a value. It doesn't matter if we have types or interfaces, autogenerated code, and so on, I just want to restrict the value of one particular field to a literal on a schema level to generate proper TS types and I can't do it.","issue_id":1660651461837,"origin_id":1087343124,"user_origin_id":1625500,"create_time":1649065662,"update_time":1649065662,"id":1666304210463,"updated_at":"2022-10-20T22:16:50.463000Z","created_at":"2022-10-20T22:16:50.463000Z"},{"_id":"6351c8d28041c95dfb0ff234","body":"It wouldn't help you have a literal type for a field, but it would help you create a system for discriminating between related types on the client exhaustively using TS typings -- in this case identical to native graphql types. I thought that was the end goal.","issue_id":1660651461837,"origin_id":1087418116,"user_origin_id":4108384,"create_time":1649070416,"update_time":1649070416,"id":1666304210465,"updated_at":"2022-10-20T22:16:50.465000Z","created_at":"2022-10-20T22:16:50.465000Z"},{"_id":"6351c8d28041c95dfb0ff235","body":"@yaacovCR Can you provide an example? It is really hard to grasp what you actually mean. When i try to interpret it it feels like what you are describing is the same as https:\/\/github.com\/graphql\/graphql-spec\/issues\/878#issuecomment-882051729","issue_id":1660651461837,"origin_id":1087448580,"user_origin_id":14338007,"create_time":1649072305,"update_time":1649072305,"id":1666304210467,"updated_at":"2022-10-20T22:16:50.467000Z","created_at":"2022-10-20T22:16:50.467000Z"},{"_id":"6351c8d28041c95dfb0ff236","body":"@n1ru4l sort of -- I assumed that I could solve it using interfaces without realizing that we don't have [empty marker interfaces](https:\/\/github.com\/graphql\/graphql-spec\/pull\/606) and so we can't have an interfaces for RangedWeapon NeutralItem without dummy fields.\r\n\r\nI think that solution with using `__typename` would be type-safe, but without empty composite types, it probably is not that useful.\r\n\r\nApologies for the distraction.","issue_id":1660651461837,"origin_id":1087594807,"user_origin_id":4108384,"create_time":1649080774,"update_time":1649080774,"id":1666304210470,"updated_at":"2022-10-20T22:16:50.469000Z","created_at":"2022-10-20T22:16:50.469000Z"},{"_id":"6351c8d28041c95dfb0ff237","body":"> __typename is useless in a case where multiple discriminators are needed.\r\n\r\ncan you please expand on this? and why this: \r\n\r\n```\r\n switch (weapon.__typeName) { ... \r\n```\r\n\r\nwouldn't work? why multiple discriminators are needed?\r\n\r\n","issue_id":1660651461837,"origin_id":1089293383,"user_origin_id":594969,"create_time":1649190131,"update_time":1649190131,"id":1666304210473,"updated_at":"2022-10-20T22:16:50.473000Z","created_at":"2022-10-20T22:16:50.473000Z"},{"_id":"6351c8d28041c95dfb0ff238","body":"@rivantsov The first post shows a good example: https:\/\/github.com\/graphql\/graphql-spec\/issues\/878#issue-947017031\r\n\r\n```graphql\r\nunion Weapon = Sword | Rifle | Spellbook\r\n```\r\n\r\nIf all of those types have different properties (weaponType, aptitude) it is impossible to discriminate them based on only one or both of those properties. Using the typename allows to only safely discriminate one property (the type itself).\r\n","issue_id":1660651461837,"origin_id":1089304540,"user_origin_id":14338007,"create_time":1649190531,"update_time":1649190531,"id":1666304210476,"updated_at":"2022-10-20T22:16:50.475000Z","created_at":"2022-10-20T22:16:50.475000Z"},{"_id":"6351c8d28041c95dfb0ff239","body":"sorry but still not getting it. Why __typeName not discriminates enough?!","issue_id":1660651461837,"origin_id":1089311122,"user_origin_id":594969,"create_time":1649190860,"update_time":1649190860,"id":1666304210478,"updated_at":"2022-10-20T22:16:50.478000Z","created_at":"2022-10-20T22:16:50.478000Z"},{"_id":"6351c8d28041c95dfb0ff23a","body":"@rivantsov Today we only have one value (aside from doing structural checks for identifying what a type actually is).\r\n\r\n```graphql\r\nenum WeaponType {\r\n melee\r\n ranged\r\n magic\r\n}\r\n\r\nenum ItemAptitude {\r\n neutral\r\n technological\r\n magical\r\n}\r\n\r\ntype Sword {\r\n weaponType: WeaponType!\r\n aptitude: ItemAptitude!\r\n damage: Float!\r\n}\r\n\r\ntype Rifle {\r\n weaponType: WeaponType!\r\n aptitude: ItemAptitude!\r\n damage: Float!\r\n}\r\n\r\ntype Crossbow {\r\n weaponType: WeaponType!\r\n aptitude: ItemAptitude!\r\n damage: Float!\r\n}\r\n\r\ntype Spellbook {\r\n weaponType: WeaponType!\r\n aptitude: ItemAptitude!\r\n damage: Float!\r\n chargesLeft: Int!\r\n}\r\n\r\nunion Weapon = Sword | Rifle | Crossbow | Spellbook\r\n```\r\n\r\nThis does not allow us to get the exact value of the `weaponType` or `aptitude` properties through introspection. Code generation tools can thus not generate code that allows making usage of [Discriminating Unions](https:\/\/www.typescriptlang.org\/docs\/handbook\/unions-and-intersections.html#discriminating-unions) for those.\r\n\r\nE.g. the `Crossbow.weaponType` field of the (enum) type `WeaponType` will always resolve to `ranged`. Today we don't have a way of expressing such behavior. Having a construct that allows this would help tooling.\r\n\r\nThe TypeScript representation of the example above could today only be expressed as the following:\r\n\r\n```ts\r\ntype WeaponType = \"melee\" | \"ranged\" | \"magic\";\r\ntype ItemAptitude = \"neutral\" | \"technological\" | \"magical\";\r\n\r\ntype Sword = {\r\n __typename: \"Sword\";\r\n weaponType: WeaponType;\r\n aptitude: ItemAptitude;\r\n damage: number;\r\n};\r\n\r\ntype Rifle = {\r\n __typename: \"Rifle\";\r\n weaponType: WeaponType;\r\n aptitude: ItemAptitude;\r\n damage: number;\r\n};\r\n\r\ntype Crossbow = {\r\n __typename: \"Crossbow\";\r\n weaponType: WeaponType;\r\n aptitude: ItemAptitude;\r\n damage: number;\r\n};\r\n\r\ntype Spellbook = {\r\n __typename: \"Spellbook\";\r\n weaponType: WeaponType;\r\n aptitude: ItemAptitude;\r\n damage: number;\r\n chargesLeft: number;\r\n};\r\n\r\ntype Weapon = Sword | Rifle | Crossbow | Spellbook;\r\n```\r\n\r\nWhere as the literal type\/exact enum type approach (from https:\/\/github.com\/graphql\/graphql-spec\/issues\/878#issuecomment-882352736) would allow generating types where the `weaponType` and `aptitude` properties can be narrowed down to the actuel runtime type.\r\n\r\n**Schema with exact enum types**\r\n\r\n```graphql\r\nenum WeaponType {\r\n melee\r\n ranged\r\n magic\r\n}\r\n\r\nenum ItemAptitude {\r\n neutral\r\n technological\r\n magical\r\n}\r\n\r\ntype Sword {\r\n weaponType: WeaponType.melee!\r\n aptitude: ItemAptitude.neutral!\r\n damage: Float!\r\n}\r\n\r\ntype Rifle {\r\n weaponType: WeaponType.ranged!\r\n aptitude: ItemAptitude.technological!\r\n damage: Float!\r\n}\r\n\r\ntype Crossbow {\r\n weaponType: WeaponType.ranged!\r\n aptitude: ItemAptitude.neutral!\r\n damage: Float!\r\n}\r\n\r\ntype Spellbook {\r\n weaponType: WeaponType.magic!\r\n aptitude: ItemAptitude.magical!\r\n damage: Float!\r\n chargesLeft: Int!\r\n}\r\n\r\nunion Weapon = Sword | Rifle | Crossbow | Spellbook\r\n```\r\n\r\n**typescript output**\r\n\r\n```ts\r\ntype Sword = {\r\n __typename: \"Sword\";\r\n\r\n weaponType: \"melee\";\r\n aptitude: \"neutral\";\r\n damage: number;\r\n};\r\n\r\ntype Rifle = {\r\n __typename: \"Rifle\";\r\n\r\n weaponType: \"ranged\";\r\n aptitude: \"technological\";\r\n damage: number;\r\n};\r\n\r\ntype Crossbow = {\r\n __typename: \"Crossbow\";\r\n\r\n weaponType: \"ranged\";\r\n aptitude: \"neutral\";\r\n damage: number;\r\n};\r\n\r\ntype Spellbook = {\r\n __typename: \"Spellbook\";\r\n\r\n weaponType: \"magic\";\r\n aptitude: \"magical\";\r\n damage: number;\r\n chargesLeft: number;\r\n};\r\n\r\ntype Weapon = Sword | Rifle | Crossbow | Spellbook;\r\n```\r\n\r\nThis allows more powerful type narowing:\r\n\r\n```ts\r\nfunction printWeapon(weapon: Weapon) {\r\n if (weapon.weaponType === \"ranged\") {\r\n \/\/ weapon is narrowed down to Rifle or Sword\r\n }\r\n \/\/ instead of doing\r\n if (weapon.__typename === \"Rifle\" || weapon.__typename === \"Crossbow\") {\r\n \/\/ weapon is narrowed down to Rifle or Sword\r\n }\r\n \/\/ or\r\n if (weapon.weaponType === \"neutral\") {\r\n \/\/ weapon is narrowed down to Crossbow or Sword\r\n }\r\n \/\/ instead of\r\n if (weapon.__typename === \"Sword\" || weapon.__typename === \"Crossbow\") {\r\n \/\/ weapon is narrowed down to Crossbow or Sword\r\n }\r\n}\r\n```\r\n\r\nThus the arguments for introducing it into GraphQL would be:\r\n\r\n- more flexible narrowing for tooling that uses introspection for code generation\r\n- more type-safety for developers that built upon GraphQL APIs\r\n\r\nWhether it shall be introduced as exact enums or actual literal types is still somethign to discuss though \ud83d\ude04 \r\n","issue_id":1660651461837,"origin_id":1089392685,"user_origin_id":14338007,"create_time":1649194858,"update_time":1649195213,"id":1666304210481,"updated_at":"2022-10-20T22:16:50.481000Z","created_at":"2022-10-20T22:16:50.481000Z"},{"_id":"6351c8d28041c95dfb0ff23b","body":"Suggesting simpler alternative: **Constant Fields**\r\n\r\nthanks for the explanation. Now I get it, kind of. \r\nSo to sum it up - you need is a way to express that a field WeaponType on SpellBook object will always return value MAGIC. And make this fact discoverable by tools thru introspection or by reading a schema file. \r\n\r\nBut then what you need is not 'literal types' but **Constant fields** , or fields with 'default-forever-value'. So instead of: \r\n\r\n```graphql\r\ntype Spellbook {\r\n weaponType: WeaponType.magic!\r\n ... ... \r\n}\r\n```\r\n\r\nwe write: \r\n\r\n```graphql\r\ntype Spellbook {\r\n weaponType: WeaponType! = Magic\r\n ... ... \r\n}\r\n```\r\n\r\n'Literal type' is an advanced type concept, not widespread, I had to google to find out WTF is that, found references to TypeScript and C++. I might be a dumb expert (I am), not knowing ALL stuff, but that makes me a good test case here - not everybody is familiar with literal types concept. It took me a while to get it what you suggest and how it will work. \r\n\r\nAt the same time, 'constant fields' is an easy, trivial concept to understand for everybody, even a dummy like myself \r\nYes, extra field(s) needed in introspection, but this the same as with literal types \r\n\r\n\r\n\r\n\r\n","issue_id":1660651461837,"origin_id":1090442534,"user_origin_id":594969,"create_time":1649261043,"update_time":1649261043,"id":1666304210485,"updated_at":"2022-10-20T22:16:50.484000Z","created_at":"2022-10-20T22:16:50.484000Z"},{"_id":"6351c8d28041c95dfb0ff23c","body":"constant fields is a harder concept than literal types and it makes things more complicated. why do I need to create enum just to express that my field has some specific value? \r\nWith literal types it would look like this:\r\n```graphql\r\ntype Sword {\r\n weaponType: \"melee\"!\r\n aptitude: \"neutral\"!\r\n damage: Float!\r\n}\r\n\r\ntype Rifle {\r\n weaponType: \"ranged\"!\r\n aptitude: \"technological\"!\r\n damage: Float!\r\n}\r\n\r\ntype Spellbook {\r\n weaponType: \"magic\"!\r\n aptitude: \"magical\"!\r\n damage: Float!\r\n chargesLeft: Int!\r\n}\r\n\r\nunion Weapon = Sword | Rifle | Spellbook\r\n```\r\nwith constant fields it would look like this:\r\n```graphql\r\nenum WeaponType {\r\n melee\r\n ranged\r\n magic\r\n}\r\n\r\nenum ItemAptitude {\r\n neutral\r\n technological\r\n magical\r\n}\r\n\r\ntype Sword {\r\n weaponType: WeaponType! = melee\r\n aptitude: ItemAptitude! = neutral\r\n damage: Float!\r\n}\r\n\r\ntype Rifle {\r\n weaponType: WeaponType! = ranged\r\n aptitude: ItemAptitude! = technological\r\n damage: Float!\r\n}\r\n\r\ntype Spellbook {\r\n weaponType: WeaponType! = magic\r\n aptitude: ItemAptitude! = magical\r\n damage: Float!\r\n chargesLeft: Int!\r\n}\r\n\r\nunion Weapon = Sword | Rifle | Spellbook\r\n```\r\nit takes much more code and it also requires creating 2 additional enums I will never need in my code. Of course, I can create a dummy enum for all literal values like this:\r\n```graphql\r\nenum Literal {\r\n melee\r\n ranged\r\n magic\r\n neutral\r\n technological\r\n magical\r\n}\r\n\r\ntype Sword {\r\n weaponType: Literal! = melee\r\n aptitude: Literal! = neutral\r\n damage: Float!\r\n}\r\n\r\ntype Rifle {\r\n weaponType: Literal! = ranged\r\n aptitude: Literal! = technological\r\n damage: Float!\r\n}\r\n\r\ntype Spellbook {\r\n weaponType: Literal! = magic\r\n aptitude: Literal! = magical\r\n damage: Float!\r\n chargesLeft: Int!\r\n}\r\n\r\nunion Weapon = Sword | Rifle | Spellbook\r\n```\r\nbut still why create an additional enum and have more code than needed? yes, ultimately it would solve the purpose to generate proper TS types from such a schema, but constant fields looks like unnecessary complexity\r\n\r\nEdit: I just realized that nobody forces me to use enums here :D \r\n\r\n```graphql\r\ntype Sword {\r\n weaponType: String! = melee\r\n aptitude: String! = neutral\r\n damage: Float!\r\n}\r\n\r\ntype Rifle {\r\n weaponType: String! = ranged\r\n aptitude: String! = technological\r\n damage: Float!\r\n}\r\n\r\ntype Spellbook {\r\n weaponType: String! = magic\r\n aptitude: String! = magical\r\n damage: Float!\r\n chargesLeft: Int!\r\n}\r\n\r\nunion Weapon = Sword | Rifle | Spellbook\r\n```\r\nSo version with constants is actually just a few characters longer that with literals","issue_id":1660651461837,"origin_id":1090832298,"user_origin_id":1625500,"create_time":1649280969,"update_time":1649281429,"id":1666304210490,"updated_at":"2022-10-20T22:16:50.489000Z","created_at":"2022-10-20T22:16:50.489000Z"},{"_id":"6351c8d28041c95dfb0ff23d","body":"> So version with constants is actually just a few characters longer that with literals\r\n\r\nbut much simpler conceptually\r\nIn your last sample, with strings, I think values should be in double quotes","issue_id":1660651461837,"origin_id":1090845031,"user_origin_id":594969,"create_time":1649281924,"update_time":1649281924,"id":1666304210492,"updated_at":"2022-10-20T22:16:50.492000Z","created_at":"2022-10-20T22:16:50.492000Z"},{"_id":"6351c8d28041c95dfb0ff23e","body":"by the way, the same can be achieved today, with a custom directive:\r\n \\@ const(str: value)","issue_id":1660651461837,"origin_id":1090855487,"user_origin_id":594969,"create_time":1649282683,"update_time":1649282714,"id":1666304210495,"updated_at":"2022-10-20T22:16:50.494000Z","created_at":"2022-10-20T22:16:50.494000Z"},{"_id":"6351c8d28041c95dfb0ff23f","body":"I can't agree that constants is a simpler context though. I speak from a frontend perspective (TS\/Flow), where literal types are widely used (in all the codebases I worked with they are even more common than enums). Constants still require some additional mental work: \"first we declared type as a set of values, but then narrowed it down to a single value\" vs \"we declared type as a single value\". Why should I narrow it down, if I can properly specify it straight away? What this narrowing down implies? Is it safe to assume that here `weaponType: String! = \"magic\"` weaponType can be a \"magic\"? If so, why do we specify it as a sting? What `=` means? In lots of languages it means \"default value\", not a constant. And so on and so on. But when I see `weaponType: \"magic\"!` it's pretty straightforward. It means that weaponType can only accept a single value, \"magic\". No need to narrow anything down in the thought process, no need to think about meaning of `=` symbol, it's just simple","issue_id":1660651461837,"origin_id":1090857264,"user_origin_id":1625500,"create_time":1649282809,"update_time":1649282809,"id":1666304210497,"updated_at":"2022-10-20T22:16:50.497000Z","created_at":"2022-10-20T22:16:50.497000Z"},{"_id":"6351c8d28041c95dfb0ff240","body":"> by the way, the same can be achieved today, with a custom directive:\r\n> @ const(str: value)\r\n\r\nThere is only the limitation that the directives have no proper \"on field type validation\" and are not visible via introspection","issue_id":1660651461837,"origin_id":1090862710,"user_origin_id":14338007,"create_time":1649282980,"update_time":1649282980,"id":1666304210499,"updated_at":"2022-10-20T22:16:50.499000Z","created_at":"2022-10-20T22:16:50.499000Z"},{"_id":"6351c8d28041c95dfb0ff241","body":"directives on fields are not visible on fields - \r\nthen let's fix the introspection! it is long overdue and does not make sense that some things are not available in introspection. I tried to scream wtf, but was shutdown. It is nonsense\r\n\r\nAs for 'literal types' easy - good for you guys you spend most of your time in typeScript. I don't. I am a server side guy, never encountered it. The concept is not trivial. \"ABC\" is a type - whaaat? Constant fields are easier for sure. In c#, java etc, constants are static immutable fields with initial values. \r\n\r\nWhat \"=\" means? same thing as for args with default values, this is in line with existing syntax. \r\n ","issue_id":1660651461837,"origin_id":1090871371,"user_origin_id":594969,"create_time":1649283773,"update_time":1649283849,"id":1666304210502,"updated_at":"2022-10-20T22:16:50.501000Z","created_at":"2022-10-20T22:16:50.501000Z"},{"_id":"6351c8d28041c95dfb0ff242","body":"For default values, you need the type because when supplied, the argument must match the type.\n\nSo the question becomes, with literals or constants, for the executor to validate the object against the type, is a type necessary?\n\nI think it might be necessary for something like a constant custom scalar.\n\nBut if you just want to express the literal types that can be in sdl like string and it's equivalents (ID, enum) you wouldn't need it.","issue_id":1660651461837,"origin_id":1091009499,"user_origin_id":4108384,"create_time":1649297973,"update_time":1649298023,"id":1666304210504,"updated_at":"2022-10-20T22:16:50.504000Z","created_at":"2022-10-20T22:16:50.504000Z"},{"_id":"664c34312cfd0d66a8125a35","body":"Hello all, kinda late to the convo and sadly, there hasn't been any activity on this for almost a year. Just wanted to share I found this because I too found myself needing GraphQL support for Typescript's discriminated unions, especially within the context of codegen tools like [this one](https:\/\/the-guild.dev\/graphql\/codegen). \r\n\r\nWhen I first started my project, I was manually maintaining TS types alongside a GraphQL schema that somewhat reflected these types but as my project began to grow, I found that this is a painstaking task and source of many bugs, so I decided to try and adopt usage of previously linked codegen tool. What I am finding is that discriminated unions are really difficult to model in a GraphQL schema, and the best idea I've had on how to do so is using custom scalars like:\r\n\r\n```\r\nscalar RootPostType\r\nscalar ReplyPostType\r\n\r\ntype RootPost {\r\n type: RootPostType\r\n ...\r\n}\r\n\r\ntype ReplyPost {\r\n type: ReplyPostType\r\n ...\r\n}\r\n```\r\n\r\nAnd then, within my `codegen.ts` file, within the config section, I can add something like:\r\n```\r\nscalars: {\r\n RootPostType: \"'root'\",\r\n ReplyPostType: \"'reply'\",\r\n},\r\n```\r\n\r\nHowever, as I'm still relatively new to GraphQL and currently using Apollo Server\/Client tools, I've read I need to implement [custom scalar logic](https:\/\/www.apollographql.com\/docs\/apollo-server\/schema\/custom-scalars\/), and since I'm using discriminated unions a fair bit, this might become quite a pain (not sure yet though). \r\n\r\nI tried making use of the `__typename` property but I had a couple of issues with it:\r\n\r\n1. This is a property supplied only to the client (codegen tool does not create `__typename` for inputs), but my server would also sometimes need to distinguish types. For example, in my case above, when a user is submitting a root or reply post with different content inputs, they use a type like: `union ContentInput = TextContentInput | LinkContentInput | ImageContentInput | ...`, depending on the nature of the content, I'd like to process it differently when a root\/reply post submission request is received server side. As it is, this already requires two separate mutation endpoints (if this is the right term) on the server side because again, I have no way of distinguishing whether a user is attempting to submit a root post or a reply post even though the logic is nearly identical.\r\n2. Even when it is supplied to the client, one of its potential values is `undefined`, and it's rather annoying having to first check that it isn't undefined and add logic to deal with the case when it is undefined even though I know this won't happen. Even when I do check that it isn't undefined, TS for whatever reason doesn't register the narrowing, like so:\r\n<img width=\"738\" alt=\"image\" src=\"https:\/\/user-images.githubusercontent.com\/17789545\/227736733-c0abfb03-296f-4c80-bd3c-2ed84ff4abda.png\"> Nevermind the `toHexString()` error, what I'm trying to show is that I've ruled out `__typename` being `undefined`, `RootPostWithId` and so the only possibility left is `ReplyPostWithId` which does contain the `parentPath` property and yet TS won't recognize it? \r\n\r\n\r\nSo, excuse the long post but I don't really want to rewrite a substantial part of my codebase that depended on discriminated unions so I'm hoping someone can suggest the best way to approach this problem or at the very least, be another scenario where GraphQL support for discriminated unions (however that may be, through literal types, exact enum types, or constant fields).\r\n","issue_id":1660651461837,"origin_id":1483900286,"user_origin_id":17789545,"create_time":1679771571,"update_time":1679772188,"id":1716270129446,"updated_at":"2024-05-21T05:42:09.446000Z","created_at":"2024-05-21T05:42:09.446000Z"}] comment

Consider adding literal types support to be able to express a union with more than a single discriminator: ```graphql type Sword { weaponType: "melee"! aptitude: "neutral"! damage: Float! } type...

Add support for directives on directives

[{"_id":"6351ca00ea01ec786e75a8c2","body":"\u2714\ufe0f Deploy Preview for *graphql-spec-draft* ready!\n\n\n\ud83d\udd28 Explore the source changes: 93eb69457242b2fd2d30181d6badf90032dd448b\n\n\ud83d\udd0d Inspect the deploy log: [https:\/\/app.netlify.com\/sites\/graphql-spec-draft\/deploys\/61a8ffa89a70010007283c1d](https:\/\/app.netlify.com\/sites\/graphql-spec-draft\/deploys\/61a8ffa89a70010007283c1d)\n\n\ud83d\ude0e Browse the preview: [https:\/\/deploy-preview-907--graphql-spec-draft.netlify.app](https:\/\/deploy-preview-907--graphql-spec-draft.netlify.app)\n","issue_id":1660651461841,"origin_id":984832515,"user_origin_id":40209326,"create_time":1638465452,"update_time":1638465482,"id":1666304512321,"updated_at":"2022-10-20T22:21:52.320000Z","created_at":"2022-10-20T22:21:52.320000Z"},{"_id":"6351ca00ea01ec786e75a8c3","body":"why are we so scared of these recursive definitions? things like that happen in real progr languages, no trouble. Why all this word soup to prohibit smth like that - if there's potential trouble, it would be a choice of the server-side dev, he wants it for some reason - he would handle the consequences if any\r\n","issue_id":1660651461841,"origin_id":985672462,"user_origin_id":594969,"create_time":1638550250,"update_time":1638557418,"id":1666304512325,"updated_at":"2022-10-20T22:21:52.324000Z","created_at":"2022-10-20T22:21:52.324000Z"},{"_id":"6351ca00ea01ec786e75a8c4","body":"> why are we so scared of these recursive definitions? things like that happen in real progr languages, no trouble. Why all this word soup to prohibit smth like that - if there's potential trouble, it would be a choice of the server-side dev, he wants it for some reason - he would handle the consequences if any\r\n\r\nGraphQL is supposed to be non-Turing Complete, to provide a guarantee to the server that, outside of the code used by Resolvers, the program itself will halt. The requirement for directives on directives to not form a cycle may or may not be required to keep GraphQL from becoming Turing Complete, but whenever we are adding new constructs to the language, by default we usually try to avoid recursion in the first pass to reduce Turing Completeness considerations from the RFC. ","issue_id":1660651461841,"origin_id":986050049,"user_origin_id":1741248,"create_time":1638633661,"update_time":1638633661,"id":1666304512329,"updated_at":"2022-10-20T22:21:52.328000Z","created_at":"2022-10-20T22:21:52.328000Z"},{"_id":"6351ca00ea01ec786e75a8c5","body":"Turing?! complete?! what are you talking about?! it is not a programming language. Guarantee to the server?!!! I am a server-side programmer, and I can tell you nobody other than myself, no spec can guarantee anything about my server code, will it complete, crash or loop forever. Spec can't guarantee anything, especially about server implementation code, period. What Spec can do is introduce unnecessary, hard to understand restrictions that leave with one question - why is this word soup there at all\r\nIf server can implement recursive directives - let it do it. If it can't - it wont. ","issue_id":1660651461841,"origin_id":986070875,"user_origin_id":594969,"create_time":1638641970,"update_time":1638641970,"id":1666304512332,"updated_at":"2022-10-20T22:21:52.332000Z","created_at":"2022-10-20T22:21:52.332000Z"},{"_id":"6351ca00ea01ec786e75a8c6","body":"> GraphQL is supposed to be non-Turing Complete, to provide a guarantee to the server that, outside of the code used by Resolvers, the program itself will halt.\r\n\r\nThis is really interesting? Is there a reference in the spec or other originating material documenting this?\r\n\r\nIn the spec, I just see a statement I read as noting that GraphQL is not a programming language capable of arbitrary computation, but nothing per se that we have to avoid recursion. I see the point you are raising in terms of guarantees of completion when resolvers are properly implemented, but perhaps not every recursion application instance would prohibit this.\r\n\r\nMaybe it would? I guess I am wondering if the specifiedBy directive could recursively apply to itself, for example, without non-halting concerns\u2026","issue_id":1660651461841,"origin_id":989991443,"user_origin_id":4108384,"create_time":1639065945,"update_time":1639065945,"id":1666304512336,"updated_at":"2022-10-20T22:21:52.336000Z","created_at":"2022-10-20T22:21:52.336000Z"},{"_id":"6351ca00ea01ec786e75a8c7","body":"I guess the question is: considering some recursive directive references could be nonparsable, nonsensical, etc, etc, should all such references be disallowed?\r\n\r\nConsidering that even some non recursive directive references have the same problem and require separate validation, I am not sure that recursion itself has to be forbidden.\r\n\r\nmaybe it should for now for simplicity, of course! That would be my preference, until a compelling use case presents itself","issue_id":1660651461841,"origin_id":990799343,"user_origin_id":4108384,"create_time":1639130380,"update_time":1639130380,"id":1666304512341,"updated_at":"2022-10-20T22:21:52.340000Z","created_at":"2022-10-20T22:21:52.340000Z"},{"_id":"6351ca00ea01ec786e75a8c8","body":"@benjie \r\n> This text needs to be modified to cover direct reference to itself\r\n\r\nThat seems to already exist, see https:\/\/spec.graphql.org\/draft\/#sel-EAHnBTEBAAAEDDA_FtwX\r\n\r\n@IvanGoncharov\r\n\r\nI think putting directives at the end of the list of locations isn't consistent with similar syntax of [Union types](https:\/\/spec.graphql.org\/draft\/#UnionTypeDefinition)\r\n\r\n```graphql\r\nunion Example @directive =\r\n | TypeA\r\n | TypeB\r\n | TypeC\r\n```\r\n\r\ncompare to:\r\n\r\n```graphql\r\ndirective @directive(arg: Type) on\r\n | Field\r\n | Fragment @deprecated\r\n```\r\n\r\nIt also reads like the deprecation is applying to the `Fragment` location instead of the directive itself.\r\n\r\nPutting it after the argument list would be more consistent with directives on FieldDefinitions:\r\n\r\n```graphql\r\ndirective @directive(arg: Type) @deprecated on\r\n | Field\r\n | Fragment\r\n```\r\n\r\nIn the case where there are no args and repeatable:\r\n\r\n```graphql\r\ndirective @directive @deprecated repeatable on\r\n | Field\r\n | Fragment\r\n```\r\n\r\nEither way, I still don't love this syntax. The repeated `@name` is hard to read, but I dislike other alternatives more","issue_id":1660651461841,"origin_id":1006920457,"user_origin_id":50130,"create_time":1641501717,"update_time":1641501743,"id":1666304512345,"updated_at":"2022-10-20T22:21:52.344000Z","created_at":"2022-10-20T22:21:52.344000Z"},{"_id":"6351ca00ea01ec786e75a8c9","body":"re syntax: Would it be crazy to generally allow directives to be used within docstrings? For directive definitions, this could then be the only way to apply a directive in order to keep the syntax clean.","issue_id":1660651461841,"origin_id":1006920613,"user_origin_id":693596,"create_time":1641501732,"update_time":1641501732,"id":1666304512348,"updated_at":"2022-10-20T22:21:52.347000Z","created_at":"2022-10-20T22:21:52.347000Z"},{"_id":"6351ca00ea01ec786e75a8ca","body":"What are potential use-cases for directives that transform the actual behavior of an existing directive?\r\n\r\nIn the WG we mentioned `@deprecated` and `@specifiedBy`. Both of those mainly enrich the parts on which they are specified with additional information that is available via introspection.\r\n\r\nWhile discussing this I noticed a lot of similarities to JSDOC `@deprecated` and `@link`.\r\n\r\nWhat if those \"metadata enrichment directives\" could instead be part of the field\/argument\/directive description string?\r\n\r\n```graphql\r\ndirective @deprecated(reason: String) on TYPE_DESCRIPTION, FIELD_DESCRIPTION, ARGUMENT_DESCRIPTION\r\n\r\ntype User {\r\n \"\"\"\r\n This is the id\r\n \"\"\"\r\n id: ID!\r\n \"\"\"\r\n This is the name\r\n @deprecated(reason: \"This is deprecated.\")\r\n \"\"\"\r\n name: String!\r\n}\r\n\r\n\"\"\"\r\n@deprecated(reason: \"This is deprecated.\")\r\n\"\"\"\r\ndirective @bar on FIELD\r\n```\r\n\r\nEdit: @fotoetienne [was faster](https:\/\/github.com\/graphql\/graphql-spec\/pull\/907#issuecomment-1006920613) than me","issue_id":1660651461841,"origin_id":1006928261,"user_origin_id":14338007,"create_time":1641502515,"update_time":1641503391,"id":1666304512351,"updated_at":"2022-10-20T22:21:52.351000Z","created_at":"2022-10-20T22:21:52.351000Z"},{"_id":"6351ca00ea01ec786e75a8cb","body":"could we consider allowing d-o-ds to apply to individual locations?\r\n\r\na use case is when a directive is `@deprecated` in one location, but not in another:\r\n\r\n```graphql\r\ndirective @explode(arg: Type) @specifiedBy(url: X) on\r\n | FIELD \r\n | FRAGMENT @deprecated\r\n```\r\n\r\nthe `@explode` directive here:\r\n- is `@specifiedBy(url: X)` in all locations\r\n- its use on `FRAGMENT`s is `@deprecated`","issue_id":1660651461841,"origin_id":1022884171,"user_origin_id":7763406,"create_time":1643264301,"update_time":1643264301,"id":1666304512355,"updated_at":"2022-10-20T22:21:52.354000Z","created_at":"2022-10-20T22:21:52.354000Z"},{"_id":"6351ca00ea01ec786e75a8cc","body":"> What are potential use-cases for directives that transform the actual behavior of an existing directive?\r\n\r\nI have a couple of directives that modify the behavior of the contiguous directive(s) in the query\/SDL:\r\n\r\n- `@forEach`: It iterates the items in the field value (whenever it is a List), and passes each of them to the next directive\r\n- `@advancePointerInArrayOrObject`: Given an associative array or object in the field value, it places the pointer into a certain path, and the next directive is applied on that element\r\n\r\nThese are useful to apply a directive that does not expect a List. For instance, let's say that `@titleCase` only handles an input of type `String`:\r\n\r\n```graphql\r\ndirective @titleCase on FIELD | FIELD_DEFINITION\r\n\r\ntype Query {\r\n siteName: String\r\n @titleCase\r\n}\r\n```\r\n\r\nThen it can receive `[String]` by placing `@forEach` before it:\r\n\r\n```graphql\r\ntype Query {\r\n categoryNames: [String] \r\n @forEach \r\n @titleCase\r\n}\r\n```\r\n\r\nIn the query:\r\n\r\n```graphql\r\nquery {\r\n categoryNames\r\n @forEach \r\n @titleCase\r\n}\r\n```\r\n\r\nThese directives can also nest each other, as many times as needed. For instance, if the input is `[[String]]`, it can do this:\r\n\r\n```graphql\r\nquery {\r\n customerAllNames\r\n @forEach \r\n @forEach \r\n @titleCase\r\n}\r\n```\r\n\r\nI use `@advancePointerInArrayOrObject` mainly to modify the response from an external source that I got via REST. For instance, I have field `getJSON` that returns a `JSONObject`. Let's say some REST endpoint returns this:\r\n\r\n```json\r\n[\r\n {\r\n \"name\": \"Leo\",\r\n \"email\": \"[email protected]\"\r\n },\r\n {\r\n \"name\": \"Manuel\",\r\n \"email\": \"[email protected]\"\r\n }\r\n]\r\n```\r\n\r\nI can then apply `@titleCase` only on the `\"name\"` entry of each result, like this:\r\n\r\n```graphql\r\nquery {\r\n userData: getJSON(url: \"https:\/\/...\")\r\n @forEach \r\n @advancePointerInArrayOrObject(path: \"name\") \r\n @titleCase\r\n}\r\n```\r\n\r\nThese directives have an `affect` param to indicate which are the directives whose behavior must be modified, then they can modify more than one. This param is an `[Int]` indicating the relative position(s) to the modified directive(s):\r\n\r\n```graphql\r\ntype Query {\r\n categoryNames: [String] \r\n @forEach(affect: [1, 2])\r\n @titleCase\r\n @translate(from: \"en\", to: \"fr\")\r\n}\r\n```\r\n\r\nBy default `affect` has value `[1]`, that's why in the previous examples, where a directive modifies the directive to its right, `affect` needs not be provided.\r\n\r\nBtw, I just published a more detailed article explaining all this, [here](https:\/\/stepzen.com\/blog\/graphql-directives-transforming-behavior-of-directives).\r\n","issue_id":1660651461841,"origin_id":1079580772,"user_origin_id":1981996,"create_time":1648264100,"update_time":1648264100,"id":1666304512358,"updated_at":"2022-10-20T22:21:52.358000Z","created_at":"2022-10-20T22:21:52.358000Z"},{"_id":"6351ca00ea01ec786e75a8cd","body":"Every time I see an example such as this:\r\n\r\n```graphql\r\ntype Post {\r\n categories: [String] @forEach @titleCase\r\n}\r\n\r\ndirective @forEach on FIELD_DEFINITION\r\ndirective @titleCaseon FIELD_DEFINITION\r\n```\r\n\r\nI immediately think that the following might be the better solution:\r\n\r\n```graphql\r\nenum StringFormat {\r\n titleCase\r\n upperCase\r\n snakeCase\r\n}\r\n\r\ntype Post {\r\n categories(format: StringFormat): [String]\r\n}\r\n```\r\n\r\nMy main reasons:\r\n\r\n`@titleCase` could be applied on any field as directives don't have an \"on applied field type\" constraint.\r\n\r\nThe following cannot be caught by GraphQL validation:\r\n\r\n```graphql\r\ntype Post {\r\n a: Int @titleCase\r\n}\r\n```","issue_id":1660651461841,"origin_id":1082877844,"user_origin_id":14338007,"create_time":1648634101,"update_time":1648634101,"id":1666304512361,"updated_at":"2022-10-20T22:21:52.361000Z","created_at":"2022-10-20T22:21:52.361000Z"},{"_id":"6351ca00ea01ec786e75a8ce","body":"@n1ru4l I acknowledge that not everybody likes this solution, but I don't think it makes the use case invalid.\r\n\r\nThere are examples of things we can do in different ways in GraphQL, which can work better for different applications, and they are all valid. For instance:\r\n\r\n- pagination via cursor connections or not\r\n- modeling errors via unions of types or simple descriptions\r\n\r\nIn what context would `@forEach @titleClase` work better? As to simplify the resolvers (whether field resolver or directive resolver), so that they don't need to apply different logic if the input is `[[String]]`, `[String]` or `String`; they only handle `String`.\r\n\r\nMy concern is to not have to update the resolvers whenever the client has a novel type input, such as `[[[String]]]`, and not have to think all possibilities in advance (and have to code all of them, bloating the code). Because of this, for my own API, I find `@forEach @titleClase` more suitable.\r\n\r\nEven if you prefer an alternative solution, don't you think that `@forEach @titleClase` is valid? Shouldn't it be considered an actual (not only potential, since I'm already using it in my server) use case for directives that transform the actual behavior of an existing directive?","issue_id":1660651461841,"origin_id":1083997950,"user_origin_id":1981996,"create_time":1648693355,"update_time":1648693355,"id":1666304512364,"updated_at":"2022-10-20T22:21:52.364000Z","created_at":"2022-10-20T22:21:52.364000Z"},{"_id":"6351ca00ea01ec786e75a8cf","body":"I think we got two threads mixed up here. The original post suggests allowing directives on **directive definitions**. That seems logical and unambiguous to me. \r\n\r\nThe later post by @leoloso (with \\@forEach and \\@titleCase) suggests directives on directive instances in queries. This is quite different I think. My biggest problem with this: having \r\n\r\n```graphql\r\nquery {\r\n customerAllNames\r\n @forEach \r\n @titleCase\r\n}\r\n```\r\n\r\nthe idea is that in this case titleCase is applied to forEach? and why not both directives apply to customerAllNames field?! what's the rule to distinguish the case that the second directive is applied to previous directive, not the field?\r\n \r\n\r\n","issue_id":1660651461841,"origin_id":1090471545,"user_origin_id":594969,"create_time":1649262806,"update_time":1649262806,"id":1666304512367,"updated_at":"2022-10-20T22:21:52.367000Z","created_at":"2022-10-20T22:21:52.367000Z"},{"_id":"6351ca00ea01ec786e75a8d0","body":"@rivantsov You have a point! The question was about directives modifying the behavior of other directives, which happens with `@forEach`, but it works by being applied on the same field, so it must be defined in `FIELD | FIELD_DEFINITION`. Now that you mention, I agree we are talking about two separate issues (sorry for the mix-up).\r\n\r\nHere is an idea to implement a similar concept using `DIRECTIVE_DEFINITION` (I'm not really sure this makes a lot of sense, though, but I still bring it out to explore ideas for this issue):\r\n\r\nA directive `@composeDirectives` could create a new directive from combining the behavior of other directives. The magic would be that the SDL would be enough, so the new directive (`@forEachTitleCase`) would be created without any resolver code:\r\n\r\n```graphql\r\ndirective @titleCase on FIELD | FIELD_DEFINITION\r\n\r\n# It converts an input of type `[String]` into an array of `String`, passes each downstream to the composed directive, and finally recreates the original array\r\ndirective @forEach on FIELD | FIELD_DEFINITION\r\n\r\n# Create a new directive from composing 2 or more directives\r\ndirective @composeDirectives($directiveNames: [String!]!) on DIRECTIVE_DEFINITION\r\n\r\n# Create a new directive combining the behavior of other directives, just through SDL\r\ndirective @forEachTitleCase on FIELD | FIELD_DEFINITION\r\n @composeDirectives(directiveNames: [\"forEach\", \"titleCase\"])\r\n```\r\n\r\n(This solution will not work for my server, though, since it's code-first, so I need to stick to using `@forEach` in the query)","issue_id":1660651461841,"origin_id":1091008927,"user_origin_id":1981996,"create_time":1649297908,"update_time":1649297908,"id":1666304512369,"updated_at":"2022-10-20T22:21:52.369000Z","created_at":"2022-10-20T22:21:52.369000Z"}] comment

I suggest allowing to specify directives on directives with the following syntax: ``` directive @foo on DIRECTIVE_DEFINITION directive @bar on FIELD @foo ``` ## Motivation Allow applying directive-exclusive features (e.g....

💡 Proposal (RFC 1)

[RFC] Collections / CollectionTypeDefinition

[{"_id":"6351bc96cecf4e081a1a6b9f","body":"I do not quite understand the purpose and benefits. The whole reasoning is based on these 'requirements', which are quite questionable. Like number 4: \r\n\r\n> 4. Item slots should not be queried\/selected individually, the query either includes all slots or non.\r\n\r\nwhy this thing is so necessary (in certain cases?) that it warrants a new concept and new syntax?! Is it like transactional - all or nothing? all fields or none? What is the case when it's critical?!\r\n\r\nand req 5, along with the suggested benefit: \r\n\r\n> Gets rid of unnecessary\/repetitive lines in queries to select the same nested fields across multiple fields.\r\n\r\nthere is a thing already that does this. It's called Fragments\r\n\r\n\r\n\r\n","issue_id":1660651461843,"origin_id":1088284237,"user_origin_id":594969,"create_time":1649136618,"update_time":1649136618,"id":1666301078744,"updated_at":"2022-10-20T21:24:38.743000Z","created_at":"2022-10-20T21:24:38.743000Z"}] comment

# TL;DR: This RFC introduces a new variant of Lists/Arrays that has named entries key-value pairs. Which can be queried exactly like arrays, but a result is an object. ##...

Polymorphic name

[{"_id":"6351bfaad297b621322eb401","body":"I don't 100% understand the issue here, but would an interface be a better fit? Then you'd just do `... on SimpleInterface` in both places?","issue_id":1660651461846,"origin_id":1061018799,"user_origin_id":129910,"create_time":1646679225,"update_time":1646679225,"id":1666301866380,"updated_at":"2022-10-20T21:37:46.380000Z","created_at":"2022-10-20T21:37:46.380000Z"},{"_id":"6351bfaad297b621322eb402","body":"sorry, my english is not so good sometimes.\r\n\r\n> but would an interface be a better fit? Then you'd just do ... on SimpleInterface in both places? \r\n\r\nno because the nested type has less fields than the original type. \r\n\r\nThink about domains. \r\nWe have the `Product` domain which is an interface where the `Product` type is full of info like name, value, user owner etc and have sub types like `Physical` or `Virtual`. \r\nIn the domain `User` you can also fetch some `Product` info on `User.products`, however, with a different type that has less fields than the `Product` in its original domain\/type. But their names are the same: Product, Physical and Virtual. \r\n\r\nAs I can't have two types with same name, the branch `User.products` will be a list of `UserProduct`, then its subtypes will be `UserPhysical` and `UserVirtual`. \r\nI would like to avoid that only in fragments, so instead of `User { products { ...on UserPhysical { foo } } }` I set a polymorphic alias in `UserPhysical` to `Physical` so I then can use `User { products { ...on Physical { foo } } }` even thought the original `Physical` is not being used there, just the name. \r\n\r\nis it better now? :(","issue_id":1660651461846,"origin_id":1061037629,"user_origin_id":6199518,"create_time":1646680397,"update_time":1646680397,"id":1666301866383,"updated_at":"2022-10-20T21:37:46.383000Z","created_at":"2022-10-20T21:37:46.383000Z"},{"_id":"6351bfaad297b621322eb403","body":"I guess I don't really see the benefits and only drawbacks (particularly type evolution constraints, but also impact on validation, mismatch of `__typename`, etc). If there's fields in common it feels like rather than declaring a \"polymorphic alias\" an interface would be the way to do this, and it should already work.","issue_id":1660651461846,"origin_id":1061083666,"user_origin_id":129910,"create_time":1646683526,"update_time":1646683526,"id":1666301866386,"updated_at":"2022-10-20T21:37:46.386000Z","created_at":"2022-10-20T21:37:46.386000Z"},{"_id":"6351bfaad297b621322eb404","body":"I think it shouldn't impact on validation or mismatch of `__typename` as it is processed only in fragments and before entering validation area. \r\nIf I was to use an interface it would still have not so nice names in one of the branches.","issue_id":1660651461846,"origin_id":1061101708,"user_origin_id":6199518,"create_time":1646684671,"update_time":1646684671,"id":1666301866388,"updated_at":"2022-10-20T21:37:46.388000Z","created_at":"2022-10-20T21:37:46.388000Z"},{"_id":"6351bfaad297b621322eb405","body":"If I understand correctly, you're wanting to narrow the types as you venture further down the tree?\r\n\r\n```graphql\r\ninterface Product {\r\n name: String!\r\n price: Price \r\n}\r\n\r\ntype VirtualProduct implements Product {\r\n # removed above for brevity\r\n\r\n downloadUrl: String!\r\n}\r\n\r\ntype PhsyicalProduct implements Product {\r\n weight: Number!\r\n}\r\n\r\nunion ProductsUnion = VirtualProducts | PhysicalProducts;\r\n```\r\n\r\nand then as you venture into the tree, like:\r\n\r\n```graphql\r\n{\r\n\tproducts { # SomethingElse\r\n\t\tshippable { # PhysicalProduct\r\n\t\t\tweight\r\n\t\t}\r\n\t\tdownloadable { # VirtualProduct\r\n\r\n\t\t}\r\n\t}\r\n}\r\n```\r\n\r\nI suspect you've got something like this, where with recursive types you could have already limited, but then given the option to expand?\r\n\r\n```graphql\r\n{\r\n\tproducts { # ProductUnion\r\n\t\tvirtualOnly {\r\n\t\t\titems { # ProductUnion\r\n\t\t\t\t# but now given the option to get shippable ones\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n```\r\n\r\n--- \r\n\r\nin anycase, and hope this adds value. You generally want to be expressive, rather than rely on interface or type spreading.\r\n\r\nAnd if that means more types then that is the go.\r\n\r\n```graphql\r\ntype Downloadable implements VirtualProduct {\r\n\r\n}\r\n\r\ntype Shippable implements Product {\r\n\r\n}\r\n\r\n# or even\r\n\r\ninterface Base { }\r\ninterface Broad { }\r\ntype BroadType implements Base, Broad { }\r\ntype Narrow implements Base { }\r\n``","issue_id":1660651461846,"origin_id":1061333464,"user_origin_id":599459,"create_time":1646705432,"update_time":1646705432,"id":1666301866391,"updated_at":"2022-10-20T21:37:46.391000Z","created_at":"2022-10-20T21:37:46.391000Z"},{"_id":"6351bfaad297b621322eb406","body":"the problem is that we can have many places that a `Type` may have different pieces of information from the original `Type`. \r\nSo having `Narrow` or `BroadType` would get to be `SomeNestingInformationNarrow` somewhere.\r\n\r\nHaving an alias only for fragments would solve this easily while keeping it clean.","issue_id":1660651461846,"origin_id":1064041316,"user_origin_id":6199518,"create_time":1646917842,"update_time":1646917842,"id":1666301866394,"updated_at":"2022-10-20T21:37:46.394000Z","created_at":"2022-10-20T21:37:46.394000Z"},{"_id":"6351bfaad297b621322eb407","body":"Also, our domains in GraphQL are source generated, so we can't pinpoint the exact location where partial types of a type intersects, thus, using one common alias just fits without breaking anything","issue_id":1660651461846,"origin_id":1064044783,"user_origin_id":6199518,"create_time":1646918034,"update_time":1646918034,"id":1666301866396,"updated_at":"2022-10-20T21:37:46.396000Z","created_at":"2022-10-20T21:37:46.396000Z"}] comment

Hi, I haven't found a way to give an alias to a type, so I was wondering if we could have alias for type only on polymorph fragments. Consider we...

Named Lists

[{"_id":"6351bd0eea01ec786e759e24","body":"Interesting idea; the concept of \u201cadding additional type information\u201d to an existing type is not dissimilar to the oneof proposal; however adding this to a wrapping type rather than a named type will bring its own interesting challenges I suspect.\r\n\r\nI suggest you add this topic to an upcoming WG for discussion; you can do so by sending a PR to this (or any) agenda: https:\/\/github.com\/graphql\/graphql-wg\/blob\/main\/agendas\/2022\/2022-01-06.md","issue_id":1660651461849,"origin_id":1002753353,"user_origin_id":129910,"create_time":1640807582,"update_time":1640807582,"id":1666301198979,"updated_at":"2022-10-20T21:26:38.979000Z","created_at":"2022-10-20T21:26:38.979000Z"},{"_id":"6351bd0eea01ec786e759e25","body":"Definitely worth discussing! I *believe* this could be solved more generally with generic types, i.e. you should be able to create your own custom `type Set<T> { values: [T] }`. Lots of prior discussion in this space: required reading is probably @leebyron's explanation for why generics weren't added in the original redesign of GraphQL in 2015: https:\/\/github.com\/graphql\/graphql-spec\/issues\/190#issuecomment-230078626. Personally I think we've developed more motivating use cases in the last 6 years (error\/result types, set and map types as you're proposing, and any other wrapper type people need generally) to revisit some form of generic typing beyond what we have with List and NonNull. Constrained list types are an interesting subset of the problem, and may in fact be a little orthogonal (as in your proposal, the JSON response will still be just a list the client knows is server-side validated rather than a wrapped type with an inner list).","issue_id":1660651461849,"origin_id":1003458653,"user_origin_id":1741248,"create_time":1640988878,"update_time":1640988878,"id":1666301198984,"updated_at":"2022-10-20T21:26:38.984000Z","created_at":"2022-10-20T21:26:38.984000Z"},{"_id":"6351bd0eea01ec786e759e26","body":"@mjmahone thanks. actually generic types does not solve problem with Sets. First, it would be more cumbersome to unwrap elements from set. However major issue will be following.\r\n\r\n```gql\r\ninput Address { street : String, house: Int }\r\ntype User { name: String }\r\n\r\ntype Set<a> { values: [a] }\r\n\r\ntype Query {\r\n residents(addresses: Set<Address>): Set<User>\r\n}\r\n```\r\n\r\nas we see, this schema will be invalid, since output type can't be used as input value. \r\nHowever, with `Named Lists` it is possible.\r\n\r\n```gql\r\ninput Address { street : String, house: Int }\r\ntype User { name: String }\r\nlist Set\r\n\r\ntype Query {\r\n residents(addresses: Set<Address>): Set<User>\r\n}\r\n```\r\n\r\n","issue_id":1660651461849,"origin_id":1005705433,"user_origin_id":18636038,"create_time":1641390900,"update_time":1641391080,"id":1666301198989,"updated_at":"2022-10-20T21:26:38.989000Z","created_at":"2022-10-20T21:26:38.989000Z"},{"_id":"6351bd0eea01ec786e759e27","body":"> this schema will be invalid, since output type can't be used as input value.\r\n\r\nHeh we'd need an `InputSet<T>` and `OutputSet<T>` (personally I think we messed up, for instance, in not splitting enums by input\/output, as input enums can evolve differently from output enums in terms of what's future\/backwards compatible).","issue_id":1660651461849,"origin_id":1006891079,"user_origin_id":1741248,"create_time":1641498876,"update_time":1641498876,"id":1666301198992,"updated_at":"2022-10-20T21:26:38.992000Z","created_at":"2022-10-20T21:26:38.992000Z"},{"_id":"6351bd0eea01ec786e759e28","body":"One use-case for named lists is that it makes it possible to apply directives to lists. Currently, this isn't possible for nested lists in the SDL.","issue_id":1660651461849,"origin_id":1006893952,"user_origin_id":693596,"create_time":1641499158,"update_time":1641499158,"id":1666301198996,"updated_at":"2022-10-20T21:26:38.995000Z","created_at":"2022-10-20T21:26:38.995000Z"},{"_id":"6351bd0eea01ec786e759e29","body":"Similarly, it would allow doc-strings on lists","issue_id":1660651461849,"origin_id":1006898182,"user_origin_id":693596,"create_time":1641499552,"update_time":1641499552,"id":1666301198998,"updated_at":"2022-10-20T21:26:38.998000Z","created_at":"2022-10-20T21:26:38.998000Z"},{"_id":"6351bd0fea01ec786e759e2a","body":"Opened a discussion of some considerations related to this issue: \r\nhttps:\/\/github.com\/graphql\/graphql-wg\/discussions\/860","issue_id":1660651461849,"origin_id":1008491568,"user_origin_id":594969,"create_time":1641780894,"update_time":1641780894,"id":1666301199002,"updated_at":"2022-10-20T21:26:39.001000Z","created_at":"2022-10-20T21:26:39.001000Z"},{"_id":"6351bd0fea01ec786e759e2b","body":"@mjmahone technically output enums are union variants without fields. however GraphQL does not support it. you can checkout how it could theoretically work in [iris](https:\/\/github.com\/nalchevanidze\/iris)\r\n\r\n","issue_id":1660651461849,"origin_id":1018565238,"user_origin_id":18636038,"create_time":1642776057,"update_time":1642776076,"id":1666301199005,"updated_at":"2022-10-20T21:26:39.005000Z","created_at":"2022-10-20T21:26:39.005000Z"},{"_id":"6351bd0fea01ec786e759e2c","body":"### NonEmpty lists. \r\nEasily solved by a NonEmpty directive and does not require new syntax or new concepts. The directive does not need to be 'standard', defined in spec; a custom dir is enough. If the API designer thinks that expressing this constraint is important enough to express in SDL, then he can define @NonEmpty dir, add doc string to it, and then use it in SDL. Problem solved. \r\n\r\n### Set (no duplicated elements). \r\nSame as NonEmpty, can be done with a custom directive.\r\nThere is one more important aspect - when you talk about 'uniqueness', you need to talk about 'equality', because you catch non-uniqueness by finding 'equal' elements. In languages like c#, there are concepts like IComparable(IEquatable) interfaces, and Comparer objects etc. To create a dictionary or hash table, you have to provide a method for comparing values - which is not always obvious, and often there's some flexibility. For your unique lists, how to compare floats? strings equality - believe me it is not that obvious for some languages. Equality and comparison for sorting usually provided by language 'driver' (collation for databases).\r\n\r\nAnd complex custom type with with a few properties - what does it mean that two objects are 'equal' - all property values are equal? You have to state it explicitly.\r\n\r\nThe whole issue of uniqueness gets messy very quickly, and I do not think adding this complexity to spec is worth limited potential benefit for not so many beneficiaries (I think there would be not many uses in practice). But in fact, with custom @unique dir defined by an API, the server\/docs can specify what equality means for types allowed in Lists with this directive. \r\n\r\nMap: elements must provide unique key - here 'unique' again, with the same 'comparable' challenge. \r\n\r\n### Summary: \r\nNonEmpty and Unique lists can be perfectly handled by custom directives, no new concepts are needed.\r\n\r\nMaps (through extra tuple type) - is a separate matter\r\n\r\n","issue_id":1660651461849,"origin_id":1020865156,"user_origin_id":594969,"create_time":1643093533,"update_time":1643101337,"id":1666301199008,"updated_at":"2022-10-20T21:26:39.008000Z","created_at":"2022-10-20T21:26:39.008000Z"},{"_id":"6351bd0fea01ec786e759e2d","body":"> Easily solved by a NonEmpty directive and does not require new syntax or new concepts. The directive does not need to be 'standard', defined in spec; a custom dir is enough. If the API designer thinks that expressing this constraint is important enough to express in SDL, then he can define @nonempty dir, add doc string to it, and then use it in SDL. Problem solved.\r\n\r\nIf you define a schema like:\r\n\r\n```graphql\r\ndirective @nonEmpty on FIELD\r\ntype Query {\r\n numbers: [Int] @nonEmpty\r\n}\r\n```\r\n\r\nIntrospection will not reflect that the `@nonEmpty` directive applied to that field, therefore a consumer of the GraphQL API cannot know that field was defined to be non-empty - this applies to IDEs like GraphiQL, code generators, clients and the like.\r\n\r\nHopefully we'll add a way to expose user-defined meta-information via introspection API in form of directives (#300) at some point, but we're not there yet.","issue_id":1660651461849,"origin_id":1028805357,"user_origin_id":129910,"create_time":1643882145,"update_time":1643882145,"id":1666301199011,"updated_at":"2022-10-20T21:26:39.011000Z","created_at":"2022-10-20T21:26:39.011000Z"},{"_id":"6351bd0fea01ec786e759e2e","body":"@benjie - and that's the problem with introspection, we already discussed this briefly; and that SHOULD be fixed anyway, and SDL file and Introspection set should become one and the same thing, only in different formats. ","issue_id":1660651461849,"origin_id":1029081354,"user_origin_id":594969,"create_time":1643900643,"update_time":1643900643,"id":1666301199014,"updated_at":"2022-10-20T21:26:39.014000Z","created_at":"2022-10-20T21:26:39.014000Z"},{"_id":"6351bd0fea01ec786e759e2f","body":"@benjie this is being explored. GraphQL-Java, GraphQL-DotNet, and HotChocolate have implemented a proposal that lets you introspect schema directives.\r\n\r\nhttps:\/\/github.com\/graphql-java\/graphql-java\/pull\/2221","issue_id":1660651461849,"origin_id":1053991302,"user_origin_id":9714350,"create_time":1646035619,"update_time":1646035619,"id":1666301199018,"updated_at":"2022-10-20T21:26:39.018000Z","created_at":"2022-10-20T21:26:39.018000Z"},{"_id":"6351bd0fea01ec786e759e30","body":"Indeed, I'm a big proponent of #300 as linked in my comment above :+1: ","issue_id":1660651461849,"origin_id":1055160044,"user_origin_id":129910,"create_time":1646123881,"update_time":1646123881,"id":1666301199022,"updated_at":"2022-10-20T21:26:39.022000Z","created_at":"2022-10-20T21:26:39.022000Z"}] comment

# Named Lists ## Motivation Since GraphQL has only one type (List) for collections, we cannot represent collections with certain constraints. examples of constrained lists: - Set: no duplicated elements...

GraphQL can be less strict and complicated

[{"_id":"6351c235cecf4e081a1a6f60","body":"regarding recursive refs in fragments, this is under discussion: \r\n\r\nhttps:\/\/github.com\/graphql\/graphql-spec\/issues\/929\r\n\r\nby the way, in the sample, did you mean \"...Node\" as fragment spread?\r\n\r\n\r\n```graphql\r\nfragment Node on TreeNode {\r\n label\r\n children {\r\n ...Node @RecursionLimit(100)\r\n }\r\n}\r\n```\r\n","issue_id":1660651461853,"origin_id":1053589534,"user_origin_id":594969,"create_time":1645975787,"update_time":1645975972,"id":1666302517100,"updated_at":"2022-10-20T21:48:37.100000Z","created_at":"2022-10-20T21:48:37.100000Z"},{"_id":"6351c235cecf4e081a1a6f61","body":"Using interfaces instead of 'Object types' - interesting approach, I think it works already as-is, and for backward compatibility we have to keep 'type' forever. \r\nabandoning input types - I doubt it would work, because of the problems of fields with parameters cannot be used in 'inputs' or 'input interfaces'. I think a very good improvement would be to allow input types as return types (Object types). If working with interfaces - server can just allow only interfaces as inputs that are without such parameters fields, without special designation of them as 'input interfaces', and report an error if violated\r\n\r\n","issue_id":1660651461853,"origin_id":1053594253,"user_origin_id":594969,"create_time":1645976672,"update_time":1645976672,"id":1666302517103,"updated_at":"2022-10-20T21:48:37.102000Z","created_at":"2022-10-20T21:48:37.102000Z"},{"_id":"6351c235cecf4e081a1a6f62","body":"Here's some reasons why input (`InputObject`) and output object (`Object`) types probably shouldn't be the same thing:\r\n\r\n- Nullability: Changing an Object's field to be non-nullable is a non-breaking change, changing it to be nullable is a breaking change. Conversely, making an InputObject's field nullable is a non-breaking change, but making it non-nullable is a breaking change. Combine these two together (because the type is now both input and output) and you can no-longer change the nullability of the fields, which limits schema evolution options.\r\n- Field addition: Adding any field to an Object type is a non-breaking change (because GraphQL makes you explicitly state which fields you need, so a new field will not affect any existing queries). Adding a _nullable_ field to an InputObject type is a non-breaking change (a non-nullable field would be a breaking change because it would make all previous operations using this InputObject invalid since this field will not have been supplied). Therefore you'd only be able to add nullable fields to the GraphQL schema, limiting schema evolution options.\r\n- Symmetry: If you use the same type for input as output then a user might expect to be able to supply an Object that they queried back as input to a future operation; however this may or may not be valid depending on what their selection set was, and as the schema evolves it all but guarantees that people doing this will lose data.\r\n- Asymmetry: Whereas output objects link to many other types, input objects much more rarely want inputs for these links, so when a link like this wants to be added to an existing type that's used in both input and output much thought will have to be given to whether or not to add the relating field (since it will also affect inputs). This again limits schema evolution options.\r\n- Cycles: It's perfectly valid for an Object to state that it references itself in a non-nullable way, e.g. `type Query { query: Query! }`, however a type like this cannot be valid for input due to cycles. Now consider that this cycle might not be between the type and itself but between any types - now you're requiring that the type tree is a directed acyclic graph which seriously limits the usefulness of the type system (e.g. a Post can have an Author, but the Author is not allowed to link back to Posts because that would be a cycle)\r\n\r\nI'm sure we can come up with solutions to all these issues (and more) by adding complexity to GraphQL - e.g. making the nullability of a field dependent on whether it's input\/output, making some fields input-only or output-only, etc - but the current solution is also the simple solution, i.e. that input types and output types are inherently separate because their concerns do not align.","issue_id":1660651461853,"origin_id":1055158221,"user_origin_id":129910,"create_time":1646123741,"update_time":1646123741,"id":1666302517106,"updated_at":"2022-10-20T21:48:37.105000Z","created_at":"2022-10-20T21:48:37.105000Z"},{"_id":"6351c235cecf4e081a1a6f63","body":"> * Cycles: It's perfectly valid for an Object to state that it references itself in a non-nullable way, e.g. `type Query { query: Query! }`, however a type like this cannot be valid for input due to cycles.\r\n\r\nConsider these examples:\r\n\r\n```graphql\r\n# This is fine.\r\ntype Query { a: A! }\r\ntype A { b: B! }\r\ntype B { a: A! name: String! }\r\n```\r\n\r\n```graphql\r\nquery {a{b{a{b{a{b{\r\n name # cycle is broken\r\n}}}}}}}\r\n```\r\n\r\nHowever, this schema **can't be queried legally**:\r\n\r\n```graphql\r\n# this cycle can't be broken and should be illegal\r\n# there is no valid way to query it.\r\ntype Query { a: A! }\r\ntype A { b: B! }\r\ntype B { a: A! }\r\n```\r\n\r\n```graphql\r\nquery {a{b{a{b{a{b{\r\n a # illegal\r\n}}}}}}}\r\n```\r\n\r\nThe spec allows this construct but it really shouldn't.\r\nProbably a topic for another issue though.","issue_id":1660651461853,"origin_id":1246848102,"user_origin_id":9574743,"create_time":1663165606,"update_time":1663165606,"id":1666302517109,"updated_at":"2022-10-20T21:48:37.109000Z","created_at":"2022-10-20T21:48:37.109000Z"},{"_id":"6351c235cecf4e081a1a6f64","body":"it's illegal not because of loop of non-null references, but because there are no LEAF type fields!; if you make fields a and b nullable, you still won't be able to construct the query, because there's no field that can end the query!","issue_id":1660651461853,"origin_id":1246870017,"user_origin_id":594969,"create_time":1663166401,"update_time":1663166401,"id":1666302517112,"updated_at":"2022-10-20T21:48:37.111000Z","created_at":"2022-10-20T21:48:37.111000Z"},{"_id":"6351c235cecf4e081a1a6f65","body":"> it's illegal not because of loop of non-null references, but because there are no LEAF type fields!; if you make fields a and b nullable, you still won't be able to construct the query, because there's no field that can end the query!\r\n\r\nThat's correct.\r\n\r\nWhat about the `input` types? I still haven't found the paragraph that explicitly forbids cyclic dependency in input types.","issue_id":1660651461853,"origin_id":1246877948,"user_origin_id":9574743,"create_time":1663166730,"update_time":1663166730,"id":1666302517114,"updated_at":"2022-10-20T21:48:37.114000Z","created_at":"2022-10-20T21:48:37.114000Z"},{"_id":"6351c235cecf4e081a1a6f66","body":"Your query can be legal, you just need to provide a selection set since `a` is not a leaf. Here's a valid query:\r\n\r\n```graphql\r\nquery {a{b{a{b{a{b{\r\n a { __typename }\r\n}}}}}}}\r\n```","issue_id":1660651461853,"origin_id":1246879156,"user_origin_id":129910,"create_time":1663166783,"update_time":1663166879,"id":1666302517116,"updated_at":"2022-10-20T21:48:37.116000Z","created_at":"2022-10-20T21:48:37.116000Z"},{"_id":"6351c235cecf4e081a1a6f67","body":"> What about the input types? I still haven't found the paragraph that explicitly forbids cyclic dependency in input types.\r\n\r\nIt's in the \"Input Objects\" section under the heading \"Circular References\":\r\n\r\nhttps:\/\/spec.graphql.org\/draft\/#sec-Input-Objects.Circular-References","issue_id":1660651461853,"origin_id":1246880581,"user_origin_id":129910,"create_time":1663166845,"update_time":1663166845,"id":1666302517119,"updated_at":"2022-10-20T21:48:37.118000Z","created_at":"2022-10-20T21:48:37.118000Z"},{"_id":"664c34404a8e87d14e1c1141","body":"So... There are three glaringly obvious reasons why input and output types should **not** be distinct:\r\n\r\n1. The partitioning means that data cannot be forwarded. A service cannot accept an input object and then turn around and pass it along as an output object without rewriting the darned thing into a (frequently identical) output object. As an example of why this is important, consider message queues. Which bear a strong resemblance to subscriptions...\r\n2. The partitioning forces a lot of replicated code at every layer of the software stack. Consider, as an incomplete illustration, the complexity of mapping an existing SQL schema to a corresponding GraphQL schema (and, of course, back, since what gets read eventually tends to get written).\r\n3. From a formal type system perspective, directionality of I\/O is completely orthogonal to type. Formally speaking, the partition of input and output types makes the GraphQL type system unsound (I'm using \"unsound\" here in a strictly technical mathematical sense, not as a value judgement).\r\n\r\nIf there is a credible motivating explanation for this division, I haven't seen it. I've looked pretty hard, and if somebody can point me the right way I'd be grateful. The issues that @benjie identifies aren't things that a protocol can fix - they are fundamental to the evolution of the underlying information architecture. I really _do_ understand why being able to rapidly evolve a protocol without going through protocol versioning hell is very appealing. The approach taken by Kenton Vardy with protocol buffers and CapnProto accomplishes a lot of the same goals without breaking the concept of types. In effect, they distinguish usefully between the static and the dynamic type of the object without giving up either.\r\n\r\nThe separation also adds obscurity to a more fundamental issue that arises from the interaction between the query language and the client cache merging strategy: inconsistency.\r\n\r\nSuppose I do a query that requests fields A and B of some object. Later, I do a second query that accepts fields D and C of that same object. There is no reason to believe - and no way to check - that I now have a consistent version of the object in my client cache. It's entirely possible that there have been 85 mutations of the underlying object in the persistent store between these two queries, and that one or more of them modified the A field or the B field. If so, my cached copy on the client now blends two different versions of the object. The very last thing you want to do in this case is send that object back as an update.\r\n\r\nThis is one of the issues that ultimately made me put GraphQL down. A potential \"fix\" here, if you want one, is to ensure that all object [fragments] have a version number (or a lastStored field) whether you asked for it or not, and that the version number gets passed in both directions. This wouldn't significantly impeded the ability to expose a third party API through a GraphQL interface. A more extreme approach would make queries persistent, in effect creating a subscription on the server. The challenge with that is that it would require a significant amount of per-client server state, which makes service replication for scaling much harder. Ultimately I suspect this would run fairly hard into some of the scaling issues that Meteor pub\/sub ran into. \r\n\r\nThe other issue that drove me away is that field-level selectivity and statically typed programming languages really play badly together. If all of your client targets are some variant of a browser (potentially including things like electron), great. But a GraphQL API is quite difficult to invoke from, say, C#. In my opinion, GraphQL fits the browser-based client niche extremely well, but there's more to the world than browsers. Which, ironically, is one of the reasons Geoff Schmidt left Meteor to found Apollo GraphQL. As an example, Shopify's adoption of a GraphQL-based API made life very dramatically harder for a large number of clients written in C#.\r\n\r\nWe've been building APIs since the earliest days of networking - the first API specification language I leraned came from Apollo Computer more than forty years ago. I'm not a fan of discarding new ideas without a clear reason, but skepticism is healthy. GraphQL's type partitioning idea has many strikes against it. The biggest one, from my perspective, is that it is mathematically unsound.","issue_id":1660651461853,"origin_id":1959795887,"user_origin_id":18054538,"create_time":1708618770,"update_time":1708618770,"id":1716270144065,"updated_at":"2024-05-21T05:42:24.065000Z","created_at":"2024-05-21T05:42:24.065000Z"},{"_id":"664c34404a8e87d14e1c1142","body":"@jsshapiro ,\r\nagree 100%. Or maybe 99. I tried to push these issues but gave up, it's no use. The guys who make decisions there are absolutely against ANY change.\r\nOne question, why are you saying consuming graphql from c# is a trouble\/problem? GraphQL client (the one that I have), returns c# types\/objects which are partially filled, depending on the query. Yes, this might be inconsistent depending on how you define types' internal consistency rules, but if you accept this as a basic premise - that the returned object fields (any of them) might be just defaults (because they were not listed in query) - then you can go with it just fine. \r\nI have a sizable app, built in web assembly Blazor, and the GraphQL client is a c# component, and all client logic around it is c#. It works great - except occasional situation like \"why this new field\/control is empty?! - I see value in the database... ah, I forgot to add it to the query\". ","issue_id":1660651461853,"origin_id":1961500103,"user_origin_id":594969,"create_time":1708700892,"update_time":1708700997,"id":1716270144069,"updated_at":"2024-05-21T05:42:24.068000Z","created_at":"2024-05-21T05:42:24.068000Z"},{"_id":"664c34404a8e87d14e1c1143","body":"ah, and about input types and mutations - in my app. There are around 40 types to be loaded\/updated, so we recognized a problem from the start - we didn't want to define extra 40+ input types and mutations, so we came up with a concept of 'one mutation', using one update endpoint, when you send a list of update packs, each is ObjectType and list of field-newValue pairs. we integrated it with server-side ORM, using mapping to entities which is already there for querying. \r\nSo now adding a type does NOT need any extra input types and new mutation endpoints. I think this might be actual solution for this input types conundrum; hell with the spec, we have a nice workaround. (by the way, building an update pack from input form - fully automatic, c# code running thru model and comparing field values)\r\n","issue_id":1660651461853,"origin_id":1961523518,"user_origin_id":594969,"create_time":1708701723,"update_time":1708701822,"id":1716270144071,"updated_at":"2024-05-21T05:42:24.070000Z","created_at":"2024-05-21T05:42:24.070000Z"}] comment

I'm a software engineer for almost 20 years and I recently started using GraphQL extensively. While I understand the original thoughts of making GraphQL as simple as possible, we end...

Allow recursive references in fragments selection subsets

[{"_id":"6351cc3dcecf4e081a1a7687","body":"As a note: GraphQL the language is purposefully not Turing Complete: you must not be able to create an operation which, when executed with known-to-halt resolvers, does not halt. Basically, if all your scalar field resolvers always just return a value (and do no additional server work), and your non-scalar field resolvers just create a Map\/JSON Object out of the resolved child fields, is it possible to create an operation that will not complete its execution?\r\n\r\nWe know it's possible to have GraphQL not complete if you have a field resolver that doesn't halt, but if you assume all resolvers halt then is it guaranteed that the operation halts too? I believe proving that will be a requirement to adding any recursion to fragments. Or we'd need to gain consensus that we want to allow operations that might not halt.","issue_id":1660651461855,"origin_id":1029290821,"user_origin_id":1741248,"create_time":1643913834,"update_time":1643914039,"id":1666305085538,"updated_at":"2022-10-20T22:31:25.538000Z","created_at":"2022-10-20T22:31:25.538000Z"},{"_id":"6351cc3dcecf4e081a1a7688","body":"GraphQL is not a programming language. So I believe Turing-complete stuff is out of place here. \r\n\r\n> I believe proving that will be a requirement to adding any recursion to fragments.\r\n\r\nAllow me to respectfully disagree. IMO: requirement to adding something to spec is to **show that benefits of the change are bigger** than potential drawbacks or added complexity. I think I provided enough arguments for this. \r\nPlus I am not actually adding something - I am removing strange and unnecessary (it seems like unnecessary) constraint. \r\nAnd also, as I showed, the way the constraint is currently formulated in the spec, it is logically flawed - circular refs do NOT necessarily produce infinite loops; but spec actually argues they always do. \r\n","issue_id":1660651461855,"origin_id":1029301671,"user_origin_id":594969,"create_time":1643914664,"update_time":1643917493,"id":1666305085542,"updated_at":"2022-10-20T22:31:25.541000Z","created_at":"2022-10-20T22:31:25.541000Z"},{"_id":"6351cc3dcecf4e081a1a7689","body":"## Discussion of RecursiveFragments, response to arguments in WG meeting Feb 03, 2022\r\nBefore responding to particular argumentats expressed in the meeting, let me give you an idea how it looks for a server developer. It is important, since the recursive fragments feature mostly concerns the server side, the complexity and 'safety' of processing. I will refer to this material later in my counter-arguments for args expressed in the meeting. \r\n\r\n## How the problem of recursive fragments is seen by a server dev\r\nContext: a server dev reads GraphQL spec or some introductory material for the first time.\r\n\r\nAll right, I am reading GraphQL spec. You can ask for multiple things in one query, cool! No more multiple roundtrips to the server. And you can go deep into child objects and lists! Cool! So the client can express exactly what fields and child\/grandchild objects it wants and what fields there... Very cool! \r\n\r\nBut...!!! Clearly it is so easy to produce a ROGUE, BAD query - by mistake or by evil intent - that will overwhelm my server, hog all resources and eventually kill\/DDOS it with a few repeats. I better start thinking early about ways to protect the server. \r\n\r\nI will use this Facebook-like model\/Query as an example:\r\n\r\n```graphql\r\nquery {\r\n user(id: 123) {\r\n name friends {name friends {name friends {name friends {name} }}}\r\n }\r\n}\r\n```\r\n\r\nConsidering that it's not unusual for a user to have 500+ \"friends\", this query will definitely blow up into millions. And has to be aborted. Yes, I am not Facebook, but my model has similar type relations with list fields, and the difference for me is just that rogue query needs to be a couple of nesting layers longer. By the way, even if this Facebook API limits friends to 100\/query, all bad guy needs to do is add a few more levels, to get the same 'explosion' into millions. \r\n\r\nSo... what should I do? Static analysis of the query would not help. Just limiting nesting level to say 5 - that's too restrictive for valid queries with limited size collections. Clearly, it's all dynamic, in the actual data, all depends on actual size of particular data 'slices'.\r\n\r\nI need to introduce a lot of stoppers, limiters, circuit breakers in my server code. And limiting values would not be constant, depend on 'user'. What's allowed to internal import process should not be allowed to external anonymous user. So it is a system of quotas, varying by user\/customer, most likely. Max values for return objects, response sizes, resolving nesting levels, processing time limits, total number of field values in response, total size of the response etc. I need many of these because it does not look like any single one can protect the server.\r\n\r\nContinuing reading. Oh, fragments - cool. Ah, spec prohibits recursion in fragments... Well, does not change much, **one can abuse the hell out of a server without any recursion.** Hmm.. spec wants me to detect cycles early, with static analysis? Ok, doable, not a rocket science, finding loops in graphs, well known algorithms. Will code it and run for every incoming query.\r\n\r\nBut wait... this code will be running for all incoming queries?! Many many of them. For almost all of them, nothing will be detected. Only one in a million\/zillion bad query will have a deadly loop. But would this query be stopped and aborted by dynamic limitors and circuit breakers I already have? Of course! Would the request do much damage before it is aborted? No, just like with other rogue quieries, an effective protection must be in place. And punishing system as well - if client tries to repeat the query multiple times, just cut him off for an hour or a year, to prevent DDoS. **With or without fragment recursion, rogue queries are detected, aborted and the server is protected.**\r\n\r\nBut then it means that this static analysis is just a waste of CPU cycles for all queries; and with a redundant result for quite rare and exceptional event of a BAD query. So hell with the static analysis of fragment loops, disable it, cut the waste. Remove the code - any non-trivial but not used code sitting in the repo is no good.\r\n\r\nThen will my server become non-compliant with the spec? NO - any valid query is handled as before. But also YES, sort of, invalid query with fragment loop, although rejected (correct behavior), but rejected kinda late, and the rejection\/error is not kind of compliant. Do I care? - not really. \r\n\r\n(end of server dev thoughts)\r\n\r\nSo that is the train of thought and action; I do believe I represented it accurately for a typical server dev. \r\n\r\nThe main conclusion is: **Allowing Recursive Fragments does NOT make it easier to misuse or abuse a GraphQL API - it is already REALLY EASY without them. The server should have (already has!) a protection system built to defend against ANY bad query. Allowing recursive refs DOES NOT create any new problems for server developers, and is in fact IRRELEVANT.** \r\n \r\n## Specific points in Feb 03 discussion\r\n\r\nAnswering the arguments in discussion at WG meeting on Feb 03, 2022; as recorded in meeting notes here: \r\n[Allowing recursive references in fragments](https:\/\/github.com\/graphql\/graphql-wg\/blob\/main\/notes\/2022\/2022-02-03.md#allowing-recursive-references-in-fragments),\r\n\r\n> Lee: Three major concerns:\r\n infinite recursion; limitations wouldn't just be specification - how should it halt and when\r\n data validation; returning the same value multiple times, how is that represented in the data. Ideally you want to detect it's cyclic and halt straight away, but some servers cannot detect this and may loop many times before they detect something went wrong and stop\r\n what's the cost of not having this; does it warrant these problems? No it doesn't; it's always possible for you to specify the number of levels deep in your query - that's effectively the desugared version of what we'd do if we were to handle this in GraphQL\r\n\r\nResponses and counter-arguments: \r\n**Infinite recursion** - it is infinite only hypothetically; any real server would have a hard stop at some nesting level and\/or visited field count or an output object count. **returning the same value multiple times** - same rules as for invoking 2 different fragments with common fields at the top level - whatever they are, the result is the same key\/value coming from different sources.\r\n**some servers cannot detect this and may loop many times before they detect something went wrong and stop** - so what?! 'loop many times' - how many? as many as server dev considers acceptable. Resource hogging and killing the server? it is possible with \"users\/friends\" example above, without any recursion. Server will just have to explore a few fields before it becomes clear, it's not doable, halt it. \r\n**what's the cost of not having this; does it warrant these problems? No it doesn't** - Disagree. Problems? - there are no problems identified so far. The cost of not having this is the cost of having no-recursion rule - as it is now. So the cost is non-zero - having extra page in spec for no real reason, having special case for 'no-recursion' rule, which is different from other languages - this is NON-ZERO cost, more on this later. \r\n\r\n> Lee: We'd have to be very careful that implementations don't DDoS themselves.\r\n\r\nI do not think 'themselves' is the right term - who is DDoS-ing who? A client sends 'arrogant' request that overloads the server, multiple bad requests maybe (DDoS?). It is easy enough to do with or without recursion as I explained before. Recursion does not make any difference. \r\n\r\n> Lee: this is really important - it essentially comes down to the halting problem - we want to be able to figure out what the complexity of a query is... \r\n\r\nSorry, Lee, that's not important at all. Because there's no 'halting problem' - server process has a hard stop at 50 cycles\/nesting levels (100 or whatever). I don't care if the query would halt eventually (after 10K cycles? 1 million cycles?) or if it does NOT halt at all. Hard stop; one of many circuit breakers for different 'query complexity\/required effort' indicators - that work for non-recursive queries as well. Any server MUST have these limiters. So there is NO 'stopping problem', at all. By the way, the limiting number (max iter) should NOT come with the query, from the client. It is a strict server limit, so we do NOT need to discuss any extra directive (@maxIter?) as you did in the past. \r\n\r\n> Roman: these same problems (infinite loops) apply to all programming languages and programming systems.\r\n Michael: GraphQL is not a programming language. \r\n> Matt: ... GraphQL's goal is very different from an arbitrary programming language.\r\n \r\nWell, we are not that different I think. One of possible semantic\/mental models of a GraphQL query is that a Query is a set of invocations of fields - which are methods, especially clear when there are arguments; and there is method on the server - resolver, which we invoke remotely. So GraphQL query is a kind of list of remote proc calls - then GraphQL is a kind of a programming language, for encoding RPC calls. Sounds reasonable I think. Fragments are separate functions that can be invoked from 'mainline' code. And these functions - well, may be called recursively, maybe. \r\n\r\nEven if GraphQL is really VERY different - many things still apply. **The principle of the 'least surprise'.** Whenever we introduce a concept that is similar to something that the reader already knows, we should not 'surprise' with behavior that is different from reader's expectations. But if it is different, then it requires lengthy explanations of this difference in the spec. And the reader has to remember that \"X is different in GraphQL'. We must try to reduce the 'mental load' on readers, cut-off all the unneeded 'fat' - unless it is really important for us and GraphQL to be different.\r\n\r\nWhat could be a simple one-sentence comment like 'Recursion OK, but servers - beware of infinite loops' - instead we have a whole section, larger than a page, explaining in details an absolutely trivial case - how you screw up with recursion. Even more surprising for a reader, after going thru this - wait, other real programming languages face the same problem\/challenge. But they do NOT prohibit recursion nevertheless. We say 'we are different', GraphQL is not a programming language. OK, but it would not be clear to the spec reader what's so different here. \r\n\r\n> Lee: ... what do we need to add to the spec to reach the safety that we have today?\r\n\r\nWe don't have any 'safety' today. As I explained with users\/friends example, it is already very easy to abuse the API, without any fragment recursion. Allowing recursion does not change anything regarding safety. \r\n\r\n> Lee: ... Can you raise more use cases for it to make it more convincing?\r\n\r\nI bring up one case - a server dev thinking about this whole issue. And that it makes sense to disable this static check for fragment cycles if he ends up coding it - it is wasteful and useless. It would burn CPU cycles for all good queries with 0 effect, and once in a million queries would find something that would be detected anyway. If this is not convincing, I don't know what would be. **Basically what we ended up with here is a feature that likely will be disabled.**\r\n\r\n## In conclusion \r\nThe reason I do not give up and keep beating on this is not that I think that recursive fragments are so crucially important - they are not. But this small issue is just one example of a stuff that is in the spec, but should not be there; there are other cases like this, and I intend to bring them up. Pushing the spec forward is not only adding stuff, but it is also important to 'optimize' it, cut off the fluff that does not belong there. \r\n \r\n ","issue_id":1660651461855,"origin_id":1046586511,"user_origin_id":594969,"create_time":1645431481,"update_time":1645431481,"id":1666305085545,"updated_at":"2022-10-20T22:31:25.545000Z","created_at":"2022-10-20T22:31:25.545000Z"},{"_id":"639129d770db72139b215670","body":"I do humbly agree with @rivantsov on this and think the most profound point made here is that malicious queries can already overwhelm GraphQL APIs regardless of whether recursive fragments are involved. In this regard, the backend developer must already be conscious of thinking ahead for how to best protect the server. Therefore, allowing recursive references in fragments could be an opt-in feature, perhaps restricted in scope to usage on only certain types and\/or fields.\r\n\r\n@rivantsov provided the example of a client wanting to resolve all managerial levels of an organization without making assumptions on query depth. In these cases, where one is dealing with acyclic data it would be great to allow a client to flexibly request the full-graph in a structured response. Another example would be the product tree typical in CAD software:\r\n\r\n```graphql\r\ntype Query {\r\n parts: [Part!]\r\n}\r\n\r\ntype Part {\r\n name: String\r\n created: DateTime!\r\n children: [Part]\r\n}\r\n\r\nfragment allParts on Part {\r\n name\r\n children {\r\n ...allParts\r\n }\r\n}\r\n\r\n# Resolve full product tree using recursive references in fragment\r\nquery {\r\n parts {\r\n ...allParts\r\n }\r\n}\r\n```\r\n\r\nI see that this topic was discussed in the GraphQL Spec WG, are there currently any plans for a follow up on that discussion?","issue_id":1660651461855,"origin_id":1294284387,"user_origin_id":29230371,"create_time":1666919046,"update_time":1666919143,"id":1670457815511,"updated_at":"2022-12-08T00:03:35.510000Z","created_at":"2022-12-08T00:03:35.510000Z"},{"_id":"639129d770db72139b215671","body":"Hi, and thank you for your support! \r\nI should bring in even more context: @benjie, one of the influencers here, was at the time not in favor of this change (allowing recursive fragments) - as far as I remember - nobody at the WG meeting expressed much support. But later looks like he turned in favor for this in his [Struct RFC](https:\/\/github.com\/graphql\/graphql-wg\/blob\/main\/rfcs\/Struct.md#non-infinite-recursion), referencing again the *Graphiql* introspection query (as I did) and also TableOfContents structures, with unknown depth, like your Parts example or my Org chart example. \r\n\r\nAt the time of WG meeting in Feb, the outcome was - need real-life examples why it's needed. So sounded like I needed to bring in a few people like John TheHacker who would testify that he definitely needs it for his new project yada-yada blah blah. So I in fact just gave up. IMHO, the situation should be opposite, we FORBID something in the spec, bring in restriction, and we should have arguments or real-life cases FOR doing this. But whatever, looks like the issue resurfaced. We can bring it up again in the next meeting, I might sign-up and add agenda item (really busy with other urgent stuff now). But if I do, please attend and voice your support please!\r\n \r\nThank you\r\nRoman","issue_id":1660651461855,"origin_id":1295171632,"user_origin_id":594969,"create_time":1666972869,"update_time":1666972869,"id":1670457815514,"updated_at":"2022-12-08T00:03:35.514000Z","created_at":"2022-12-08T00:03:35.514000Z"},{"_id":"639129d770db72139b215672","body":"> I should bring in even more context: @benjie, one of the influencers here, was at the time not in favor of this change (allowing recursive fragments) - as far as I remember - nobody at the WG meeting expressed much support. But later looks like he turned in favor for this in his [Struct RFC](https:\/\/github.com\/graphql\/graphql-wg\/blob\/main\/rfcs\/Struct.md?rgh-link-date=2022-10-28T16%3A01%3A09Z#non-infinite-recursion), referencing again the Graphiql introspection query (as I did) and also TableOfContents structures, with unknown depth, like your Parts example or my Org chart example.\r\n\r\nTo be clear: **I am not in favour of recursive fragments.** Struct does not have recursive fragments, as currently proposed it doesn't allow fragments at all in fact (though that may change). Struct allows for pure data to be finitely recursive on output in a similar way to how an `input` object can be finitely recursive on input in GraphQL today. Critical to this is that we are talking about _pure data_ with `struct` (as you would with an `input` object) - there are no resolvers, no business logic, it's just a finite blob of (acyclic) data. To recurse, we don't specify a recursive selection set, we _explicitly omit the selection set_ and the server can just send us the remainder of the data verbatim.\r\n\r\n> IMHO, the situation should be opposite\r\n\r\nYou shouldn't give people things and then take them away in a future release, that's a breaking change. GraphQL's approach is to be conservative in what we offer and remove restrictions as the needs arise (and the trade-offs are evaluated).","issue_id":1660651461855,"origin_id":1295347565,"user_origin_id":129910,"create_time":1666983421,"update_time":1666983421,"id":1670457815518,"updated_at":"2022-12-08T00:03:35.517000Z","created_at":"2022-12-08T00:03:35.517000Z"},{"_id":"639129d770db72139b215673","body":"hmm.. sorry for misunderstanding of your intents in STRUCT. \r\n> A better solution would be to stick to the tenets of GraphQL and return the data in the shape that the client needs, fully type-safe.\r\n\r\n - I understood it as 'let's allow recursion' instead of your Json workaround; how else?\r\n \r\nRegarding breaking backwards compatibility. This is not 'taking things away', this is allowing MORE. Allowing recursive fragments (RF) do not break any old stuff. All old engines and queries (that did not have RF) - still continue to work. We now ALLOW extra stuff - for servers to support RFs if they want to and for devs to use these in queries. \r\n ","issue_id":1660651461855,"origin_id":1295395277,"user_origin_id":594969,"create_time":1666986298,"update_time":1666986298,"id":1670457815521,"updated_at":"2022-12-08T00:03:35.520000Z","created_at":"2022-12-08T00:03:35.520000Z"},{"_id":"664c34544a8e87d14e1c1157","body":"+1","issue_id":1660651461855,"origin_id":1574942005,"user_origin_id":23432493,"create_time":1685798285,"update_time":1685798285,"id":1716270164913,"updated_at":"2024-05-21T05:42:44.912000Z","created_at":"2024-05-21T05:42:44.912000Z"},{"_id":"664c34544a8e87d14e1c1158","body":"I've just stumbled across this issue and want to voice my support. There are many cases where recursive queries will be useful for describing acyclic data. One major example of this is for any graph that can be represented as a hierarchy or tree. \r\n\r\nAs a compromise for the objections, would it be possible to add a built-in `@supportsRecursion` directive and a `recursiveFragment` specialized fragment?\r\n\r\nThis way it is up to the server\/schema to declare whether recursion is allowed for that field and the client has to knowingly request recursive data. This makes it explicit when recursion is requested and allowed and static analysis can easily check that `recursiveFragments` are only allowed on `supportsRecursion` fields.","issue_id":1660651461855,"origin_id":1577184348,"user_origin_id":8935611,"create_time":1685985682,"update_time":1685985682,"id":1716270164917,"updated_at":"2024-05-21T05:42:44.916000Z","created_at":"2024-05-21T05:42:44.916000Z"},{"_id":"664c34544a8e87d14e1c1159","body":"+1 - this would be a useful, practical addition to the schema.","issue_id":1660651461855,"origin_id":1782719265,"user_origin_id":75626416,"create_time":1698404521,"update_time":1698404521,"id":1716270164922,"updated_at":"2024-05-21T05:42:44.922000Z","created_at":"2024-05-21T05:42:44.922000Z"},{"_id":"664c34544a8e87d14e1c115a","body":"I have come across this issue and believe our API would benefit from allowing recursive GraphQL queries. Our schema contains types that have a field of the same type, but the overall data structure is still finite and acyclic. Without recursive query support, one is forced into awkward workarounds like:\r\n- Querying the API multiple times recursively to traverse the full data structure (one of the things GraphQL is supposed to avoid)\r\n- Assuming a specific max depth and writing separate fragments for level 1, level 2, ..., level N\r\n- Representing objects as `String` \/ `Any` \/ `Json` scalars which return the full graph, instead of using proper Object Types\r\n\r\nBeing able to write a recursive query would make this situation a lot simpler.","issue_id":1660651461855,"origin_id":1782740035,"user_origin_id":35232497,"create_time":1698405514,"update_time":1698405514,"id":1716270164925,"updated_at":"2024-05-21T05:42:44.925000Z","created_at":"2024-05-21T05:42:44.925000Z"},{"_id":"664c34544a8e87d14e1c115b","body":"@AlexKubiesa Please could you expand with a concrete example?","issue_id":1660651461855,"origin_id":1782753874,"user_origin_id":129910,"create_time":1698406157,"update_time":1698406157,"id":1716270164929,"updated_at":"2024-05-21T05:42:44.928000Z","created_at":"2024-05-21T05:42:44.928000Z"},{"_id":"664c34544a8e87d14e1c115c","body":"OK, here is a subset of the old version of our electronics design schema.\r\n\r\n```graphql\r\n# ...\r\n\r\ntype DesCadDesign {\r\n # ...\r\n boardOutline: DesCadComplexShape\r\n # ...\r\n}\r\n\r\ninterface DesCadGeometricShape {\r\n shapeType: DesCadGeometricShapeType!\r\n startPoint: DesCadPoint!\r\n endPoint: DesCadPoint!\r\n}\r\n\r\nenum DesCadGeometricShapeType {\r\n ARC\r\n B_SPLINE\r\n CIRCLE\r\n COMPLEX\r\n ELLIPSE\r\n ELLIPTICAL_ARC\r\n PARABOLA\r\n POLYLINE\r\n ARC_SIMPLE\r\n}\r\n\r\ntype DesCadComplexShape implements DesCadGeometricShape {\r\n isHole: Boolean!\r\n shapes: [DesCadGeometricShape!]\r\n shapeType: DesCadGeometricShapeType!\r\n startPoint: DesCadPoint!\r\n endPoint: DesCadPoint!\r\n}\r\n\r\ntype DesCadCircleShape implements DesCadGeometricShape {\r\n diameter: Int!\r\n center: DesCadPoint!\r\n shapeType: DesCadGeometricShapeType!\r\n startPoint: DesCadPoint!\r\n endPoint: DesCadPoint!\r\n}\r\n\r\ntype DesCadPolylineShape implements DesCadGeometricShape {\r\n points: [DesCadPoint!]!\r\n shapeType: DesCadGeometricShapeType!\r\n startPoint: DesCadPoint!\r\n endPoint: DesCadPoint!\r\n}\r\n\r\n# ...\r\n```\r\n\r\nI didn't include all the shape types but as you can see, we have `DesCadComplexShape`, which is a shape consisting of multiple other shapes, each of which could be complex shapes, and so on.\r\n\r\nTo query this API, the client would need to write a query including fragments like this:\r\n\r\n```graphql\r\n# ...\r\n\r\nfragment MyCadDesign on DesCadDesign {\r\n # ...\r\n boardOutline {...MyCadComplexShape}\r\n # ...\r\n}\r\n\r\nfragment MyCadGeometricShape on DesCadGeometricShape {\r\n shapeType\r\n startPoint {...MyCadPoint}\r\n endPoint {...MyCadPoint}\r\n ...MyCadArcShape\r\n ...MyCadSimpleArcShape\r\n ...MyCadBSplineShape\r\n ...MyCadCircleShape\r\n ...MyCadEllipseShape\r\n ...MyCadEllipticalArcShape\r\n ...MyCadParabolaShape\r\n ...MyCadPolylineShape\r\n ...MyCadComplexShape\r\n}\r\n\r\nfragment MyCadGeometricShape2 on DesCadGeometricShape {\r\n shapeType\r\n startPoint {...MyCadPoint}\r\n endPoint {...MyCadPoint}\r\n ...MyCadArcShape\r\n ...MyCadSimpleArcShape\r\n ...MyCadBSplineShape\r\n ...MyCadCircleShape\r\n ...MyCadEllipseShape\r\n ...MyCadEllipticalArcShape\r\n ...MyCadParabolaShape\r\n ...MyCadPolylineShape\r\n ...MyCadComplexShape2\r\n}\r\n\r\nfragment MyCadGeometricShape3 on DesCadGeometricShape {\r\n shapeType\r\n startPoint {...MyCadPoint}\r\n endPoint {...MyCadPoint}\r\n ...MyCadArcShape\r\n ...MyCadSimpleArcShape\r\n ...MyCadBSplineShape\r\n ...MyCadCircleShape\r\n ...MyCadEllipseShape\r\n ...MyCadEllipticalArcShape\r\n ...MyCadParabolaShape\r\n ...MyCadPolylineShape\r\n}\r\n\r\nfragment MyCadComplexShape on DesCadComplexShape {\r\n isHole\r\n shapes {...MyCadGeometricShape2}\r\n}\r\n\r\nfragment MyCadComplexShape2 on DesCadComplexShape {\r\n isHole\r\n shapes {...MyCadGeometricShape3}\r\n}\r\n\r\nfragment MyCadCircleShape on DesCadCircleShape {\r\n diameter\r\n center {...MyCadPoint}\r\n}\r\n\r\nfragment MyCadPolylineShape on DesCadPolylineShape {\r\n points {...MyCadPoint}\r\n}\r\n\r\n# ...\r\n```\r\n\r\nAnd that's assuming there are only 3 levels, there may be more.\r\n\r\nIn the end we felt this was too big an ask for our clients, so we just changed `DesCadDesign.boardOutline` to be of type `String` and in that string we return the whole data structure, regardless of how many levels it has.","issue_id":1660651461855,"origin_id":1782953049,"user_origin_id":35232497,"create_time":1698414543,"update_time":1698414543,"id":1716270164932,"updated_at":"2024-05-21T05:42:44.931000Z","created_at":"2024-05-21T05:42:44.931000Z"},{"_id":"664c34544a8e87d14e1c115d","body":"@AlexKubiesa Please could you look at the `struct` RFC and see if you think this would suit your needs? It looks to me like it would (with the caveat that the current proposal only supports union-based polymorphism and not interface-based polymorphism):\r\n\r\nhttps:\/\/github.com\/graphql\/graphql-wg\/blob\/main\/rfcs\/Struct.md","issue_id":1660651461855,"origin_id":1782965366,"user_origin_id":129910,"create_time":1698415060,"update_time":1698415060,"id":1716270164934,"updated_at":"2024-05-21T05:42:44.934000Z","created_at":"2024-05-21T05:42:44.934000Z"},{"_id":"664c34544a8e87d14e1c115e","body":"@AlexKubiesa the use case seems closely related to what I was referring to here https:\/\/github.com\/graphql\/graphql-spec\/issues\/929#issuecomment-1294284387\n\nWould your clients benefit from being able to formulate a query like: give me the start and end points of all sub-shapes?\n\nI ask since the struct RFC of @benjie (which I really like by the way!) doesn't allow selection sets to apply recursively. Please correct me if I'm wrong @benjie ","issue_id":1660651461855,"origin_id":1783220613,"user_origin_id":29230371,"create_time":1698425422,"update_time":1698425483,"id":1716270164937,"updated_at":"2024-05-21T05:42:44.936000Z","created_at":"2024-05-21T05:42:44.936000Z"},{"_id":"664c34544a8e87d14e1c115f","body":"@skilkis Indeed it doesn\u2019t BUT omitting the selection set for a field will return everything in that field as if you had exhaustively written the selection sets recursively. The result being that you can simply query the `DesCadDesign.boardOutline` field with no selection set and you\u2019d get everything, like the current solution of String except it\u2019s an object and it\u2019s strongly typed.","issue_id":1660651461855,"origin_id":1783745367,"user_origin_id":129910,"create_time":1698481250,"update_time":1698481250,"id":1716270164939,"updated_at":"2024-05-21T05:42:44.939000Z","created_at":"2024-05-21T05:42:44.939000Z"},{"_id":"664c34544a8e87d14e1c1160","body":" @benjie @skilkis thank you for your suggestions.\r\n\r\nThe Struct RFC feels like a good fit. Our current use case involves a client querying the whole board outline, making some local modifications, and then uploading the whole modified outline (like the RESTful PUT described in the RFC). So, having a complex type that functions as both an input and output is quite appealing. It would allow our clients to use strongly-typed client libraries like Strawberry Shake without having to set up an input-to-output type mapping. I think we could switch to union-based polymorphism quite easily.\r\n\r\nhttps:\/\/github.com\/graphql\/graphql-spec\/issues\/929#issuecomment-1294284387 would also address the recursion issue, but doesn't address the input-vs-output issue.","issue_id":1660651461855,"origin_id":1795415075,"user_origin_id":35232497,"create_time":1699288712,"update_time":1699288712,"id":1716270164942,"updated_at":"2024-05-21T05:42:44.942000Z","created_at":"2024-05-21T05:42:44.942000Z"},{"_id":"664c34544a8e87d14e1c1161","body":"Thank you for the datapoint @AlexKubiesa :raised_hands: ","issue_id":1660651461855,"origin_id":1795446361,"user_origin_id":129910,"create_time":1699289112,"update_time":1699289112,"id":1716270164945,"updated_at":"2024-05-21T05:42:44.945000Z","created_at":"2024-05-21T05:42:44.945000Z"},{"_id":"664c34544a8e87d14e1c1162","body":"I wanted to share my use case which is along the lines of this and the structs proposal. I'm not sure where to share this but I think perhaps this issue is the right place. \r\n\r\nI develop and maintain [Ordbok API](https:\/\/ordbokapi.org) which is a public and free GraphQL API for data from the Norwegian dictionaries (Yes, there's multiple. It's a long story). One of the use cases I have for finite recursion is definitions in dictionary articles, which can have subdefinitions, which can themselves have subdefinitions, and so forth.\r\n\r\nCurrently, writing a query would require writing a lot of boilerplate up to a specified depth past which the user can reasonably expect there not to be any further subdefinitions, as the depth can vary from article to article. Some definitions have more depth than one may expect.\r\n\r\nEach definition has multiple fields that may or may not be desired by the client application. This includes, for example, content in either plain text or structured formats, or relationships to other articles on a definition level, or other data a definition contains. Thus it is desirable to maintain the ability to pick what fields the user desires while still allowing recursion to a reasonable depth.\r\n\r\nHere's what queries have to look like currently:\r\n\r\n```graphql\r\n# Fragment using textContent instead of richContent for simple use cases\r\nfragment DefinitionContent on Definition {\r\n content {\r\n textContent\r\n }\r\n examples {\r\n textContent\r\n }\r\n}\r\n\r\nquery WordDefinitions(\r\n $word: String!\r\n $dictionaries: [Dictionary!]\r\n $wordClass: WordClass\r\n) {\r\n word(word: $word, dictionaries: $dictionaries, wordClass: $wordClass) {\r\n articles {\r\n id\r\n dictionary\r\n lemmas {\r\n lemma\r\n }\r\n gender\r\n wordClass\r\n definitions {\r\n ...DefinitionContent\r\n subDefinitions {\r\n ...DefinitionContent\r\n subDefinitions {\r\n ...DefinitionContent\r\n subDefinitions {\r\n ...DefinitionContent\r\n subDefinitions {\r\n ...DefinitionContent\r\n subDefinitions {\r\n ...DefinitionContent\r\n subDefinitions {\r\n ...DefinitionContent\r\n subDefinitions {\r\n ...DefinitionContent\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n}\r\n```\r\n\r\nWhat would be much preferable is some kind of recursion-friendly syntax that would continue to allow users to select the fields they need from a Definition. A naive example with fragments could be:\r\n\r\n```graphql\r\nfragment DefinitionContent on Definition {\r\n content {\r\n textContent\r\n }\r\n examples {\r\n textContent\r\n }\r\n subDefinitions {\r\n ...DefinitionContent\r\n }\r\n}\r\n\r\nquery WordDefinitions(\r\n $word: String!\r\n $dictionaries: [Dictionary!]\r\n $wordClass: WordClass\r\n) {\r\n word(word: $word, dictionaries: $dictionaries, wordClass: $wordClass) {\r\n articles {\r\n id\r\n dictionary\r\n lemmas {\r\n lemma\r\n }\r\n gender\r\n wordClass\r\n definitions {\r\n ...DefinitionContent\r\n }\r\n }\r\n }\r\n}\r\n```\r\n\r\nHowever, of course, infinite recursion is a problem in other use cases though it is not in mine.","issue_id":1660651461855,"origin_id":1987650262,"user_origin_id":9868643,"create_time":1710134238,"update_time":1710134238,"id":1716270164949,"updated_at":"2024-05-21T05:42:44.949000Z","created_at":"2024-05-21T05:42:44.949000Z"},{"_id":"664c34544a8e87d14e1c1163","body":"@adalinesimonian at some point you probably don't intend to show the entire tree of recursive subdefinitions on a single screen. At which point the recommended pattern would be to split into a recursive *query* rather then rely on recursive fragments:\r\n```\r\nquery WordDefinitions(\r\n $word: String!\r\n $dictionaries: [Dictionary!]\r\n $wordClass: WordClass\r\n) {\r\n word(word: $word, dictionaries: $dictionaries, wordClass: $wordClass) {\r\n articles {\r\n id\r\n dictionary\r\n lemmas {\r\n lemma\r\n }\r\n gender\r\n wordClass\r\n definitions {\r\n ...DefinitionContent\r\n }\r\n }\r\n }\r\n}\r\n\r\nfragment DefinitionContent on Definition {\r\n id\r\n content {\r\n textContent\r\n }\r\n examples {\r\n textContent\r\n }\r\n}\r\n\r\nquery Subdefinitions($id: ID!) {\r\n definition(id: $id) {\r\n subdefinitions(parent: $parent) {\r\n ...DefinitionContent\r\n }\r\n }\r\n}\r\n```\r\n\r\nYou can choose *how deep* to recursively request subdefinitions in a single round trip, and you can recurse infinitely via a pattern similar to [pagination](https:\/\/relay.dev\/docs\/guided-tour\/list-data\/rendering-connections\/), but what you *will not* accidentally do is DDOS yourself because someone added a cyclically-referential subdefinition.","issue_id":1660651461855,"origin_id":1988426620,"user_origin_id":1741248,"create_time":1710163207,"update_time":1710163207,"id":1716270164954,"updated_at":"2024-05-21T05:42:44.953000Z","created_at":"2024-05-21T05:42:44.953000Z"},{"_id":"664c34544a8e87d14e1c1164","body":"> at some point you probably don't intend to show the entire tree of recursive subdefinitions on a single screen. At which point the recommended pattern would be to split into a recursive _query_ rather then rely on recursive fragments\r\n\r\nThe most common use case for definitions is to display the entire definition tree. Though it may be deep, it does not necessarily take up that much room, or at least not that much room relatively speaking. And even when it does, the data is usually needed all together as most client implementations are not displaying articles in parts when definitions are included in the response. There are certain use cases where it's possible that the client may not want the _entire_ definition tree all at once, but those use cases for this particular API are not the majority.\r\n\r\n> You can choose _how deep_ to recursively request subdefinitions in a single round trip, and you can recurse infinitely via a pattern similar to [pagination](https:\/\/relay.dev\/docs\/guided-tour\/list-data\/rendering-connections\/), but what you _will not_ accidentally do is DDOS yourself because someone added a cyclically-referential subdefinition.\r\n\r\nWith the way the data is stored, it's impossible for a cyclical subdefinition to be added. Each article is stored as a JSON document in Redis, and so is the definition tree per article. When the definitions are requested, they are processed from the document that is retrieved from Redis, according to the client's demands (e.g. returning rich content with article references or just plain text, etc.). Unless Redis finds a way to allow infinitely long key values, we'll be fine on that front. \u263a\ufe0f\r\n\r\nA limitation of the dataset is that subdefinition IDs are not unique dataset but to each article. Together with the fact that articles and subdefinitions are stored together as documents means that querying by a subdefinition ID would require passing in the article ID to know which subdefinition to query. Currently, the server implementation is quite straightforward (with the one exception being data processing) and is easily able to respond to definition data requests without any additional implementation work as the data is available on the object retrieved from the database with all definitions attached to it, given how the dataset is structured (something I have little control over \u2014 academia, etc. etc.).\r\n\r\n---\r\n\r\nDefinitions aside, there are other areas where such recursion _could_ and _would_ result in infinite recursion, for example, references to related articles. While definitions are guaranteed to never infinitely recurse, this is not true with references to articles. The word skule may be related to l\u00e6rar, which in turn may be related back to skule. Infinite recursion with the article object is a real danger and is why I am not particularly in favour of syntax like what I naively wrote earlier. Otherwise it would send my server into a loop I don't want it to be in.\r\n\r\nSome kind of way to indicate a maximum recursion depth per key, both on the server and the client, would make it such that the client still can send really intuitive queries but without the risk of a ridiculous response from the server.\r\n\r\nI've read the structs proposal, but am not entirely certain what the equivalent may look like in that paradigm. Here's a naive and by no means perfect (read: ugly) approach using fragments. I'm not advocating for this specific syntax as much as the ability to effectively do something similar.\r\n\r\n```graphql\r\nfragment DefinitionContent on Definition {\r\n content {\r\n textContent\r\n }\r\n subDefinitions {\r\n ...DefinitionContent\r\n }\r\n}\r\n\r\n# Phrases are articles for phrases that include the current article\r\nfragment PhraseFragment on Phrase {\r\n phrases {\r\n ...PhraseFragment\r\n }\r\n}\r\n\r\nquery WordDefinitions(\r\n $word: String!\r\n $dictionaries: [Dictionary!]\r\n $wordClass: WordClass\r\n) {\r\n word(word: $word, dictionaries: $dictionaries, wordClass: $wordClass) {\r\n articles {\r\n id\r\n dictionary\r\n lemmas {\r\n lemma\r\n }\r\n gender\r\n wordClass\r\n # Max 10 steps deep from this point onwards\r\n # Server is configured to allow a max depth of 15 for this field.\r\n definitions(#depth: 10) {\r\n ...DefinitionContent\r\n }\r\n # Error as recursion is not allowed here, default n is 0\r\n phrases {\r\n ...PhraseFragment\r\n }\r\n }\r\n }\r\n}\r\n```","issue_id":1660651461855,"origin_id":1988740700,"user_origin_id":9868643,"create_time":1710171516,"update_time":1710171616,"id":1716270164957,"updated_at":"2024-05-21T05:42:44.957000Z","created_at":"2024-05-21T05:42:44.957000Z"},{"_id":"664c34544a8e87d14e1c1165","body":"Stop talking about philosophy !!!\r\nTake a good look at the actual industry needs !!!!!!\r\nRecursive fragment is powerful for query need , and some scene using gql as DSL only","issue_id":1660651461855,"origin_id":2047770887,"user_origin_id":21015670,"create_time":1712760711,"update_time":1712760711,"id":1716270164961,"updated_at":"2024-05-21T05:42:44.961000Z","created_at":"2024-05-21T05:42:44.961000Z"}] comment

## Problem statement GraphQL spec currently forbids recursive references in fragments - section 5.5.2.2: > 5.5.2.2 Fragment spreads must not form cycles The reasoning given is that reference cycles result...