Apollo-client: Difficulty upgrading to Apollo 2.0 (Meteor)

Created on 15 Sep 2017  路  8Comments  路  Source: apollographql/apollo-client

Having some trouble upgrading from 1.0 to 2.0.

First I ran:

meteor npm i --save apollo-client@beta apollo-cache-inmemory@beta apollo-link-http@beta

Then I updated my file as below:

My previous config:

import ApolloClient from 'apollo-client';
import { meteorClientConfig } from 'meteor/apollo';

const client = new ApolloClient({
  ...meteorClientConfig(),
  dataIdFromObject: (o) => {
    if (o.__typename && o._id)
      return `${o.__typename}-${o._id}`;

    return null;
  },
});

export default client;

My new config:

import ApolloClient from 'apollo-client';
import Link from 'apollo-link-http';
import Cache from 'apollo-cache-inmemory';
import { meteorClientConfig } from 'meteor/apollo';

const cache = new Cache({
  dataIdFromObject: (o) => {
    if (o.__typename && o._id)
      return `${o.__typename}-${o._id}`;

    return null;
  },
});

const client = new ApolloClient({
  link: new Link({ uri: 'http://localhost:3000' }),
  cache: cache.restore(window.__APOLLO_STATE || {}),
});

export default client;

In graphiql I get this error:

{
  "errors": [
    {
      "message": "Unknown operation named \"null\"."
    }
  ]
}

In the console when going to localhost I get:

modules.js?hash=7e87ea7a3f80914f1259a3df9e77c78fcc3b994c:52815 Uncaught (in promise) Error: Network error: Network request failed to return valid JSON
    at new ApolloError (modules.js?hash=7e87ea7a3f80914f1259a3df9e77c78fcc3b994c:52815)
    at modules.js?hash=7e87ea7a3f80914f1259a3df9e77c78fcc3b994c:53605
    at meteor.js?hash=6d285d84547b3dad9717a7c89c664b61b45ea3d8:1117
    at <anonymous>

Previous I was on:

"apollo-client": "^1.4.2",

Also, I'm not fully sure how this line fits into Apollo 2.0 setup:

import { meteorClientConfig } from 'meteor/apollo';

Most helpful comment

If anyone else comes across this, this is how I had to configure the apollo client and server to get this to work:

// graphql/client.js
import { Meteor } from 'meteor/meteor';
import { Accounts } from 'meteor/accounts-base';
import ApolloClient from 'apollo-client';
import { ApolloLink } from 'apollo-link';
import HttpLink from 'apollo-link-http';
import Cache from 'apollo-cache-inmemory';

const httpLink = new HttpLink({ uri: '/graphql' });
const middlewareLink = new ApolloLink((operation, forward) => {
  operation.setContext({
    headers: {
      'meteor-login-token': Accounts._storedLoginToken(),
    },
  });
  return forward(operation);
});

const link = middlewareLink.concat(httpLink);

const client = new ApolloClient({
  link,
  cache: new Cache().restore(window.__APOLLO_STATE__),
});

export default client;
// graphql/server.js
import { createApolloServer } from 'meteor/apollo';
import { makeExecutableSchema } from 'graphql-tools';
import { typeDefs } from './schemas';
import { resolvers } from './resolvers';

const schema = makeExecutableSchema({
  typeDefs,
  resolvers,
});

createApolloServer({
  schema,
});

The createApolloServer function looks for a header named meteor-login-token and uses it attach a user object to the context.

All 8 comments

@elie222 I think your uri is incorrected base on this line. https://github.com/apollographql/meteor-integration/blob/master/src/main-client.js#L10

And you have to using apollo-link-set-context to set custom token from meteor.

            request.options.headers['meteor-login-token'] = meteorLoginToken;

Fortunately, meteorLoginToken was exported. So:

import { meteorClientConfig, meteorLoginToken } from 'meteor/apollo';
import SetContextLink from 'apollo-link-set-context';


new SetContextLink((context) => ({
   ...context,
  headers: {
    ...context.headers,
    'meteor-login-token': meteorLoginToken(meteorClientConfig()),
  },
})),

Following document at here: https://github.com/apollographql/apollo-link/blob/master/docs/summary.md#authentication

Here is an official upgrade guide if anyone else runs into this! https://github.com/apollographql/apollo-client/blob/master/Upgrade.md#upgrading-from-custom-networkinteface-with-middleware--afterware

If anyone else comes across this, this is how I had to configure the apollo client and server to get this to work:

// graphql/client.js
import { Meteor } from 'meteor/meteor';
import { Accounts } from 'meteor/accounts-base';
import ApolloClient from 'apollo-client';
import { ApolloLink } from 'apollo-link';
import HttpLink from 'apollo-link-http';
import Cache from 'apollo-cache-inmemory';

const httpLink = new HttpLink({ uri: '/graphql' });
const middlewareLink = new ApolloLink((operation, forward) => {
  operation.setContext({
    headers: {
      'meteor-login-token': Accounts._storedLoginToken(),
    },
  });
  return forward(operation);
});

const link = middlewareLink.concat(httpLink);

const client = new ApolloClient({
  link,
  cache: new Cache().restore(window.__APOLLO_STATE__),
});

export default client;
// graphql/server.js
import { createApolloServer } from 'meteor/apollo';
import { makeExecutableSchema } from 'graphql-tools';
import { typeDefs } from './schemas';
import { resolvers } from './resolvers';

const schema = makeExecutableSchema({
  typeDefs,
  resolvers,
});

createApolloServer({
  schema,
});

The createApolloServer function looks for a header named meteor-login-token and uses it attach a user object to the context.

thanks, for the client side code I had to update a couple lines:

import { HttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';

and

cache: new InMemoryCache().restore(window.__APOLLO_STATE__),

It appears that this entire issue thread is now out-of-date. I came across it when doing an internet search and was going to follow some of the recommendations. In order to prevent other people from finding this thread and wasting time playing around with outdated techniques, I will outline the latest best practices.

apollographql/meteor-integration is now at version 3.0.0. It has MeteorAccountsLink for client-side and getUser() for server-side. There is a simple implementation at https://github.com/lorensr/test-meteor-apollo.

There is now Apollo Server 2 with Data Sources which facilitates separation of application layer and data layer. You can see a simple example of using SQL here:
https://github.com/apollographql/fullstack-workshop-server/blob/datasources/src/datasources/LikesDB.js

The ApolloServer constructor now has a dataSources option. e.g.:

import { DSBooks } from "./DSBooks.js"
import { getUser } from 'meteor/apollo'

  const server = new ApolloServer({
    typeDefs,
    resolvers,
    dataSources: () => ({
      dsBooks: new DSBooks()
    }),
    context: async ({ req }) => ({
      user: await getUser(req.headers.authorization)
    })
  })

All boiler plates or starter kits should now implement these new concepts and syntax in order to follow best practice.

Documentation like Integrating with Meteor needs to be updated.

Thanks @tab00 - there is an open PR for this: https://github.com/apollographql/apollo-client/pull/3739
We'll be getting it merged shortly. One thing to note - you might want to also check out https://github.com/Swydo/ddp-apollo. It's excellent.

there is an open PR for this

That's great, @hwillson. I hope it will show new syntax for Subscriptions using https://github.com/apollographql/subscriptions-transport-ws (with websocket link, without SubscriptionManager, and with SubscriptionServer), as I've been having trouble getting it working and have been looking around. The new documentation that you refer to still has old code.

I've been using https://github.com/Swydo/ddp-apollo for a while and it has been great. Subscriptions work well via DDPLink and is so easy to set up (very little code) in comparison to the normal official way. But I think ddp-apollo is now incompatible with the new datasources in Apollo Server 2, which is why I have been looking around.

I looked at cult-of-coders/apollo but their subscription syntax ("live queries") looks different to the standard Apollo Subscriptions syntax, which would make it difficult to refactor in future to use the official packages. With ddp-apollo you could use all the same standard Subscriptions syntax.

Was this page helpful?
0 / 5 - 0 ratings