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

async registerApolloClient ? #195

Open
Dakuan opened this issue Feb 14, 2024 · 5 comments
Open

async registerApolloClient ? #195

Dakuan opened this issue Feb 14, 2024 · 5 comments

Comments

@Dakuan
Copy link

Dakuan commented Feb 14, 2024

Be really handy if registerApolloClient was async...here's what im trying to do

import { HttpLink } from "@apollo/client";
import {
  NextSSRInMemoryCache,
  NextSSRApolloClient,
} from "@apollo/experimental-nextjs-app-support/ssr";
import { registerApolloClient } from "@apollo/experimental-nextjs-app-support/rsc";
import { runWithAmplifyServerContext } from "../amplify/amplifyServerUtils";
import { fetchAuthSession } from "aws-amplify/auth/server";
import { cookies } from "next/headers";

export const { getClient } = registerApolloClient(async () => {
  const token = await runWithAmplifyServerContext({
    nextServerContext: { cookies },
    operation: async (contextSpec) => {
      const session = await fetchAuthSession(contextSpec);
      return session.tokens?.accessToken.toString();
    },
  });
  const httpLink = new HttpLink({
    uri: "http://localhost:4000/graphql",
    headers: {
      Authorization: `Bearer ${token}`,
    },
  });

  return new NextSSRApolloClient({
    cache: new NextSSRInMemoryCache(),
    link: httpLink,
  });
});

all my auth its handled by aws congnito / amplify. I can get my jwts using the amplify utils, and them pass them to the API. But, its an async process, so needs to live in an async fn...

@Dakuan
Copy link
Author

Dakuan commented Feb 14, 2024

this is my workaround, ugly but works:

import { HttpLink } from "@apollo/client";
import {
  NextSSRInMemoryCache,
  NextSSRApolloClient,
} from "@apollo/experimental-nextjs-app-support/ssr";
import { registerApolloClient } from "@apollo/experimental-nextjs-app-support/rsc";
import { runWithAmplifyServerContext } from "../amplify/amplifyServerUtils";
import { fetchAuthSession } from "aws-amplify/auth/server";
import { cookies } from "next/headers";

export const getClient = async () => {
  const token = await runWithAmplifyServerContext({
    nextServerContext: { cookies },
    operation: async (contextSpec) => {
      const session = await fetchAuthSession(contextSpec);
      return session.tokens?.accessToken.toString();
    },
  });
  const { getClient } = registerApolloClient(() => {
    const httpLink = new HttpLink({
      uri: "http://localhost:4000/graphql",
      headers: {
        Authorization: `Bearer ${token}`,
      },
    });
    return new NextSSRApolloClient({
      cache: new NextSSRInMemoryCache(),
      link: httpLink,
    });
  });

  return getClient();
};

@phryneas
Copy link
Member

phryneas commented Feb 14, 2024

That sounds like a reasonable request - I'll take a look at that in a bit, but right now we're in the middle of a big refactor we have to finish first (#189, #193) - but I'll get to it after that :)

@jerelmiller
Copy link
Member

@Dakuan is there any reason you couldn't use the setContext link for this? This handles async functions and you can set headers that will be sent in the request from this link.

const tokenLink = setContext(async () => ({
  headers: { 
    Authorization: `Bearer ${await getToken()}`
  }
})

@Dakuan
Copy link
Author

Dakuan commented Feb 14, 2024

yeah, thats what i tried originally but it complained about client code running on the server

@jerelmiller
Copy link
Member

jerelmiller commented Feb 14, 2024

I'm curious how you set that up. This doesn't have anything to do with React and is part of the Apollo Client link chain. Did you perhaps try and use React context for this? That is something completely different 🙂

Here is a more full example to show what I mean:

import { setContext } from "@apollo/client/link/context";

async function getToken() {
  return runWithAmplifyServerContext({
    nextServerContext: { cookies },
    operation: async (contextSpec) => {
      const session = await fetchAuthSession(contextSpec);
      return session.tokens?.accessToken.toString();
    },
  });
}

export const { getClient } = registerApolloClient(() => {
  const contextLink = setContext(async () => ({
    headers: {
      Authorization: `Bearer ${await getToken()}`,
    }   
  }));

  const httpLink = new HttpLink({
    uri: "http://localhost:4000/graphql",
  });

  return new NextSSRApolloClient({
    cache: new NextSSRInMemoryCache(),
    link: contextLink.concat(httpLink),
  });
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants