Announcing three open source Rust crates for the GraphQL ecosystem

Tom HouléTom Houlé

Announcing open source Rust crates for validating, diffing and composing GraphQL schemas

One of the major strengths of GraphQL is a single, well defined standard, with a schema language, validation rules, and adjacent specs. Libraries can effectively implement the common interfaces, standard-defined behavior, and compose within the GraphQL ecosystem in any language.

To expand GraphQL support in Rust, we are introducing three open-source crates today:

The graphql-schema-validation crate provides a much-needed tool for the Rust ecosystem - a way to validate GraphQL schemas against the latest version of the specification (October 2021). It ensures that schemas conform to the rules of validation as defined in the spec, a fundamental requirement for consistent and interoperable GraphQL implementations.

Key Features:

  • Spec Compliance Validation: Validates GraphQL schemas against the October 2021 GraphQL specification.
  • Detailed Error Reporting: Offers comprehensive error reporting for discrepancies found during validation.

Example:

let graphql = "schema { query: MyQueryDoesNotExist }";

let diagnostics = graphql_schema_validation::validate(graphql);

assert!(diagnostics.has_errors());

let formatted_diagnostics = diagnostics.iter().map(|err| format!("{}", err)).collect::<Vec<String>>();
assert_eq!(formatted_diagnostics, ["Cannot set schema query root to unknown type `MyQueryDoesNotExist`"]);

The graphql-schema-diff crate serves a different purpose: it facilitates the comparison of two GraphQL schemas to identify changes. This crate is particularly useful for understanding schema evolution over time, helping developers track and document modifications. It does not perform backward compatibility analysis but provides a clear view of schema alterations.

Key Features:

  • Schema Comparison: Identifies differences between two versions of a GraphQL schema.
  • Change Documentation: Aids in documenting changes for better version control.

Example:

use graphql_schema_diff::{diff, Change, ChangeKind};

fn main() {
  let source = r#"
    type Pizza {
      id: ID!
      name: String!
      toppings: [Topping!]!
    }

    enum Topping {
      OLIVES
      MUSHROOMS
      PINEAPPLE
    }
  "#;

  let target = r#"
    type Pizza {
      id: ID!
      name: PizzaName
      toppings: [Topping!]!
    }

    type PizzaName {
      english: String
      italian: String!
    }

    enum Topping {
      OLIVES
      MUSHROOMS
      POTATO
    }
  "#;

  let changes = diff(source, target).unwrap();

  assert_eq!(changes,
     &[
          Change {
              path: String::from("Pizza.name"),
              kind: ChangeKind::ChangeFieldType
          },
          Change {
              path: String::from("PizzaName"),
              kind: ChangeKind::AddObjectType
          },
          Change {
              path: String::from("PizzaName.english"),
              kind: ChangeKind::AddField
          },
          Change {
              path: String::from("PizzaName.italian"),
              kind: ChangeKind::AddField
          },
          Change {
              path: String::from("Topping.PINEAPPLE"),
              kind: ChangeKind::RemoveEnumValue
          },
          Change {
              path: String::from("Topping.POTATO"),
              kind: ChangeKind::AddEnumValue
          }
  ]);
}

Our third crate, graphql-composition, addresses the need for schema composition, in other words the creation of federated graphs. It enables the combination of multiple GraphQL schemas, referred to as subgraphs, into a unified schema. This is becoming a widely adopted solution to build scalable and modular GraphQL APIs, especially in microservices environments.

Key Features:

  • Subgraph Composition: Combines multiple GraphQL schemas into a single, unified schema.
  • Less friction in federation through better error messages: we aim to balance familiarity of errors (consistency with the existing ecosystem) with pushing the envelope in giving users more context, better, more explanatory diagnostics.
  • Two output formats: structured output or GraphQL SDL with join spec directives.

Example:

The example would be a bit long for this blog post, so have a look at the one in the README.

Released under the Apache v2 license, these crates embody our commitment to open-source development. They are built strictly according to GraphQL specifications and standards, ensuring broad applicability across various GraphQL implementations.

Stay tuned for more from us in that direction.

Many of the new features we have released recently rely on these three crates. The graphql-schema-diff crate for example is integral to our project API changelog and the upcoming operation checks. By sharing these tools with the community, we aim to encourage collaboration and continuous improvement. The crates are all relatively young, and while we'll aim for 1.0 releases as soon as we are comfortable with the design and APIs, they are far from set in stone yet.

We welcome contributions from the community. Whether it's through feedback, feature suggestions, or direct code contributions, your usage and involvement is appreciated.

For example, if you would like to see Wasm builds of these libraries on npm, this is possible and something we'd love to discuss.

Come talk to us on Discord or in GitHub issues.

Get Started

Start building your backend of the future now.