Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

document how to use persisted queries #37

Closed
n1ru4l opened this issue Oct 23, 2020 · 5 comments · Fixed by #40
Closed

document how to use persisted queries #37

n1ru4l opened this issue Oct 23, 2020 · 5 comments · Fixed by #40
Labels
enhancement New feature or request good first issue Issue tackles a good aspect released Has been released and published

Comments

@n1ru4l
Copy link
Contributor

n1ru4l commented Oct 23, 2020

Story

I want to be able to only send an id instead of a full GraphQL document to the server and then read the actual GraphQL document from a hash table (maybe even asynchronous).


Edit: #36 showed that this is already possible. It just needs to be documented.

In my Socket.io GraphQL layer I choose to omit passing a context, schema, execute, subscribe etc parameters on a server factory level, but instead choose that a getParameter function must be passed to the server factory. That function is invoked for each GraphQL operation executed with the socket and the sent payload. The user can then decide to map the provided GraphQL Payload to anything else and providing a different context/schema/execute/subscribe based on that.

It has the following type signature

export type GetParameterFunctionParameter = {
  socket: SocketIO.Socket;
  graphQLPayload: {
    source: string;
    variableValues: { [key: string]: any } | null;
    operationName: string | null;
  };
};

export type GetParameterFunction = (
  parameter: GetParameterFunctionParameter
) => PromiseOrPlain<{
  graphQLExecutionParameter: {
    schema: GraphQLSchema;
    contextValue?: unknown;
    rootValue?: unknown;
    // These will overwrite the initials if provided; Useful for persisted queries etc.
    operationName?: string;
    source?: string;
    variableValues?: { [key: string]: any } | null;
  };
  execute?: typeof execute;
  subscribe?: typeof subscribe;
}>;

Which then allows doing stuff like this:

import socketIO from "socket.io";

const persistedOperations = {
    "1": "query { ping }"
    "2": "mutation { ping }"
}

const socketServer = socketIO();

const graphqlServer  = registerSocketIOGraphQLServer({
  socketServer,
  getParameter: ({ socket, graphQLPayload }) => ({
    /* The paramaters used for the operation execution. */
    graphQLExecutionParameter: {
      schema,
      rootValue:,
      contextValue: {
        socket,
      },
      // client source is just the id instead of a full document.
      // we map the id to the actual document.
      source: persistedOperations[graphQLPayload.source]
    },
  }),
});

(This design could also address #36 as the getParameter function could throw an error or return a rejected Promise etc).

graphql-transport-ws might get some inspiration from this.

@enisdenjo enisdenjo added enhancement New feature or request good first issue Issue tackles a good aspect labels Oct 23, 2020
@enisdenjo
Copy link
Owner

enisdenjo commented Oct 23, 2020

Currently you'd have a hard time setting up persisted queries because AST parsing is run on the subscribe payload query before the onSubscribe.

https://github.com/enisdenjo/graphql-transport-ws/blob/e9d8ee45487f2a81c493b1b6d8d1c209111ff878/src/server.ts#L403-L436

I will lift this limitation and then you should be able to request something like this:

{
  "id": "unique-transport-id",
  "type": "subscribe",
  "payload": {
    "query": "persisted-query-id",
    "variables": { "hey": "there" }
  }
}

Find the persisted query in onSubscribe, supplement it, validate and then execute.

@n1ru4l
Copy link
Contributor Author

n1ru4l commented Oct 23, 2020

Could we implement a handler that is run before that e.g. onOperation?

@enisdenjo
Copy link
Owner

enisdenjo commented Oct 23, 2020

Good idea! We should offer a handler like that.

However, onOperation is a better suited name for when an operation resolves, and onSubscribe for immediately when the user requests a subscription (operation execution).

The current onSubscribe has to change. Even if its a breaking change, its worthwhile! Check #40 out.

@enisdenjo
Copy link
Owner

🎉 This issue has been resolved in version 1.9.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@enisdenjo enisdenjo added the released Has been released and published label Oct 24, 2020
@enisdenjo
Copy link
Owner

Quick heads up, @n1ru4l, graphql-ws@v4.7.0 just landed, adding the extensions field in the subscribe message payload.

This means that you now can pass along the persistedQuery through that field on each subscribe as various other libraries/frameworks suggest. And of course, extend with your custom requirements. 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Issue tackles a good aspect released Has been released and published
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants