GitHub API v4 - Get contributors from specific repository - graphql

I'm trying to build a query with the GitHub API v4 (GraphQL) to get the number of contributors.
At the moment I have something of the likes of
query ($owner: String!, $name: String!) {
repository(owner: $owner, name: $name) {
ref(qualifiedName: "master") {
target {
... on Commit {
history(first: 100) {
nodes {
author {
name
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
}
}
}
where I'm going through all the commits and get the name of the Authors (at the time I was trying to get the number of commits for contributor), but for repositories with a large amount of commits, this takes a lot of time.
So back to my question, is the a way to get only the number of contributors in a repository?

As far as I know, this is only possible with the REST API (v3), by requesting only one item per page, and extracting the total number of pages in the Response headers.

With this graphql query you can get the:
- total releases count
- total branches count
- total commits count
query{
repository(owner:"kasadawa", name:"vmware-task") {
Releases:refs(first: 0, refPrefix: "refs/tags/") {
totalCount
}
Branches:refs(first: 0, refPrefix: "refs/heads/") {
totalCount
}
object(expression:"master") {
... on Commit {
history {
totalCount
}
}
}
}
}
But if you want to get the contributors, you should do it with the REST API, because currently there is no simple way to implement it with GRAPHQL API.
Here is a solutions with the REST API.
const options = {
url: 'https://api.github.com/repos/vmware/contributors' ,
'json': true ,
headers: {
'User-Agent':'request',
'Authorization': 'token API_KEY_GENERATED_FROM_GITHUB'
}
};
var lastPageNum = 0 ; // global variable
request.getAsync(options).then((res) =>{
this.checkHeaders(res.headers.status) // just check the header status
// check if there are more pages
if(!!res.headers.link){
const [ , lastURL] = res.headers.link.split(','); // getting the last page link from the header
lastPageNum = +lastURL.match(/page=(\d+)/)[1]; // get the number from the url string
options.url = licenseUrl + lastPageNum;
return request.getAsync(options) // make Request with the last page, in order to get the last page results, they could be less than 30
}else{
// if its single page just resolve on to the chain
return Promise.resolve(res.body.length);
}
})
.then((lastPageRes)=>{
return (lastPageNum !== 0
? ( (lastPageNum-1)*30 + lastPageRes.body.length )
: lastPageRes)
})
.catch() // handle errors
Checkout for updates: https://github.community/t5/GitHub-API-Development-and/Get-contributor-count-with-the-graphql-api/td-p/18593

Related

Strapi GraphQL search by multiple attributes

I've got a very simple Nuxt app with Strapi GraphQL backend that I'm trying to use and learn more about GraphQL in the process.
One of my last features is to implement a search feature where a user enters a search query, and Strapi/GraphQL performs that search based on attributes such as image name and tag names that are associated with that image. I've been reading the Strapi documentation and there's a segment about performing a search.
So in my schema.graphql, I've added this line:
type Query {
...other generated queries
searchImages(searchQuery: String): [Image
}
Then in the /api/image/config/schema.graphql.js file, I've added this:
module.exports = {
query: `
searchImages(searchQuery: String): [Image]
`,
resolver: {
Query: {
searchImages: {
resolverOf: 'Image.find',
async resolver(_, { searchQuery }) {
if (searchQuery) {
const params = {
name_contains: searchQuery,
// tags_contains: searchQuery,
// location_contains: searchQuery,
}
const searchResults = await strapi.services.image.search(params);
console.log('searchResults: ', searchResults);
return searchResults;
}
}
}
},
},
};
At this point I'm just trying to return results in the GraphQL playground, however when I run something simple in the Playground like:
query($searchQuery: String!) {
searchImages(searchQuery:$searchQuery) {
id
name
}
}
I get the error: "TypeError: Cannot read property 'split' of undefined".
Any ideas what might be going on here?
UPDATE:
For now, I'm using deep filtering instead of the search like so:
query($searchQuery: String) {
images(
where: {
tags: { title_contains: $searchQuery }
name_contains: $searchQuery
}
) {
id
name
slug
src {
url
formats
}
}
}
This is not ideal because it's not an OR/WHERE operator, meaning it's not searching by tag title or image name. It seems to only hit the first where. Ideally I would like to use Strapi's search service.
I actually ran into this problem not to recently and took a different solution.
the where condition can be combined with using either _and or _or. as seen below.
_or
articles(where: {
_or: [
{ content_contains: $dataContains },
{ description_contains: $dataContains }
]})
_and
(where: {
_and: [
{slug_contains: $categoriesContains}
]})
Additionally, these operators can be combined given that where in this instance is an object.
For your solution I would presume you want an or condition in your where filter predicate like below
images(where: {
_or: [
{ title_contains: $searchQuery },
{ name_contains: $searchQuery }
]})
Lastly, you can perform a query that filters by a predicate by creating an event schema and adding the #search directive as seen here

Multiple graphql queries in Gatsby component

I need to run multiple graphQL queries within a component and within the gatsby-node.js file. (Because Prismic is limited to 20 entries per answer...🙄)
I tried the following, just to see if I could create the graphql loop in the default function:
export default () => {
async function allPosts() {
let data
await graphql(`
query allDitherImages {
prismic {
allProjects(sortBy: meta_firstPublicationDate_DESC) {
totalCount
pageInfo {
startCursor
endCursor
hasNextPage
hasPreviousPage
}
edges {
node {
cover_image
cover_imageSharp {
name
}
}
}
}
}
}
`).then(initialRes => {
data = initialRes
})
return data
}
allPosts().then(result => {
console.log(result)
})
return null
}
But then Gatsby tells me that Gatsby related 'graphql' calls are supposed to only be evaluated at compile time, and then compiled away. Unfortunately, something went wrong and the query was left in the compiled code.
How can I run multiple graphql queries?
Thank you in advance :)
Michael
The gatsby-source-prismic-graphql package will create pages for all of your Prismic items (more than just the first 20), as it iterates over all items under the hood, so I'd advise looking into using that if you are looking to generate pages for all of those items.
But if you need to get all items and pass them in the pageContext or something, you'll need to do the recursion yourself in the gatsby-node.
In the gatsby-node, after you have defined the query, you can use something like this to iterate over the results and push to an array.
let documents = [];
async function getAllDocumentsRecursively (query, prop, endCursor = '') {
const results = await graphql(query, { after: endCursor })
const hasNextPage = results.data.prismic[prop].pageInfo.hasNextPage
endCursor = results.data.prismic[prop].pageInfo.endCursor
results.data.prismic[prop].edges.forEach(({node}) => {
documents.push(node)
});
if (hasNextPage) {
await getAllDocumentsRecursively(query, 'allDitherImages ', endCursor)
}
}
await getAllDocumentsRecursively(documentsQuery, 'allDitherImages ');
Then in your createPage, pass the array into the context:
createPage({
path: `/`+ node._meta.uid,
component: allDitherTempate,
context: {
documents: documents
}
})

How to implement subscriptions in graphql.js?

This is a pretty simple question.
How to implement subscriptions in graphql?
I'm asking specifically for when using graphql.js constructors like below ?
I could not find a clean/simple implementation.
There is another question here, but it deals with relay.js - i don't want to unnecessarily increase the nr of external dependencies in my app.
What i have:
module.exports = function (database){
return new GraphQLSchema(
{ query: RootQuery(database)
, mutation: RootMutation(database)
, subscription: RootSubscription(database) -- i can see this in graphiql - see below
}
);
}
function RootSubscription(database){
return new GraphQLObjectType(
{ name: "RootSubscriptionType"
, fields:
{ getCounterEvery2Seconds:
{ type: new GraphQLNonNull(GraphQLInt)
, args :
{ id: { type: GraphQLString }
}
, subscribe(parent, args, context){
// this subscribe function is never called .. why?
const iterator = simpleIterator()
return iterator
}
}
}
}
)
}
I learned that i need a subscribe() which must return an iterator from this github issue.
And here is a simple async iterator. All this iterator does - is to increase and return the counter every 2 seconds. When it reaches 10 it stops.
function simpleIterator(){
return {
[ Symbol.asyncIterator ]: () => {
let i = 0
return {
next: async function(){
i++
await delay(2000)
if(i > 10){
return { done: true }
}
return {
value: i,
done: false
}
}
}
}
}
}
When i run the graphiql subscription, it returns null for some reason:
I'm piecing together code from multiple sources - wasting time and hacking it basically. Can you help me figure this one out?
Subscriptions are such a big feature, where are they properly documented? Where is that snippet of code which you just copy paste - like queries are for example - look here.
Also, i can't use an example where the schema is separate - as a string/from a file. I already created my schema as javascript constructors. Now since im trying to add subscriptions i can't just move back to using a schema as a string. Requires rewriting the entire project. Or can i actually have both? Thanks :)

Chat app list last messages of each peer using parse server

I am doing a chat app using parse server, everything is great but i tried make to list just last message for every remote peer. i didn't find any query limitation how to get just one message from every remote peer how can i make this ?
Query limitation with Parse SDK
To limit the number of object that you get from a query you use limit
Here is a little example:
const Messages = Parse.Object.extend("Messages");
const query = new Parse.Query(Messages);
query.descending("createdAt");
query.limit(1); // Get only one result
Get the first object of a query with Parse SDK
In you case as you really want only one result you can use Query.first.
Like Query.find the method Query.first make a query and will return only the first result of the Query
Here is an example:
const Messages = Parse.Object.extend("Messages");
const query = new Parse.Query(Messages);
query.descending("createdAt");
const message = await query.first();
I hope my answer help you 😊
If you want to do this using a single query, you will have to use aggregate:
https://docs.parseplatform.org/js/guide/#aggregate
Try something like this:
var query = new Parse.Query("Messages");
var pipeline = [
{ match: { local: '_User$' + userID } },
{ sort: { createdAt: 1 } },
{ group: { remote: '$remote', lastMessage: { $last: '$body' } } },
];
query.aggregate(pipeline)
.then(function(results) {
// results contains unique score values
})
.catch(function(error) {
// There was an error.
});

Display more than 100 entries through GraphQL API

I have tired pagination using endCursor and hasNextPage in github grpahQL API to get more than 100 data. Query I used is:
query {
organization(login:"XXX") {
repository(name:"XX") {
pullRequests(first:100, states:[OPEN], after: "XXX" ) {
pageInfo{
hasNextPage
endCursor
}
}
}
It is working. But in order to access further details,iterative pagination needs to be done. Can anyone provides an efficient alternative to traverse all pages programatically in GraphQL API?
Taking inspiration from Simon Willison's 'Paginating through the GitHub GraphQL API with Python' here's what I've been doing to paginate my queries:
query {
node(id: "PROJECT_ID") {
... on ProjectNext {
items(first: 100 after: CURSOR) {
pageInfo {
hasNextPage
endCursor
}
nodes {
title
fieldValues(first: 8) {
nodes {
value
}
}
content {
... on Issue {
number
labels(first: 50) {
nodes {
name
}}}}}}}}}
In my Python code I'm splicing in PROJECT_ID with a variable set to the project ID I'm referencing.
For the cursor after: CURSOR is replaced with "" initially, and then for the next page I set cursor = 'after:\\"' + response["data"]["node"]["items"]["pageInfo"]["endCursor"] + '\\"'
My full code is in the atdumpmemex module of my dump_cards utility.
The key here is to get pageInfo along with other relevant nodes, and then grab the endCursor each time hasNextPage is true so that it can be fed into the query for the next iteration.
pageInfo will look something like:
"pageInfo": {
"hasNextPage": false,
"endCursor": "Y3Vyc29yOnYyOpHOAAhOsg=="
}
At the moment the endCursor is base64 encoded cursor:v2:XYZ, but don't rely on that as GitHub have moved other IDs from being base64 encoded to other schemes.
Pagination using endCursor is the one solution. Like REST API, you cannot traverse all pages pragmatically. As you specified you can specify endCursor and traverse if there is next page

Resources