Skip to Content
Schema Stitching
DocsTransformsCustom Transforms

Custom Transforms

Custom transforms are fairly straightforward to write. They are simply objects with up to three methods:

  • transformSchema: receives the original subschema and applies modifications to it, returning a modified wrapper (proxy) schema. This method runs once while initially wrapping the subschema.
  • transformRequest: receives each request made to the wrapped schema. The shape of a request matches the wrapper schema and must be returned in a shape that matches the original subschema.
  • transformResult: receives each result returned from the original subschema. The shape of the result matches the original subschema and must be returned in a shape that matches the wrapper schema.

The complete transform object API is as follows:

export interface Transform<T = Record<string, any>> { transformSchema?: SchemaTransform transformRequest?: RequestTransform<T> transformResult?: ResultTransform<T> } export type SchemaTransform = ( originalWrappingSchema: GraphQLSchema, subschemaConfig: SubschemaConfig, transformedSchema?: GraphQLSchema ) => GraphQLSchema export type RequestTransform<T = Record<string, any>> = ( originalRequest: Request, delegationContext: DelegationContext, transformationContext: T ) => Request export type ResultTransform<T = Record<string, any>> = ( originalResult: ExecutionResult, delegationContext: DelegationContext, transformationContext: T ) => ExecutionResult type Request = { document: DocumentNode variables: Record<string, any> extensions?: Record<string, any> }

A simple transform that removes types, fields, and arguments prefixed by an underscore might look like this:

import { stitchSchemas } from '@graphql-tools/stitch' import { filterSchema, pruneSchema } from '@graphql-tools/utils' class RemovePrivateElementsTransform { transformSchema(originalWrappingSchema) { const isPublicName = name => !name.startsWith('_') return pruneSchema( filterSchema({ schema: originalWrappingSchema, typeFilter: typeName => isPublicName(typeName), rootFieldFilter: (operationName, fieldName) => isPublicName(fieldName), fieldFilter: (typeName, fieldName) => isPublicName(fieldName), argumentFilter: (typeName, fieldName, argName) => isPublicName(argName) }) ) } // no need for operational transforms } const subschema = { schema: myRemoteSchema, transforms: [new RemovePrivateElementsTransform()] } const gatewaySchema = stitchSchemas({ subschemas: [subschema] })
Last updated on