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

104 lines
3 KiB
JavaScript
Raw Normal View History

2017-02-08 09:15:09 +08:00
import { createMemoryHistory } from 'react-router';
2017-02-08 04:36:57 +08:00
import { Meteor } from 'meteor/meteor';
import { DDP } from 'meteor/ddp';
import { Accounts } from 'meteor/accounts-base';
2017-02-08 09:15:09 +08:00
import { RoutePolicy } from 'meteor/routepolicy';
2017-02-08 04:36:57 +08:00
import { createApolloClient, getReducers, getMiddlewares } from '../modules/index.js';
import { configureStore } from './store.js';
const Fiber = Npm.require('fibers');
export const renderContext = new Meteor.EnvironmentVariable();
export const getRenderContext = () => renderContext.get();
2017-02-08 09:15:09 +08:00
function isAppUrl(req) {
const url = req.url;
if (url === '/favicon.ico' || url === '/robots.txt') {
return false;
}
if (url === '/app.manifest') {
return false;
}
// Avoid serving app HTML for declared routes such as /sockjs/.
if (RoutePolicy.classify(url)) {
return false;
}
// we only need to support HTML pages only
// this is a check to do it
return /html/.test(req.headers.accept);
}
2017-02-08 04:36:57 +08:00
const LoginContext = function LoginContext(loginToken) {
this._loginToken = loginToken;
// get the user
if (Meteor.users) {
// check to make sure, we've the loginToken,
// otherwise a random user will fetched from the db
let user;
if (loginToken) {
const hashedToken = loginToken && Accounts._hashLoginToken(loginToken);
const query = { 'services.resume.loginTokens.hashedToken': hashedToken };
const options = { fields: { _id: 1 } };
user = Meteor.users.findOne(query, options);
}
if (user) {
this.userId = user._id;
}
}
};
2017-02-08 09:15:09 +08:00
export const withRenderContextRaw = (func, options = {}) => {
2017-02-08 04:36:57 +08:00
const newFunc = Meteor.bindEnvironment((req, res, next) => {
Fiber.current._meteor_dynamics = Fiber.current._meteor_dynamics || [];
Fiber.current._meteor_dynamics[DDP._CurrentInvocation.slot] = req.loginContext;
Fiber.current._meteor_dynamics[renderContext.slot] = req.renderContext;
func(req, res, next);
if (options.autoNext) {
next();
}
})
if (options.name) {
Object.defineProperty(newFunc, 'name', { value: options.name });
}
WebApp.connectHandlers.use(newFunc);
}
2017-02-08 09:15:09 +08:00
export const withRenderContext = (func) => {
withRenderContextRaw(func, { autoNext: true });
};
WebApp.connectHandlers.use(Meteor.bindEnvironment((req, res, next) => {
if (!isAppUrl(req)) {
next();
return;
}
2017-02-08 04:36:57 +08:00
2017-02-08 09:15:09 +08:00
req.history = createMemoryHistory(req.url);
req.loginToken = req.cookies && req.cookies.meteor_login_token;
req.apolloClient = createApolloClient({ currentUserToken: req.loginToken });
req.reducers = { ...getReducers(), apollo: req.apolloClient.reducer() };
req.middlewares = [...getMiddlewares(), req.apolloClient.middleware()];
req.store = configureStore(req.reducers, {}, req.middlewares);
req.loginContext = new LoginContext(req.loginToken);
req.renderContext = {
history: req.history,
loginToken: req.loginToken,
apolloClient: req.apolloClient,
reducers: req.reducers,
middlewares: req.middlewares,
store: req.store,
};
2017-02-08 04:36:57 +08:00
next();
2017-02-08 09:15:09 +08:00
}));