[SOLVED] Using `client.subscribe` does not work? (to AppSync, from Node)

I have a working Python code (see the subscription_client.py code on this page) that does receive subscriptions from AWS AppSync. I have tried to replicate the same thing in Node.js with Apollo Client but it does not work - connection to AppSync succeeds (according to the WebSocketLink鈥檚 connectionCallback) but I never get any data. And if I subscribe to a subscription that does not exist, I do not get any error. What do I do wrong? :pray:

const { ApolloClient, InMemoryCache, gql } = require("@apollo/client");
const { WebSocketLink } = require('@apollo/client/link/ws');
const ws = require('ws');

const API_URL = "https://<some id>.appsync-api.eu-west-1.amazonaws.com/graphql"
const API_KEY = "da2-<secret>"
const WSS_URL = API_URL.replace('https','wss').replace('appsync-api','appsync-realtime-api')
const HOST = API_URL.replace('https://','').replace('/graphql','')
const api_header = {
  'host': HOST,
  'x-api-key': API_KEY
}
const header_encode = obj => btoa(JSON.stringify(obj));
const connection_url = WSS_URL + '?header=' + header_encode(api_header) + '&payload=e30='
console.log("connection_url", connection_url);

const wsLink = new WebSocketLink({
uri: connection_url,
webSocketImpl: ws,
options: {
  timeout: 1000,
  connectionCallback: (err, res) => console.log("connectionCallback", err ? "ERR" : "OK", err)
}
});

const client = new ApolloClient({
  cache: new InMemoryCache(),
  link: wsLink,
});

client.subscribe({
  query: gql`
  subscription JhTestSubscription {
onOrderAndRequestOwnerConsent(id: "281c6d08-146b-4b05-aeb9-ef12c5ed1cc5") {
  id,orderId,state}
}
  `,
  variables: {},
  fetchPolicy: 'network-only'
}).subscribe({
  next(v) { console.log("subs. result", v); }, // never printed
  error(err) { console.log("subs. err", err); }, // never printed
  complete() { console.log("subs. DONE"); }, // never printed
});

setTimeout(() => console.log("50s have passed..."), 50000);
// package.json
  "dependencies": {
    "@apollo/client": "^3.3.19",
    "cross-fetch": "^3.1.4",
    "graphql": "^15.5.0",
    "react": "^17.0.2",
    "subscriptions-transport-ws": "^0.9.18",
    "ws": "^7.4.6"
  }

SOLVED: see Document how to use client with AppSync 路 Issue #224 路 apollographql/apollo-feature-requests 路 GitHub

Interesting, I wasn鈥檛 even aware that ApolloClient had a subscribe function, which is why I can鈥檛 help you with that specifically, but have you tried the useSubscription hook as presented in the guide here? Subscriptions - Client (React) - Apollo GraphQL Docs

I鈥檝e been using that extensively, and it works like a charm.

Yes, I have. The same problem - it does not work. The code above is just a simplification so that I can test it by running a single node script.

Update: I I have described in Using Apollo with AppSync directly on iOS - #3 by holyjak, I am getting the same error as the author there:

ws.msg {"type":"connection_ack","payload":{"connectionTimeoutMs":300000}}
ws.msg {"type":"ka"}
ws.msg {"type":"error","payload":{"errors":[{"errorType":"UnsupportedOperation","message":"unknown not supported through the realtime channel"}]}}

The problem is also discussed in this AWS forum /message.jspa?messageID=935705 with some valuable reference, with this conclusion:

To get AppSync Subscriptions working with subscription-transport-ws, you need to follow the instructions in this GitHub issue: Document how to use client with AppSync 路 Issue #224 路 apollographql/apollo-feature-requests 路 GitHub

Solved by the code in Document how to use client with AppSync 路 Issue #224 路 apollographql/apollo-feature-requests 路 GitHub - i.e. we need to format the data as AppSync expects, include auth with each request, and ignore messages the client cannot handle.