Skip to content

Commit 297b11e

Browse files
martinbonninbenjie
andauthored
Add FullSchemas.md (#1375)
* Add full schemas * Update rfcs/FullSchemas.md --------- Co-authored-by: Benjie <benjie@jemjie.com>
1 parent d4264b0 commit 297b11e

File tree

1 file changed

+108
-0
lines changed

1 file changed

+108
-0
lines changed

rfcs/FullSchemas.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# RFC: Full Schemas
2+
3+
**Proposed by:** [Martin Bonnin](https://mastodon.mbonnin.net/@mb) - Apollo
4+
5+
## Problem statement
6+
7+
In its current form the GraphQL specification contains language about the presence of built-in definitions in SDL schemas:
8+
9+
* scalars MUST be absent from SDL ([here](https://spec.graphql.org/October2021/#sel-GAHXJHABAB_D4G))
10+
* directives SHOULD be absent([here](https://spec.graphql.org/October2021/#sel-FAHnBPLCAACCcooU))
11+
* introspection types are not mentioned in the spec (See [here](https://github.com/graphql/graphql-spec/pull/1036) for a pull request to address this)
12+
13+
This is made for brevity and correctness reasons. When the SDL document is fed to a GraphQL implementation like graphql-js, there is no need to add the built-in definitions as the implementation will add them. Adding built-in definitions in the input schema could also be confusing: what definition is used? The one from the input schema or the one from the implementation? It makes sense overall to omit built-in definitions from SDL documents that are used by GraphQL implementations.
14+
15+
But the absence of built-in definitions can make it impossible for client tools to validate an operation without knowing more details about what is supported by the server.
16+
17+
For an example, the below query is valid if the server uses the latest draft but is not valid if the server uses the [Oct2021 specification](https://spec.graphql.org/October2021/#sel-GAJXNFADgHAADkHABsrC):
18+
19+
```graphql
20+
{
21+
__schema {
22+
types {
23+
name
24+
inputFields {
25+
name
26+
# isDeprecated is only present in latest versions of the specification
27+
isDeprecated
28+
deprecationReason
29+
}
30+
}
31+
}
32+
}
33+
```
34+
35+
In general, it would be nice to have a SDL format that would be a full representation of the server schema, even if it means it is more verbose.
36+
37+
This proposal is about allowing SDL documents that contain all the information required for tooling to validate any operation, later denominated as "full schema".
38+
39+
## Proposal 1: relax SDL requirements
40+
41+
An easy solution is to relax the SDL requirements and leave it up to tools to determine how they react to missing or existing built-in definitions.
42+
43+
A GraphQL implementation like graphql-js could decide to throw an error if it is fed with a definition that it itself provides. It could also decide to react on what is in the input schema. For an example, `@include`/`@skip` could be left unsupported by not adding them in the input schema.
44+
45+
A GraphQL client like apollo-kotlin could decide to throw an error if the introspection types are missing. Or add options to specify manually what built-in definitions to use for validation.
46+
47+
## Proposal 2: be explicit about "full schemas" vs current, regular "schemas"
48+
49+
Another solution is to introduce "full schemas" in addition to the existing SDL schemas. A "full schema" is a schema that also contains the built-in definitions added by the implementation.
50+
51+
This proposal is more opinionated but also less flexible than proposal 1. It's either "regular schema" or "full schema" but an implementation could not decide to use some of the input definitions while still adding its own on top of them.
52+
53+
## Questions
54+
55+
### Q: Why not always use introspection results?
56+
57+
Introspection is the tool that was designed for clients to consume schemas, so it could be argued that client should use that. However:
58+
59+
1. Some servers have introspection disabled making it hard for clients to get an introspection schema
60+
2. In general, SDL is a much more readable and concise representation than the introspection JSON, making it more suited for workflows where the file is read by humans (IDEs, codegen, etc...)
61+
3. SDL schemas can represent applied directives, which introspection can't (see [#300](https://github.com/graphql/graphql-spec/issues/300)). Tools could use that information to provide a better developer experience, add functionality, etc...
62+
63+
### Q: Wouldn't that make inconsistent SDL documents containing unused definitions?
64+
65+
There is a (unwritten?) rule that SDL definitions must all be used (with an exception for built-in scalars and directive definitions). Hence, adding the introspection types to SDL would result in this schema being valid:
66+
67+
```graphql
68+
type Query {
69+
random: String
70+
}
71+
72+
type __Schema { ... }
73+
type __Type { ... }
74+
enum __TypeKind { ... }
75+
type __Field { ... }
76+
type __InputValue { ... }
77+
type __EnumValue { ... }
78+
type __Directive { ... }
79+
enum __DirectiveLocation { ... }
80+
```
81+
82+
Although technically nothing would use the `__Schema` type. For this, we would need to add the `__schema` meta-field:
83+
84+
```graphql
85+
type Query {
86+
random: String
87+
__schema: __Schema
88+
}
89+
90+
```
91+
92+
But then doing so for typename would become very noisy:
93+
94+
```graphql
95+
type Foo {
96+
# add __typename here
97+
__typename: String!
98+
}
99+
type Bar {
100+
# and here as well
101+
__typename: String!
102+
}
103+
union SomeUnion = Foo | Bar {
104+
# Technically unions have __typename, should we do this?
105+
__typename: String!
106+
}
107+
108+
```

0 commit comments

Comments
 (0)