2019-08-06 17:37:58 -04:00
# graphql.js
> GitHub GraphQL API client for browsers and Node
[](https://www.npmjs.com/package/@octokit/graphql )
2020-05-15 15:25:57 -04:00
[](https://github.com/octokit/graphql.js/actions?query=workflow%3ATest+branch%3Amaster)
2019-08-06 17:37:58 -04:00
[](https://greenkeeper.io/)
<!-- toc -->
- [Usage ](#usage )
2020-05-15 15:25:57 -04:00
- [Send a simple query ](#send-a-simple-query )
- [Authentication ](#authentication )
- [Variables ](#variables )
- [Pass query together with headers and variables ](#pass-query-together-with-headers-and-variables )
- [Use with GitHub Enterprise ](#use-with-github-enterprise )
- [Use custom `@octokit/request` instance ](#use-custom-octokitrequest-instance )
2019-08-06 17:37:58 -04:00
- [Errors ](#errors )
2020-05-15 15:25:57 -04:00
- [Partial responses ](#partial-responses )
2019-08-06 17:37:58 -04:00
- [Writing tests ](#writing-tests )
- [License ](#license )
<!-- tocstop -->
## Usage
2020-05-15 15:25:57 -04:00
<table>
<tbody valign=top align=left>
<tr><th>
Browsers
</th><td width=100%>
Load `@octokit/graphql` directly from [cdn.pika.dev ](https://cdn.pika.dev )
```html
< script type = "module" >
import { endpoint } from "https://cdn.pika.dev/@octokit/graphql" ;
</ script >
```
</td></tr>
<tr><th>
Node
</th><td>
Install with <code>npm install @octokit/graphql </code>
2019-08-06 17:37:58 -04:00
```js
2020-05-15 15:25:57 -04:00
const { graphql } = require ( "@octokit/graphql" );
// or: import { graphql } from "@octokit/graphql";
```
</td></tr>
</tbody>
</table>
### Send a simple query
```js
const { repository } = await graphql (
`
{
repository(owner: "octokit", name: "graphql.js") {
issues(last: 3) {
edges {
node {
title
}
}
}
}
}
` ,
{
headers : {
authorization : `token secret123` ,
},
}
);
```
### Authentication
The simplest way to authenticate a request is to set the `Authorization` header, e.g. to a [personal access token ](https://github.com/settings/tokens/ ).
```js
const graphqlWithAuth = graphql . defaults ({
headers : {
authorization : `token secret123` ,
},
});
const { repository } = await graphqlWithAuth ( `
{
repository(owner: "octokit", name: "graphql.js") {
issues(last: 3) {
edges {
node {
title
}
2019-08-06 17:37:58 -04:00
}
}
}
}
2020-05-15 15:25:57 -04:00
` );
2019-08-06 17:37:58 -04:00
```
2020-05-15 15:25:57 -04:00
For more complex authentication strategies such as GitHub Apps or Basic, we recommend the according authentication library exported by [`@octokit/auth` ](https://github.com/octokit/auth.js ).
```js
const { createAppAuth } = require ( "@octokit/auth-app" );
const auth = createAppAuth ({
id : process . env . APP_ID ,
privateKey : process . env . PRIVATE_KEY ,
installationId : 123 ,
});
const graphqlWithAuth = graphql . defaults ({
request : {
hook : auth . hook ,
},
});
const { repository } = await graphqlWithAuth (
`{
repository(owner: "octokit", name: "graphql.js") {
issues(last: 3) {
edges {
node {
title
}
}
}
}
}`
);
```
### Variables
2019-08-06 17:37:58 -04:00
⚠️ Do not use [template literals ](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals ) in the query strings as they make your code vulnerable to query injection attacks (see [#2 ](https://github.com/octokit/graphql.js/issues/2 )). Use variables instead:
```js
const { lastIssues } = await graphql ( `query lastIssues($owner: String!, $repo: String!, $num: Int = 3) {
repository(owner:$owner, name:$repo) {
issues(last:$num) {
edges {
node {
title
}
}
}
}
}` , {
owner : 'octokit' ,
repo : 'graphql.js'
headers : {
authorization : `token secret123`
}
}
})
```
2020-05-15 15:25:57 -04:00
### Pass query together with headers and variables
2019-08-06 17:37:58 -04:00
```js
2020-05-15 15:25:57 -04:00
const { graphql } = require ( '@octokit/graphql' )
2019-08-06 17:37:58 -04:00
const { lastIssues } = await graphql ({
query : `query lastIssues($owner: String!, $repo: String!, $num: Int = 3) {
repository(owner:$owner, name:$repo) {
issues(last:$num) {
edges {
node {
title
}
}
}
}
}` ,
owner : 'octokit' ,
repo : 'graphql.js'
headers : {
authorization : `token secret123`
}
})
```
2020-05-15 15:25:57 -04:00
### Use with GitHub Enterprise
2019-08-06 17:37:58 -04:00
```js
2020-05-15 15:25:57 -04:00
let { graphql } = require ( "@octokit/graphql" );
graphql = graphql . defaults ({
baseUrl : "https://github-enterprise.acme-inc.com/api" ,
2019-08-06 17:37:58 -04:00
headers : {
2020-05-15 15:25:57 -04:00
authorization : `token secret123` ,
},
});
const { repository } = await graphql ( `
{
repository(owner: "acme-project", name: "acme-repo") {
issues(last: 3) {
edges {
node {
title
}
2019-08-06 17:37:58 -04:00
}
}
}
}
2020-05-15 15:25:57 -04:00
` );
```
### Use custom `@octokit/request` instance
```js
const { request } = require ( "@octokit/request" );
const { withCustomRequest } = require ( "@octokit/graphql" );
let requestCounter = 0 ;
const myRequest = request . defaults ({
headers : {
authentication : "token secret123" ,
},
request : {
hook ( request , options ) {
requestCounter ++ ;
return request ( options );
},
},
});
const myGraphql = withCustomRequest ( myRequest );
await request ( "/" );
await myGraphql ( `
{
repository(owner: "acme-project", name: "acme-repo") {
issues(last: 3) {
edges {
node {
title
}
}
}
}
}
` );
// requestCounter is now 2
2019-08-06 17:37:58 -04:00
```
## Errors
In case of a GraphQL error, `error.message` is set to the first error from the response’s `errors` array. All errors can be accessed at `error.errors` . `error.request` has the request options such as query, variables and headers set for easier debugging.
```js
2020-05-15 15:25:57 -04:00
let { graphql } = require ( "@octokit/graphql" );
graphqlt = graphql . defaults ({
2019-08-06 17:37:58 -04:00
headers : {
2020-05-15 15:25:57 -04:00
authorization : `token secret123` ,
},
});
2019-08-06 17:37:58 -04:00
const query = `{
viewer {
bioHtml
}
2020-05-15 15:25:57 -04:00
}` ;
2019-08-06 17:37:58 -04:00
try {
2020-05-15 15:25:57 -04:00
const result = await graphql ( query );
2019-08-06 17:37:58 -04:00
} catch ( error ) {
// server responds with
// {
// "data": null,
// "errors": [{
// "message": "Field 'bioHtml' doesn't exist on type 'User'",
// "locations": [{
// "line": 3,
// "column": 5
// }]
// }]
// }
2020-05-15 15:25:57 -04:00
console . log ( "Request failed:" , error . request ); // { query, variables: {}, headers: { authorization: 'token secret123' } }
console . log ( error . message ); // Field 'bioHtml' doesn't exist on type 'User'
2019-08-06 17:37:58 -04:00
}
```
## Partial responses
A GraphQL query may respond with partial data accompanied by errors. In this case we will throw an error but the partial data will still be accessible through `error.data`
```js
2020-05-15 15:25:57 -04:00
let { graphql } = require ( "@octokit/graphql" );
graphql = graphql . defaults ({
2019-08-06 17:37:58 -04:00
headers : {
2020-05-15 15:25:57 -04:00
authorization : `token secret123` ,
},
});
2019-08-06 17:37:58 -04:00
const query = `{
repository(name: "probot", owner: "probot") {
name
ref(qualifiedName: "master") {
target {
... on Commit {
history(first: 25, after: "invalid cursor") {
nodes {
message
}
}
}
}
}
}
2020-05-15 15:25:57 -04:00
}` ;
2019-08-06 17:37:58 -04:00
try {
2020-05-15 15:25:57 -04:00
const result = await graphql ( query );
2019-08-06 17:37:58 -04:00
} catch ( error ) {
// server responds with
2020-05-15 15:25:57 -04:00
// {
// "data": {
// "repository": {
// "name": "probot",
// "ref": null
// }
// },
// "errors": [
// {
// "type": "INVALID_CURSOR_ARGUMENTS",
// "path": [
// "repository",
// "ref",
// "target",
// "history"
// ],
// "locations": [
// {
// "line": 7,
// "column": 11
// }
// ],
// "message": "`invalid cursor` does not appear to be a valid cursor."
// }
// ]
// }
2019-08-06 17:37:58 -04:00
2020-05-15 15:25:57 -04:00
console . log ( "Request failed:" , error . request ); // { query, variables: {}, headers: { authorization: 'token secret123' } }
console . log ( error . message ); // `invalid cursor` does not appear to be a valid cursor.
console . log ( error . data ); // { repository: { name: 'probot', ref: null } }
2019-08-06 17:37:58 -04:00
}
```
## Writing tests
You can pass a replacement for [the built-in fetch implementation ](https://github.com/bitinn/node-fetch ) as `request.fetch` option. For example, using [fetch-mock ](http://www.wheresrhys.co.uk/fetch-mock/ ) works great to write tests
```js
2020-05-15 15:25:57 -04:00
const assert = require ( "assert" );
const fetchMock = require ( "fetch-mock/es5/server" );
2019-08-06 17:37:58 -04:00
2020-05-15 15:25:57 -04:00
const { graphql } = require ( "@octokit/graphql" );
2019-08-06 17:37:58 -04:00
2020-05-15 15:25:57 -04:00
graphql ( "{ viewer { login } }" , {
2019-08-06 17:37:58 -04:00
headers : {
2020-05-15 15:25:57 -04:00
authorization : "token secret123" ,
2019-08-06 17:37:58 -04:00
},
request : {
2020-05-15 15:25:57 -04:00
fetch : fetchMock
. sandbox ()
. post ( "https://api.github.com/graphql" , ( url , options ) => {
assert . strictEqual ( options . headers . authorization , "token secret123" );
assert . strictEqual (
options . body ,
'{"query":"{ viewer { login } }"}' ,
"Sends correct query"
);
return { data : {} };
}),
},
});
2019-08-06 17:37:58 -04:00
```
## License
[MIT ](LICENSE )