JSON Schema or Samples
This handler allows you to load any remote REST service and describe its request/response using the YAML config.
You can easily customize and control the built GraphQL schema with this handler.
How to use?
To get started, install the handler library:
npm i @omnigraph/json-schema
Now, you can use it directly in your Mesh config file:
import { defineConfig } from '@graphql-mesh/compose-cli'
import { loadJSONSchemaSubgraph } from '@omnigraph/json-schema'
export const composeConfig = defineConfig({
subgraphs: [
{
sourceHandler: loadJSONSchemaSubgraph('MyApi', {
endpoint: 'https://some-service-url/endpoint-path/',
operations: [
{
type: 'Query',
field: 'users',
path: '/users',
method: 'GET',
responseSchema: './json-schemas/users.json'
}
]
})
}
]
})
Headers
Read about configuration and examples
From Arguments
Mesh automatically generates arguments for operations if needed;
import { defineConfig } from '@graphql-mesh/compose-cli'
import { loadJSONSchemaSubgraph } from '@omnigraph/json-schema'
export const composeConfig = defineConfig({
subgraphs: [
{
sourceHandler: loadJSONSchemaSubgraph('MyApi', {
endpoint: 'https://some-service-url/endpoint-path/',
operations: [
{
type: 'Query',
field: 'user',
path: '/user/{args.id}',
method: 'GET',
responseSchema: './json-schemas/user.json'
}
]
})
}
]
})
This example operation definition will generate a root field with id: ID
argument. Mesh will
interpolate the expression in path
to get id
value from args
.
From JSON Samples
Mesh can also load JSON samples from a remote service. Add a json-samples
directory in your
project root, and put the JSON samples there
(responseSample: './jsons/MyField.response.json'
- Create a new folder like jsons
). By
declaring the responseSample
, you can use the JSON sample in the GraphQL schema.
import { defineConfig } from '@graphql-mesh/compose-cli'
import { loadJSONSchemaSubgraph } from '@omnigraph/json-schema'
export const composeConfig = defineConfig({
subgraphs: [
{
sourceHandler: loadJSONSchemaSubgraph('MyApi', {
endpoint: 'https://some-service-url/endpoint-path/',
operations: [
{
type: 'Query',
field: 'myField',
path: '/myField?id={args.id}',
method: 'GET',
responseSample: './jsons/MyField.response.json',
responseTypeName: 'MyResponseName',
argTypeMap: {
id: {
type: 'string'
}
}
}
]
})
}
]
})
Any JSON sample file can be used.
Query Parameters
There are a few methods to define the query parameters, select the one that fits your needs (Or combine them):
Auto declare:
Mesh automatically generates arguments for operations if needed. Note that the arguments are generated as nullable strings by default.
import { defineConfig } from '@graphql-mesh/compose-cli'
import { loadJSONSchemaSubgraph } from '@omnigraph/json-schema'
export const composeConfig = defineConfig({
subgraphs: [
{
sourceHandler: loadJSONSchemaSubgraph('MyApi', {
endpoint: 'https://some-service-url/endpoint-path/',
operations: [
{
type: 'Query',
field: 'user',
path: '/user?id={args.id}',
method: 'GET',
responseSchema: './json-schemas/user.json'
}
]
})
}
]
})
With Samples
You can use the JSON samples to define the query parameters.
In this example we declare limit
and offset
properties:
import { defineConfig } from '@graphql-mesh/compose-cli'
import { loadJSONSchemaSubgraph } from '@omnigraph/json-schema'
export const composeConfig = defineConfig({
subgraphs: [
{
sourceHandler: loadJSONSchemaSubgraph('MyApi', {
endpoint: 'https://some-service-url/endpoint-path/',
operations: [
{
type: 'Query',
field: 'getUsers',
path: '/users',
method: 'GET',
queryParamsSample: './jsons/users.queryParams.json',
responseSchema: './jsons/users.response.json'
}
]
})
}
]
})
In ./jsons/users.queryParams.json
:
{
"limit": 10,
"offset": 0
}
Manual Declare
You can define the arguments of the operation using the argTypeMap
config field, according to the
JSON Schema spec.
type: number
will set the property to Float
and type: integer
will set it as Int.
In this example we declare page
argument as an object with limit
and offset
properties:
argTypeMap: {
page: {
type: 'object',
properties: {
limit: {
type: 'integer'
},
offset: {
type: 'integer'
}
}
}
}
Array can be defined as type: array
with items:
and their own type:
argTypeMap: {
page: {
type: 'array',
items: {
limit: {
type: 'integer'
},
offset: {
type: 'integer'
}
}
}
}
If you need to use symbols that will cause GraphQL to error like ’:’ or ’[’ in the query param name,
you can map an alternative definition. With the below example using name_like
in the query will
end up being name:like
as the API call.
argTypeMap: {
name_like: {
type: 'string'
}
queryParamArgMap: {
'name:like': 'name_like'
}
}
In addition, especially for non-primitive types, the arguments should be added to the path using the
queryParamArgMap
config field.
Here we add the page
argument to the query parameters:
queryParamArgMap: {
page: 'page'
}
And here is the final config:
import { defineConfig } from '@graphql-mesh/compose-cli'
import { loadJSONSchemaSubgraph } from '@omnigraph/json-schema'
export const composeConfig = defineConfig({
subgraphs: [
{
sourceHandler: loadJSONSchemaSubgraph('MyApi', {
endpoint: 'https://some-service-url/endpoint-path/',
operations: [
{
type: 'Query',
field: 'getUsers',
path: '/users',
method: 'GET',
responseSample: './jsons/users.response.json',
responseTypeName: 'MyResponseName',
argTypeMap: {
page: {
type: 'object',
properties: {
limit: {
type: 'integer'
},
offset: {
type: 'integer'
}
}
}
},
queryParamArgMap: {
page: 'page'
}
}
]
})
}
]
})
Global Arguments
Query arguments could be defined globally, on handler level, so they are added to all operations.
In this example we declare limit
parameter with the default value of 10
, and api_key
with
dynamic value taken from the environment:
import { defineConfig } from '@graphql-mesh/compose-cli'
import { loadJSONSchemaSubgraph } from '@omnigraph/json-schema'
export const composeConfig = defineConfig({
subgraphs: [
{
sourceHandler: loadJSONSchemaSubgraph('MyApi', {
endpoint: 'https://some-service-url/endpoint-path/',
operations: [
// Operations here
],
queryParams: {
limit: 10,
api_key: '{env.MY_API_KEY}'
}
})
}
]
})
Note that queryParams
are automatically added to the query. If argument is defined both on
handler AND operation level, the operation level argument will be used.