graphql-hive / graphql-hive/console

advanced breaking change detection for input types

Open
#7,176 3 comments 0 reactions 0 assignees View on GitHub
idea improvement needs-customer
Dominant language
TypeScript
Stars
483
Forks
145
Avg merge
2d 5h
Merged PRs (30d)
65

Description

## The problem

Tracking whether removing fields used by input types is tricky.

Today, treating all fields reachable from within an input type as being "in use" is the safest bet. However, this does not make it easy to systematically deprecated and remove these fields.

Today, as an additional feature, we allow a usage reporting for analysing the input variables and reporting input usage based on this. Also this approach is not 100% safe, as e.g. a nullable field not being used today could be a coincidence as it is a value that is rarely provided by a client.

Thus these options cannot guarantee hazzle-free (conditional) breaking changes.

____

## Idea for an alternative way to track input usage

What if the clients define what input types they use for their GraphQL operation? This could be an annotation on the GraphQL operation variables definition and tools like GraphQL Code Generator or Relay could compliment the DX by only generating variable types based on that constraint definition.

**Example GraphQL Schema:**

```graphql
enum ProjectType {
FEDERATION
MONOLITH
STITCHING
}

type ProjectSettingsInput {
compositionUrl: String
someOtherSetting: String
}

input CreateProjectInput {
type: ProjectType!
slug: String!
settings: ProjectSettingsInput
}

type Mutation {
createProject(input: CreateProjectInput!): Boolean
}
```

**Example GraphQL Operation**:

```graphql
mutation CreateProject(
$input: CreateProjectInput!
@constraints(selectionSet:
"""
{
type @constraints(enumValues: [ProjectType.Federation, ProjectType.STITCHING])
slug
settings {
compositionUrl
}
}
"""
)
) {
createProject(input: $input)
}
```

The `@constraints` directive would be used on input types for defining the contract of the input type for this operation type. The argument `@constraints(selectionSet:)`, would be a multi-line string that specifies the (deep) selection set being used within the input type.

In addition to that `@constraints(enumValues:)` can also be used to restrict enum input values.

Based on the above operation, the GraphQL API could remove `ProjectType.MONOLITH` and `ProjectSettingsInput.someOtherSetting`, without the client being affected.

### Input constraint usage implications:

- The GraphQL would raise an error if the above operation is executed with either `ProjectType.MONOLITH` or `ProjectSettingsInput.someOtherSetting` within the variable values, based on the defined contract.
- GraphQL Code Generator would generate the variable definitions for the mutation with the contraints in mind:

```ts
type CreateProjectVariables = {
type: "FEDERATION" | "STITCHING";
slug: string;
settings: { compositionUrl: string } | null
}
```
- The Hive Router/SDK reporting could report the usage to the registry based on the specified constraint.
- The registry can provide conditional breaking changes based on the constrained usage reporting/ app deployemt operation sets

### How would the deprecation/removal process for a field look like

Based on the above operation and schema, let's say we want to remove `ProjectSettingsInput.settings`. As usual we would first mark it as `deprecated`. As soon as the field is marked as deprecated, client consumers using that field would be informed (based on alert configuration etc.). They can then update their operation input contract to remove that field usage.

```diff
mutation CreateProject(
$input: CreateProjectInput!
@constraints(selectionSet:
"""
{
type @constraints(enumValues: [ProjectType.Federation, ProjectType.STITCHING])
slug
- settings {
- compositionUrl
- }
}
"""
)
) {
createProject(input: $input)
}
```

Once the client usage is in production and the contract definition is reflected in the usage of the schema, the field `ProjectSettingsInput.settings` is then safe to be removed.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.