kowainik / github-graphql Goto Github PK
View Code? Open in Web Editor NEWπΈοΈ GraphQL bindings to GitHub API
Home Page: https://kowainik.github.io/projects/github-graphql
License: Mozilla Public License 2.0
πΈοΈ GraphQL bindings to GitHub API
Home Page: https://kowainik.github.io/projects/github-graphql
License: Mozilla Public License 2.0
Currently we don't have a way to query Milestone
by number:
query {
repository(owner: "kowainik", name: "hit-on") {
milestone(number: 1) {
id
}
}
}
With the response:
{
"data": {
"repository": {
"milestone": {
"id": "MDk6TWlsZXN0b25lNDQ4MDI1Mg=="
}
}
}
}
For this, we need to add a milestone connection to Repository
. Similar to Issue
/Issues
we need to have Milestone
/Milestones
:
github-graphql/src/GitHub/Repository.hs
Lines 120 to 126 in 19abc17
Additionally, it would be nice to have a helper function to query MilestoneId
similar to querying RepositoryId
:
github-graphql/src/GitHub/Query.hs
Lines 84 to 115 in 19abc17
And add tests for this function (e.g. using the example in this issue).
Currently, when something is wrong, it's hard to understand why. I propose to add a custom data type and return it as an error.
The data type will contain:
When you provide an invalid query like this:
query {
repository(owner: "kowainik", "github-graphql") {
issue(number: 5) {
bodies
}
}
}
GitHub API returns the following message:
{
"errors": [
{
"message": "Parse error on \"github-graphql\" (STRING) at [2, 33]",
"locations": [
{
"line": 2,
"column": 33
}
]
}
]
}
Ideally, this shouldn't happen in users' code (because we provide type-safe API), but this still can happen due to errors in our library, so it's good to provide more info here.
Example:
query {
repository(owner: "kowainik", name: "github-graphql") {
issues(last: 3) {
nodes {
title
author{
login
}
}
}
}
}
GitHub GraphQL API is huge! And it won't be ideal to keep all types in the same single module. So let's refactor a bit and move them into separate modules.
For now, it can return ByteString
if we want to avoid dependencies on aeson
and let users decide what library to use aeson
or microaeson
or something else.
The function should take token and a query. An example curl
command looks like this:
$ curl -H "Authorization: bearer token" -X POST -d " \
{ \
\"query\": \"query { viewer { login }}\" \
} \
" https://api.github.com/graphql
I think, we can use the httpLbs
function to call server and http-client-tls
library for creating TLS manager:
It's a bit heavy on the dependencies side but that's the only Haskell-only solution... Maybe we can just use curl
? π€
Similar to the Repository
type. Messages probably will have the same structure, so maybe it makes sense to have a helper type family that takes several arguments and builds the message from them.
The following types currently lack custom error messages:
According to GraphQL, if we want to create news issues, we need to implement the Mutation
type similar to Query
...
So we can fetch the latest milestone using the following query:
query {
repository(owner: "kowainik", name: "hit-on") {
milestones(last: 1, orderBy: {field: NUMBER, direction: DESC}) {
nodes {
title
}
}
}
}
I realized, that with current types it's a bit hard to test, and will require a bit of work...
I propose to use the following query to write the test, because the output of this query won't change with time:
query {
repository(owner: "kowainik", name: "hit-on") {
issues(last: 2, states: [CLOSED], orderBy: {field: CREATED_AT, direction: DESC}) {
nodes {
title
author{
login
}
}
}
}
}
The output looks like this:
{
"data": {
"repository": {
"issues": {
"nodes": [
{
"title": "Implement \"git-new\"-like command: `hit hop`",
"author": {
"login": "chshersh"
}
},
{
"title": "Implement basic CLI interface",
"author": {
"login": "vrom911"
}
}
]
}
}
}
}
For this we need to do the following:
GITHUB_TOKEN
{}
OrderDirection
type with ASC
and DESC
constructorsThe first project to use github-graphql
is going to be hit-on
. And for this to happen, we need to support the following types and operations:
let headPrMod = optionsHead $ untagName owner <> ":" <> curBranch
Since GitHub GraphQL API provides more flexibility than the REST API, we probably can improve some of our queries in hit-on by fetching less or by filtering directly in the query. So, other possible suggestions and improvements are welcome π
Current structure of modules is a bit messy:
GitHub
GitHub.Author
GitHub.Connection
GitHub.GraphQL
GitHub.Id
GitHub.Issue
GitHub.Label
GitHub.Lens
GitHub.Milestone
GitHub.Order
GitHub.PullRequests
GitHub.Render
GitHub.Query
GitHub.Repository
GitHub.RequiredField
GitHub.Title
GitHub.User
Current problem is that we have fields for different types (title of issue, login of user, etc.) and we also have different connections with input parameters (issue by state, pullrequests, etc.). Some connections can be polymorphic, so to abstract further, it's better to separate types.
I propose a new structure with clearer boundaries (and probably avoiding recursive dependencies).
I will write in a shorter syntax for clarity. Mostly duplicates the GitHub API structure:
GitHub
Types
Connection
Issue
Milestone
PullRequest
User
Id
Connections
Labels
Issue -- issue by number
Issues -- list of issues
PullRequests
Milestones
Interface
Actor -- has author name
Enums
IssueState
PullRequestState
IssueOrder
Queries
Repository
Viewer
Mutations
CreateIssue
AddAssigneesToAssignable
GraphQL
Query
Mutation
Render
API -- calling remote API, better name needed
Common
Query
Mutation
Abstraction -- local abstractions for better UX and UI, better name needed
Lens
Author -- HasAuthor typeclass and instances
Title -- HasTitle typeclass and instances
RequiredField
With this structure, it's clear what to add and where:
GitHub.Types
.GitHub.Connection
GitHub.API
module.GitHub.Abstraction
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.