1
1
import { getDataFromTree } from "@apollo/react-ssr" ;
2
- import { InMemoryCache } from "apollo-cache-inmemory" ;
2
+ import { InMemoryCache , NormalizedCacheObject } from "apollo-cache-inmemory" ;
3
3
import { ApolloClient } from "apollo-client" ;
4
4
import { ApolloLink , split } from "apollo-link" ;
5
5
import { onError } from "apollo-link-error" ;
6
6
import { HttpLink } from "apollo-link-http" ;
7
7
import { WebSocketLink } from "apollo-link-ws" ;
8
8
import { getOperationAST } from "graphql" ;
9
- import withApolloBase from "next-with-apollo" ;
9
+ import withApolloBase , { InitApolloOptions } from "next-with-apollo" ;
10
+ import React from "react" ;
10
11
import { SubscriptionClient } from "subscriptions-transport-ws" ;
11
12
import ws from "ws" ;
12
13
13
14
import { GraphileApolloLink } from "./GraphileApolloLink" ;
14
15
16
+ interface WithApolloOptions {
17
+ useNext ?: boolean ;
18
+ rootUrl ?: string ;
19
+ }
20
+
15
21
let wsClient : SubscriptionClient | null = null ;
16
22
17
23
export function resetWebsocketConnection ( ) : void {
@@ -29,18 +35,18 @@ function makeServerSideLink(req: any, res: any) {
29
35
}
30
36
31
37
function 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 ;
35
44
}
36
- const data = JSON . parse ( nextDataEl . textContent ) ;
37
- const CSRF_TOKEN = data . query . CSRF_TOKEN ;
38
45
const httpLink = new HttpLink ( {
39
46
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,
44
50
} ) ;
45
51
wsClient = new SubscriptionClient (
46
52
`${ ROOT_URL . replace ( / ^ h t t p / , "ws" ) } /graphql` ,
@@ -65,47 +71,61 @@ function makeClientSideLink(ROOT_URL: string) {
65
71
return mainLink ;
66
72
}
67
73
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
+ } ) ;
74
94
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 ) ;
86
101
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
+ } ) ;
93
113
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
+ } ;
105
116
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