[SOLVED] Meteor create --apollo: Context in Resolvers?

My app uses Apollo. I’m updating it to use apollo-server-express, following the sample code generated using Meteor create --apollo.

My client is successfully connecting to my Apollo resolvers. However, I have not yet figured out how to capture context including the user id.

Following the sample code from Meteor create --apollo, I have:

import { getUser } from 'meteor/apollo';
[.....]
const server = new ApolloServer({
    typeDefs,
    resolvers,
    context: async ({ req }) => ({
        user: await getUser(req.headers.authorization)
    })
});

A typical resolver looks like this:

messageFolders: function (_, args, context) {
	const user = context.user;
	[.....]	

A breakpoint in this resolver shows context.user as undefined, even with a user logged in:

How can I correct this?

Your resolver needs to be an async function. So something like this:

messageFolders: async (obj, _, { user }) => {
  // now you should get user
}
1 Like

With:

        messageFolders: async (obj, _, { user }) => {
            debugger;

user is still coming in as undefined.

:thinking:

Interesting: if I do it like this as a test:

const server = new ApolloServer({
    typeDefs,
    resolvers,
    context: {'user': 'testing 123'}
});

…then it successfully comes into the resolver:

…which means that there’s something I need to do to help getUser:

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

Here’s what getUser looks like, located at .meteor/packages/apollo/4.1.0/web.browser/src/client.js, as a field of MeteorAccountsLink:

import { ApolloLink } from '@apollo/client'
import { Accounts } from 'meteor/accounts-base'

const DEFAULT_HEADER = 'authorization'

export const MeteorAccountsLink = ({ headerName = DEFAULT_HEADER } = {}) =>
  new ApolloLink((operation, forward) => {
    const token = Accounts._storedLoginToken()

    if (token) {
      operation.setContext(() => ({
        headers: {
          [headerName]: token,
        },
      }))
    }

    return forward(operation)
  })

What am I missing?

SOLVED.

The sample code provided by Meteor create --apollo at /meteor-apollo-app/imports/ui/App.jsx contains a couple of commented-out lines referencing MeteorAccountsLink:

import React from 'react';
import { InMemoryCache, ApolloProvider, ApolloClient, ApolloLink } from '@apollo/client';
import { BatchHttpLink } from '@apollo/client/link/batch-http'
// import { MeteorAccountsLink } from 'meteor/apollo'
import { Hello } from './Hello.jsx';
import { Info } from './Info.jsx';

debugger;
const cache = new InMemoryCache().restore(window.__APOLLO_STATE__);

const link = ApolloLink.from([
  // MeteorAccountsLink(),
  new BatchHttpLink({
    uri: '/graphql'
  })
]);

const client = new ApolloClient({
  uri: '/graphql',
  cache,
  link,
});

export const App = () => (
  <ApolloProvider client={client}>
    <div>
      <h1>Welcome to Meteor! ☄</h1>
      <Hello/>
      <Info/>
    </div>
  </ApolloProvider>
);

Un-commenting them fixed the anomaly. :grinning:

1 Like

Yes, if I remember correctly the users package is needed so that is why they were commented out by default.