Skip to content

Commit e9d690a

Browse files
committed
Add solution 7.
1 parent 058bf90 commit e9d690a

File tree

1 file changed

+114
-54
lines changed

1 file changed

+114
-54
lines changed

rfcs/SemanticNullability.md

Lines changed: 114 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -226,9 +226,9 @@ Note: Traditional non-nullable types will effectively become semantically
226226
non-nullable when error propagation is disabled no matter which solution is
227227
chosen, so this criteria is only concerned with traditionally nullable types.
228228

229-
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] |
230-
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
231-
||||| 🚫👍 ||
229+
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] | [7][solution-7] |
230+
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
231+
||||| 🚫👍 || |
232232

233233
Criteria score: 🥈
234234

@@ -240,9 +240,9 @@ Users should be able to adopt semantic nullability into an existing schema, and
240240
when doing so all existing operations should remain valid, and should have the
241241
same meaning as they always did.
242242

243-
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] |
244-
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
245-
|| 🚫 |||||
243+
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] | [7][solution-7] |
244+
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
245+
|| 🚫 |||| ||
246246

247247
Criteria score: 🥈
248248

@@ -254,9 +254,9 @@ GraphQL has been public for 10 years and there's a lot of content out there
254254
noting that GraphQL types are nullable by default (unadorned type is nullable)
255255
and our changes should not invalidate this content.
256256

257-
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] |
258-
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
259-
|| 🚫 || 🚫 |||
257+
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] | [7][solution-7] |
258+
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
259+
|| 🚫 || 🚫 || ||
260260

261261
Criteria score: 🥉
262262

@@ -268,9 +268,9 @@ The GraphQL languages similarity to JSON is one of its strengths, making it
268268
immediately feel familiar. Syntax used should feel obvious to developers new to
269269
GraphQL.
270270

271-
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] |
272-
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
273-
| 🚫 |||| ⚠️ ||
271+
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] | [7][solution-7] |
272+
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|-------------|
273+
| 🚫 |||| ⚠️ |||
274274

275275
Criteria score: 🥇
276276

@@ -282,9 +282,9 @@ When a user wishes to replace the value for an input field or argument with a
282282
variable in their GraphQL operation, the type syntax should be either identical
283283
or similar, and should carry the same meaning.
284284

285-
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] |
286-
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
287-
|||| 🚫 |||
285+
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] | [7][solution-7] |
286+
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|--------------|
287+
|||| 🚫 ||||
288288

289289
Criteria score: 🥇
290290

@@ -295,9 +295,9 @@ Criteria score: 🥇
295295
Where a proposal allows alternative syntaxes to be used, the two syntaxes should
296296
not cause confusion.
297297

298-
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] |
299-
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
300-
|||| 🚫 |||
298+
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] | [7][solution-7] |
299+
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|--------------|
300+
|||| 🚫 ||||
301301

302302
Criteria score: 🥇
303303

@@ -311,9 +311,9 @@ still keep errors local to the same positions that they did when they were
311311
published), allowing for the "partial success" feature of GraphQL to continue to
312312
shine and not compromising the resiliency of legacy deployed app versions.
313313

314-
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] |
315-
| --------------- | --------------- | --------------- | --------------- |-----------------|-----------------|
316-
||||| 🚫 ||
314+
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] | [7][solution-7] |
315+
| --------------- | --------------- | --------------- | --------------- |-----------------|-----------------|-------------|
316+
||||| 🚫 |||
317317

318318
Criteria score: 🥈
319319

@@ -326,9 +326,9 @@ path for legacy apps, the tradeoff might be acceptable.
326326

327327
The implementation required to make the proposal work should be simple.
328328

329-
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] |
330-
| --------------- | --------------- | --------------- | --------------- |-----------------|-----------------|
331-
|| 🚫 | 🚫 | 🚫 |||
329+
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] | [7][solution-7] |
330+
| --------------- | --------------- | --------------- | --------------- |-----------------|-----------------|--------------|
331+
|| 🚫 | 🚫 | 🚫 ||||
332332

333333
Criteria score: 🥇
334334

@@ -341,9 +341,9 @@ since inputs never handle "errors" ("null only on error" is the same as "not
341341
null" on input). As such, there's no benefit to clients for the syntax of
342342
executable documents to change.
343343

344-
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] |
345-
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
346-
|||| 🚫 |||
344+
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] | [7][solution-7] |
345+
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|-------------|
346+
|||| 🚫 ||||
347347

348348
Criteria score: 🥈
349349

@@ -355,9 +355,9 @@ The type of a field (`foo: Int`) can be determined by looking at the field and
355355
its type; the reader should not have to read a document or schema directive to
356356
determine how the type should be interpreted.
357357

358-
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] |
359-
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
360-
||| ⚠️ | 🚫 || ⚠️ |
358+
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] | [7][solution-7] |
359+
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|-------------|
360+
||| ⚠️ | 🚫 || ⚠️ ||
361361

362362
Criteria score: 🥇
363363

@@ -367,9 +367,9 @@ Criteria score: 🥇
367367

368368
We do not want to break existing tooling.
369369

370-
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] |
371-
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
372-
|||||||
370+
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] | [7][solution-7] |
371+
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|-------------|
372+
||||||||
373373

374374
Criteria score: 🥈
375375

@@ -383,9 +383,9 @@ to deal with nullable or non-nullable as presented to them by their client frame
383383

384384
May contradict: M
385385

386-
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] |
387-
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
388-
|||||| ⚠️ |
386+
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] | [7][solution-7] |
387+
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|--------------|
388+
|||||| ⚠️ ||
389389

390390
Criteria score: 🥈
391391

@@ -399,9 +399,9 @@ schema SDL.
399399

400400
May contradict: L
401401

402-
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] |
403-
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
404-
| ⚠️ || ⚠️ ||||
402+
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] | [7][solution-7] |
403+
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|-------------|
404+
| ⚠️ || ⚠️ |||||
405405

406406
Criteria score: 🥇
407407

@@ -415,9 +415,9 @@ that's only nullable because errors may occur. GraphQL-TOE can be used in such
415415
situations so that codegen can safely use non-nullable types in semantically
416416
non-nullable positions.
417417

418-
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] |
419-
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
420-
||||| 🚫 ||
418+
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] | [7][solution-7] |
419+
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|-------------|
420+
||||| 🚫 |||
421421

422422
Criteria score: 🥉
423423

@@ -435,9 +435,9 @@ Per Lee:
435435
> allow inconsequential changes in behavior, but bubbling the error up isn't
436436
> inconsequential.)
437437
438-
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] |
439-
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
440-
||||| 🚫 ||
438+
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] | [7][solution-7] |
439+
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|-------------|
440+
||||| 🚫 |||
441441

442442

443443
Note: though this criteria is currently not considered due to overlap with B
@@ -464,9 +464,9 @@ Per Benoit:
464464
> an outcome of this whole effort I’d like to see happening.
465465
466466

467-
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] |
468-
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
469-
||||| 🚫 | ⚠️ |
467+
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] | [7][solution-7] |
468+
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|-------------|
469+
||||| 🚫 | ⚠️ ||
470470

471471
Criteria score: 🥇
472472

@@ -478,9 +478,9 @@ The default (unadorned) type should be a type that you can migrate away from,
478478
once nullability expectations become more concrete, without breaking existing
479479
client queries.
480480

481-
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] |
482-
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
483-
|| 🚫 || 🚫 |||
481+
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] | [7][solution-7] |
482+
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|-------------|
483+
|| 🚫 || 🚫 ||||
484484

485485
Note: this is not necessarily a duplicate of C as it doesn't specifically
486486
require the unadorned type be nullable, however no proposal currently proposes
@@ -506,9 +506,9 @@ As such:
506506
- the representation in introspection for inputs (namely the `NON_NULL` type
507507
wrapper) should be unchanged
508508

509-
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] |
510-
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
511-
|||| 🚫 |||
509+
| [1][solution-1] | [2][solution-2] | [3][solution-3] | [4][solution-4] | [5][solution-5] | [6][solution-6] | [7][solution-7] |
510+
|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|-------------|
511+
|||| 🚫 ||||
512512

513513
Criteria score: 🥈
514514

@@ -1005,3 +1005,63 @@ positions.
10051005
-
10061006
- [R][criteria-r]
10071007
- ✅ Directive is only valid on output positions.
1008+
1009+
## 💡 7. `@propagateError` directive
1010+
1011+
[solution-7]: #-7-propagateerror-directive
1012+
1013+
**Champion**: @leebyron
1014+
1015+
Discussion: https://github.com/graphql/graphql-wg/discussions/1700
1016+
1017+
This proposal introduces a directive that can be added to fields to indicate that they should propagate errors.
1018+
1019+
```graphql
1020+
type Person {
1021+
id: ID! @propagateError
1022+
name: String
1023+
age: Int
1024+
picture: Url
1025+
}
1026+
```
1027+
1028+
1029+
### ⚖️ Evaluation
1030+
1031+
- [A][criteria-a]
1032+
- ✅ semantically non-null without propagateError
1033+
- [B][criteria-b]
1034+
- ~✅ This is true when existing services must ensure propagateError is set when adopting this behavior.
1035+
- [C][criteria-c]
1036+
- ✅ Existing symbology unchanged.
1037+
- [D][criteria-d]
1038+
- ✅ No new symbols. No new types. Error bubbling was previously implicit behavior, now it is explicit.
1039+
- [E][criteria-e]
1040+
- ✅ No change to input types
1041+
- [F][criteria-f]
1042+
- ✅
1043+
- [G][criteria-g]
1044+
- ✅
1045+
- [H][criteria-h]
1046+
- ~✅ One new directive/introspection field. Behavior change is straightforward. Managing adoption/migration requires careful consideration.
1047+
- [I][criteria-i]
1048+
- ✅ This proposes no change to executable documents
1049+
- [J][criteria-j]
1050+
- ✅ The propagateError introspection/directive is local to the field (the optional propagateErrorOnAllNonNullFields config just does this for you).
1051+
- [K][criteria-k]
1052+
- ✅ Adds one new field. Migration path supports existing semantics for shipped clients.
1053+
- [L][criteria-l]
1054+
- ✅ There are only two types and they remain the same as they are today. This proposal is about changing error bubbling behavior, not nullability.
1055+
- [M][criteria-m]
1056+
- ✅ First party APIs have a clear path to introduce propagateError for all consumers.
1057+
- ⚠️ Third party APIs have a more challenging migration path, and may wish to expose different Schema to different clients.
1058+
- [N][criteria-n]
1059+
- ✅ Separating nullability from error bubbling allows for more control. Clients should preferably disable error bubbling, but even if they do not - this unlocks the ability for a semantically non-null type which does not error propagate.
1060+
- [O][criteria-o]
1061+
- ✅
1062+
- [P][criteria-p]
1063+
- ✅ This is technically not breaking, however note that changing field: Type to field: Type! does introduce a new source of errors (which may be preferable!) Doing this without adding @propagateError is preferred, since changing field: Type to field: Type! @propagateError, could lose data - and is exactly why this kind change is discouraged today.
1064+
- [Q][criteria-q]
1065+
- ✅
1066+
- [R][criteria-r]
1067+
- ✅ No proposed change to inputs

0 commit comments

Comments
 (0)