11import { getDataFromTree } from "@apollo/react-ssr" ;
2- import { InMemoryCache } from "apollo-cache-inmemory" ;
2+ import { InMemoryCache , NormalizedCacheObject } from "apollo-cache-inmemory" ;
33import { ApolloClient } from "apollo-client" ;
44import { ApolloLink , split } from "apollo-link" ;
55import { onError } from "apollo-link-error" ;
66import { HttpLink } from "apollo-link-http" ;
77import { WebSocketLink } from "apollo-link-ws" ;
88import { getOperationAST } from "graphql" ;
9- import withApolloBase from "next-with-apollo" ;
9+ import withApolloBase , { InitApolloOptions } from "next-with-apollo" ;
10+ import React from "react" ;
1011import { SubscriptionClient } from "subscriptions-transport-ws" ;
1112import ws from "ws" ;
1213
1314import { GraphileApolloLink } from "./GraphileApolloLink" ;
1415
16+ interface WithApolloOptions {
17+ useNext ?: boolean ;
18+ rootUrl ?: string ;
19+ }
20+
1521let wsClient : SubscriptionClient | null = null ;
1622
1723export function resetWebsocketConnection ( ) : void {
@@ -29,18 +35,18 @@ function makeServerSideLink(req: any, res: any) {
2935}
3036
3137function makeClientSideLink ( ROOT_URL : string ) {
32- const nextDataEl = document . getElementById ( "__NEXT_DATA__" ) ;
33- if ( ! nextDataEl || ! nextDataEl . textContent ) {
34- throw new Error ( "Cannot read from __NEXT_DATA__ element" ) ;
38+ const nextDataEl =
39+ typeof document !== "undefined" && document . getElementById ( "__NEXT_DATA__" ) ;
40+ const headers = { } ;
41+ if ( nextDataEl && nextDataEl . textContent ) {
42+ const data = JSON . parse ( nextDataEl . textContent ) ;
43+ headers [ "CSRF-Token" ] = data . query . CSRF_TOKEN ;
3544 }
36- const data = JSON . parse ( nextDataEl . textContent ) ;
37- const CSRF_TOKEN = data . query . CSRF_TOKEN ;
3845 const httpLink = new HttpLink ( {
3946 uri : `${ ROOT_URL } /graphql` ,
40- credentials : "same-origin" ,
41- headers : {
42- "CSRF-Token" : CSRF_TOKEN ,
43- } ,
47+ credentials :
48+ process . env . NODE_ENV === "development" ? "include" : "same-origin" ,
49+ headers,
4450 } ) ;
4551 wsClient = new SubscriptionClient (
4652 `${ ROOT_URL . replace ( / ^ h t t p / , "ws" ) } /graphql` ,
@@ -65,47 +71,61 @@ function makeClientSideLink(ROOT_URL: string) {
6571 return mainLink ;
6672}
6773
68- export const withApollo = withApolloBase (
69- ( { initialState, ctx } ) => {
70- const ROOT_URL = process . env . ROOT_URL ;
71- if ( ! ROOT_URL ) {
72- throw new Error ( "ROOT_URL envvar is not set" ) ;
73- }
74+ const getApolloClient = (
75+ { initialState, ctx } : InitApolloOptions < NormalizedCacheObject > ,
76+ withApolloOptions ?: WithApolloOptions
77+ ) : ApolloClient < NormalizedCacheObject > => {
78+ const ROOT_URL = process . env . ROOT_URL || withApolloOptions ?. rootUrl ;
79+ if ( ! ROOT_URL ) {
80+ throw new Error ( "ROOT_URL envvar is not set" ) ;
81+ }
82+
83+ const onErrorLink = onError ( ( { graphQLErrors, networkError } ) => {
84+ if ( graphQLErrors )
85+ graphQLErrors . map ( ( { message, locations, path } ) =>
86+ console . error (
87+ `[GraphQL error]: message: ${ message } , location: ${ JSON . stringify (
88+ locations
89+ ) } , path: ${ JSON . stringify ( path ) } `
90+ )
91+ ) ;
92+ if ( networkError ) console . error ( `[Network error]: ${ networkError } ` ) ;
93+ } ) ;
7494
75- const onErrorLink = onError ( ( { graphQLErrors, networkError } ) => {
76- if ( graphQLErrors )
77- graphQLErrors . map ( ( { message, locations, path } ) =>
78- console . error (
79- `[GraphQL error]: message: ${ message } , location: ${ JSON . stringify (
80- locations
81- ) } , path: ${ JSON . stringify ( path ) } `
82- )
83- ) ;
84- if ( networkError ) console . error ( `[Network error]: ${ networkError } ` ) ;
85- } ) ;
95+ const { req, res } : any = ctx || { } ;
96+ const isServer = typeof window === "undefined" ;
97+ const mainLink =
98+ isServer && req && res
99+ ? makeServerSideLink ( req , res )
100+ : makeClientSideLink ( ROOT_URL ) ;
86101
87- const { req, res } : any = ctx || { } ;
88- const isServer = typeof window === "undefined" ;
89- const mainLink =
90- isServer && req && res
91- ? makeServerSideLink ( req , res )
92- : makeClientSideLink ( ROOT_URL ) ;
102+ const client = new ApolloClient ( {
103+ link : ApolloLink . from ( [ onErrorLink , mainLink ] ) ,
104+ cache : new InMemoryCache ( {
105+ dataIdFromObject : ( o ) =>
106+ o . __typename === "Query"
107+ ? "ROOT_QUERY"
108+ : o . id
109+ ? `${ o . __typename } :${ o . id } `
110+ : null ,
111+ } ) . restore ( initialState || { } ) ,
112+ } ) ;
93113
94- const client = new ApolloClient ( {
95- link : ApolloLink . from ( [ onErrorLink , mainLink ] ) ,
96- cache : new InMemoryCache ( {
97- dataIdFromObject : ( o ) =>
98- o . __typename === "Query"
99- ? "ROOT_QUERY"
100- : o . id
101- ? `${ o . __typename } :${ o . id } `
102- : null ,
103- } ) . restore ( initialState || { } ) ,
104- } ) ;
114+ return client ;
115+ } ;
105116
106- return client ;
107- } ,
108- {
109- getDataFromTree,
110- }
111- ) ;
117+ const withApolloWithNext = withApolloBase ( getApolloClient , {
118+ getDataFromTree,
119+ } ) ;
120+
121+ const withApolloWithoutNext = ( Component : any , options ?: WithApolloOptions ) => (
122+ props : any
123+ ) => {
124+ const apollo = getApolloClient ( { } , options ) ;
125+ return < Component { ...props } apollo = { apollo } /> ;
126+ } ;
127+
128+ export const withApollo = ( Component : any , options ?: WithApolloOptions ) =>
129+ options ?. useNext === false
130+ ? withApolloWithoutNext ( Component , options )
131+ : withApolloWithNext ( Component ) ;
0 commit comments