Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TRACKING: feature/redux → feature/apollo #1147

Closed
wants to merge 51 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
011337e
packages: apollo-client, react-apollo and graphql-tag dependencies
langpavel Feb 24, 2017
22dc950
Initial Apollo integration
langpavel Feb 24, 2017
03791e9
News now using `graphql` from react-apollo
langpavel Feb 24, 2017
48231cf
Merge branch 'feature/redux' into feature/apollo
langpavel Feb 27, 2017
0895c21
seamless transition from fetch to apollo in redux helpers
langpavel Feb 24, 2017
d6ecb1c
Avoid using gql template tag at runtime, write handy warning if so
langpavel Feb 27, 2017
cf42f90
Merge branch 'feature/redux' into feature/apollo
langpavel Mar 12, 2017
1a7e45b
Include credentials with Apollo request
langpavel Mar 15, 2017
08be6ff
Fix issue with mutations, deprecate `graphqlRequest`
langpavel Mar 16, 2017
734919a
Upgrade Apollo
langpavel Mar 16, 2017
37f1b80
Merge branch 'feature/redux' into feature/apollo
langpavel Mar 16, 2017
963ae2a
Merge branch 'feature/redux' into feature/apollo
langpavel Mar 25, 2017
86132ac
change name and unify format of package.json for createApolloClient
zirho Mar 29, 2017
5a19805
Merge branch 'feature/redux' into feature/apollo
langpavel Mar 31, 2017
f48ceff
Upgrade packages
langpavel Mar 31, 2017
9770f63
Merge branch 'feature/redux' into feature/apollo
langpavel Apr 10, 2017
b62314c
Don't listen to intellisense, you will make mistake like this..
langpavel Apr 11, 2017
705a39e
Merge branch 'feature/redux' into feature/apollo
langpavel Apr 16, 2017
54efedc
Merge branch 'feature/redux' into feature/apollo
langpavel May 23, 2017
ba4894a
Merge branch 'feature/redux' into feature/apollo
langpavel May 25, 2017
1f4f7ef
Merge branch 'feature/redux' into feature/apollo
langpavel Jun 30, 2017
da4f71f
Merge branch 'feature/redux' into feature/apollo
langpavel Jun 30, 2017
101e158
Merge branch 'feature/redux' into feature/apollo
langpavel Jul 1, 2017
58a9aa5
Merge branch 'feature/redux' into feature/apollo
langpavel Jul 10, 2017
1affa66
yarn: fix react-dom issue caused by reac-apollo
langpavel Jul 10, 2017
39d30b2
tests: jest-transform-graphql
langpavel Jul 10, 2017
2bcb7e1
Merge branch 'feature/redux' into feature/apollo
langpavel Jul 14, 2017
b429d3b
Merge branch 'feature/redux' into feature/apollo
langpavel Aug 11, 2017
4f7a1f5
WIP: Merge branch 'feature/redux' into feature/apollo
langpavel Aug 22, 2017
61bdcae
FIX: react-apollo now needs wider context, so delegate responsibility…
langpavel Aug 22, 2017
73e7705
Fix Layout test
Oct 6, 2017
f5c85f1
Use news.graphql content as fetch body query in home route
Oct 6, 2017
a65988a
[feature/Apollo] Upgrade to Apollo Client 2.0 (#1492)
tim-soft Jan 5, 2018
4ce25fc
Merge branch 'feature/redux' into feature/apollo
langpavel Jan 5, 2018
bcb056b
Downgrade graphql (0.12.3 -> 0.11.7)
langpavel Jan 5, 2018
eeac362
fix Apollo state (re)hydration
langpavel Jan 6, 2018
8effc49
Merge branch 'feature/redux' into feature/apollo
langpavel Jan 7, 2018
c956344
:sparkles: Log Apollo ops in development (#1496)
tim-soft Jan 8, 2018
712b80a
Merge branch 'feature-apollo-single-source-of-graphql-query' of git:/…
langpavel Jan 8, 2018
ea5111e
Use apollo client in router instead of fetch
langpavel Jan 8, 2018
c8f7165
Merge branch 'KrzysztofKarol-feature-apollo-single-source-of-graphql-…
langpavel Jan 8, 2018
8764b24
Merge branch 'feature/redux' into feature/apollo
langpavel Jan 8, 2018
9382aa2
:recycle: Implement GraphQL-Tools based Schema (#1498)
tim-soft Jan 13, 2018
d7d4187
Merge branch 'feature/redux' into feature/apollo
langpavel Jan 14, 2018
7373ec4
Fix errors in graphql-tools implementation (#1503)
langpavel Jan 14, 2018
4fb56bc
Merge branch 'feature/redux' into feature/apollo
langpavel Jan 23, 2018
80cac88
Merge branch 'feature/redux' into feature/apollo
langpavel Jan 31, 2018
3042323
Merge branch 'feature/redux' into feature/apollo
langpavel Mar 24, 2018
d4c8bf6
chore: yarn upgrade --latest
langpavel Mar 24, 2018
6c851d3
fix(redux): createRootReducer → rootReducer
langpavel Mar 24, 2018
d5cf707
Merge branch 'feature/redux' into feature/apollo
langpavel Mar 25, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ module.exports = {
},
],

// Allow only special identifiers
// https://eslint.org/docs/rules/no-underscore-dangle
'no-underscore-dangle': [
'error',
{
allow: ['__typename'],
},
],

// Prefer destructuring from arrays and objects
// http://eslint.org/docs/rules/prefer-destructuring
'prefer-destructuring': [
Expand Down
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ module.exports = {

transform: {
'\\.(js|jsx)$': '<rootDir>/node_modules/babel-jest',
'\\.(gql|graphql)$': '<rootDir>/node_modules/jest-transform-graphql',
'^(?!.*\\.(js|jsx|json|css|less|styl|scss|sass|sss)$)':
'<rootDir>/tools/lib/fileTransformer.js',
},
Expand Down
14 changes: 14 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@
"browserslist": [">1%", "last 4 versions", "Firefox ESR", "not ie < 9"],
"dependencies": {
"@babel/polyfill": "^7.0.0-beta.42",
"apollo-cache-inmemory": "^1.1.4",
"apollo-client": "^2.0.4",
"apollo-link": "^1.0.7",
"apollo-link-error": "^1.0.3",
"apollo-link-http": "^1.3.2",
"apollo-link-logger": "^1.1.0",
"apollo-link-schema": "^1.0.1",
"bluebird": "^3.5.1",
"body-parser": "^1.18.2",
"classnames": "^2.2.5",
Expand All @@ -18,9 +25,12 @@
"express-graphql": "^0.6.12",
"express-jwt": "^5.3.1",
"graphql": "^0.13.2",
"graphql-tag": "^2.6.1",
"graphql-tools": "^2.16.0",
"history": "^4.7.2",
"isomorphic-style-loader": "^4.0.0",
"jsonwebtoken": "^8.2.0",
"lodash": "^4.17.5",
"node-fetch": "^2.1.1",
"normalize.css": "^8.0.0",
"passport": "^0.4.0",
Expand All @@ -29,6 +39,7 @@
"prop-types": "^15.6.1",
"query-string": "^6.0.0",
"react": "^16.2.0",
"react-apollo": "^2.0.4",
"react-dom": "^16.2.0",
"react-redux": "^5.0.6",
"redux": "^3.7.2",
Expand Down Expand Up @@ -79,6 +90,9 @@
"husky": "^0.14.3",
"identity-obj-proxy": "^3.0.0",
"jest": "^22.4.3",
"jest-codemods": "^0.13.9",
"jest-transform-graphql": "^2.1.0",
"jscodeshift": "^0.5.0",
"lint-staged": "^7.0.0",
"markdown-it": "^8.4.1",
"mkdirp": "^0.5.1",
Expand Down
19 changes: 13 additions & 6 deletions src/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,18 @@ import { createPath } from 'history/PathUtils';
import App from './components/App';
import createFetch from './createFetch';
import configureStore from './store/configureStore';
import history from './history';
import { updateMeta } from './DOMUtils';
import history from './history';
import createApolloClient from './core/createApolloClient';
import router from './router';

// Universal HTTP client
const fetch = createFetch(window.fetch, {
baseUrl: window.App.apiUrl,
});

const apolloClient = createApolloClient();

// Global (context) variables that can be easily accessed from any React component
// https://facebook.github.io/react/docs/context.html
const context = {
Expand All @@ -32,13 +40,12 @@ const context = {
removeCss.forEach(f => f());
};
},
// Universal HTTP client
fetch: createFetch(fetch, {
baseUrl: window.App.apiUrl,
}),
// For react-apollo
client: apolloClient,
// Initialize a new Redux store
// http://redux.js.org/docs/basics/UsageWithReact.html
store: configureStore(window.App.state, { history }),
store: configureStore(window.App.state, { fetch, history }),
fetch,
storeSubscription: null,
};

Expand Down
9 changes: 8 additions & 1 deletion src/components/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Provider as ReduxProvider } from 'react-redux';
import { ApolloProvider } from 'react-apollo';

const ContextType = {
// Enables critical path CSS rendering
Expand All @@ -22,6 +23,8 @@ const ContextType = {
// Integrate Redux
// http://redux.js.org/docs/basics/UsageWithReact.html
...ReduxProvider.childContextTypes,
// Apollo Client
client: PropTypes.object.isRequired,
};

/**
Expand Down Expand Up @@ -59,9 +62,13 @@ class App extends React.PureComponent {
}

render() {
// Here, we are at universe level, sure? ;-)
const { client } = this.props.context;
// NOTE: If you need to add or modify header, footer etc. of the app,
// please do that inside the Layout component.
return React.Children.only(this.props.children);
return (
<ApolloProvider client={client}>{this.props.children}</ApolloProvider>
);
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/components/Layout/Layout.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import React from 'react';
import renderer from 'react-test-renderer';
import configureStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import createApolloClient from '../../core/createApolloClient';
import App from '../App';
import Layout from './Layout';

Expand All @@ -24,6 +25,8 @@ const initialState = {};
describe('Layout', () => {
test('renders children correctly', () => {
const store = mockStore(initialState);
const client = createApolloClient();

const wrapper = renderer
.create(
<App
Expand All @@ -32,6 +35,7 @@ describe('Layout', () => {
fetch: () => {},
pathname: '',
store,
client,
}}
>
<Layout>
Expand Down
36 changes: 36 additions & 0 deletions src/core/createApolloClient/createApolloClient.client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// @flow

import { ApolloClient } from 'apollo-client';
import { from } from 'apollo-link';
import { onError } from 'apollo-link-error';
import { HttpLink } from 'apollo-link-http';
import apolloLogger from 'apollo-link-logger';
import createCache from './createCache';

const link = from([
onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors)
graphQLErrors.map(({ message, locations, path }) =>
console.warn(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
),
);
if (networkError) console.warn(`[Network error]: ${networkError}`);
}),
...(__DEV__ ? [apolloLogger] : []),
new HttpLink({
uri: '/graphql',
credentials: 'include',
}),
]);

const cache = createCache();

export default function createApolloClient() {
return new ApolloClient({
link,
cache: cache.restore(window.App.apolloState),
queryDeduplication: true,
connectToDevTools: true,
});
}
29 changes: 29 additions & 0 deletions src/core/createApolloClient/createApolloClient.server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// @flow

import { ApolloClient } from 'apollo-client';
import { from } from 'apollo-link';
import { onError } from 'apollo-link-error';
import { SchemaLink } from 'apollo-link-schema';
import createCache from './createCache';

export default function createApolloClient(schema) {
const link = from([
onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors)
graphQLErrors.map(({ message, locations, path }) =>
console.warn(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
),
);
if (networkError) console.warn(`[Network error]: ${networkError}`);
}),
new SchemaLink({ ...schema }),
]);

return new ApolloClient({
link,
cache: createCache(),
ssrMode: true,
queryDeduplication: true,
});
}
19 changes: 19 additions & 0 deletions src/core/createApolloClient/createCache.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// @flow

import { InMemoryCache, defaultDataIdFromObject } from 'apollo-cache-inmemory';

function dataIdFromObject(obj) {
switch (obj.__typename) {
case 'NewsItem':
return obj.link ? `NewsItem:${obj.link}` : defaultDataIdFromObject(obj);
default:
return defaultDataIdFromObject(obj);
}
}

export default function createCache() {
// https://www.apollographql.com/docs/react/basics/caching.html#configuration
return new InMemoryCache({
dataIdFromObject,
});
}
7 changes: 7 additions & 0 deletions src/core/createApolloClient/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "createApolloClient",
"version": "0.0.0",
"private": true,
"main": "./createApolloClient.server.js",
"browser": "./createApolloClient.client.js"
}
31 changes: 31 additions & 0 deletions src/data/graphql/Database/schema.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { merge } from 'lodash';

/** * Queries ** */
import {
schema as GetAllUsers,
queries as GetAllUsersQueries,
resolvers as GetAllUsersResolver,
} from './users/GetAllUsers';
import {
queries as GetLoggedInUserQueries,
resolvers as GetLoggedInUserResolver,
} from './users/GetLoggedInUser';

/** * Mutations ** */
import {
schema as CreateUserInput,
mutation as CreateUser,
resolvers as CreateUserResolver,
} from './users/CreateUser';

export const schema = [...GetAllUsers, ...CreateUserInput];

export const queries = [...GetAllUsersQueries, ...GetLoggedInUserQueries];

export const mutations = [...CreateUser];

export const resolvers = merge(
GetAllUsersResolver,
GetLoggedInUserResolver,
CreateUserResolver,
);
65 changes: 65 additions & 0 deletions src/data/graphql/Database/users/CreateUser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { User, UserProfile } from 'data/models';

export const schema = [
`
# User profile data for creating a new local database user account
input UserProfile {
# A display name for the logged-in user
displayName: String!

# A profile picture URL
picture: String

# The user's gender
gender: String

# The user's location
location: String

# A website URL
website: String
}
`,
];

export const mutation = [
`
# Creates a new user and profile in the local database
databaseCreateUser(
# The email of the new user, this email must be unique in the database
email: String!

# User profile information for creating a new local database user account
profile: UserProfile!
): DatabaseUser
`,
];

export const resolvers = {
Mutation: {
async databaseCreateUser(parent, args) {
// If user already exists, throw error
const lookupUser = await User.findOne({ where: { email: args.email } });

if (lookupUser) {
// eslint-disable-next-line no-throw-literal
throw 'User already exists!';
}

// Create new user with profile in database
const user = await User.create(
{
email: args.email,
profile: {
...args.profile,
},
},
{
include: [{ model: UserProfile, as: 'profile' }],
},
);

return user;
},
},
};
Loading