sling_gql_link

Run sling_gql's requests through a gql_link Link chain โ€” auth, retries, persisted queries, websockets, whatever links you already have โ€” as the one Transport a SlingClient takes. sling_gql itself stays http-only.

Docs: https://tpucci.github.io/sling_gql/guides/transport/ ยท Source: https://github.com/tpucci/sling_gql

flutter pub add sling_gql_link gql_link gql_http_link
import 'package:gql_http_link/gql_http_link.dart';
import 'package:gql_link/gql_link.dart';
import 'package:sling_gql_link/sling_gql_link.dart';

final link = Link.from([authLink, retryLink, HttpLink(endpoint)]);

final client = SlingClient<Query>(
  endpoint: Uri.parse(endpoint), // nominal: the terminating link sends
  schema: slingSchema,
  transport: linkTransport(link),
  // Subscriptions too, when the link can run them (a websocket link routed
  // with Link.split):
  subscriptionTransport: linkSubscriptionTransport(link),
);

What goes in

Each batched document is parsed into the Request's DocumentNode, with its variables and operationName (sling_gql's own documents are anonymous). SlingClient.headers are put in the context as HttpLinkHeaders, so an auth link adds to them with request.updateContextEntry<HttpLinkHeaders>(...); content-type and accept are left to the terminating link.

What comes out

The first Response of the link's stream is the result: data, errors (message, locations, path, extensions) and extensions are encoded back into a JSON body the client handles exactly like an HTTP response โ€” partial errors pruned before caching and reported on the scope, data: null a SlingException.

A LinkException becomes a SlingLinkException (a SlingException):

Link exception message statusCode graphqlErrors
ServerException with a status >= 300 (HttpLinkServerException) HTTP <code> the status the body's errors
HttpLinkParserException with a status >= 300 (a 502 HTML page, an empty 401: HttpLink parses before it checks the status) HTTP <code> the status []
ServerException with errors, no error status the errors' messages the status, if any the errors
ServerException with neither data nor errors Empty response the status, if any []
ServerException of a failed connection the cause's message null []
HttpLinkParserException of a 2xx the cause's message the status []
any other LinkException the cause's message null []

linkException keeps what the link threw (and its originalException). Errors that are not LinkExceptions (a TimeoutException from your own link) surface unchanged, as with the default transport.

Subscriptions

linkSubscriptionTransport(link) maps the link's stream one to one: each Response is an event, the stream completing completes the subscription, an error is a transport failure (which reconnects when the subscription has a retryAfter), and cancelling the subscription cancels the link's stream. HttpLink cannot run subscriptions; route them to a websocket link:

final link = Link.split(
  (request) =>
      request.operation.getOperationType() == OperationType.subscription,
  websocketLink,
  Link.from([authLink, HttpLink(endpoint)]),
);

Or keep sling_gql's default GraphQL-over-SSE subscriptions and only pass transport:.

Libraries

sling_gql over gql_link: linkTransport and linkSubscriptionTransport turn a Link chain (auth, retries, persisted queries, websockets) into the one Transport / SubscriptionTransport a SlingClient takes, so the runtime itself stays http-only.