apollo-link-persisted-queries
apollo-link-persisted-queries copied to clipboard
Question: Does apollo-link-persisted-queries support apollo-link-ws ?
And if yes, can someone provide an example?
For those looking for the answer to this, my investigation suggests no at the moment. Or at least no if you use subscription-transport-ws
and apollo-server
Firstly subscription-transport-ws
doesn't support sending queries without a .query
, attached (https://github.com/apollographql/subscriptions-transport-ws/blob/567fca89cb4578371877faee09e1630dcddff544/src/client.ts#L400)
if (!query) {
throw new Error('Must provide a query.');
}
So, even when you do add a persisted queries link in front of apollo-link-ws
you will find the websocket link and subscription client do not strip the query from the payload, making it rather useless.
const client = new ApolloClient({
cache,
typeDefs,
resolvers,
link: createPersistedQueryLink().concat(new WebSocketLink(subscriptionClient)),
});
Secondly, if you write a middleware to strip the query
field from the payload if the query has a persisted extension:
const subscriptionClient = new SubscriptionClient(`${BACKEND}/graphql`, {
reconnect: true,
}).use([
{
applyMiddleware: (operation, next) => {
if (operation.extensions?.persistedQuery) {
// as this middleware has to mutate the existing object
// this is the only option
// eslint-disable-next-line no-param-reassign
delete operation.query;
}
next();
},
},
]);
and you patch subscriptions-transport-ws
to allow payloads without a query
the server will not accept the transport over ws because "no document was provided".
This seems to be missing feature in apollo-server
where it doesn't parse the incoming persistedQuery
during the onOperation
hook: https://github.com/apollographql/apollo-server/blob/4e5c0f692564781ff3f1fc6f722a87210f63dcf6/packages/apollo-server-core/src/ApolloServer.ts#L686
I am going to look into putting a PR in to make apollo-server-core
correctly convert the persistedQuery hash to a document, as it does for http queries, and then look into a PR for making subscription-transport-ws
allow payloads to go out without .query
attribute.
There is my workaround to use persisted query with subscription:
/**
* workaround to use persisted query with subscription
* https://github.com/apollographql/apollo-link-persisted-queries/issues/18
*/
function patchSubscriptionClient(client: SubscriptionClient) {
// make client to respect
// `operation.getContext().http.includeQuery`
// so apq link can work
client.use([
{
applyMiddleware: (operation, next) => {
if (operation.query) {
operation.setContext({ query: operation.query });
}
const ctx = operation.getContext();
const includeQuery: boolean | undefined = ctx?.http?.includeQuery;
if (includeQuery) {
operation.query = ctx.query;
} else {
delete operation.query;
}
next();
},
},
]);
// allow empty query
const c = (client as unknown) as Record<string, unknown>;
const raw = c.checkOperationOptions as (...args: unknown[]) => unknown;
c.checkOperationOptions = (...args: unknown[]) => {
try {
return raw(...args);
} catch (err) {
if (err instanceof Error && err.message === 'Must provide a query.') {
return;
}
throw err;
}
};
}