graphql.js
GitHub GraphQL API client for browsers and Node
Usage
Browsers
|
Load @octokit/graphql directly from cdn.skypack.dev
<script type="module">
import { endpoint } from "https://cdn.skypack.dev/@octokit/graphql";
</script>
|
---|
Node
|
Install with npm install @octokit/graphql
const { graphql } = require("@octokit/graphql");
|
---|
Send a simple query
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.
const graphqlWithAuth = graphql.defaults({
headers: {
authorization: `token secret123`,
},
});
const { repository } = await graphqlWithAuth(`
{
repository(owner: "octokit", name: "graphql.js") {
issues(last: 3) {
edges {
node {
title
}
}
}
}
}
`);
For more complex authentication strategies such as GitHub Apps or Basic, we recommend the according authentication library exported by @octokit/auth
.
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
⚠️ Do not use template literals in the query strings as they make your code vulnerable to query injection attacks (see #2). Use variables instead:
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`,
},
}
);
Pass query together with headers and variables
const { graphql } = require("@octokit/graphql");
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`,
},
});
Use with GitHub Enterprise
let { graphql } = require("@octokit/graphql");
graphql = graphql.defaults({
baseUrl: "https://github-enterprise.acme-inc.com/api",
headers: {
authorization: `token secret123`,
},
});
const { repository } = await graphql(`
{
repository(owner: "acme-project", name: "acme-repo") {
issues(last: 3) {
edges {
node {
title
}
}
}
}
}
`);
Use custom @octokit/request
instance
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
}
}
}
}
}
`);
TypeScript
@octokit/graphql
is exposing proper types for its usage with TypeScript projects.
Additional Types
Additionally, GraphQlQueryResponseData
has been exposed to users:
import type { GraphQlQueryResponseData } from "octokit/graphql";
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.
let { graphql } = require("@octokit/graphql");
graphqlt = graphql.defaults({
headers: {
authorization: `token secret123`,
},
});
const query = `{
viewer {
bioHtml
}
}`;
try {
const result = await graphql(query);
} catch (error) {
console.log("Request failed:", error.request);
console.log(error.message);
}
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
let { graphql } = require("@octokit/graphql");
graphql = graphql.defaults({
headers: {
authorization: `token secret123`,
},
});
const query = `{
repository(name: "probot", owner: "probot") {
name
ref(qualifiedName: "master") {
target {
... on Commit {
history(first: 25, after: "invalid cursor") {
nodes {
message
}
}
}
}
}
}
}`;
try {
const result = await graphql(query);
} catch (error) {
console.log("Request failed:", error.request);
console.log(error.message);
console.log(error.data);
}
Writing tests
You can pass a replacement for the built-in fetch implementation as request.fetch
option. For example, using fetch-mock works great to write tests
const assert = require("assert");
const fetchMock = require("fetch-mock/es5/server");
const { graphql } = require("@octokit/graphql");
graphql("{ viewer { login } }", {
headers: {
authorization: "token secret123",
},
request: {
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: {} };
}),
},
});
License
MIT