Grats Documentation

website·Indexed 33 days ago

https://grats.capt.dev/

A command-line utility for extracting GraphQL schemas from TypeScript projects using docblock tags. Grats supports class-based and functional style fields, custom scalars, interfaces, and strict semantic nullability, integrating with libraries such as graphql-js, graphql-yoga, and express.

Tokens
20.5K
Snippets
121
Records
176
Agent score
66%

What's inside Grats

  1. Overview of Grats GraphQL schema generation

    Grats is a build-step tool that statically analyzes TypeScript code to extract an executable GraphQL schema. Instead of manually defining a schema, Grats uses existing TypeScript type annotations and specific docblock tags (e.g., /** @gqlField */) to make the TypeScript implementation the source of truth. This ensures the implementation always matches the schema. The process generates both a TypeScript module defining the executable schema and a .graphql schema file for clients and tools.
  2. Grats Design Principles for Schema Generation

    Grats is designed to generate GraphQL schemas with a focus on the following principles:

    • Integration: Users can build GraphQL schemas by adding docblock tags to existing code without changing their coding style, similar to how TypeScript models JavaScript idioms.
    • Progressive Disclosure: The API is kept small and intuitive. Error messages are treated as part of the documentation, providing specific guidance on why a failure occurred and how to fix it only when the user encounters a complex case.
    • GraphQL Standard Alignment: Grats avoids introducing new concepts to the GraphQL ecosystem. Docblock tags are designed to correspond directly to constructs defined in the GraphQL specification.
    • Dependency Strategy: Grats leverages a small number of core dependencies (such as graphql-js for schema construction and TypeScript's own AST/type inference logic) and exposes these same types in its public APIs to avoid redundancy.
  3. Understand Grats resolver argument mapping

    Grats uses graphql-js as its execution engine but allows developers to define resolvers with flexible signatures. Instead of requiring the strict graphql-js four-argument order, Grats infers which value to provide based on the type annotations of the resolver's arguments. This allows developers to omit or reorder arguments as needed.
  4. How Grats infers GraphQL types via static analysis

    Grats implements an implementation-first GraphQL server by using static analysis to infer GraphQL types from TypeScript at build time. It specifically leverages doc-blocks (JSDoc) because they provide a machine-readable, structured format that can be parsed by the TypeScript compiler's JSDoc parsing, while signaling that the annotations do not impact the runtime behavior of the code.
  5. Understand Strict Semantic Nullability in Grats

    Strict Semantic Nullability is an experimental feature in Grats that distinguishes between "true" null values and values that are null due to an error state. In standard GraphQL, these are conflated. By marking a field as semantically non-null, clients can treat the field as non-nullable if they handle field errors out-of-band (e.g., by discarding queries with errors), reducing the need for tedious null checks in client code.

    Grats implements this using the @semanticNonNull directive rather than new schema syntax to maintain compatibility with existing GraphQL tools. A field is marked with @semanticNonNull if strictSemanticNullability is enabled and the underlying TypeScript return type is non-nullable.

  6. Experimental Grats configuration options

    The following experimental options may be renamed or removed in future releases:

    • EXPERIMENTAL__emitMetadata: When true, emits a JSON file containing metadata about the resolvers alongside the schema file. Default: false.
    • EXPERIMENTAL__emitResolverMap: When true, emits a GraphQL Tools style Resolver Map instead of a file that creates a GraphQLSchema. Default: false.
  7. Understand Grats runtime behavior

    Grats has zero footprint at runtime. It does not provide a runtime library; instead, it generates a TypeScript module that returns a GraphQLSchema object. Because the schema is pre-constructed in TypeScript, there is no need to parse GraphQL SDL at runtime, which optimizes performance for edge and browser environments.
  8. Derive a GraphQL schema from TypeScript types using Grats

    Grats allows developers to generate a GraphQL schema directly from existing TypeScript types. By using JSDoc tags like @gqlType for classes and @gqlField for properties or methods, Grats extracts an executable graphql-js schema at build time. This approach ensures that the implementation and the schema are always in sync, removing the need for manual validation and eliminating Grats-specific code from the runtime environment.
    /**
     * A user in our kick-ass system!
     * @gqlType 
     */
    class User {
      /** @gqlField */
      name: string;
    
      /** @gqlField */
      greet(greeting: string): string {
        return `${greeting}, ${this.name}`;
      }
    }
  9. Understand the Grats build-time extraction process

    Grats infers a GraphQL schema by statically analyzing TypeScript code. The process follows these steps:

    1. Configuration: Grats reads the TypeScript config to identify all project files and compiler options.
    2. Tag Detection: It uses Regex to find files containing @gql* tags.
    3. AST Analysis: For each tag mapping to a top-level GraphQL construct (e.g., type, interface), Grats retrieves the corresponding TypeScript AST node.
    4. Inference: Grats applies inference strategies to the AST node to determine the GraphQL construct. If inference fails, a diagnostic error is reported.
    5. GraphQL AST Construction: Grats builds a GraphQL AST compatible with graphql-js. It maps the location information (file path, line, and column) from the TypeScript AST to the GraphQL AST, allowing graphql-js validation errors to point directly to the TypeScript source code.
  10. Implement generic types in Grats for GraphQL schemas

    Grats allows the use of TypeScript generic types to define reusable types, interfaces, unions, and input types. Since GraphQL does not natively support user-defined generics, Grats materializes a concrete representation of the generic type in the generated schema whenever a parameter is provided.
  11. Deprecate fields in GraphQL input types

    Individual optional fields within a @gqlInput type can be marked as deprecated in the resulting GraphQL schema by using the standard JSDoc @deprecated tag. The text following the tag is used as the deprecation reason.
    import { Int } from "grats";
    
    /** @gqlInput */
    type MyInput = {
      name: string;
      /** @deprecated Don't ask for age any more */
      age?: Int;
    };
  12. Deprecate a GraphQL field without deprecating the internal TypeScript property

    Because TypeScript treats the @deprecated JSDoc tag by striking through the code in the editor, using it on a class property will mark it as deprecated both in the GraphQL schema and internally in your code. To deprecate a field in the GraphQL schema while keeping it active for internal use, define a separate wrapper method for GraphQL using @gqlField and apply the @deprecated tag to that method instead of the property.
    /** @gqlType */
    class User {
      // Not deprecated internally!
      name: string;
    
      /**
       * @gqlField name
       * @deprecated Not supported externally any more
       */
      graphQLName(): string {
        return this.name;
      }
    }