mk_graphql 1.0.0
mk_graphql: ^1.0.0 copied to clipboard
A clean, modern, simplified GraphQL client for Dart & Flutter with normalized caching, composable links, and stream-based operation execution.
mk_graphql #
A clean, modern, simplified GraphQL client for Dart and Flutter with normalized caching, composable links, typed operation execution, file uploads, SSE, and WebSockets.
β¨ Features #
- π Composable Link Architecture: Chain
AuthLink,DioLink,SseLink,WebSocketLink,HttpLink,BatchLink, andTypenameLink. - π First-Class Authentication: Automatic 401 handling, thread-safe asynchronous token refreshing, token queueing, and revocation hooks.
- π‘ Multiple Transports:
- HTTP/REST: Built-in
DioLinkand standardHttpLink. - Server-Sent Events (SSE):
SseLinkwith live subscription streaming, dynamic auth headers, and 401 refresh retries. - WebSockets:
WebSocketLinksupporting modern subscriptions.
- HTTP/REST: Built-in
- π Multipart File Uploads: Seamless GraphQL Multipart Request specification compliance for
Upload/MultipartFile. - π Request Cancellation: Direct integration with Dio's
CancelToken. - πΎ Normalized Caching: Fast in-memory cache with configurable fetch policies (
cacheFirst,networkOnly,cacheAndNetwork,cacheOnly,noCache). - β‘ Stream & Future APIs: Choose between single-shot
client.future()or reactiveclient.stream(). - πͺ΅ Built-in Logging: Pretty console logging with custom options and privacy masking.
π¦ Installation #
Add mk_graphql to your pubspec.yaml:
dependencies:
mk_graphql: ^1.0.0
Then run:
flutter pub get
π Quick Start #
1. Initialize the Client #
import 'package:mk_graphql/mk_graphql.dart';
final client = GraphQLClient(
url: 'https://api.example.com/graphql',
tokenHeader: () async {
final token = await getStoredToken();
return token != null ? {'Authorization': 'Bearer $token'} : {};
},
onTokenRefresh: (dioLink) async {
final newToken = await refreshUserToken();
return newToken != null ? {'Authorization': 'Bearer $newToken'} : null;
},
);
2. Execute Queries & Mutations #
// Using generated or custom GraphQLRequest
final response = await client.future(myRequest);
if (response.hasErrors) {
print('Errors: ${response.errors}');
} else {
print('Data: ${response.data}');
}
3. Subscriptions (SSE or WebSockets) #
For Server-Sent Events (SSE):
final client = GraphQLClient(
url: 'https://api.example.com/graphql',
sseUrl: 'https://api.example.com/graphql/sse',
tokenHeader: () async => {'Authorization': 'Bearer $token'},
);
client.stream(mySubscriptionRequest).listen((response) {
print('Real-time event: ${response.data}');
});
4. Multipart File Uploads #
import 'package:dio/dio.dart';
import 'package:mk_graphql/mk_graphql.dart';
final file = MultipartFile.fromFileSync('/path/to/avatar.png', filename: 'avatar.png');
final uploadReq = UploadAvatarReq(
variables: UploadAvatarVars(file: file),
);
final result = await client.future(uploadReq);
5. Request Cancellation with CancelToken #
final cancelToken = CancelToken();
// Cancel after 2 seconds or when user navigates away
Future.delayed(const Duration(seconds: 2), () {
cancelToken.cancel('User navigated away');
});
try {
final response = await client.future(myRequest, cancelToken: cancelToken);
} on RequestCancelledException catch (e) {
print('Request was cancelled: ${e.message}');
}
π Custom Link Composition #
Assemble custom pipelines with Link.from:
final link = Link.from([
TypenameLink(),
AuthLink(
url: 'https://api.example.com/graphql',
tokenHeader: () => {'Authorization': 'Bearer $token'},
onTokenRefresh: (dioLink) => refreshToken(),
),
DioLink('https://api.example.com/graphql'),
]);
final client = GraphQLClient.withLink(link);
π License #
This project is licensed under the MIT License - see the LICENSE file for details.