@discublog/api
Version:
A ready-to-use, reusable wrapper for the GitHub Discussions API, based on the GitHub GraphQL API.
249 lines (248 loc) • 6.5 kB
JavaScript
import { Octokit } from '@octokit/core';
function check(config) {
if (!config.client || !config.owner || !config.name) {
throw new Error(`Please call auth() first to configure the client`);
}
return config;
}
export function auth(config, params) {
config.client = new Octokit({ auth: params.token });
config.owner = params.owner;
config.name = params.name;
}
// Discussion Categories
export function queryCategories(config) {
const { client, owner, name } = check(config);
return client.graphql(
/* GraphQL */ `
query DiscussionCategories($owner: String!, $name: String!) {
repository(owner: $owner, name: $name) {
discussionCategories(first: 100) {
nodes {
id
name
}
}
}
}
`, {
owner,
name,
});
}
export function queryByCategoryId(config, { first = 100, categoryId, body = false, bodyHTML = false, bodyText = false, cursor, }) {
const { client, owner, name } = check(config);
return client.graphql(
/* GraphQL */ `
query Discussions(
$first: Int!
$owner: String!
$name: String!
$categoryId: ID!
$body: Boolean!
$bodyHTML: Boolean!
$bodyText: Boolean!
$cursor: String
) {
repository(owner: $owner, name: $name) {
discussions(
first: $first
orderBy: { field: CREATED_AT, direction: DESC }
after: $cursor
categoryId: $categoryId
) {
nodes {
author {
login
url
avatarUrl
}
number
title
createdAt
updatedAt
url
body @include(if: $body)
bodyHTML @include(if: $bodyHTML)
bodyText @include(if: $bodyText)
labels(first: 5) {
nodes {
id
name
color
}
}
}
pageInfo {
startCursor
hasPreviousPage
hasNextPage
endCursor
}
totalCount
}
}
}
`, {
first,
owner,
name,
categoryId,
body,
bodyHTML,
bodyText,
cursor,
});
}
export async function queryByCategoryName(config, params) {
const { name, ...rest } = params;
const categoriesResponse = await queryCategories(config);
const categories = categoriesResponse.repository?.discussionCategories.nodes;
const categoryId = categories?.find(category => category.name === name)?.id;
if (!categoryId) {
return null;
}
return queryByCategoryId(config, { ...rest, categoryId });
}
export async function queryByNumber(config, { number, body = false, bodyHTML = false, bodyText = false }) {
const { client, owner, name } = check(config);
return client.graphql(
/* GraphQL */ `
query Discussion(
$owner: String!
$name: String!
$number: Int!
$body: Boolean!
$bodyHTML: Boolean!
$bodyText: Boolean!
) {
repository(owner: $owner, name: $name) {
discussion(number: $number) {
author {
login
url
avatarUrl
}
number
title
createdAt
updatedAt
url
body @include(if: $body)
bodyHTML @include(if: $bodyHTML)
bodyText @include(if: $bodyText)
labels(first: 5) {
nodes {
id
name
color
}
}
}
}
}
`, {
owner,
name,
number,
body,
bodyHTML,
bodyText,
});
}
export function queryLabels(config) {
const { client, owner, name } = check(config);
return client.graphql(
/* GraphQL */ `
query AllLabels($owner: String!, $name: String!) {
repository(owner: $owner, name: $name) {
labels(first: 100, orderBy: { field: NAME, direction: ASC }) {
nodes {
id
name
color
}
}
}
}
`, {
owner,
name,
});
}
export async function search(config, params) {
const { client, owner, name } = check(config);
const { first = 100, body = false, bodyHTML = false, bodyText = false, cursor, orderBy } = params;
let query = `repo:"${owner}/${name}"`;
if ('query' in params) {
query += ` ${params.query}`;
}
else {
const { label, category } = params;
if (label) {
query += ` label:"${label}"`;
}
if (category) {
query += ` category:"${category}"`;
}
}
return client
.graphql(
/* GraphQL */ `
query DiscussionsSearch(
$queryStr: String!
$first: Int!
$body: Boolean!
$bodyHTML: Boolean!
$bodyText: Boolean!
$cursor: String
) {
search(first: $first, type: DISCUSSION, query: $queryStr, after: $cursor) {
nodes {
... on Discussion {
author {
login
url
avatarUrl
}
number
title
createdAt
updatedAt
url
body @include(if: $body)
bodyHTML @include(if: $bodyHTML)
bodyText @include(if: $bodyText)
labels(first: 5) {
nodes {
id
color
name
}
}
}
}
pageInfo {
startCursor
hasPreviousPage
hasNextPage
endCursor
}
totalCount: discussionCount
}
}
`, {
first,
cursor,
body,
bodyHTML,
bodyText,
queryStr: query,
})
.then(result => {
if (orderBy === 'createdAt') {
result.search.nodes.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
}
return result;
});
}