Skip to content

Commit 573663f

Browse files
committed
feat: graphql api
1 parent 8f5093d commit 573663f

7 files changed

Lines changed: 187 additions & 5 deletions

File tree

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,31 @@ public class Main {
103103
}
104104
```
105105

106+
## GraphQL API
107+
108+
This library also provides possibility to use [GraphQL API](https://support.crowdin.com/developer/graphql-api/)
109+
110+
```java
111+
import com.crowdin.client.Client;
112+
import com.crowdin.client.core.model.Credentials;
113+
import com.crowdin.client.core.model.GraphQLRequest;
114+
115+
import java.util.Map;
116+
117+
public class GraphQLExample {
118+
119+
public static void main(String[] args) {
120+
Credentials credentials = new Credentials("token", "organization");
121+
Client client = new Client(credentials);
122+
String query = "query { viewer { projects(first: 2) { edges { node { name } } } } }";
123+
GraphQLRequest request = new GraphQLRequest(query);
124+
Map<String, Object> response = client.graphql(request).getData();
125+
System.out.println(response);
126+
}
127+
128+
}
129+
```
130+
106131
## Seeking Assistance
107132

108133
If you find any problems or would like to suggest a feature, please read the [How can I contribute](/CONTRIBUTING.md#how-can-i-contribute) section in our contributing guidelines.

src/main/java/com/crowdin/client/core/CrowdinApi.java

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package com.crowdin.client.core;
22

33
import com.crowdin.client.core.http.HttpClient;
4+
import com.crowdin.client.core.http.HttpRequestConfig;
45
import com.crowdin.client.core.http.JsonTransformer;
56
import com.crowdin.client.core.http.impl.http.ApacheHttpClient;
67
import com.crowdin.client.core.http.impl.json.JacksonJsonTransformer;
7-
import com.crowdin.client.core.model.ClientConfig;
8-
import com.crowdin.client.core.model.Credentials;
8+
import com.crowdin.client.core.model.*;
99
import org.apache.http.client.config.CookieSpecs;
1010
import org.apache.http.client.config.RequestConfig;
1111
import org.apache.http.impl.client.HttpClientBuilder;
@@ -19,6 +19,7 @@ public abstract class CrowdinApi {
1919
protected final HttpClient httpClient;
2020
protected final ClientConfig clientConfig;
2121
protected final String url;
22+
protected final String graphqlUrl;
2223

2324
public CrowdinApi(Credentials credentials) {
2425
this(credentials, ClientConfig.builder()
@@ -38,23 +39,50 @@ public CrowdinApi(Credentials credentials, ClientConfig clientConfig) {
3839
defaultHeaders.put("X-Crowdin-Integrations-User-Agent", clientConfig.getIntegrationUserAgent());
3940
}
4041
JsonTransformer jsonTransformer = (clientConfig.getJsonTransformer() != null)
41-
? clientConfig.getJsonTransformer() : new JacksonJsonTransformer();
42+
? clientConfig.getJsonTransformer() : new JacksonJsonTransformer();
4243
this.httpClient = (clientConfig.getHttpClient() != null)
43-
? clientConfig.getHttpClient()
44-
: new ApacheHttpClient(credentials, jsonTransformer, defaultHeaders, clientConfig.getProxy(), clientConfig.getProxyCreds(), clientConfig.getHttpTimeoutMs());
44+
? clientConfig.getHttpClient()
45+
: new ApacheHttpClient(credentials, jsonTransformer, defaultHeaders, clientConfig.getProxy(), clientConfig.getProxyCreds(), clientConfig.getHttpTimeoutMs());
4546
this.clientConfig = clientConfig;
4647
if (credentials.getBaseUrl() != null) {
4748
if (credentials.getBaseUrl().endsWith("/")) {
4849
this.url = credentials.getBaseUrl() + "api/v2";
50+
this.graphqlUrl = credentials.getBaseUrl() + "api/graphql";
4951
} else {
5052
this.url = credentials.getBaseUrl() + "/api/v2";
53+
this.graphqlUrl = credentials.getBaseUrl() + "/api/graphql";
5154
}
5255
} else {
5356
if (credentials.getOrganization() != null) {
5457
this.url = "https://" + credentials.getOrganization() + ".api.crowdin.com/api/v2";
58+
this.graphqlUrl = "https://" + credentials.getOrganization() + ".api.crowdin.com/api/graphql";
5559
} else {
5660
this.url = "https://api.crowdin.com/api/v2";
61+
this.graphqlUrl = "https://api.crowdin.com/api/graphql";
5762
}
5863
}
5964
}
65+
66+
/**
67+
* @param request request object
68+
* @return newly created bundle
69+
* @see <ul>
70+
* <li><a href="https://support.crowdin.com/developer/graphql-api/" target="_blank"><b>API Documentation</b></a></li>
71+
* </ul>
72+
*/
73+
public ResponseObject<Map<String, Object>> graphql(GraphQLRequest request) {
74+
GraphQLResponse response = this.graphql(request, GraphQLResponse.class);
75+
return ResponseObject.of(response.getData());
76+
}
77+
78+
/**
79+
* @param request request object
80+
* @return newly created bundle
81+
* @see <ul>
82+
* <li><a href="https://support.crowdin.com/developer/graphql-api/" target="_blank"><b>API Documentation</b></a></li>
83+
* </ul>
84+
*/
85+
public <T> T graphql(GraphQLRequest request, Class<T> clazz) {
86+
return this.httpClient.post(this.graphqlUrl, request, new HttpRequestConfig(), clazz);
87+
}
6088
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.crowdin.client.core.model;
2+
3+
import lombok.Data;
4+
5+
import java.util.Map;
6+
7+
@Data
8+
public class GraphQLRequest {
9+
10+
private String query;
11+
private Map<String, Object> variables;
12+
private String operationName;
13+
14+
public GraphQLRequest() {
15+
}
16+
17+
public GraphQLRequest(String query) {
18+
this();
19+
this.query = query;
20+
}
21+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.crowdin.client.core.model;
2+
3+
import lombok.Data;
4+
5+
import java.util.Map;
6+
7+
@Data
8+
public class GraphQLResponse {
9+
10+
private Map<String, Object> data;
11+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package com.crowdin.client.core;
2+
3+
import com.crowdin.client.core.model.GraphQLRequest;
4+
import com.crowdin.client.framework.RequestMock;
5+
import com.crowdin.client.framework.TestClient;
6+
import lombok.Data;
7+
import lombok.var;
8+
import org.apache.http.client.methods.HttpPost;
9+
import org.junit.jupiter.api.Test;
10+
11+
import java.util.Arrays;
12+
import java.util.List;
13+
import java.util.Map;
14+
15+
import static org.junit.jupiter.api.Assertions.assertEquals;
16+
17+
public class CrowdinApiTest extends TestClient {
18+
19+
@Override
20+
public List<RequestMock> getMocks() {
21+
return Arrays.asList(
22+
RequestMock.build(this.graphqlUrl, HttpPost.METHOD_NAME, "api/core/graphQLRequest.json",
23+
"api/core/graphQLResponse.json")
24+
);
25+
}
26+
27+
@Test
28+
public void graphQLTest() {
29+
var res = this.graphql(new GraphQLRequest("query { viewer { projects(first: 2) { edges { node { name } } } } }"));
30+
var edges = List.class.cast(Map.class.cast(Map.class.cast(Map.class.cast(res.getData().get("viewer")).get("projects"))).get("edges"));
31+
assertEquals(2, edges.size());
32+
assertEquals("test1", Map.class.cast(Map.class.cast(edges.get(0)).get("node")).get("name").toString());
33+
assertEquals("test2", Map.class.cast(Map.class.cast(edges.get(1)).get("node")).get("name").toString());
34+
}
35+
36+
@Test
37+
public void graphQLCustomTypeTest() {
38+
var res = this.graphql(new GraphQLRequest("query { viewer { projects(first: 2) { edges { node { name } } } } }"), GraphQLRes.class);
39+
assertEquals(2, res.getData().getViewer().getProjects().getEdges().size());
40+
assertEquals("test1", res.getData().getViewer().getProjects().getEdges().get(0).getNode().getName());
41+
assertEquals("test2", res.getData().getViewer().getProjects().getEdges().get(1).getNode().getName());
42+
}
43+
44+
@Data
45+
public static class GraphQLRes {
46+
47+
private GraphQLResData data;
48+
49+
@Data
50+
public static class GraphQLResData {
51+
private GraphQLResViewer viewer;
52+
}
53+
54+
@Data
55+
public static class GraphQLResViewer {
56+
private GraphQLResProjects projects;
57+
}
58+
59+
@Data
60+
public static class GraphQLResProjects {
61+
private List<GraphQLResEdge> edges;
62+
}
63+
64+
@Data
65+
public static class GraphQLResEdge {
66+
private GraphQLResNode node;
67+
}
68+
69+
@Data
70+
public static class GraphQLResNode {
71+
private String name;
72+
}
73+
}
74+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"query": "query { viewer { projects(first: 2) { edges { node { name } } } } }"
3+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"data": {
3+
"viewer": {
4+
"projects": {
5+
"edges": [
6+
{
7+
"node": {
8+
"name": "test1"
9+
}
10+
},
11+
{
12+
"node": {
13+
"name": "test2"
14+
}
15+
}
16+
]
17+
}
18+
}
19+
}
20+
}

0 commit comments

Comments
 (0)