Skip to content

Commit b9921bc

Browse files
committed
clients added
1 parent 5ecbc22 commit b9921bc

File tree

3 files changed

+289
-0
lines changed

3 files changed

+289
-0
lines changed

clients/GraphQLConsoleClient.cs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// .NET Console GraphQL Client
2+
// Uses GraphQL.Client for queries, mutations, subscriptions
3+
// Add NuGet: GraphQL.Client, GraphQL.Client.Serializer.Newtonsoft
4+
5+
using System;
6+
using System.Net.Http.Headers;
7+
using System.Threading.Tasks;
8+
using GraphQL;
9+
using GraphQL.Client.Http;
10+
using GraphQL.Client.Serializer.Newtonsoft;
11+
12+
namespace GraphQLConsoleClient
13+
{
14+
class Program
15+
{
16+
private const string HTTP_URL = "http://localhost:8000/graphql";
17+
private const string WS_URL = "ws://localhost:8000/graphql-ws";
18+
private const string AUTH_TOKEN = ""; // JWT placeholder
19+
20+
static async Task Main(string[] args)
21+
{
22+
var client = new GraphQLHttpClient(new GraphQLHttpClientOptions
23+
{
24+
EndPoint = new Uri(HTTP_URL),
25+
UseWebSocketForQueriesAndMutations = false,
26+
WebSocketEndPoint = new Uri(WS_URL)
27+
}, new NewtonsoftJsonSerializer());
28+
29+
if (!string.IsNullOrEmpty(AUTH_TOKEN))
30+
{
31+
client.HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AUTH_TOKEN);
32+
}
33+
34+
// --- Query: Get All Posts ---
35+
var query = new GraphQLRequest
36+
{
37+
Query = @"query GetPosts { posts { id title content author { name email } } }"
38+
};
39+
var queryResponse = await client.SendQueryAsync<dynamic>(query);
40+
Console.WriteLine("Posts:");
41+
Console.WriteLine(queryResponse.Data);
42+
43+
// --- Mutation: Create a New Post ---
44+
var mutation = new GraphQLRequest
45+
{
46+
Query = @"mutation CreatePost($input: CreatePostInput!) { createPost(input: $input) { post { id title content } errors { message } } }",
47+
Variables = new { input = new { title = "Hello World", content = "First post!" } }
48+
};
49+
var mutationResponse = await client.SendMutationAsync<dynamic>(mutation);
50+
Console.WriteLine("Create Post Response:");
51+
Console.WriteLine(mutationResponse.Data);
52+
53+
// --- Subscription: New Post Created ---
54+
var subscription = new GraphQLRequest
55+
{
56+
Query = @"subscription OnPostCreated { onPostCreated { id title content author { name } } }"
57+
};
58+
using var sub = client.CreateSubscriptionStream<dynamic>(subscription);
59+
await foreach (var response in sub)
60+
{
61+
Console.WriteLine("New post created:");
62+
Console.WriteLine(response.Data);
63+
}
64+
}
65+
}
66+
}

clients/README.md

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# GraphQL Client Integration Guide
2+
3+
This directory contains ready-to-use GraphQL client programs for consuming the DotNet API Boilerplate GraphQL endpoint. Both frontend (TypeScript) and backend (.NET Core) clients are provided, supporting queries, mutations, and subscriptions.
4+
5+
---
6+
7+
## 1. TypeScript Client (Web/Mobile/Framework Agnostic)
8+
9+
**File:** `graphql-client.ts`
10+
11+
### Features
12+
- Connects to GraphQL endpoint via HTTP and WebSocket (`/graphql`, `/graphql-ws`)
13+
- Supports queries, mutations, and subscriptions
14+
- JWT authentication placeholder (add your token if needed)
15+
- Framework-agnostic, works with any TypeScript/JavaScript app
16+
17+
### Setup
18+
1. Install dependencies:
19+
```sh
20+
npm install graphql-ws
21+
# or
22+
yarn add graphql-ws
23+
```
24+
2. Copy `graphql-client.ts` into your project.
25+
3. Update endpoint URLs and authentication token as needed.
26+
27+
### Usage Example
28+
```typescript
29+
import { subscribeNewBlog, getBlogs, createBlog } from './graphql-client';
30+
31+
// Subscribe to new blog creation
32+
subscribeNewBlog();
33+
34+
// Query all blogs
35+
getBlogs().then(console.log);
36+
37+
// Create a new blog
38+
createBlog({ name: 'Tech Blog', description: 'A blog about tech', authorName: 'John Doe', tags: ['tech'] }).then(console.log);
39+
```
40+
41+
---
42+
43+
## 2. .NET Console Client (Backend/API Integration)
44+
45+
**File:** `GraphQLConsoleClient.cs`
46+
47+
### Features
48+
- Connects to GraphQL endpoint via HTTP and WebSocket (`/graphql`, `/graphql-ws`)
49+
- Supports queries, mutations, and subscriptions
50+
- JWT authentication placeholder (add your token if needed)
51+
- Console app, can be used as a service or starter for integration
52+
53+
### Setup
54+
1. Create a new .NET console project:
55+
```sh
56+
dotnet new console -n GraphQLConsoleClient
57+
cd GraphQLConsoleClient
58+
```
59+
2. Add NuGet packages:
60+
```sh
61+
dotnet add package GraphQL.Client
62+
dotnet add package GraphQL.Client.Serializer.Newtonsoft
63+
```
64+
3. Copy `GraphQLConsoleClient.cs` into your project and replace `Program.cs`.
65+
4. Update endpoint URLs and authentication token as needed.
66+
67+
### Usage Example
68+
Run the console app:
69+
```sh
70+
dotnet run
71+
```
72+
- Prints queried posts
73+
- Prints mutation result for creating a post
74+
- Prints new post data as received via subscription
75+
76+
---
77+
78+
## Endpoints
79+
- **HTTP:** `http://localhost:8000/graphql`
80+
- **WebSocket:** `ws://localhost:8000/graphql-ws`
81+
82+
## Authentication
83+
- No authentication required by default
84+
- Add JWT token to `AUTH_TOKEN` variable if needed
85+
86+
## Supported Operations
87+
- **Queries:** Get blogs, get posts, etc.
88+
- **Mutations:** Create blog, create post, etc.
89+
- **Subscriptions:** On blog created, on post created, etc.
90+
91+
## Customization
92+
- Update queries, mutations, and subscriptions as per your schema
93+
- Add error handling, logging, and UI integration as needed
94+
95+
## Troubleshooting
96+
- Ensure the API server is running and accessible
97+
- Check endpoint URLs and ports
98+
- For subscriptions, ensure WebSocket support is enabled on the server
99+
100+
---
101+
102+
For further help, see the main project README or contact the API maintainer.

clients/graphql-client.ts

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
// TypeScript GraphQL Client (framework agnostic)
2+
// Uses graphql-ws for subscriptions
3+
// Queries, Mutations, Subscriptions
4+
5+
import { createClient } from 'graphql-ws';
6+
7+
const WS_URL = 'ws://localhost:8000/graphql-ws';
8+
const HTTP_URL = 'http://localhost:8000/graphql';
9+
const AUTH_TOKEN = '';
10+
11+
// Subscription: New Blog Created
12+
const SUBSCRIBE_NEW_BLOG = `
13+
subscription OnBlogCreated {
14+
onBlogCreated {
15+
id
16+
name
17+
description
18+
authorName
19+
tags
20+
createdAt
21+
}
22+
}
23+
`;
24+
25+
// Query: Get All Blogs with Posts
26+
const QUERY_BLOGS = `
27+
query GetBlogsWithPosts {
28+
blogs {
29+
id
30+
name
31+
description
32+
posts {
33+
id
34+
title
35+
content
36+
author {
37+
name
38+
email
39+
}
40+
comments {
41+
id
42+
content
43+
author
44+
}
45+
}
46+
}
47+
}
48+
`;
49+
50+
// Mutation: Create a New Blog
51+
const MUTATION_CREATE_BLOG = `
52+
mutation CreateBlog($input: CreateBlogInput!) {
53+
createBlog(input: $input) {
54+
blog {
55+
id
56+
name
57+
description
58+
authorName
59+
tags
60+
createdAt
61+
}
62+
errors {
63+
message
64+
}
65+
}
66+
}
67+
`;
68+
69+
// --- Subscription Client ---
70+
export function subscribeNewBlog() {
71+
const client = createClient({
72+
url: WS_URL,
73+
connectionParams: {
74+
Authorization: AUTH_TOKEN ? `Bearer ${AUTH_TOKEN}` : undefined,
75+
},
76+
});
77+
78+
return client.subscribe(
79+
{
80+
query: SUBSCRIBE_NEW_BLOG,
81+
},
82+
{
83+
next: (data) => console.log('New blog created:', data),
84+
error: (err) => console.error('Subscription error:', err),
85+
complete: () => console.log('Subscription complete'),
86+
}
87+
);
88+
}
89+
90+
// --- Query Client ---
91+
export async function getBlogs() {
92+
const res = await fetch(HTTP_URL, {
93+
method: 'POST',
94+
headers: {
95+
'Content-Type': 'application/json',
96+
...(AUTH_TOKEN && { Authorization: `Bearer ${AUTH_TOKEN}` }),
97+
},
98+
body: JSON.stringify({ query: QUERY_BLOGS }),
99+
});
100+
const json = await res.json();
101+
return json.data;
102+
}
103+
104+
// --- Mutation Client ---
105+
export async function createBlog(input: any) {
106+
const res = await fetch(HTTP_URL, {
107+
method: 'POST',
108+
headers: {
109+
'Content-Type': 'application/json',
110+
...(AUTH_TOKEN && { Authorization: `Bearer ${AUTH_TOKEN}` }),
111+
},
112+
body: JSON.stringify({ query: MUTATION_CREATE_BLOG, variables: { input } }),
113+
});
114+
const json = await res.json();
115+
return json.data;
116+
}
117+
118+
// Usage Example
119+
// subscribeNewBlog();
120+
// getBlogs().then(console.log);
121+
// createBlog({ name: 'Tech Blog', description: 'A blog about tech', authorName: 'John Doe', tags: ['tech'] }).then(console.log);

0 commit comments

Comments
 (0)