WunderGraph allows you to extend the GraphQL Schema of an origin and replace specific fields with a custom type. This is useful when you're integrating with a GraphQL API that uses custom scalars. Instead of using a generic
JSON scalar, you can replace it with a dedicated, intuitive, and more meaningful type definition to improve type-safety and create a superior developer experience.
Custom Schema Extensions are supported for GraphQL, REST (OAS), and database-generated APIs. WunderGraph also allows you to directly integrate with databases like PostgreSQL, MySQL, or MongoDB—all of which support
JSON data types.
But that's not all. With a generic
JSON scalar, users can use any legal JSON value as an input without any guarantee on its contents. With Custom Schema Extensions, you'll automatically receive JSON Schema validation for the input while being able to store the same value in a JSON/JSONB column.
Enabling Schema Extensions
If you are replacing a JSON scalar, you do not need to include it in the
customJSONScalars array. However, if it is not being replaced, the scalar type will be inferred as a TypeScript
string unless it is added to the
There are two mandatory steps to enabling Schema Extensions. First, you must provide the
schemaExtension itself in your
wundergraph.config.ts file. Add the
schemaExtension property to the introspection configuration for a data source. Inside this property, provide the GraphQL schema that will extend your original schema. In particular, it should contain the definition of all the custom types that you'll use to replace custom scalars in the original schema.
schemaExtension is a string representation of the GraphQL schema defining the new custom types that will be added to the original GraphQL schema.
Next, add the
replaceCustomScalarTypeFields property. Inside this property, you will need to add a separate definition object for each and every replacement.
replaceCustomScalarTypeFields is an object array that defines where and what replacements should happen. Each object defines the name of the field whose custom scalar type will be replaced, the name of the "parent" (type) to which the field belongs, and the name of a replacement custom type that was defined in the
The three properties that comprise the object are further defined below:
From wundergraph/sdk version 0.162.0,
inputTypeReplacement has been deprecated and will be ignored. Moreover,
fieldName are exact matching (and case-sensitive). Please create a separate replacement definition object for each and every field you wish to replace (including GraphQL Inputs).
entityName is the exact, case-sensitive name of the GraphQL type (Object or Input). For database-generated APIs, it may represent a database table.
fieldName is the exact, case-sensitive name of the field whose type should be replaced.
responseTypeReplacement is the exact, case-sensitive name of the type that should be used as the response or input. This type must be defined in
An important note on interfaces
If the field whose type you wish to replace exists on an interface that the parent implements, the interface field response type will also be replaced. Consequently, when replacing a field that exists on an interface, replacement definitions for all Object types that implement that interface must be added to the
replaceCustomScalarTypeFields object array.
Let's take a look at some examples.
GraphQL data source with custom scalar
geography is a custom scalar, so the client has to know how to handle it.
Now the query operation looks like this:
GraphQL data source with custom scalars and interfaces
teamData are each fields that are defined on an implemented interface. Their respective types,
TrainerJSON, are custom scalars. For interface implementation to remain valid, the interface types must also be replaced.
If an object implements one or more interfaces, and you are replacing a field's response type that exists on one of those interfaces, you must add replacement definitions for all other Objects types that implement those interfaces.
Now the query operation might look like this:
And a snippet of the new schema:
Database with JSON/JSONB columns
Let's say we have a table
users with a JSONB column
And the record looks like this:
To be able to query the
contact column, we can use the following configuration:
The query operation will look like this:
Without the Custom Schema Extension, you wouldn't be able to select the
As we're generating an input type as well (
db_ContactInput), users cannot use any arbitrary JSON data as input but need to specify the
REST API with arbitrary JSON type
This example explains how to use the Custom Schema Extension to add a custom type to an existing REST API.
In a similar way to the previous examples, we can use the introspection configuration to replace the
contact field with a custom type: