Skip to content

Commit 665547e

Browse files
committed
renderContext fix
1 parent efe56c2 commit 665547e

File tree

12 files changed

+115
-71
lines changed

12 files changed

+115
-71
lines changed

packages/nova-core/lib/modules/index.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import './callbacks.js';
33
// import and re-export
44
export {
55
// apollo
6-
createApolloClient, renderContext,
6+
createApolloClient,
77
// callbacks
88
Callbacks, addCallback, removeCallback, runCallbacks, runCallbacksAsync,
99
// components
@@ -18,6 +18,8 @@ export {
1818
Headtags,
1919
// redux
2020
getActions, addAction, getReducers, addReducer, getMiddlewares, addMiddleware,
21+
// render
22+
renderContext, getRenderContext,
2123
// routes
2224
Routes, addRoute, getRoute, populateRoutesApp,
2325
// settings
@@ -30,6 +32,8 @@ export {
3032
configureStore,
3133
// mutations (for server only)
3234
newMutation, editMutation, removeMutation,
35+
// ssr (for server only)
36+
ssr, ssrNext
3337
} from 'meteor/nova:lib';
3438

3539
export { default as App } from "./components/App.jsx";

packages/nova-core/lib/server/apollo_server.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ const createApolloServer = (givenOptions = {}, givenConfig = {}) => {
140140
}
141141

142142
// This binds the specified paths to the Express server running Apollo + GraphiQL
143-
WebApp.connectHandlers.use(graphQLServer);
143+
WebApp.connectHandlers.use(Meteor.bindEnvironment(graphQLServer));
144144
};
145145

146146
Meteor.startup(function () {

packages/nova-lib/lib/client/auth.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import cookie from 'react-cookie';
22

33
import { Meteor } from 'meteor/meteor';
44

5-
import { renderContext } from './render_context.js';
5+
import { getRenderContext } from './render.js';
66

7-
const context = renderContext.get();
7+
const context = getRenderContext();
88

99
function setToken(loginToken, expires) {
1010
if (loginToken && expires !== -1) {

packages/nova-lib/lib/client/main.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import './auth.js';
22

33
export * from '../modules/index.js';
44
export * from './mongo_redux.js';
5-
export * from './render_context.js';
5+
export * from './render.js';

packages/nova-lib/lib/client/mongo_redux.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { renderContext } from './render_context.js';
1+
import { getRenderContext } from './render.js';
22

3-
const { store } = renderContext.get();
3+
const { store } = getRenderContext;
44

55
// use global store
66
Mongo.Collection.prototype.findRedux = function (selector = {}, options = {}) {

packages/nova-lib/lib/client/render_context.js packages/nova-lib/lib/client/render.js

+2
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,5 @@ export const renderContext = {
4444
return context;
4545
},
4646
};
47+
48+
export const getRenderContext = () => renderContext.get();

packages/nova-lib/lib/server/main.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ import './oauth_config.js';
33
export * from '../modules/index.js';
44
export * from './store.js';
55
export * from './mutations.js';
6-
export * from './render_context.js';
6+
export * from './render.js';
+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { Meteor } from 'meteor/meteor';
2+
import { DDP } from 'meteor/ddp';
3+
import { Accounts } from 'meteor/accounts-base';
4+
5+
import { createApolloClient, getReducers, getMiddlewares } from '../modules/index.js';
6+
import { configureStore } from './store.js';
7+
8+
const Fiber = Npm.require('fibers');
9+
10+
export const renderContext = new Meteor.EnvironmentVariable();
11+
12+
export const getRenderContext = () => renderContext.get();
13+
14+
const LoginContext = function LoginContext(loginToken) {
15+
this._loginToken = loginToken;
16+
17+
// get the user
18+
if (Meteor.users) {
19+
// check to make sure, we've the loginToken,
20+
// otherwise a random user will fetched from the db
21+
let user;
22+
if (loginToken) {
23+
const hashedToken = loginToken && Accounts._hashLoginToken(loginToken);
24+
const query = { 'services.resume.loginTokens.hashedToken': hashedToken };
25+
const options = { fields: { _id: 1 } };
26+
user = Meteor.users.findOne(query, options);
27+
}
28+
29+
if (user) {
30+
this.userId = user._id;
31+
}
32+
}
33+
};
34+
35+
export const ssr = (func, options = {}) => {
36+
const newFunc = Meteor.bindEnvironment((req, res, next) => {
37+
req.loginToken = req.loginToken || (req.cookies && req.cookies.meteor_login_token);
38+
req.apolloClient = req.apolloClient || createApolloClient({ currentUserToken: req.loginToken });
39+
req.reducers = req.reducers || { ...getReducers(), apollo: req.apolloClient.reducer() };
40+
req.middlewares = req.middlewares || [...getMiddlewares(), req.apolloClient.middleware()];
41+
req.store = req.store || configureStore(req.reducers, {}, req.middlewares);
42+
req.loginContext = req.loginContext || new LoginContext(req.loginToken);
43+
req.renderContext = req.renderContext || {
44+
loginToken: req.loginToken,
45+
apolloClient: req.apolloClient,
46+
reducers: req.reducers,
47+
middlewares: req.middlewares,
48+
store: req.store,
49+
};
50+
51+
Fiber.current._meteor_dynamics = Fiber.current._meteor_dynamics || [];
52+
Fiber.current._meteor_dynamics[DDP._CurrentInvocation.slot] = req.loginContext;
53+
Fiber.current._meteor_dynamics[renderContext.slot] = req.renderContext;
54+
55+
func(req, res, next);
56+
57+
if (options.autoNext) {
58+
next();
59+
}
60+
})
61+
62+
if (options.name) {
63+
Object.defineProperty(newFunc, 'name', { value: options.name });
64+
}
65+
WebApp.connectHandlers.use(newFunc);
66+
}
67+
68+
export const ssrNext = (func) => {
69+
ssr(func, { autoNext: true });
70+
}
71+
72+
ssr((req, res, next) => {
73+
// initialize
74+
// console.log(Fiber.current)
75+
next();
76+
});

packages/nova-lib/lib/server/render_context.js

-53
This file was deleted.

packages/nova-routing/lib/client/routing.jsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
addRoute,
1111
addReducer, addMiddleware,
1212
Routes, populateComponentsApp, populateRoutesApp, runCallbacks,
13-
renderContext,
13+
getRenderContext,
1414
} from 'meteor/nova:core';
1515

1616
import { RouterClient } from './router.jsx';
@@ -37,7 +37,7 @@ Meteor.startup(() => {
3737
const options = {
3838
rehydrateHook(data) {
3939
const initialState = data;
40-
const context = renderContext.get();
40+
const context = getRenderContext();
4141
context.initialState = initialState;
4242

4343
// configure apollo
@@ -50,13 +50,13 @@ Meteor.startup(() => {
5050
store.reload();
5151
},
5252
historyHook(newHistory) {
53-
const context = renderContext.get();
53+
const context = getRenderContext();
5454
const history = newHistory;
5555
context.history = history;
5656
return history;
5757
},
5858
wrapperHook(appGenerator) {
59-
const { apolloClient, store } = renderContext.get();
59+
const { apolloClient, store } = getRenderContext();
6060
const app = appGenerator({
6161
onUpdate: () => {
6262
// the first argument is an item to iterate on, needed by nova:lib/callbacks

packages/nova-routing/lib/server/router.jsx

+17-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import cookieParser from 'cookie-parser';
66
import { RoutePolicy } from 'meteor/routepolicy';
77
import { WebApp } from 'meteor/webapp';
88

9+
import { ssr, ssrNext } from 'meteor/nova:core';
10+
911
import { InjectData } from './inject_data.js';
1012

1113
function isAppUrl(req) {
@@ -114,7 +116,20 @@ export const RouterServer = {
114116

115117
WebApp.rawConnectHandlers.use(cookieParser());
116118

117-
WebApp.connectHandlers.use((req, res, next) => {
119+
// Ensure router middleware is at the end
120+
ssrNext(() => {
121+
const stack = WebApp.connectHandlers.stack;
122+
if (stack[stack.length - 1].handle.name === 'routerMiddleware') {
123+
return;
124+
}
125+
for (let i in stack) {
126+
if (stack[i].handle.name === 'routerMiddleware') {
127+
stack.push(stack.splice(i, 1)[0]);
128+
}
129+
}
130+
});
131+
132+
ssr((req, res, next) => {
118133
if (!isAppUrl(req)) {
119134
next();
120135
return;
@@ -142,6 +157,6 @@ export const RouterServer = {
142157
res.end();
143158
}
144159
});
145-
});
160+
}, { name: 'routerMiddleware' });
146161
},
147162
};

packages/nova-routing/lib/server/routing.jsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
Components,
1010
addRoute,
1111
Routes, populateComponentsApp, populateRoutesApp,
12-
renderContext,
12+
getRenderContext,
1313
} from 'meteor/nova:core';
1414

1515
import { RouterServer } from './router.jsx';
@@ -36,20 +36,20 @@ Meteor.startup(() => {
3636
const options = {
3737
historyHook(req, res, newHistory) {
3838
req.history = newHistory;
39-
const context = renderContext.get();
39+
const context = getRenderContext();
4040
context.history = req.history;
4141
return req.history;
4242
},
4343
wrapperHook(req, res, appGenerator) {
44-
const { apolloClient, store } = renderContext.get();
44+
const { apolloClient, store } = getRenderContext();
4545
const app = appGenerator();
4646
return <ApolloProvider store={store} client={apolloClient}>{app}</ApolloProvider>;
4747
},
4848
preRender(req, res, app) {
4949
return Promise.await(getDataFromTree(app));
5050
},
5151
dehydrateHook(req, res) {
52-
const context = renderContext.get();
52+
const context = getRenderContext();
5353
return context.apolloClient.store.getState();
5454
},
5555
postRender(req, res) {

0 commit comments

Comments
 (0)