gql-dart / ferry

Stream-based strongly typed GraphQL client for Dart
https://ferrygraphql.com/
MIT License
602 stars 116 forks source link

docs: subscription is missing #289

Open jjangga0214 opened 3 years ago

jjangga0214 commented 3 years ago

Screenshot from 2021-10-03 13-48-04

Subscription is missing..!

mnts commented 2 years ago

it seems like they don't care

smkhalsa commented 2 years ago

PRs welcome

SOMONSOUM commented 9 months ago

I can't find the doc about how to use subscription too.

knaeckeKami commented 9 months ago

PRs are still welcome!

cmaccarone commented 1 week ago

Do subscriptions actually work with ferry? I am trying to get them to work an haven't had success yet. I am integrating with Apollo Graphql

knaeckeKami commented 1 week ago

Yes.

cmaccarone commented 1 week ago

Awesome, are there any examples anywhere? I'd be happy to add an example to the docs after I figure it out

knaeckeKami commented 1 week ago

you likely need a split link as shown in https://pub.dev/packages/graphql#subscriptions and you probably want to use the newer protocol implemented by TransportWebsocketLink

cmaccarone commented 1 week ago

does this look right?

Here is where I am trying to create the stream from the WS. I guess mainly my question is if I am doing this correctly. Do I use the same .request method call for all types of Operations (query, mutation, and subscription)?

Stream<PlatformDownloadProgress?> getDownloadProgress(String adPlatformId) {
    final request = GProgressReq(
      (b) => b..vars.progressId = adPlatformId,
    );

    try {
      final resultStream =
          _graphQLService.request<GProgressData, GProgressVars>(request);
      return resultStream.asyncMap((response) {
        final data = response.data?.progress;        
        if (data != null) {
          return PlatformDownloadProgress(
            id: data.id,
            entities: data.entities,
            metrics: data.metrics,
          );
        }
        return null;
      });
    } catch (e) {
      print('Failed to get download progress: $e');
      rethrow;
    }
  }

This is utilizing a graphQl service class that wraps ferry and does stuff like creates the links and also initializes the client, and Caches tokens ect.. All regular operations are working fine query, mutation ect. I just want to make sure I am doing the subscription properly.

here is how I was creating the client

Client _client() {
    final dio = Dio();
    dio.interceptors.add(
      InterceptorsWrapper(
        onResponse: (response, handler) {
          _handleResponse(response);
          return handler.next(response);
        },
        onError: (error, handler) {
          print('Http error: ${error.message}');
          return handler.next(error);
        },
      ),
    );
    return Client(
      defaultFetchPolicies: {
        OperationType.query: FetchPolicy.NetworkOnly,
        OperationType.mutation: FetchPolicy.NetworkOnly,
        OperationType.subscription: FetchPolicy.NetworkOnly,
      },
      link: Link.from([
        DioLink(EnvConfig.env.url, client: dio, defaultHeaders: headers),
        WebSocketLink(null,
            initialPayload: webSocketHeaders,
            channelGenerator: () => WebSocketChannel.connect(Uri.parse(EnvConfig.env.socketUrl), protocols: ['graphql-transport-ws']),),
      ]),
      cache: Cache(),
    );
  }

Tmrw I will try using that graphql link package you suggested. Also last question: In the .graphql files where I put my mutations, subscriptions, and queries can I put more than one query in a single file or is it recommended to break them down? I noticed when I put more than one in a file it seems to send them all in the request.

cmaccarone commented 1 week ago

you likely need a split link as shown in https://pub.dev/packages/graphql#subscriptions and you probably want to use the newer protocol implemented by TransportWebsocketLink

Thank you this worked for me. Using the Web-socket link suggested and changing to a split link instead.

Client _client() {
    final dio = Dio();
    dio.interceptors.add(
      InterceptorsWrapper(
        onResponse: (response, handler) {
          _handleResponse(response);
          return handler.next(response);
        },
        onError: (error, handler) {
          print('Http error: ${error.message}');
          return handler.next(error);
        },
      ),
    );
    return Client(
      defaultFetchPolicies: {
        OperationType.query: FetchPolicy.NetworkOnly,
        OperationType.mutation: FetchPolicy.NetworkOnly,
        OperationType.subscription: FetchPolicy.NetworkOnly,
      },
      link: Link.split(
        (request) =>
            request.operation.getOperationType() == OperationType.subscription,
        TransportWebSocketLink(
          TransportWsClientOptions(
              socketMaker: WebSocketMaker.url(() => EnvConfig.env.socketUrl),
/// Passing in the initial socket headers for authorizing with my Apollo server.
              connectionParams: () => webSocketHeaders),
        ),
        DioLink(EnvConfig.env.url, client: dio, defaultHeaders: headers),
      ),
      cache: Cache(),
    );
  }
cmaccarone commented 1 week ago

613