diff --git a/packages/vulcan-lib/lib/server/apollo-server/apollo_server2.js b/packages/vulcan-lib/lib/server/apollo-server/apollo_server2.js
index c235e0ad9..f074895f9 100644
--- a/packages/vulcan-lib/lib/server/apollo-server/apollo_server2.js
+++ b/packages/vulcan-lib/lib/server/apollo-server/apollo_server2.js
@@ -32,24 +32,27 @@ import { enableSSR } from '../apollo-ssr'
*
* Config: a config specific to Vulcan
*/
-const createApolloServer = ({ options: givenOptions = {}, config: givenConfig = {}, contextFromReq }) => {
+const createApolloServer = ({ options: givenOptions = {}, config: givenConfig = {}, customContextFromReq }) => {
const graphiqlOptions = { ...defaultConfig.graphiqlOptions, ...givenConfig.graphiqlOptions };
const config = { ...defaultConfig, ...givenConfig };
config.graphiqlOptions = graphiqlOptions;
// get the options and merge in defaults
const options = { ...defaultOptions, ...givenOptions };
- const context = initContext(options.context);
+ const initialContext = initContext(options.context);
+
+ // this replace the previous syntax graphqlExpress(async req => { ... })
+ // this function takes the context, which contains the current request,
+ // and setup the options accordingly ({req}) => { ...; return options }
+ const contextFromReq = computeContextFromReq(initialContext, customContextFromReq)
// given options contains the schema
const apolloServer = new ApolloServer({
engine: engineConfig,
// graphql playground (replacement to graphiql), available on the app path
playground: getPlaygroundConfig(config),
...options,
- // this replace the previous syntax graphqlExpress(async req => { ... })
- // this function takes the context, which contains the current request,
- // and setup the options accordingly ({req}) => { ...; return options }
- context: computeContextFromReq(context, contextFromReq)
+ // context optionbject or a function of the current request (+ maybe some other params)
+ context: ({req}) => contextFromReq(req)
});
// default function does nothing
@@ -90,7 +93,7 @@ const createApolloServer = ({ options: givenOptions = {}, config: givenConfig =
// ssr
- enableSSR()
+ enableSSR({ computeContext: contextFromReq})
/*
* Alternative syntax with Express instead of Connect
diff --git a/packages/vulcan-lib/lib/server/apollo-server/context.js b/packages/vulcan-lib/lib/server/apollo-server/context.js
index 65082d116..5430320cb 100644
--- a/packages/vulcan-lib/lib/server/apollo-server/context.js
+++ b/packages/vulcan-lib/lib/server/apollo-server/context.js
@@ -45,24 +45,24 @@ export const initContext = currentContext => {
return context;
};
-// Call on every request
-export const computeContextFromReq = (currentContext, contextFromReq) => {
+// @see https://www.apollographql.com/docs/react/recipes/meteor#Server
+const setupAuthToken = async (context, req) => {
+ const user = await getUser(req.headers.authorization);
+ if (user) {
+ context.userId = user._id;
+ context.currentUser = user;
+ // identify user to any server-side analytics providers
+ runCallbacks('events.identify', user);
+ } else {
+ context.userId = undefined;
+ context.currentUser = undefined;
+ }
+};
+// Returns a function called on every request to compute context
+export const computeContextFromReq = (currentContext, customContextFromReq) => {
// givenOptions can be either a function of the request or an object
const getBaseContext = req =>
- contextFromReq ? { ...currentContext, ...contextFromReq(req) } : { ...currentContext };
- // @see https://www.apollographql.com/docs/react/recipes/meteor#Server
- const setupAuthToken = async (context, req) => {
- const user = await getUser(req.headers.authorization);
- if (user) {
- context.userId = user._id;
- context.currentUser = user;
- // identify user to any server-side analytics providers
- runCallbacks('events.identify', user);
- } else {
- context.userId = undefined;
- context.currentUser = undefined;
- }
- };
+ customContextFromReq ? { ...currentContext, ...customContextFromReq(req) } : { ...currentContext };
// Previous implementation
// Now meteor/apollo already provide this
// Get the token from the header
@@ -91,7 +91,7 @@ export const computeContextFromReq = (currentContext, contextFromReq) => {
//}
// create options given the current request
- const handleReq = async ({ req }) => {
+ const handleReq = async (req) => {
let context;
let user = null;
diff --git a/packages/vulcan-lib/lib/server/apollo-ssr/apolloClient.js b/packages/vulcan-lib/lib/server/apollo-ssr/apolloClient.js
index 4b96705e8..210b27ec6 100644
--- a/packages/vulcan-lib/lib/server/apollo-ssr/apolloClient.js
+++ b/packages/vulcan-lib/lib/server/apollo-ssr/apolloClient.js
@@ -18,14 +18,16 @@ import { ApolloLink } from 'apollo-link';
// import { createHttpLink } from 'apollo-link-http';
// import fetch from 'node-fetch'
-export const createClient = (req) => {
+export const createClient = async ({req, computeContext}) => {
// init
// stateLink will init the client internal state
const cache = new InMemoryCache()
const stateLink = createStateLink({ cache });
// schemaLink will fetch data directly based on the executable schema
const schema = GraphQLSchema.getExecutableSchema()
- const schemaLink = new SchemaLink({ schema })
+ // this is the resolver context
+ const context = await computeContext(req)
+ const schemaLink = new SchemaLink({ schema, context })
const client = new ApolloClient({
ssrMode: true,
link: ApolloLink.from([stateLink, schemaLink, errorLink]),
diff --git a/packages/vulcan-lib/lib/server/apollo-ssr/enableSSR.js b/packages/vulcan-lib/lib/server/apollo-ssr/enableSSR.js
index fdab5deab..33baa8e70 100644
--- a/packages/vulcan-lib/lib/server/apollo-ssr/enableSSR.js
+++ b/packages/vulcan-lib/lib/server/apollo-ssr/enableSSR.js
@@ -11,17 +11,17 @@ import {
// excepts it is tailored to handle Meteor server side rendering
import { onPageLoad } from 'meteor/server-render'
-import renderPage from './renderPage'
+import makePageRenderer from './renderPage'
-const enableSSR = () => {
+const enableSSR = ({computeContext}) => {
Meteor.startup(() => {
// init the application components and routes, including components & routes from 3rd-party packages
initializeFragments();
populateComponentsApp();
populateRoutesApp();
// render the page
- onPageLoad(renderPage)
+ onPageLoad(makePageRenderer({computeContext}))
});
}
diff --git a/packages/vulcan-lib/lib/server/apollo-ssr/renderPage.js b/packages/vulcan-lib/lib/server/apollo-ssr/renderPage.js
index b6a23a0df..f8fbc4b13 100644
--- a/packages/vulcan-lib/lib/server/apollo-ssr/renderPage.js
+++ b/packages/vulcan-lib/lib/server/apollo-ssr/renderPage.js
@@ -14,40 +14,44 @@ import Head from './components/Head'
import ApolloState from './components/ApolloState'
import AppGenerator from './components/AppGenerator';
-const renderPage = async sink => {
- const req = sink.request
- // according to the Apollo doc, client needs to be recreated on every request
- // this avoids caching server side
- const client = createClient(req);
+const makePageRenderer = ({ computeContext }) => {
+ // onPageLoad callback
+ const renderPage = async sink => {
+ const req = sink.request
+ // according to the Apollo doc, client needs to be recreated on every request
+ // this avoids caching server side
+ const client = await createClient({req, computeContext});
- // TODO? do we need this?
- const context = {};
+ // TODO? do we need this?
+ const context = {};
- // equivalent to calling getDataFromTree and then renderToStringWithData
- const content = await renderToStringWithData(
-