You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: graphql_design_doc.md
+42-24Lines changed: 42 additions & 24 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -70,7 +70,7 @@ The main design constraint is that we only want to traverse the TSP program once
70
70
We need to consider two main scenarios when designing the GraphQL emitter:
71
71
72
72
1. When the TypeSpec code is specifically designed for emitting GraphQL, we can equip developers with GraphQL-specific decorators, and objects. This will aid in crafting TypeSpec code that generates well-designed GraphQL schemas. Given that GraphQL does not employ HTTP or REST concepts, developers should be able to bypass those libraries. However, it should still be feasible to emit OpenAPI or any other schema by adding the appropriate decorators (like `@route`) to the existing TypeSpec code used to generate the GraphQL schema and the existing graphql emitter should continue to work as expected.
73
-
2. When a developer aims to create a GraphQL service from an existing TypeSpec schema originally used for emitters like OpenAPI, we focus on designing a usable GraphQL schema. This may involve using `Any` scalars for unsupported GraphQL objects and emitting all the operations in the TypeSpec code. Although the emitted GraphQL schema might lack optimal design, it remains functional. If a specific pattern can enhance the GraphQL schema and aligns with our design guidelines, it should be applied. We will also offer warnings and recommendations to assist developers in modifying the TypeSpec code to improve their emitted GraphQL schema incrementally.
73
+
2. When a developer aims to create a GraphQL service from an existing TypeSpec schema originally used for emitters like OpenAPI, we focus on producing a GraphQL schema that represents the TypeSpec with no loss of specificity. Instead of assuming intent, we will provide errors and warnings as soon as possible when something in the TypeSpec schema is not directly compatible with GraphQL and the means of making it compatible are not deterministic.
74
74
75
75
## Output Types
76
76
@@ -261,7 +261,7 @@ To emit a valid GraphQL and still represent the schema defined in TypeSpec, the
261
261
- If the input type is a `Model` and all the properties of the `Model` are of valid Input types, a new `Input` object will be created in GraphQL, with the typename as the original type \+ `Input` suffix.
262
262
- **🔴 Design decision:** Allmodelsarecreatedwiththe `Input` suffixregardlessofwhetherornotitisusedasboth, because the model can be used as both `input` and `output` in the future and changing the type name will cause issues with schema evolution.
263
263
- **Cons:** the `Input` suffixcanbeannoyingorresultintypeslike `UserInputInput`
264
-
- Ifthe `model` oritspropertiesareinvalidInputtypes, the type of the invalid model or property will be assigned to the `Any` scalar type and a warning will be emitted.
264
+
- Ifthe `model` oritspropertiesareinvalidInputtypes, an error will be raised.
265
265
- **🔴 Design decision:** InordertoprovideadifferentdefinitionofthesamefieldsothattheGraphQLtypecanberepresentedmoreaccurately, we will use the [upcoming visibility redesign to provide an alternative definition](https://discord.com/channels/1247582902930116749/1250119513681301514/1300865256679276655), seetheexamplestoseewhatthatcouldlooklike.
1. Use the type name instead of values for integer and floating point values. But, we would need to be consistent and use TSP enums in the type context rather than the value context which feels wrong.
1141
-
2. Emit `Any` for enums with values as integers or floating points and let the developer define an alternate type using the [upcoming visibility redesign to provide an alternative definition](https://discord.com/channels/1247582902930116749/1250119513681301514/1300865256679276655).
1141
+
2. Emit `Any` for enums with values as integers or floating points and let the developer define an alternate type [using visibility](#visibility--never).
1142
1142
1. If the `@invisible` decorator can be applied to `EnumMembers`, we can provide alternate enum members for GraphQL in the same enum definition which change the emitter to emit the GraphQL enum values as shown below:
* HTTPlibraryhasthe [automaticvisibility](https://typespec.io/docs/libraries/http/operations/#automatic-visibility) concept that automatically filters the properties from the model based on the HTTP type of the operation, with no need of generating explicit filtered models.
@@ -1580,12 +1580,29 @@ type Query {
1580
1580
Addtotheemitterthehandlingofthe *`never`* type, and exclude any field from the Model before emitting the Model.
* Toemitaschema closer to those emitted by other emitters, if the operation is marked with a HTTP verb decorator, we will need to follow the HTTP library specification to filter the models before using them, and if needed, generate new models based on the visibility and the operation type. For example: for the operations responding using a Model, we will emit a new model named ModelRead with the properties filtered using the "read" visibility.
1588
-
Note that the naming should include the Input suffix and this approach will generate models like UserCreateInput, UserUpdateInput, UserDeleteInput, etc.
1585
+
```typespec
1586
+
enumOperationType {
1587
+
Query,
1588
+
Mutation,
1589
+
Subscription,
1590
+
}
1591
+
```
1592
+
1593
+
For implicit filtered models (automaticvisibility):
1594
+
1595
+
GraphQLdoesnothaveanequivalentconceptlikeHTTPverbsthatmaptothe `Lifecycle` visibilitymodifiers. However, GraphQLmutationswillcommonlyadheretothesetypeof"CRUD"operations.
1596
+
1597
+
TSPdeveloperswillneedtotakeadvantageofthe [`@parameterVisibility`](https://typespec.io/docs/standard-library/built-in-decorators/#@parameterVisibility) and [`@returnTypeVisibility`](https://typespec.io/docs/standard-library/built-in-decorators/#@returnTypeVisibility) decorators to filter the models based on the semantic operation type.
1598
+
InthecasewheretheoperationdoesnothaveexplicitvisibilityspecifiedandisalreadydecoratedwithanHTTPverb, the emitter will use [the HTTP library specification](https://typespec.io/docs/libraries/http/operations/#automatic-visibility) to apply the related visibility to the input types.
1599
+
1600
+
Ifnoneofthestandard"CRUD"operationsapply, whether the [operation](#operations) is a query, mutation, or subscription will apply the `OperationType.Query`, `OperationType.Mutation`, or `OperationType.Subscription` visibility to input types, respectively.
1601
+
1602
+
For practical reasons, we will follow lead of the HTTP library on response types and filter them to `Lifecycle.Read` by default.
1603
+
1604
+
Generated model names will be suffixed with the appropriate operation type, e.g. `UserQueryInput`, `UserRead`, `UserCreateInput`, `UserMutationInput`, etc.
1605
+
The new models would be generated only if they are distinct from the original Model.
1589
1606
1590
1607
### Examples
1591
1608
<table>
@@ -1599,18 +1616,18 @@ Note that the naming should include the Input suffix and this approach will gene
* ShouldwekeeptheoriginalModelsintheschema, even if they are not used?
1793
+
* We should expect that `<Model>Read` types will be the most common; should we have the `Lifecycle.Read`-filtered model instead be called `<Model>`, and the unfiltered model be something like `<Model>Full`?
0 commit comments