apollographql / meteor-integration

🚀 meteor add apollo
http://dev.apollodata.com/core/meteor.html
108 stars 45 forks source link

Suggestion: Use the DDP connection as a network interface #39

Closed jamiter closed 8 years ago

jamiter commented 8 years ago

Meteor supplies us with a great websocket implementation with authentication, retries and more. We could simply leverage this power by making a network interface that calls a DDP method:

Client

// ddp-network-interface.js
class DDPNetworkInterface {
    constructor({
        connection,
        noRetry = true,
        method = '/graphql' } = {}
    ) {
        this.connection = connection;
        this.noRetry = noRetry;
        this.method = method;
    }

    query(request) {
        return new Promise((resolve, reject) => {
            this.connection.apply(this.method, [request], { noRetry: this.noRetry }, (err, data) => {
                if (err) {
                    reject(err);
                } else {
                    resolve(data);
                }
            });
        });
    }
}

export { DDPNetworkInterface };
// client.js
import ApolloClient from 'apollo-client';
import { DDPNetworkInterface } from './ddp-network-interface';

export const client = new ApolloClient ({
  networkInterface: new DDPNetworkInterface({ connection: Meteor.connection })
})

Server

import { schema } from './schema';
import { runQuery } from 'apollo-server';

export const methods = {
    '/graphql'({ query, variables }) {
        this.unblock();

        const { userId } = this;

        return runQuery({
            schema,
            query,
            variables,
            context: {
                userId
            }
        }).await();
    }
};

Meteor.methods(methods);

I'm testing this for our own app and it's seems to work perfectly so far.

If people are interested in this I would love to make a PR for it. What do you think @lorensr?

lorensr commented 8 years ago

Nice! @stubailo ? Are there any downsides?

Maybe this could be the default connection for meteor clients, for network efficiency's sake, and then we could also keep the /graphql rest endpoint with current auth logic to support graphiql (on by default in dev) and prod rest API (off by default in prod)?

markudevelop commented 8 years ago

that is a really cool way of thinking, that will also make apollo subscriptions easier to manage with meteor :)

stubailo commented 8 years ago

Honestly I'm not a big fan of this because there's a huge risk that the Meteor-specific transport will fall behind new features in the "standard" one. For example, if Meteor is doing retries under the hood and Apollo gets retry functionality, things are going to get weird.

jamiter commented 8 years ago

@stubailo, thanks for the feedback. I understand the hesitation.

For websockets there isn't a good standard yet though (is there?), but we require a websocket connection for our specific app. So for me it looked like needless work to create a new websocket connection and implement authentication and everything, while I get it for free in Meteor. subscriptions-transport-ws is still WIP, so this seems like a safe bet until it's ready.

For who's interested in using this, we open-sourced the above implementation: https://github.com/Swydo/ddp-apollo

meteor add swydo:ddp-apollo
lorensr commented 8 years ago

Thanks for open-sourcing!