1 | import { ApolloClient } from 'apollo-client';
|
2 | import { ApolloLink } from 'apollo-link';
|
3 | import { onError } from 'apollo-link-error';
|
4 | import { createHttpLink } from 'apollo-link-http';
|
5 | import { createPersistedQueryLink } from 'apollo-link-persisted-queries';
|
6 | import { SchemaLink } from 'apollo-link-schema';
|
7 | import get from 'lodash.get';
|
8 | import qs from 'qs';
|
9 | import { createNetworkStatusNotifier } from 'react-apollo-network-status';
|
10 | import createCache from '../data/cache';
|
11 | import report from '../errorReporting';
|
12 | import { resolvers } from '../resolvers';
|
13 | import typeDefs from './client-schema.gql';
|
14 | import { logOperationTime } from './utils/queryLoggingMiddleware';
|
15 | export const createClient = ({ apolloConfig: { token, shopid, enableGateway, graphQLURI }, schema, authHandler, channelHandler, previewHandler, req }) => {
|
16 | if (!token || !shopid) {
|
17 | throw new Error(`Missing ${!token && `token`} ${!shopid && `shopid`}`);
|
18 | }
|
19 | const channelHeaders = channelHandler
|
20 | ? channelHandler.getChannelHeaders()
|
21 | : {};
|
22 | const authHeaders = authHandler ? authHandler.getAuthHeaders() : {};
|
23 | const previewHeaders = previewHandler
|
24 | ? previewHandler.getPreviewHeaders()
|
25 | : {};
|
26 | const createGatewayLink = () => __IN_SERVER__
|
27 | ? schema
|
28 | ? new SchemaLink({
|
29 | schema,
|
30 | context: {
|
31 | headers: Object.assign(Object.assign(Object.assign({}, channelHeaders), authHeaders), previewHeaders)
|
32 | }
|
33 | })
|
34 | : createHttpLink({
|
35 | uri: `http://localhost:${process.env.PORT || 3000}/graphql`,
|
36 | headers: {},
|
37 | fetch: require('node-fetch').default
|
38 | })
|
39 | : createHttpLink({
|
40 | uri: '/graphql',
|
41 | headers: {}
|
42 | });
|
43 | const createDirectLink = () => {
|
44 | if (__IN_SERVER__) {
|
45 | return createHttpLink({
|
46 | uri: graphQLURI,
|
47 | headers: {
|
48 | token: token,
|
49 | shopid: shopid
|
50 | },
|
51 | fetch: require('node-fetch').default,
|
52 | fetchOptions: {
|
53 | agent: graphQLURI.indexOf('https') === 0
|
54 | ? new (require('https').Agent)({
|
55 | keepAlive: true
|
56 | })
|
57 | : undefined
|
58 | }
|
59 | });
|
60 | }
|
61 | return createHttpLink({
|
62 | uri: graphQLURI,
|
63 | headers: {
|
64 | token: token,
|
65 | shopid: shopid
|
66 | },
|
67 | fetchOptions: {
|
68 | keepAlive: true
|
69 | }
|
70 | });
|
71 | };
|
72 | const apiLink = enableGateway ? createGatewayLink() : createDirectLink();
|
73 | const channelMiddleware = channelHandler &&
|
74 | new ApolloLink((operation, forward) => {
|
75 |
|
76 | operation.setContext(({ headers = {} }) => ({
|
77 | headers: Object.assign(Object.assign({}, headers), channelHandler.getChannelHeaders())
|
78 | }));
|
79 | return forward ? forward(operation) : null;
|
80 | });
|
81 | const authMiddleware = authHandler &&
|
82 | new ApolloLink((operation, forward) => {
|
83 |
|
84 | authHandler.loadAuthToken();
|
85 | operation.setContext(({ headers = {} }) => ({
|
86 | headers: Object.assign(Object.assign({}, headers), authHandler.getAuthHeaders())
|
87 | }));
|
88 | return forward ? forward(operation) : null;
|
89 | });
|
90 | const previewMiddleware = previewHandler &&
|
91 | new ApolloLink((operation, forward) => {
|
92 | operation.setContext(({ headers = {} }) => ({
|
93 | headers: Object.assign(Object.assign({}, headers), previewHandler.getPreviewHeaders())
|
94 | }));
|
95 | return forward ? forward(operation) : null;
|
96 | });
|
97 | const errorMiddleware = onError(({ graphQLErrors, networkError, operation }) => {
|
98 | if (graphQLErrors) {
|
99 | graphQLErrors.forEach(error => {
|
100 | const code = get(error, 'extensions.code');
|
101 | if (code === 'EmptyRoute') {
|
102 | console.log(`[404 error at ${operation.variables.path}]`);
|
103 | report(new Error(`MissingRoute: Attempted to access ${operation.variables.path}`));
|
104 | }
|
105 | else if (code === 'InvalidToken') {
|
106 | authHandler.clearAuthToken();
|
107 | if (typeof window !== 'undefined') {
|
108 | window.location.href = '/';
|
109 | }
|
110 | }
|
111 | else {
|
112 | console.log(error);
|
113 |
|
114 | report(new Error(`${error.message || code}`), {
|
115 |
|
116 | operation,
|
117 | code,
|
118 | error
|
119 | });
|
120 | }
|
121 | });
|
122 | }
|
123 |
|
124 | if (networkError) {
|
125 | console.log(`[Network error]: ${networkError}`);
|
126 | report(networkError);
|
127 | }
|
128 | });
|
129 | const { link: networkStatusNotifierLink, NetworkStatusNotifier } = createNetworkStatusNotifier();
|
130 | const links = [
|
131 | errorMiddleware,
|
132 |
|
133 | ...(channelMiddleware ? [channelMiddleware] : []),
|
134 | ...(authMiddleware ? [authMiddleware] : []),
|
135 | ...(previewMiddleware ? [previewMiddleware] : []),
|
136 | networkStatusNotifierLink,
|
137 | apiLink
|
138 | ];
|
139 | if (process.env.DEBUG_MODE === 'true') {
|
140 | links.unshift(logOperationTime);
|
141 | }
|
142 | if (enableGateway) {
|
143 | links.unshift(createPersistedQueryLink({ useGETForHashedQueries: true }));
|
144 | }
|
145 | const link = ApolloLink.from(links);
|
146 | const cache = createCache();
|
147 | const client = new ApolloClient({
|
148 | link,
|
149 | assumeImmutableResults: true,
|
150 | cache: __IN_SERVER__
|
151 | ? cache
|
152 | : cache.restore(window.__APOLLO_STATE__),
|
153 | ssrMode: !!__IN_SERVER__,
|
154 | resolvers: resolvers(qs.stringify(req === null || req === void 0 ? void 0 : req.query, { encode: true, encodeValuesOnly: true })),
|
155 | typeDefs
|
156 | });
|
157 | return { client, NetworkStatusNotifier };
|
158 | };
|
159 |
|
\ | No newline at end of file |