Query JSON API compliant services with GraphQL
npm install apollo-link-json-apiAn Apollo Link to easily use GraphQL with a JSON API
compliant server.
Built on top ofapollo-link-rest. If you
have a non-JSON API REST service, check that out as an alternative.
``bash
npm install apollo-link-json-api apollo-link graphql graphql-anywhere qs humps --save
yarn add apollo-link-json-api apollo-link graphql graphql-anywhere qs humps
`
apollo-link, graphql, qs, humps, and graphql-anywhere are peer dependencies needed by apollo-link-json-api.
`js
import { JsonApiLink } from "apollo-link-json-api";
// Other necessary imports...
// Create a JsonApiLink for the JSON API
// If you are using multiple link types, jsonApiLink should go before httpLink,
// as httpLink will swallow any calls that should be routed through jsonApi!
const jsonApiLink = new JsonApiLink({
uri: 'http://jsonapiplayground.reyesoft.com/v2/',
});
// Configure the ApolloClient with the default cache and JsonApiLink
const client = new ApolloClient({
link: jsonApiLink,
cache: new InMemoryCache(),
});
// A simple query to retrieve data about the first author
const query = gql
query firstAuthor {
author @jsonapi(path: "authors/1") {
name
}
};
// Invoke the query and log the person's name
client.query({ query }).then(response => {
console.log(response.data.name);
});
`
JSON API Link supports unpacking related resources
into a friendlier GraphQL query structure.
`js
const query = gql
query firstAuthor {
author @jsonapi(path: "authors/1?include=series,series.books") {
name
series {
title
books {
title
}
}
}
};
`
While JSON API Link does support running multiple nested queries, prefer
sideloading resources in a single request by using the ?include parameter if
your JSON API server supports it.
`js
// Avoid this
const badQuery = gql
query firstAuthor {
author @jsonapi(path: "authors/1") {
name
series @jsonapi(path: "authors/1/series") {
title
}
}
};
// Prefer this
const query = gql
query firstAuthor {
author @jsonapi(path: "authors/1?include=series") {
name
series {
title
}
}
};`
`js
import React from 'react'
import gql from 'graphql-tag'
import { Mutation } from 'react-apollo'
export const UPDATE_BOOK_TITLE = gql
mutation UpdateBookTitle($input: UpdateBookTitleInput!) {
book(input: $input) @jsonapi(path: "/books/{args.input.data.id}", method: "PATCH") {
title
}
}
const UpdateBookTitleButton = ({ bookId }) => (
update={(store, { data: { book } }) => {
// Update your Apollo cache with result
console.log(book.title)
}}
>
{mutate => (
)}
)
`
JSON API Link takes an object with some options on it to customize the behavior of the link. The options you can pass are outlined below:
- uri: the URI key is a string endpoint (optional when endpoints provides a default)endpoints
- : root endpoint (uri) to apply paths to or a map of endpointscustomFetch
- : a custom fetch to handle API callsheaders
- : an object representing values to be sent as headers on the requestcredentials
- : a string representing the credentials policy you want for the fetch callfieldNameNormalizer
- : function that takes the response field name and converts it into a GraphQL compliant namefieldNameDenormalizer
- : function that takes the JavaScript object key name and converts it into a JSON API compliant nametypeNameNormalizer
- : function that takes the JSON API resource type and__typename
converts it to a GraphQL .
JSON API Link uses the headers field on the context to allow passing headers to the HTTP request. It also supports the credentials field for defining credentials policy.
- headers: an object representing values to be sent as headers on the requestcredentials
- : a string representing the credentials policy you want for the fetch call
By default, this library flattens your server response. If you need to access
values that are unavailable by this simple querying method, you can add
includeJsonapi: true to your @jsonapi directive, which will instead returngraphql
the flattened "GraphQL-like" structure under a key, and the originaljsonapi
response structure under a key. Resources are still nested in a treejsonapi
structure under the key, but data/attribute/relatioship keys are
not flattened out.
`gql
query authorsWithMeta {
authors @jsonapi(path: "authors?include=series", includeJsonapi: true) {
graphql {
name
series {
title
}
}
jsonapi {
meta {
pageCount
}
links {
first
last
current
}
// The resource data is available here, though it's probably easier to
// grab from the graphql structure`
data {
attributes {
name
}
relationships {
series {
data {
attributes {
title
}
}
links {
related
}
}
}
}
}
}
}
This project uses TypeScript to bring static types to JavaScript and uses Jest for testing. To get started, clone the repo and run the following commands:
`bashyarn
npm install # or
npm test # or yarn test to run tests
npm test -- --watch # run tests in watch mode
npm run check-types # or yarn check-types to check TypeScript types`
To run the library locally in another project, you can do the following:
`bash
npm link