|
| 1 | +# GraphQL Emitter Follow-up Items |
| 2 | + |
| 3 | +## ~~Input Type Nullability Bug~~ (RESOLVED) |
| 4 | + |
| 5 | +**Status**: Fixed in PR #77 (commit ea85714d2) |
| 6 | + |
| 7 | +**Original issue**: Optional fields in input types were being made non-null. |
| 8 | + |
| 9 | +**Resolution**: Per the GraphQL spec, "nullability directly determines whether a field is required." Optional fields (`?`) should be nullable in both input and output contexts. This also enables circular references in input types (e.g., `Author.friend?: Author` → `friend: AuthorInput` is valid because it's nullable). |
| 10 | + |
| 11 | +**Correct behavior** (now implemented): |
| 12 | + |
| 13 | +| TypeSpec | Output | Input | |
| 14 | +|--------------------|----------|----------| |
| 15 | +| a: string | String! | String! | |
| 16 | +| b?: string | String | String | |
| 17 | +| c: string \| null | String | String | |
| 18 | + |
| 19 | +--- |
| 20 | + |
| 21 | +## @oneOf Input Union Bug (Priority: Medium) |
| 22 | + |
| 23 | +**Issue**: Unions used in input context (e.g., mutation parameters) should be converted to `@oneOf` input objects per the GraphQL spec, but the emitter crashes with "Unknown GraphQL type" when attempting this. |
| 24 | + |
| 25 | +**Test case that exposes the bug**: |
| 26 | +```typespec |
| 27 | +@schema |
| 28 | +namespace TestNamespace { |
| 29 | + model TextContent { |
| 30 | + text: string; |
| 31 | + } |
| 32 | +
|
| 33 | + model ImageContent { |
| 34 | + url: string; |
| 35 | + } |
| 36 | +
|
| 37 | + union Content { |
| 38 | + text: TextContent, |
| 39 | + image: ImageContent, |
| 40 | + } |
| 41 | +
|
| 42 | + model Post { |
| 43 | + id: string; |
| 44 | + content: Content; |
| 45 | + } |
| 46 | +
|
| 47 | + @query |
| 48 | + op getPost(id: string): Post; |
| 49 | +
|
| 50 | + @mutation |
| 51 | + op createPost(content: Content): Post; |
| 52 | +} |
| 53 | +``` |
| 54 | + |
| 55 | +**Error**: |
| 56 | +``` |
| 57 | +Error: Unknown GraphQL type "ContentInput". |
| 58 | + at resolveNamedType (src/schema/build/types.ts:100:11) |
| 59 | +``` |
| 60 | + |
| 61 | +**Root cause**: The `GraphQLUnionMutation.mutateAsOneOfInput()` correctly creates the `@oneOf` input model (e.g., `ContentInput`), but this synthetic model is not being registered in the type registry that `buildArgsMap` uses to resolve argument types. |
| 62 | + |
| 63 | +**Expected behavior**: |
| 64 | +- In output context: `union Content = TextContent | ImageContent` |
| 65 | +- In input context: `input ContentInput @oneOf { text: TextContentInput, image: ImageContentInput }` |
| 66 | + |
| 67 | +**Files to investigate**: |
| 68 | +- `src/mutation-engine/mutations/union.ts` - `mutateAsOneOfInput()` creates the @oneOf model |
| 69 | +- `src/schema/build/types.ts` - where the type registry is built and `resolveNamedType` fails |
| 70 | +- `src/mutation-engine/schema-mutator.ts` - may need to register synthetic types |
| 71 | + |
| 72 | +**Related**: Similar bug exists for complex input types used in `@operationFields` arguments (the `FilterOptions` model isn't discovered when used only as an operation field argument type). |
0 commit comments