ApolloClientBrowser.ts 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import { cache as reactCache } from "react";
  2. import { HttpLink,ApolloLink } from "@apollo/client";
  3. import { SetContextLink } from "@apollo/client/link/context";
  4. import {
  5. ApolloClient,
  6. InMemoryCache,
  7. } from "@apollo/client-integration-nextjs";
  8. import { ErrorLink } from "@apollo/client/link/error";
  9. import {CombinedProtocolErrors} from "@apollo/client/errors";
  10. import {handleErrorForErrorLink} from "@/lib/ApolloErrorHandler";
  11. import { getSession } from "next-auth/react";
  12. import { getCartToken } from "@/utils/getCartToken";
  13. import { BagistoSession } from "@/types/types";
  14. // 这里注册的是客户端使用的apollo client
  15. CombinedProtocolErrors.formatMessage = (errors,{defaultFormatMessage})=>{
  16. return "[Subscription Error] " + defaultFormatMessage(errors);
  17. };
  18. let sessionCache: { session: BagistoSession | null; timestamp: number } | null = null;
  19. const SESSION_CACHE_TTL = 5000;
  20. const getSessionForRequest = reactCache(async () => {
  21. return (await getSession()) as BagistoSession | null;
  22. });
  23. async function getCachedSession(): Promise<BagistoSession | null> {
  24. if (typeof window === "undefined") {
  25. return getSessionForRequest();
  26. }
  27. const now = Date.now();
  28. if (sessionCache && now - sessionCache.timestamp < SESSION_CACHE_TTL) {
  29. return sessionCache.session;
  30. }
  31. const session = (await getSession()) as BagistoSession | null;
  32. sessionCache = { session, timestamp: now };
  33. return session;
  34. }
  35. export default function makeClient() {
  36. const httpLink = new HttpLink({
  37. uri: "/api/graphql",
  38. credentials: "include",
  39. /*fetchOptions: {
  40. // Optional: Next.js-specific fetch options
  41. // Note: This doesn't work with `export const dynamic = "force-static"`
  42. },*/
  43. });
  44. const errorLink = new ErrorLink(({ error }) => {
  45. handleErrorForErrorLink(error);
  46. });
  47. const authLink = new SetContextLink(async (prevContext) => {
  48. const session = await getCachedSession();
  49. const userToken = session?.user?.accessToken;
  50. const guestToken = !userToken ? getCartToken() : null;
  51. const token = userToken || guestToken;
  52. return {
  53. headers: {
  54. ...prevContext.headers,
  55. ...(token && { Authorization: `Bearer ${token}` }),
  56. "Content-Type": "application/json",
  57. },
  58. };
  59. });
  60. // httpLink 要放在最后
  61. const link = ApolloLink.from([errorLink, authLink, httpLink]);
  62. return new ApolloClient({
  63. // ssrMode,
  64. link,
  65. cache: new InMemoryCache(),
  66. // defaultOptions: {
  67. // watchQuery: {
  68. // fetchPolicy: "cache-first",
  69. // nextFetchPolicy: "cache-first",
  70. // },
  71. // query: {
  72. // fetchPolicy: "cache-first",
  73. // },
  74. // },
  75. });
  76. }