Skip to content

bump apollo-compiler to 2.0.0-beta.1 for the built-in @oneOf - #59

Merged
XiNiHa merged 1 commit into
mainfrom
apollo-compiler-2-beta
Oct 19, 2026
Merged

XiNiHa merged 1 commit into
mainfrom
apollo-compiler-2-beta

Conversation

@XiNiHa

@XiNiHa XiNiHa commented Oct 19, 2026

Copy link
Copy Markdown
Owner

Summary

apollo-compiler 2.0.0-beta.1 supplies @oneOf end to end; greem's side of the move is two renames and two field reads.

 [workspace.dependencies]
-apollo-compiler = "1.33"
+# Exact: beta.2 makes `Field::selection_set` an `Option`, which breaks tree.rs.
+apollo-compiler = "=2.0.0-beta.1"
 greem/src/tree.rs
-  field.response_key()            ×2
+  field.response_name()
-  definition.node.clone()         # Component<FieldDefinition>
+  definition.clone()              # Node<FieldDefinition>
 greem-build/src/codegen.rs
-  m.name.clone()                  # ComponentName
+  (**m).clone()                   # Node<Name>
 greem-compliance/schemas/graphql_js/oneof.graphql
-  directive @oneOf on INPUT_OBJECT   # now built in

Who enforces the exactly-one rule after this PR:

Schema::parse        apollo validates literal @oneOf values
Schema::plan         apollo's coerce_variable_values rejects bad variables
literal_to_input     unchanged; never sees a rejected value
codegen              unchanged struct; the enum is #42

The pin is exact because the v2 branch already carries the selection_set change for beta.2. #39 and #42 carry the re-scope comments.

Evidence

  • Before: on 1.33 the oneOf area schema had to declare @oneOf itself, and the 9 rejecting ported cases passed their inputs through to the resolver.
    After: full workspace suite green (cargo test --workspace), clippy and fmt clean. With --include-ignored oneof, the 9 cases now reject at apollo; they differ from the expected JSON only in wording and request-vs-field shape, which Support @oneOf input objects #42 adopts:

    < "@oneOf input object `TestInputObject` must specify exactly one key, but 2 were given"
    > "variable `$input` got an invalid value: @oneOf input object `TestInputObject` requires exactly one non-null field"
    

    No fixture tripped apollo 2's stricter validation (default-value coercion, @deprecated on required inputs, rule 5.8.5 on nested variables).

Merge Danger

Door: two-way

Reverting the two commits restores 1.33; nothing apollo-typed is public (#14), so no consumer sees the change.

Blast Radius: validation

apollo 2 is stricter: user SDLs with uncoercible defaults or @deprecated on required inputs, and operations with nested variable usages that violate rule 5.8.5, now fail where 1.33 accepted them. Those are spec-correct rejections, and graphql-js v17 agrees, but they are a behaviour change for anyone relying on the older leniency. Later betas are a manual bump by design.

🤖 Generated with Claude Code

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-19T06:32:02.914856Z 0a6e483 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

Copy link
Copy Markdown

GraphQL-over-HTTP audit passes

graphql-http 1.23.1 against http://127.0.0.1:8080/graphql: 39 pass, 4 overridden warnings, 18 notices.

These SHOULD audits contradict the GraphQL-over-HTTP draft, which greem follows:

Audit Expects Draft
572B SHOULD use 200 status code on document parsing failure when accepting application/json Response > Body has a legacy application/json client treated as one accepting application/graphql-response+json, so a document that does not parse is 400 (Response > Status Codes), not 200
FDE2 SHOULD use 200 status code on document validation failure when accepting application/json The audit's document, { 8f31403dfe404bccbb0e835f2629c6a7 }, does not lex, so it is a parse failure: 400 under Response > Status Codes, and Response > Body gives a legacy application/json client the same code, not 200
7B9B SHOULD use a status code of 200 on variable coercion failure when accepting application/json Response > Body has a legacy application/json client treated as one accepting application/graphql-response+json, so a variable coercion failure is 422 (Response > Status Codes), not 200
86EE SHOULD use a status code of 400 on variable coercion failure when accepting application/graphql-response+json Response > Status Codes > Examples makes a variable coercion failure 422 (Unprocessable Content), not 400
Full graphql-http report

* This report was auto-generated by graphql-http

GraphQL over HTTP audit report

  • 61 audits in total
  • ✅ 39 pass
  • 💡 18 notices (suggestions)
  • ❗️ 4 warnings (optional)

Passing

  1. 22EB SHOULD accept application/graphql-response+json and match the content-type
  2. 4655 MUST accept application/json and match the content-type
  3. 47DE SHOULD accept */* and use application/json for the content-type
  4. 80D8 SHOULD assume application/json content-type when accept is missing
  5. 82A3 MUST use utf-8 encoding when responding
  6. BF61 MUST accept utf-8 encoded request
  7. 78D5 MUST assume utf-8 in request if encoding is unspecified
  8. 2C94 MUST accept POST requests
  9. 5A70 MAY accept application/x-www-form-urlencoded formatted GET requests
  10. 9C48 MAY NOT allow executing mutations on GET requests
  11. 9ABE SHOULD respond with 4xx status code if content-type is not supplied on POST requests
  12. 03D4 MUST accept application/json POST requests
  13. A5BF MAY use 400 status code when request body is missing on POST
  14. 34A2 SHOULD allow string {query} parameter when accepting application/graphql-response+json
  15. 13EE MUST allow string {query} parameter when accepting application/json
  16. 8161 SHOULD allow string {operationName} parameter when accepting application/graphql-response+json
  17. B8B3 MUST allow string {operationName} parameter when accepting application/json
  18. 94B0 SHOULD allow null {variables} parameter when accepting application/graphql-response+json
  19. 0220 MUST allow null {variables} parameter when accepting application/json
  20. 94B1 SHOULD allow null {operationName} parameter when accepting application/graphql-response+json
  21. 0221 MUST allow null {operationName} parameter when accepting application/json
  22. 94B2 SHOULD allow null {extensions} parameter when accepting application/graphql-response+json
  23. 0222 MUST allow null {extensions} parameter when accepting application/json
  24. 2EA1 SHOULD allow map {variables} parameter when accepting application/graphql-response+json
  25. 28B9 MUST allow map {variables} parameter when accepting application/json
  26. D6D5 MAY allow URL-encoded JSON string {variables} parameter in GETs when accepting application/graphql-response+json
  27. 6A70 MAY allow URL-encoded JSON string {variables} parameter in GETs when accepting application/json
  28. 428F SHOULD allow map {extensions} parameter when accepting application/graphql-response+json
  29. 1B7A MUST allow map {extensions} parameter when accepting application/json
  30. B6DC MAY use 2xx, 4xx, or 5xx status codes on JSON parsing failure when accepting application/json
  31. BCF8 SHOULD use 400 status code on JSON parsing failure when accepting application/json
  32. B7N8 SHOULD use 400 status code on JSON parsing failure when accepting application/graphql-response+json
  33. 8764 MAY use 4xx or 5xx status codes if parameters are invalid
  34. 865D SHOULD use 4xx or 5xx status codes on document parsing failure when accepting application/graphql-response+json
  35. 556A SHOULD use 400 status code on document parsing failure when accepting application/graphql-response+json
  36. D586 SHOULD not contain the data entry on document parsing failure when accepting application/graphql-response+json
  37. 51FE SHOULD use 4xx or 5xx status codes on document validation failure when accepting application/graphql-response+json
  38. 74FF SHOULD use 400 status code on document validation failure when accepting application/graphql-response+json
  39. 5E5B SHOULD not contain the data entry on document validation failure when accepting application/graphql-response+json

Notices

The server MAY support these, but are truly optional. These are suggestions following recommended conventions.
  1. 423L MAY use 400 status code on missing {query} parameter
    Response status code is not 400
    {
      "statusText": "Unprocessable Entity",
      "status": 422,
      "headers": {
        "date": "",
        "content-type": "application/json; charset=utf-8",
        "content-length": "51"
      },
      "body": {
        "errors": [
          {
            "message": "the request has no query"
          }
        ]
      }
    }
    
  2. LKJ0 MAY use 400 status code on object {query} parameter
    Response status code is not 400
    {
      "statusText": "Unprocessable Entity",
      "status": 422,
      "headers": {
        "date": "",
        "content-type": "application/json; charset=utf-8",
        "content-length": "49"
      },
      "body": {
        "errors": [
          {
            "message": "query must be a string"
          }
        ]
      }
    }
    
  3. LKJ1 MAY use 400 status code on number {query} parameter
    Response status code is not 400
    {
      "statusText": "Unprocessable Entity",
      "status": 422,
      "headers": {
        "date": "",
        "content-type": "application/json; charset=utf-8",
        "content-length": "49"
      },
      "body": {
        "errors": [
          {
            "message": "query must be a string"
          }
        ]
      }
    }
    
  4. LKJ2 MAY use 400 status code on boolean {query} parameter
    Response status code is not 400
    {
      "statusText": "Unprocessable Entity",
      "status": 422,
      "headers": {
        "date": "",
        "content-type": "application/json; charset=utf-8",
        "content-length": "49"
      },
      "body": {
        "errors": [
          {
            "message": "query must be a string"
          }
        ]
      }
    }
    
  5. LKJ3 MAY use 400 status code on array {query} parameter
    Response status code is not 400
    {
      "statusText": "Unprocessable Entity",
      "status": 422,
      "headers": {
        "date": "",
        "content-type": "application/json; charset=utf-8",
        "content-length": "49"
      },
      "body": {
        "errors": [
          {
            "message": "query must be a string"
          }
        ]
      }
    }
    
  6. 6C00 MAY use 400 status code on object {operationName} parameter
    Response status code is not 400
    {
      "statusText": "Unprocessable Entity",
      "status": 422,
      "headers": {
        "date": "",
        "content-type": "application/json; charset=utf-8",
        "content-length": "57"
      },
      "body": {
        "errors": [
          {
            "message": "operationName must be a string"
          }
        ]
      }
    }
    
  7. 6C01 MAY use 400 status code on number {operationName} parameter
    Response status code is not 400
    {
      "statusText": "Unprocessable Entity",
      "status": 422,
      "headers": {
        "date": "",
        "content-type": "application/json; charset=utf-8",
        "content-length": "57"
      },
      "body": {
        "errors": [
          {
            "message": "operationName must be a string"
          }
        ]
      }
    }
    
  8. 6C02 MAY use 400 status code on boolean {operationName} parameter
    Response status code is not 400
    {
      "statusText": "Unprocessable Entity",
      "status": 422,
      "headers": {
        "date": "",
        "content-type": "application/json; charset=utf-8",
        "content-length": "57"
      },
      "body": {
        "errors": [
          {
            "message": "operationName must be a string"
          }
        ]
      }
    }
    
  9. 6C03 MAY use 400 status code on array {operationName} parameter
    Response status code is not 400
    {
      "statusText": "Unprocessable Entity",
      "status": 422,
      "headers": {
        "date": "",
        "content-type": "application/json; charset=utf-8",
        "content-length": "57"
      },
      "body": {
        "errors": [
          {
            "message": "operationName must be a string"
          }
        ]
      }
    }
    
  10. 4760 MAY use 400 status code on string {variables} parameter
    Response status code is not 400
    {
      "statusText": "Unprocessable Entity",
      "status": 422,
      "headers": {
        "date": "",
        "content-type": "application/json; charset=utf-8",
        "content-length": "50"
      },
      "body": {
        "errors": [
          {
            "message": "variables must be a map"
          }
        ]
      }
    }
    
  11. 4761 MAY use 400 status code on number {variables} parameter
    Response status code is not 400
    {
      "statusText": "Unprocessable Entity",
      "status": 422,
      "headers": {
        "date": "",
        "content-type": "application/json; charset=utf-8",
        "content-length": "50"
      },
      "body": {
        "errors": [
          {
            "message": "variables must be a map"
          }
        ]
      }
    }
    
  12. 4762 MAY use 400 status code on boolean {variables} parameter
    Response status code is not 400
    {
      "statusText": "Unprocessable Entity",
      "status": 422,
      "headers": {
        "date": "",
        "content-type": "application/json; charset=utf-8",
        "content-length": "50"
      },
      "body": {
        "errors": [
          {
            "message": "variables must be a map"
          }
        ]
      }
    }
    
  13. 4763 MAY use 400 status code on array {variables} parameter
    Response status code is not 400
    {
      "statusText": "Unprocessable Entity",
      "status": 422,
      "headers": {
        "date": "",
        "content-type": "application/json; charset=utf-8",
        "content-length": "50"
      },
      "body": {
        "errors": [
          {
            "message": "variables must be a map"
          }
        ]
      }
    }
    
  14. 58B0 MAY use 400 status code on string {extensions} parameter
    Response status code is not 400
    {
      "statusText": "Unprocessable Entity",
      "status": 422,
      "headers": {
        "date": "",
        "content-type": "application/json; charset=utf-8",
        "content-length": "51"
      },
      "body": {
        "errors": [
          {
            "message": "extensions must be a map"
          }
        ]
      }
    }
    
  15. 58B1 MAY use 400 status code on number {extensions} parameter
    Response status code is not 400
    {
      "statusText": "Unprocessable Entity",
      "status": 422,
      "headers": {
        "date": "",
        "content-type": "application/json; charset=utf-8",
        "content-length": "51"
      },
      "body": {
        "errors": [
          {
            "message": "extensions must be a map"
          }
        ]
      }
    }
    
  16. 58B2 MAY use 400 status code on boolean {extensions} parameter
    Response status code is not 400
    {
      "statusText": "Unprocessable Entity",
      "status": 422,
      "headers": {
        "date": "",
        "content-type": "application/json; charset=utf-8",
        "content-length": "51"
      },
      "body": {
        "errors": [
          {
            "message": "extensions must be a map"
          }
        ]
      }
    }
    
  17. 58B3 MAY use 400 status code on array {extensions} parameter
    Response status code is not 400
    {
      "statusText": "Unprocessable Entity",
      "status": 422,
      "headers": {
        "date": "",
        "content-type": "application/json; charset=utf-8",
        "content-length": "51"
      },
      "body": {
        "errors": [
          {
            "message": "extensions must be a map"
          }
        ]
      }
    }
    
  18. 3E3A MAY use 400 status code if parameters are invalid
    Response status code is not 400
    {
      "statusText": "Unprocessable Entity",
      "status": 422,
      "headers": {
        "date": "",
        "content-type": "application/json; charset=utf-8",
        "content-length": "51"
      },
      "body": {
        "errors": [
          {
            "message": "the request has no query"
          }
        ]
      }
    }
    

Warnings

The server SHOULD support these, but is not required.
  1. 572B SHOULD use 200 status code on document parsing failure when accepting application/json
    Response status code is not 200
    {
      "statusText": "Bad Request",
      "status": 400,
      "headers": {
        "date": "",
        "content-type": "application/graphql-response+json; charset=utf-8",
        "content-length": "215"
      },
      "body": {
        "errors": [
          {
            "message": "syntax error: expected at least one Selection in Selection Set",
            "locations": [
              {
                "line": 1,
                "column": 2
              }
            ]
          },
          {
            "message": "syntax error: expected R_CURLY, got EOF",
            "locations": [
              {
                "line": 1,
                "column": 2
              }
            ]
          }
        ]
      }
    }
    
  2. FDE2 SHOULD use 200 status code on document validation failure when accepting application/json
    Response status code is not 200
    {
      "statusText": "Bad Request",
      "status": 400,
      "headers": {
        "date": "",
        "content-type": "application/graphql-response+json; charset=utf-8",
        "content-length": "226"
      },
      "body": {
        "errors": [
          {
            "message": "syntax error: Unexpected character `f` as integer suffix",
            "locations": [
              {
                "line": 1,
                "column": 3
              }
            ]
          },
          {
            "message": "syntax error: Unexpected character `d` as integer suffix",
            "locations": [
              {
                "line": 1,
                "column": 5
              }
            ]
          }
        ]
      }
    }
    
  3. 7B9B SHOULD use a status code of 200 on variable coercion failure when accepting application/json
    Response status code is not 200
    {
      "statusText": "Unprocessable Entity",
      "status": 422,
      "headers": {
        "date": "",
        "content-type": "application/graphql-response+json; charset=utf-8",
        "content-length": "86"
      },
      "body": {
        "errors": [
          {
            "message": "unused variable: `$id`",
            "locations": [
              {
                "line": 1,
                "column": 21
              }
            ]
          }
        ]
      }
    }
    
  4. 86EE SHOULD use a status code of 400 on variable coercion failure when accepting application/graphql-response+json
    Response status code is not 400
    {
      "statusText": "Unprocessable Entity",
      "status": 422,
      "headers": {
        "date": "",
        "content-type": "application/graphql-response+json; charset=utf-8",
        "content-length": "86"
      },
      "body": {
        "errors": [
          {
            "message": "unused variable: `$id`",
            "locations": [
              {
                "line": 1,
                "column": 21
              }
            ]
          }
        ]
      }
    }
    

@XiNiHa
XiNiHa force-pushed the apollo-compiler-2-beta branch from 3ca61a7 to 265fd28 Compare October 19, 2026 06:16
@codspeed

codspeed Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 35 untouched benchmarks


Comparing apollo-compiler-2-beta (0a6e483) with main (2f10392)

Open in CodSpeed

@XiNiHa
XiNiHa force-pushed the apollo-compiler-2-beta branch from 265fd28 to 0a6e483 Compare October 19, 2026 06:30
The pin is exact: a caret on a pre-release would let `cargo update` reach
beta.2, whose `Field::selection_set: Option<SelectionSet>` change breaks
`tree.rs`. Relax it at 2.0.0 stable.

greem's exposure to the 2.0 API is `response_key()` → `response_name()`
and two `Component`-era field reads that are now plain `Node` derefs. The
oneof area schema stops declaring `@oneOf`: apollo-compiler supplies it,
and a user SDL that still declares it shadows the built-in, so no
strip-if-present rule is needed. No fixture tripped the stricter 2.0
validation; the ported oneOf rejections now fail only on apollo's wording,
which #42 adopts when it unignores them.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@XiNiHa
XiNiHa merged commit 0a6e483 into main Oct 19, 2026
9 checks passed
@XiNiHa
XiNiHa deleted the apollo-compiler-2-beta branch October 19, 2026 06:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant