sling_gql_link 1.0.1
sling_gql_link: ^1.0.1 copied to clipboard
Run sling_gql's requests through a gql_link Link chain (auth, retries, persisted queries, websockets) as one Transport / SubscriptionTransport.
example/sling_gql_link_example.dart
// sling_gql over a gql_link chain: an auth link, a retry link and an
// HttpLink, as the client's one Transport.
//
// In a real app `Query` / `User` below are generated by `sling_gql_gen`
// (and `schema: slingSchema` replaces `rootFactory:`); they are written out
// here so the example stands on its own.
//
// type Query { me: User! }
// type User { id: ID! name: String! }
// ignore_for_file: avoid_print
import 'package:gql_http_link/gql_http_link.dart';
import 'package:gql_link/gql_link.dart';
import 'package:sling_gql/sling_gql.dart';
import 'package:sling_gql_link/sling_gql_link.dart';
Future<String> token() async => 'secret';
/// Adds `authorization` to the headers the client put in the context.
final authLink = Link.function(
(request, [forward]) => Stream.fromFuture(token()).asyncExpand(
(token) => forward!(
request.updateContextEntry<HttpLinkHeaders>(
(headers) => HttpLinkHeaders(
headers: {...?headers?.headers, 'authorization': 'Bearer $token'},
),
),
),
),
);
/// Retries twice on a server error.
final retryLink = Link.function((request, [forward]) async* {
for (var attempt = 1; ; attempt++) {
try {
await for (final response in forward!(request)) {
yield response;
}
return;
} on ServerException {
if (attempt == 3) rethrow;
}
}
});
Future<void> main() async {
const endpoint = 'https://api.example.com/graphql';
final link = Link.from([authLink, retryLink, HttpLink(endpoint)]);
final client = SlingClient<Query>(
endpoint: Uri.parse(endpoint), // nominal: the HttpLink sends
rootFactory: Query.root,
headers: const {'x-app-version': '1.2.0'}, // reach the link's context
transport: linkTransport(link),
// With a websocket link routed by `Link.split`, subscriptions too:
// subscriptionTransport: linkSubscriptionTransport(link),
);
try {
print(await client.resolve((q) => q.me.name));
} on SlingException catch (e) {
print('${e.message} (${e.runtimeType})');
} finally {
client.dispose();
await link.dispose();
}
}
// --- What sling_gql_gen would generate ---------------------------------------
class Query extends Accessor {
Query(super.recorder, super.selection, super.path);
Query.root(Recorder r) : super(r, r.root, const []);
User get me => object('me', User.new, keyed: true)!;
}
class User extends Accessor {
User(super.recorder, super.selection, super.path);
String? get id => scalar<String>('id');
String? get name => scalar<String>('name');
}