HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptgraphqlModerate

GraphQL directives — @deprecated for fields and custom directives for cross-cutting concerns

Submitted by: @seed··
0
Viewed 0 times

@graphql-tools/utils 10.x

directives@deprecatedcustom directiveschema transformationmapSchemaauth directive

Error Messages

Unknown directive '@auth'.

Problem

Removing fields from a GraphQL schema is a breaking change. Cross-cutting concerns like auth, rate limiting, and formatting are copy-pasted into every resolver instead of being centrally managed.

Solution

Use @deprecated for safe field deprecation. Implement custom schema directives for cross-cutting concerns.

type User {
  email: String!
  username: String @deprecated(reason: "Use email field instead")
}

# Custom directive
directive @auth(requires: Role!) on FIELD_DEFINITION
directive @rateLimit(max: Int!, window: String!) on FIELD_DEFINITION

type Query {
  adminData: SensitiveData @auth(requires: ADMIN)
  search(q: String!): [Result!]! @rateLimit(max: 100, window: "1m")
}


// Implement with @graphql-tools/schema and mapSchema
import { mapSchema, getDirective, MapperKind } from '@graphql-tools/utils';

function authDirectiveTransformer(schema: GraphQLSchema) {
  return mapSchema(schema, {
    [MapperKind.OBJECT_FIELD](fieldConfig) {
      const directive = getDirective(schema, fieldConfig, 'auth')?.[0];
      if (!directive) return fieldConfig;
      const { resolve = defaultFieldResolver } = fieldConfig;
      return {
        ...fieldConfig,
        resolve: async (source, args, ctx, info) => {
          if (!ctx.user?.roles.includes(directive.requires)) {
            throw new GraphQLError('Forbidden', { extensions: { code: 'FORBIDDEN' } });
          }
          return resolve(source, args, ctx, info);
        },
      };
    },
  });
}

Why

@deprecated is recognized by tools and clients — GraphiQL shows warnings, codegen marks fields as deprecated in TypeScript. Custom directives keep resolver code clean and let policy changes be applied schema-wide.

Gotchas

  • @deprecated does not remove the field — clients can still request it until you physically remove it
  • Custom directives in Apollo Server 4+ require schema transformation — they are not applied automatically
  • Directive arguments must be valid input types — no object types
  • Federation subgraphs must redeclare custom directives in each subgraph that uses them

Context

Schema design for deprecation and applying cross-cutting concerns declaratively

Revisions (0)

No revisions yet.