Skip to content

Instantly share code, notes, and snippets.

@captbaritone
Created February 9, 2025 22:24
Show Gist options
  • Save captbaritone/83bed8a3365bd15dbc276d2a83d71d8c to your computer and use it in GitHub Desktop.
Save captbaritone/83bed8a3365bd15dbc276d2a83d71d8c to your computer and use it in GitHub Desktop.

You can annotate parts of your Grats GraphQL schema with directives (link to define directives) using the @gqlAnnotate docblock tag.

/**
 * @gqlQueryField
 * @gqlAnnotate myDirective
 */
export function greet(): string {
  return "Hello";
}

Directive annotations can also accept arguments:

/**
 * @gqlQueryField
 * @gqlAnnotate myDirective(someArg: "Some String")
 */
export function greet(): string {
  return "Hello";
}

Note: The GraphQL directive @deprecated is unique in that it it is a built-in GraphQL directive and has a built-in TypeScript equivalent in the form of the @deprecated docblock tag. Because of this, @deprecated docblock tags are treated as directives without the need for @gqlAnnotate.

Directive Validation

While the GraphQL Spec does not actually specify that arguments passed to directives used in the schema should be validated against the types specified in that directive’s declaration, Grats adds its own validation to ensure that arguments used in @gqlAnnotate are typechecked against their directive declaration.

Using Schema Directive Annotations

Directive annotations added to your schema will be included in Grats’ generated .graphql file. For directives meant to be consumed by clients or other infrastructure, this should be sufficient.

For directives which are intended to be used at runtime, they must be included in the graphql-js class GraphQLSchema which Grats generates. Unfortunately GraphQLSchema does not support a first-class mechanism for including directive annotations. To work around this, Grats includes directives under as part of the relevant class’ extensions object namespaced under a grats key.

The grats key will contain a property directives which is an object where each key is a directive name, and the value is an object containing the directive’s arguments. If no arguments are specified, the object will be empty.

TODO: Full Example

Annotating with Directives

extensions: {
    grats: {
      directives: { max: { count: 10 } }
    }
}

If a directive is defined with @gqlRepeatable the value of the directive’s key will be an array of objects:

extensions: {
    grats: {
      directives: { tag: [{ name: "internal" }, {name: "analytics"}] }
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment