Skip to content

Commit

Permalink
Merge pull request #4143 from kiva/MARS-178-migrate-to-apollo-3
Browse files Browse the repository at this point in the history
MARS-178: Apollo 3 Migrate
  • Loading branch information
emuvente authored Dec 15, 2022
2 parents dae566f + b5ccd95 commit b6270ac
Show file tree
Hide file tree
Showing 147 changed files with 826 additions and 768 deletions.
704 changes: 313 additions & 391 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 1 addition & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"deploy-storybook": "storybook-to-ghpages"
},
"dependencies": {
"@apollo/client": "^3.6.9",
"@babel/eslint-parser": "^7.18.2",
"@babel/polyfill": "^7.10.4",
"@babel/runtime": "^7.12.5",
Expand All @@ -55,12 +56,6 @@
"@sentry/vue": "^6.19.6",
"@vue/composition-api": "^1.4.6",
"algoliasearch": "^3.34.0",
"apollo-cache-inmemory": "^1.6.6",
"apollo-client": "2.6.10",
"apollo-link": "^1.2.14",
"apollo-link-batch-http": "^1.2.14",
"apollo-link-context": "^1.0.20",
"apollo-link-error": "^1.1.13",
"apollo-server-express": "^2.18.2",
"auth0-js": "^9.19.2",
"body-parser": "^1.19.0",
Expand Down Expand Up @@ -88,7 +83,6 @@
"fuse.js": "^5.2.3",
"get-user-locale": "^1.4.0",
"graphql": "^15.4.0",
"graphql-tag": "^2.12.6",
"gsap": "^3.5.1",
"helmet": "^4.6.0",
"instantsearch.js": "^3.6.0",
Expand Down
60 changes: 0 additions & 60 deletions server/util/getGqlFragmentTypes.js

This file was deleted.

94 changes: 94 additions & 0 deletions server/util/getGqlPossibleTypes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
const fetch = require('./fetch');
const { log } = require('./log');
const tracer = require('./ddTrace');

const GQL_BUILT_IN_TYPES = [
'__Schema',
'__Type',
'__TypeKind',
'__Field',
'__InputValue',
'__EnumValue',
'__Directive'
];

function fetchGqlPossibleTypes(url, cache) {
return fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
// eslint-disable-next-line max-len
query: '{ __schema { queryType { name } mutationType { name } subscriptionType { name } types { name fields { name } possibleTypes { name } } } }'
}),
})
.then(result => result.json())
// eslint-disable-next-line no-underscore-dangle
.then(result => result?.data?.__schema ?? {})
.then(({
types, queryType, mutationType, subscriptionType
}) => {
const possibleTypes = { Mergable: [] };
types?.forEach(type => {
// Skip adding possible types for built-in GraphQL types and root types
if (GQL_BUILT_IN_TYPES.includes(type.name)
|| type.name === queryType?.name
|| type.name === mutationType?.name
|| type.name === subscriptionType?.name
) {
return;
}
// If this type has possible types, include them in the possibleTypes
// object as { Typename: ['PossibleTypenameA', 'PossibleTypenameB'] }
if (type.possibleTypes && type.possibleTypes.length) {
possibleTypes[type.name] = type.possibleTypes.map(({ name }) => name);
}
// If this type doesn't have an ID field, declare it as mergeable.
// See https://github.com/apollographql/apollo-client/pull/7070#issue-708438002
if (type.fields && type.fields.length && !type.fields.some(field => field.name === 'id')) {
possibleTypes.Mergable.push(type.name);
}
});

cache.set(
'ui-gql-possible-types',
JSON.stringify(possibleTypes),
{ expires: 24 * 60 * 60 },
(error, success) => {
if (error) {
log(`MemJS Error Setting Cache for ui-gql-fragment-types, Error: ${error}`, 'error');
}
if (success) {
log(`MemJS Success Setting Cache for ui-gql-fragment-types, Success: ${success}`);
}
}
);

return possibleTypes;
});
}

function getGqlPossibleTypesFromCache(cache) {
return new Promise(resolve => {
cache.get('ui-gql-possible-types', (error, data) => {
let parsedData = [];
if (error) {
log(`MemJS Error Getting ui-gql-fragment-types, Error: ${error}`, 'error');
}
if (data) parsedData = JSON.parse(data);
resolve(parsedData);
});
});
}

module.exports = function getGqlPossibleTypes(url, cache) {
return tracer.trace('getGqlFragmentTypes', () => {
return tracer.trace('getGqlFragmentsFromCache', () => {
return getGqlPossibleTypesFromCache(cache).then(data => {
if (data.length) {
return data;
}
return tracer.trace('fetchGqlFragments', () => fetchGqlPossibleTypes(url, cache));
});
});
});
};
10 changes: 5 additions & 5 deletions server/vue-middleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const path = require('path');
const Bowser = require('bowser');
const cookie = require('cookie');
const { createBundleRenderer } = require('vue-server-renderer');
const getGqlFragmentTypes = require('./util/getGqlFragmentTypes');
const getGqlPossibleTypes = require('./util/getGqlPossibleTypes');
const getSessionCookies = require('./util/getSessionCookies');
const vueSsrCache = require('./util/vueSsrCache');
const tracer = require('./util/ddTrace');
Expand Down Expand Up @@ -75,8 +75,8 @@ module.exports = function createMiddleware({
res.setHeader('Content-Type', 'text/html');
res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');

// get graphql api fragment types for the graphql client
const typesPromise = getGqlFragmentTypes(config.server.graphqlUri, cache);
// get graphql api possible types for the graphql client
const typesPromise = getGqlPossibleTypes(config.server.graphqlUri, cache);

// fetch initial session cookies in case starting session with this request
const cookiePromise = getSessionCookies(config.server.sessionUri, cookies);
Expand All @@ -85,7 +85,7 @@ module.exports = function createMiddleware({
typesPromise.then(() => console.info(JSON.stringify({
meta: {},
level: 'info',
message: `fragment fetch: ${Date.now() - s}ms`
message: `types fetch: ${Date.now() - s}ms`
})));
cookiePromise.then(() => console.info(JSON.stringify({
meta: {},
Expand All @@ -97,7 +97,7 @@ module.exports = function createMiddleware({
Promise.all([typesPromise, cookiePromise])
.then(([types, cookieInfo]) => {
// add fetched types to rendering context
context.config.graphqlFragmentTypes = types;
context.config.graphqlPossibleTypes = types;
// update cookies in the rendering context with any newly fetched session cookies
context.cookies = Object.assign(context.cookies, cookieInfo.cookies);
// forward any newly fetched 'Set-Cookie' headers
Expand Down
2 changes: 1 addition & 1 deletion src/api/Auth0Link.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { setContext } from 'apollo-link-context';
import { setContext } from '@apollo/client/link/context';
import _set from 'lodash/set';

// Add the user info to the context and add the access token to the authorization header
Expand Down
2 changes: 1 addition & 1 deletion src/api/BasketLink.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import _get from 'lodash/get';
import _set from 'lodash/set';
import { ApolloLink } from 'apollo-link';
import { ApolloLink } from '@apollo/client/core';

export default ({ cookieStore }) => {
return new ApolloLink((operation, forward) => {
Expand Down
2 changes: 1 addition & 1 deletion src/api/ContentfulPreviewLink.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ApolloLink } from 'apollo-link';
import { ApolloLink } from '@apollo/client/core';

export default ({ cookieStore }) => {
return new ApolloLink((operation, forward) => {
Expand Down
2 changes: 1 addition & 1 deletion src/api/ExperimentIdLink.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { setContext } from 'apollo-link-context';
import { setContext } from '@apollo/client/link/context';
import _set from 'lodash/set';

// Experiment Ids from setting that will be passed in the X-Experiment Header
Expand Down
2 changes: 1 addition & 1 deletion src/api/HttpLink.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as Sentry from '@sentry/vue';
import { BatchHttpLink } from 'apollo-link-batch-http';
import { BatchHttpLink } from '@apollo/client/link/batch-http';

export default ({ kvAuth0, uri = '', fetch }) => {
const onVm = uri.indexOf('vm') > -1;
Expand Down
2 changes: 1 addition & 1 deletion src/api/NetworkErrorLink.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { onError } from 'apollo-link-error';
import { onError } from '@apollo/client/link/error';
import logFormatter from '@/util/logFormatter';

export default () => {
Expand Down
2 changes: 1 addition & 1 deletion src/api/SnowplowSessionLink.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { setContext } from 'apollo-link-context';
import { setContext } from '@apollo/client/link/context';
import _set from 'lodash/set';

function getSPCookieSession(cookieStore) {
Expand Down
44 changes: 15 additions & 29 deletions src/api/apollo.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,34 @@
/* eslint-disable no-underscore-dangle */
import ApolloClient from 'apollo-client';
import { ApolloLink } from 'apollo-link';
import {
IntrospectionFragmentMatcher,
InMemoryCache,
defaultDataIdFromObject,
} from 'apollo-cache-inmemory';
import { ApolloLink, ApolloClient, InMemoryCache } from '@apollo/client/core';
import Auth0LinkCreator from './Auth0Link';
import BasketLinkCreator from './BasketLink';
import ContentfulPreviewLink from './ContentfulPreviewLink';
import ExperimentIdLink from './ExperimentIdLink';
import HttpLinkCreator from './HttpLink';
import NetworkErrorLink from './NetworkErrorLink';
import SnowplowSessionLink from './SnowplowSessionLink';
import initState from './localState';
import { initState, setLocalState } from './localState';

export default function createApolloClient({
appConfig,
cookieStore,
kvAuth0,
types = [],
types,
uri,
fetch
}) {
const cache = new InMemoryCache({
fragmentMatcher: new IntrospectionFragmentMatcher({
introspectionQueryResultData: {
__schema: { types }
}
}),
// Return a custom cache id for types that don't have an id field
dataIdFromObject: object => {
if (object.__typename === 'Setting' && object.key) return `Setting:${object.key}`;
return defaultDataIdFromObject(object);
},
// Use a simpler underlying cache for server renders
resultCaching: typeof window !== 'undefined',
// Block modifying cache results outside of normal operations
// see https://github.com/apollographql/apollo-client/pull/4543
freezeResults: true,
possibleTypes: types,
typePolicies: {
Mergable: {
merge: true,
},
Setting: {
keyFields: ['key'],
},
}
});

// initialize local state resolvers
const { resolvers, defaults } = initState({ appConfig, cookieStore, kvAuth0 });
const { resolvers } = initState({ appConfig, cookieStore, kvAuth0 });

const client = new ApolloClient({
link: ApolloLink.from([
Expand Down Expand Up @@ -73,8 +59,8 @@ export default function createApolloClient({
});

// set default local state
cache.writeData({ data: defaults });
client.onResetStore(() => cache.writeData({ data: defaults }));
setLocalState({ appConfig, cookieStore, kvAuth0 }, cache);
client.onResetStore(() => setLocalState({ appConfig, cookieStore, kvAuth0 }, cache));

return client;
}
Loading

0 comments on commit b6270ac

Please sign in to comment.