webSocketLinkForNhost function

Link webSocketLinkForNhost(
  1. String nhostGqlEndpointUrl,
  2. HasuraAuthClient nhostAuth,
  3. {Map<String, String>? defaultHeaders = const {},
  4. @visibleForTesting ChannelGenerator? testChannelGenerator,
  5. @visibleForTesting Duration? testInactivityTimeout,
  6. @visibleForTesting Duration testReconnectTimeout = const Duration(seconds: 3)}
)

Creates a web socket link that configures (and reconfigures) automatically based on nhostAuth's authentication state.

nhostGqlEndpointUrl can be found at NhostClient.gqlEndpointUrl.

defaultHeaders (optional) A set of headers that will be provided in the initial payload when opening the socket.

Implementation

Link webSocketLinkForNhost(
  String nhostGqlEndpointUrl,
  HasuraAuthClient nhostAuth, {
  Map<String, String>? defaultHeaders = const {},
  @visibleForTesting ChannelGenerator? testChannelGenerator,
  @visibleForTesting Duration? testInactivityTimeout,
  @visibleForTesting Duration testReconnectTimeout = const Duration(seconds: 3),
}) {
  final uri = Uri.parse(nhostGqlEndpointUrl);
  final wsEndpointUri = uri.replace(
    scheme: uri.scheme == 'https' ? 'wss' : 'ws',
  );

  WebSocketChannel? channel;
  final channelGenerator = testChannelGenerator != null
      ? (() async => channel = await testChannelGenerator()) as ChannelGenerator
      : () {
          log.finest('Creating GraphQL web socket, uri=$wsEndpointUri');
          return channel = WebSocketChannel.connect(
            wsEndpointUri,
            protocols: ['graphql-ws'],
          );
        };

  // If authentication state changes, we reconnect the socket, which will also
  // re-evaluate the initialPayload to provide the auth header if available.
  nhostAuth.addTokenChangedCallback(
    () {
      if (channel != null) {
        log.finest('Reconnecting GraphQL web socket as result of token change');
        channel?.sink.close(webSocketNormalCloseCode, 'Auth changed');
      }
    },
  );
  final webSocketLink = WebSocketLink(
    /* url — provided via channelGenerator */ null,
    autoReconnect: true,
    channelGenerator: channelGenerator,
    initialPayload: () => {
      'headers': {
        ...?defaultHeaders,
        if (nhostAuth.authenticationState == AuthenticationState.signedIn)
          'Authorization': 'Bearer ${nhostAuth.accessToken}',
      },
    },
    inactivityTimeout: testInactivityTimeout,
    reconnectInterval: testReconnectTimeout,
  );

  return webSocketLink;
}