mirror of
https://github.com/cookiecutter/cookiecutter-django.git
synced 2025-08-13 16:34:52 +03:00
Add React Apollo for the GraphQL client side
This commit is contained in:
parent
f01e3bfd16
commit
2952e46bb7
|
@ -18,9 +18,22 @@
|
|||
"react-scripts": "3.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@apollo/react-common": "3.1.2",
|
||||
"@apollo/react-components": "3.1.2",
|
||||
"@apollo/react-hooks": "3.1.2",
|
||||
"@apollo/react-testing": "3.1.2",
|
||||
"apollo-boost": "0.4.4",
|
||||
"apollo-cache-persist": "0.1.1",
|
||||
"apollo-link-context": "1.0.19",
|
||||
"apollo-link-rest": "0.7.3",
|
||||
"apollo-link-schema": "1.2.4",
|
||||
"apollo-link-state": "0.4.2",
|
||||
"apollo-upload-client": "11.0.0",
|
||||
"axios": "0.19.0",
|
||||
"node-sass": "4.12.0",
|
||||
"raven-js": "3.27.2",
|
||||
"react-alert": "5.5.0",
|
||||
"react-alert-template-basic": "1.0.0",
|
||||
"react-document-title": "2.0.3",
|
||||
"react-router-dom": "5.1.2"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import { InMemoryCache } from 'apollo-cache-inmemory'
|
||||
import { persistCache } from 'apollo-cache-persist'
|
||||
import localForage from 'localforage'
|
||||
|
||||
const cache = new InMemoryCache()
|
||||
|
||||
persistCache({cache, storage: localForage})
|
||||
|
||||
export default cache
|
36
{{cookiecutter.project_slug}}/frontend/src/apollo/client.js
Normal file
36
{{cookiecutter.project_slug}}/frontend/src/apollo/client.js
Normal file
|
@ -0,0 +1,36 @@
|
|||
import { ApolloClient } from 'apollo-client'
|
||||
import { ApolloLink } from 'apollo-link'
|
||||
|
||||
import { authLink, restLink, stateLink, uploadLink } from './links'
|
||||
import cache from './cache'
|
||||
import { mockLink } from './mocks'
|
||||
|
||||
const defaultOptions = {
|
||||
watchQuery: {
|
||||
fetchPolicy: 'cache-and-network',
|
||||
errorPolicy: 'ignore',
|
||||
},
|
||||
query: {
|
||||
fetchPolicy: 'cache-and-network',
|
||||
errorPolicy: 'all',
|
||||
},
|
||||
mutate: {
|
||||
// NOTE: Using 'none' will allow Apollo to recognize errors even if the response
|
||||
// includes {data: null} in it (graphene does this with each unsuccessful mutation!)
|
||||
errorPolicy: 'none',
|
||||
},
|
||||
}
|
||||
|
||||
const link = ApolloLink.from([stateLink, restLink, authLink.concat(uploadLink)])
|
||||
|
||||
const client = new ApolloClient({
|
||||
link:
|
||||
process.env.NODE_ENV === 'production'
|
||||
? link // never use mock for production
|
||||
: ApolloLink.split(operation => operation.getContext().mock, mockLink, link),
|
||||
cache,
|
||||
connectToDevTools: process.env.NODE_ENV === 'production' ? false : true,
|
||||
defaultOptions,
|
||||
})
|
||||
|
||||
export default client
|
43
{{cookiecutter.project_slug}}/frontend/src/apollo/links.js
Normal file
43
{{cookiecutter.project_slug}}/frontend/src/apollo/links.js
Normal file
|
@ -0,0 +1,43 @@
|
|||
import cookie from 'react-cookies'
|
||||
import { setContext } from 'apollo-link-context'
|
||||
import { createHttpLink } from 'apollo-link-http'
|
||||
import { RestLink } from 'apollo-link-rest'
|
||||
import { withClientState } from 'apollo-link-state'
|
||||
import { createUploadLink } from 'apollo-upload-client'
|
||||
import { merge } from 'lodash'
|
||||
|
||||
import cache from './cache'
|
||||
|
||||
// docs: https://www.apollographql.com/docs/link/links/http.html
|
||||
export const httpLink = createHttpLink({
|
||||
uri: '/graphql/',
|
||||
credentials: 'same-origin',
|
||||
})
|
||||
|
||||
// docs: https://github.com/jaydenseric/apollo-upload-client
|
||||
export const uploadLink = createUploadLink({
|
||||
uri: '/graphql/',
|
||||
credentials: 'same-origin',
|
||||
})
|
||||
|
||||
// docs: https://www.apollographql.com/docs/link/links/rest.html
|
||||
export const restLink = new RestLink({
|
||||
uri: '/api/',
|
||||
endpoints: {},
|
||||
})
|
||||
|
||||
// docs: https://www.apollographql.com/docs/link/links/state.html
|
||||
export const stateLink = withClientState({
|
||||
cache,
|
||||
...merge({}),
|
||||
})
|
||||
|
||||
export const authLink = setContext((_, { headers }) => {
|
||||
return {
|
||||
headers: {
|
||||
...headers,
|
||||
'X-CSRFToken': cookie.load('csrftoken'),
|
||||
Authorization: `JWT ${cookie.load('jwt')}`,
|
||||
},
|
||||
}
|
||||
})
|
|
@ -0,0 +1,19 @@
|
|||
import { SchemaLink } from 'apollo-link-schema'
|
||||
import { addMockFunctionsToSchema } from 'graphql-tools'
|
||||
import { assign } from 'lodash'
|
||||
|
||||
import { mockSchema } from '../schema-parser'
|
||||
|
||||
export const baseMocks = {}
|
||||
|
||||
// Use this devMocks object for your development mock override
|
||||
// Make sure to empty this part before your pull request
|
||||
const devMocks = {}
|
||||
|
||||
const combinedMocks = assign({}, baseMocks, devMocks)
|
||||
|
||||
const schema = mockSchema()
|
||||
|
||||
addMockFunctionsToSchema({ schema, mocks: combinedMocks })
|
||||
|
||||
export const mockLink = new SchemaLink({ schema })
|
|
@ -0,0 +1,24 @@
|
|||
import { findIndex, remove } from 'lodash'
|
||||
import { buildClientSchema } from 'graphql'
|
||||
|
||||
import * as jsonFile from './schema'
|
||||
|
||||
export const mockSchema = () => {
|
||||
// new json loader update adds a `defulat` parent level to json
|
||||
const x = jsonFile.default
|
||||
|
||||
// Apollo won't accept introspection that has any '__debug' values in json file, so the parser should remove them first
|
||||
// To read more: https://github.research.chop.edu/DGD/nexus/issues/1318#issuecomment-18281
|
||||
|
||||
const queryTypeIndex = findIndex(x.data.__schema.types, ['name', 'Query'])
|
||||
const mutationTypeIndex = findIndex(x.data.__schema.types, ['name', 'Mutation'])
|
||||
|
||||
// remove the fields:
|
||||
|
||||
remove(x.data.__schema.types[queryTypeIndex].fields, field => field.name === '__debug')
|
||||
remove(x.data.__schema.types[mutationTypeIndex].fields, field => field.name === '__debug')
|
||||
|
||||
const schema = buildClientSchema(x.data)
|
||||
|
||||
return schema
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
import { assign } from 'lodash'
|
||||
import { baseMocks } from './mocks'
|
||||
import { graphql } from 'graphql'
|
||||
import { addMockFunctionsToSchema } from 'graphql-tools'
|
||||
import { mockSchema } from './schema-parser'
|
||||
import { print as gqlToString } from 'graphql/language'
|
||||
|
||||
|
||||
export const mockQuery = ({query, mocks, variables = { id: 'id' }, log = false}) => {
|
||||
// Arguments:
|
||||
// (required) QUERY
|
||||
// (optional) Mock object : to override base mocks
|
||||
// (optional) Variables : If not passed, it will use a fake id only (most frequently used)
|
||||
// (optional) Log : In case you want the query result to be shown with test results.
|
||||
|
||||
/// MOCKING SCHEMA:
|
||||
const schema = mockSchema()
|
||||
const combinedMocks = mocks ? assign({}, baseMocks, mocks) : baseMocks
|
||||
addMockFunctionsToSchema({ schema, mocks: combinedMocks })
|
||||
|
||||
// need the first 'return' so that the final output is the promise result
|
||||
return graphql(schema, gqlToString(query), null, null, variables).then(result => {
|
||||
if (log) console.log('mockQuery result', result)
|
||||
const { data, errors } = result
|
||||
expect(errors).toBe()
|
||||
return data
|
||||
})
|
||||
}
|
|
@ -1,8 +1,12 @@
|
|||
import React from 'react'
|
||||
import { Provider as AlertProvider } from 'react-alert'
|
||||
import AlertTemplate from 'react-alert-template-basic'
|
||||
import { Router } from 'react-router-dom'
|
||||
import { ApolloProvider } from '@apollo/react-hooks'
|
||||
import { createBrowserHistory as createHistory } from 'history'
|
||||
import Raven from 'raven-js'
|
||||
|
||||
import client from 'apollo/client'
|
||||
import Routes from './routes'
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
|
@ -12,9 +16,13 @@ if (process.env.NODE_ENV === 'production') {
|
|||
const history = createHistory()
|
||||
|
||||
const Root = () => (
|
||||
<Router history={history}>
|
||||
<Routes />
|
||||
</Router>
|
||||
<ApolloProvider client={client}>
|
||||
<AlertProvider template={AlertTemplate}>
|
||||
<Router history={history}>
|
||||
<Routes />
|
||||
</Router>
|
||||
</AlertProvider>
|
||||
</ApolloProvider>
|
||||
)
|
||||
|
||||
export default Root
|
||||
|
|
Loading…
Reference in New Issue
Block a user