How to fetch GitHub branch names using GraphQL - branch

Using GitHub GraphQL API (v.4) I would like to get all the branch names existing on a given repository.
My attempt
{
repository(name: "my-repository", owner: "my-account") {
... on Ref {
name
}
}
}
returns error:
{'data': None, 'errors': [{'message': "Fragment on Ref can't be spread inside Repository", 'locations': [{'line': 4, 'column': 13}]}]}

Here's how to retrieve 10 branches from a repo:
{
repository(name: "git-point", owner: "gitpoint") {
refs(first: 10, , refPrefix:"refs/heads/") {
nodes {
name
}
}
}
}
PS: You usually use spread when dealing with an Union type (like IssueTimeline for example, which is composed of different kind of objects, so you can spread on a particular object type to query specific fields.
You might need to use pagination to get all branches

Related

Can I use TypeOrm's FindOperators inside a base class without getting bad SQL Unknown column '_type' in 'where clause'

I am trying to write a base class for CRUD operations for "typeorm": "~0.2.45" under "#nestjs/typeorm": "~8.0.3" using node v14.19.3.
The base class looks like this:
export class CrudService<T> {
protected repository: Repository<T>;
constructor(repository: Repository<T>) {
this.repository = repository;
}
...
// Minimized code example
async find() {
return this.repository.find({
where: {
created: Between("2022-06-21T14:18:00.000Z", "2022-06-21T14:19:00.000Z")
}
});
}
}
This generates the following SQL query (which is wrong), it seems to use the Between() object as a literal equality comparison.
query failed: SELECT ... FROM `carts` `CartEntity` WHERE `CartEntity`.`created` = ?
-- PARAMETERS: {
"_type":"between",
"_value":[
"2022-06-21T14:18:00.000Z",
"2022-06-21T14:19:00.000Z"
],
"_useParameter":true,
"_multipleParameters":true
}
If I implement the same code inside the CartsEntity service like this:
#Injectable()
export class CartsService extends CrudService<CartEntity> {
constructor(
#InjectRepository(CartsRepository) repository: CartsRepository
) {
super(repository);
}
...
async find() {
return this.repository.find({
where: {
created: Between("2022-06-21T14:18:00.000Z", "2022-06-21T14:19:00.000Z")
}
});
}
It works fine and retrieves the data with valid SQL using BETWEEN on MySql.
I am wondering what is wrong here since I am using the same instance of repository in both code examples. I tried looking at the TypeOrm FindOperator logic but could not pinpoint it.
It turns out that the problem is a difference in the typeorm npm versions I was using.
The CrudEntity described above is inside a private npm using typeorm 0.2.45 as are my microservices extending CrudEntity like the CartEntity above.
Since #nestjs/typeorm is tagged to typeorm 0.2.34 the type was not the same for FindOperator and thus returned as an object condition instead of a FindOperator generating the proper BETWEEN SQL statement.
Basically, make sure all typeorm versions are the same across all your projects sharing code.

AsyncAPI enum with specific values

Is it possible to create an enum with specific values in AsyncAPI? In my legacy c# code theres an enum like this
public enum OrderStatus
{
Ordered = 30,
UnderDelivery = 40,
Deliveret = 50,
Cancelled = 99
}
I would like to create the same enum, with the same values in AsyncAPI. But it seems that you cannot specify the values in async API. Am I missing something? Is there an alternative solution?
It is not, or at least not in the general sense.
With AsyncAPI 2.4 you can define payloads with different schema formats (schemaFormat), by default this is an AsyncAPI Schema Object which is a superset of JSON Schema Draft 7. There might exist a schema format you can use that allows this, I just don't recall knowing one, for example not even JDT allows this.
Looking into JSON Schema Draft 7, you will not find it possible to define an enum value with an associated name such as Ordered and UnderDelivery. This means the only way to define it is something like this:
{
"title": "OrderStatus",
"type": "number",
"enum": [
30,
40,
50,
99
]
}
This is because JSON Schema focuses on validating JSON data, and in the JSON world, there is no such thing as an associated name to the enum value. That is entirely related to programming languages.
Solution
There are a couple of solutions and how you can proceed, let me highlight one way I see it could be achieved.
Specification Extensions
If you use the default AsyncAPI 2.4.0 Schema Object, AsyncAPI allows you to add your own extension such as:
{
"title": "OrderStatus",
"type": "number",
"enum": [
30,
40,
50,
99
],
"x-enumNames": {
30: "Ordered",
40: "UnderDelivery",
50: "Deliveret",
99: "Cancelled"
}
}
This will also work if you use pure JSON Schema draft 7 because any extra properties are allowed.
In newer versions of JSON Schema, they introduce something called vocabularies, which could standardize this feature. I started some work around a code generation vocabulary unfortunately, there are many other areas that need to be solved first, so I don't have the bandwidth to personally push it forward.
Generating the enum model
Regardless of how you actually define it with the specification, I expect you want tooling to generate the "accurate" enum model in code generation so here is one way to do it.
Modelina is an open-source tool that is being developed exactly for these cases. I have added an example test case to showcase how it could be done for Modelina v0.59.
Let me break the implementation down:
const generator = new CSharpGenerator({
presets: [
{
enum: {
item: ({model, item, content}) => {
// Lets see if an enum has any associated names
const hasCustomName = model.originalInput !== undefined && model.originalInput['x-enumNames'] !== undefined;
if (hasCustomName) {
// Lets see if the specific value has an associated name
const customName = model.originalInput['x-enumNames'][item];
if (customName !== undefined) {
return customName;
}
}
return content;
}
}
}
]
});
The Csharp generator is being instructed to use a custom preset (can be seen as a Node.js middleware) for the enum renderer. Here we add a middleware to overwrite the name of each enum "item"/value based on whether it has our extension or not.
This results in the following generated model:
public enum OrderStatus
{
Ordered,
UnderDelivery,
Deliveret,
Cancelled
}
public static class OrderStatusExtensions
{
public static dynamic GetValue(this OrderStatus enumValue)
{
switch (enumValue)
{
case OrderStatus.Ordered: return 30;
case OrderStatus.UnderDelivery: return 40;
case OrderStatus.Deliveret: return 50;
case OrderStatus.Cancelled: return 99;
}
return null;
}
public static OrderStatus? ToOrderStatus(dynamic value)
{
switch (value)
{
case 30: return OrderStatus.Ordered;
case 40: return OrderStatus.UnderDelivery;
case 50: return OrderStatus.Deliveret;
case 99: return OrderStatus.Cancelled;
}
return null;
}
}

Filter Github issues by author using their graphql API

I'm trying to figure out how to get the list of issues by author. I can get the list of issues but I don't know is how to filter 'by author'.
The following returns a list of issues from the repo "Hello-World" of the owner "octocat". What I want to do is to filter issue author: "yosuke-furukawa" or any other author. How to do that?
You may try it out at the explorer.
repository(owner:"octocat", name:"Hello-World") {
issues(last:20, states:CLOSED) {
edges {
node {
bodyText
author{
login
}
}
}
}
}
}
To get the list of issues created by a specific author, you can query for objects of type ISSUE, adding the repository information and the author name in the query string:
query {
search(
type: ISSUE,
query: """
repo:octocat/Hello-World
author:yosuke-furukawa
state:closed
""",
last: 20
) {
edges {
node {
... on Issue {
id
title
bodyText
author {
login
}
}
}
}
}
}
The full syntax for querying issues can be found here:
https://help.github.com/en/articles/searching-issues-and-pull-requests

Extracting additional data with query with keen.io

I have a (simplified) query that looks as follows.
var pageViews = new Keen.Query('count', {
eventCollection: 'Loaded a Page',
groupBy: 'company.id'
});
And use it as follows.
client.run(pageViews, function(result, error) {
// Do something here
});
This will give me the following JSON to work with:
{
"result": [
{
"company.id": 1,
"result": 3
},
{
"company.id": 2,
"result": 11
},
{
"company.id": 3,
"result": 7
}
]
}
However, I would also like to get back the name of each company, i.e. the company.name property. I looked through keen.io's documentation, and I could find no way of doing this. Is there a way to do this? Logically speaking, I don't see any reason why it would not be possible, but the question is if it has been implemented.
Grouping by multiple properties will get you what you're looking for:
var pageViews = new Keen.Query('count', {
eventCollection: 'Loaded a Page',
groupBy: ['company.id','company.name']
});
That being said, it's important to note that Keen is not an entity database. Keen is optimized to store and analyze event data, which is different than entity data. More complex uses of entity data may not perform well using this solution.

Sproutcore datasources and model relationships

I currently have a Sproutcore app setup with the following relationships on my models:
App.Client = SC.Record.extend({
name: SC.Record.attr(String),
brands: SC.Record.toMany('App.Brand', {isMaster: YES, inverse: 'client'})
});
App.Brand = SC.Record.extend({
name: SC.Record.attr(String),
client: SC.Record.toOne('App.Client, {isMaster: NO, inverse: 'brands'})
});
When I was working with fixtures my fixture for a client looked like this:
{
guid: 1,
name: 'My client',
brands: [1, 2]
}
And my fixture for a brand looked like this:
{
guid: 1,
name: 'My brand',
client: 1
}
Which all worked fine for me getting a clients brands and getting a brands client.
My question is in regards to how Datasources then fit into this and how the server response should be formatted.
Should the data returned from the server mirror exactly the format of the fixtures file? So clients should always contain a brands property containing an array of brand ids? And vice versa.
If I have a source list view which displays Clients with brands below them grouped. How would I go about loading that data for the source view with my datasource? Should I make a call to the server to get all the Clients and then follow that up with a call to fetch all the brands?
Thanks
Mark
The json you return will mostly mirror the fixtures. I recently had pretty much the same question as you, so I built a backend in Grails and a front end in SC, just to explore the store and datasources. My models are:
Scds.Project = SC.Record.extend(
/** #scope Scds.Project.prototype */ {
primaryKey: 'id',
name: SC.Record.attr(String),
tasks: SC.Record.toMany("Scds.Task", {
isMaster: YES,
inverse: 'project'
})
});
Scds.Task = SC.Record.extend(
/** #scope Scds.Task.prototype */ {
name: SC.Record.attr(String),
project: SC.Record.toOne("Scds.Project", {
isMaster: NO
})
});
The json returned for Projects is
[{"id":1,"name":"Project 1","tasks":[1,2,3,4,5]},{"id":2,"name":"Project 2","tasks":[6,7,8]}]
and the json returned for tasks, when I select a Project, is
{"id":1,"name":"task 1"}
obviously, this is the json for 1 task only. If you look in the projects json, you see that i put a "tasks" array with ids in it -- thats how the internals know which tasks to get. so to answer your first question, you dont need the id from child to parent, you need the parent to load with all the children, so the json does not match the fixtures exactly.
Now, it gets a bit tricky. When I load the app, I do a query to get all the Projects. The store calls the fetch method on the datasource. Here is my implementation.
Scds.PROJECTS_QUERY = SC.Query.local(Scds.Project);
var projects = Scds.store.find(Scds.PROJECTS_QUERY);
...
fetch: function(store, query) {
console.log('fetch called');
if (query === Scds.PROJECTS_QUERY) {
console.log('fetch projects');
SC.Request.getUrl('scds/project/list').json().
notify(this, '_projectsLoaded', store, query).
send();
} else if (query === Scds.TASKS_QUERY) {
console.log('tasks query');
}
return YES; // return YES if you handled the query
},
_projectsLoaded: function(response, store, query) {
console.log('projects loaded....');
if (SC.ok(response)) {
var recordType = query.get('recordType'),
records = response.get('body');
store.loadRecords(recordType, records);
store.dataSourceDidFetchQuery(query);
Scds.Statechart.sendEvent('projectsLoaded')
} else {
console.log('oops...error loading projects');
// Tell the store that your server returned an error
store.dataSourceDidErrorQuery(query, response);
}
}
This will get the Projects, but not the tasks. Sproutcore knows that as soon as I access the tasks array on a Project, it needs to get them. What it does is call retrieveRecords in the datasource. That method in turn calls retrieveRecord for every id in the tasks array. My retrieveRecord method looks like
retrieveRecord: function(store, storeKey) {
var id = Scds.store.idFor(storeKey);
console.log('retrieveRecord called with [storeKey, id] [%#, %#]'.fmt(storeKey, id));
SC.Request.getUrl('scds/task/get/%#'.fmt(id)).json().
notify(this, "_didRetrieveRecord", store, storeKey).
send();
return YES;
},
_didRetrieveRecord: function(response, store, storeKey) {
if (SC.ok(response)) {
console.log('succesfully loaded task %#'.fmt(response.get('body')));
var dataHash = response.get('body');
store.dataSourceDidComplete(storeKey, dataHash);
} ...
},
Note that you should use sc-gen to generate your datasource, because it provides a fairly well flushed out stub that guides you towards the methods you need to implement. It does not provide a retrieveMethods implementation, but you can provide your own if you don't want to do a single request for each child record you are loading.
Note that you always have options. If I wanted to, I could have created a Tasks query and loaded all the tasks data up front, that way I wouldn't need to go to my server when I clicked a project. So in answer to your second question, it depends. You can either load the brands when you click on the client, or you can load all the data up front, which is probably a good idea if there isn't that much data.