diff --git a/packages/vulcan-core/lib/modules/containers/withMessages.js b/packages/vulcan-core/lib/modules/containers/withMessages.js index b63b9bab54..9c00f13a93 100644 --- a/packages/vulcan-core/lib/modules/containers/withMessages.js +++ b/packages/vulcan-core/lib/modules/containers/withMessages.js @@ -1,101 +1,104 @@ -/* - -HoC that provides access to flash messages stored in Redux state and actions to operate on them - -*/ - -import { getActions, addAction, addReducer } from 'meteor/vulcan:lib'; -import { bindActionCreators } from 'redux'; -import { connect } from 'react-redux'; - -/* - - Messages actions - -*/ - -addAction({ - messages: { - flash(content) { - return { - type: 'FLASH', - content, - }; - }, - clear(i) { - return { - type: 'CLEAR', - i, - }; - }, - markAsSeen(i) { - return { - type: 'MARK_AS_SEEN', - i, - }; - }, - clearSeen() { - return { - type: 'CLEAR_SEEN' - }; - }, - } -}); - - -/* - - Messages reducers - -*/ - -addReducer({ - messages: (state = [], action) => { - // default values - const flashType = action.content && typeof action.content.type !== 'undefined' ? action.content.type : 'error'; - const currentMsg = typeof action.i === 'undefined' ? {} : state[action.i]; - - switch(action.type) { - case 'FLASH': - return [ - ...state, - { - _id: state.length, - ...action.content, - type: flashType, - seen: false, - show: true, - }, - ]; - case 'MARK_AS_SEEN': - return [ - ...state.slice(0, action.i), - { ...currentMsg, seen: true }, - ...state.slice(action.i + 1), - ]; - case 'CLEAR': - return [ - ...state.slice(0, action.i), - { ...currentMsg, show: false }, - ...state.slice(action.i + 1), - ]; - case 'CLEAR_SEEN': - return state.map(message => message.seen ? { ...message, show: false } : message); - default: - return state; - } - }, -}); - -/* - - withMessages HOC - -*/ - -const mapStateToProps = state => ({ messages: state.messages, }); -const mapDispatchToProps = dispatch => bindActionCreators(getActions().messages, dispatch); - -const withMessages = component => connect(mapStateToProps, mapDispatchToProps)(component); - -export default withMessages; +// /* + +// HoC that provides access to flash messages stored in Redux state and actions to operate on them + +// */ + +// import { getActions, addAction, addReducer } from 'meteor/vulcan:lib'; +// import { bindActionCreators } from 'redux'; +// import { connect } from 'react-redux'; + +// /* + +// Messages actions + +// */ + +// addAction({ +// messages: { +// flash(content) { +// return { +// type: 'FLASH', +// content, +// }; +// }, +// clear(i) { +// return { +// type: 'CLEAR', +// i, +// }; +// }, +// markAsSeen(i) { +// return { +// type: 'MARK_AS_SEEN', +// i, +// }; +// }, +// clearSeen() { +// return { +// type: 'CLEAR_SEEN' +// }; +// }, +// } +// }); + + +// /* + +// Messages reducers + +// */ + +// addReducer({ +// messages: (state = [], action) => { +// // default values +// const flashType = action.content && typeof action.content.type !== 'undefined' ? action.content.type : 'error'; +// const currentMsg = typeof action.i === 'undefined' ? {} : state[action.i]; + +// switch(action.type) { +// case 'FLASH': +// return [ +// ...state, +// { +// _id: state.length, +// ...action.content, +// type: flashType, +// seen: false, +// show: true, +// }, +// ]; +// case 'MARK_AS_SEEN': +// return [ +// ...state.slice(0, action.i), +// { ...currentMsg, seen: true }, +// ...state.slice(action.i + 1), +// ]; +// case 'CLEAR': +// return [ +// ...state.slice(0, action.i), +// { ...currentMsg, show: false }, +// ...state.slice(action.i + 1), +// ]; +// case 'CLEAR_SEEN': +// return state.map(message => message.seen ? { ...message, show: false } : message); +// default: +// return state; +// } +// }, +// }); + +// /* + +// withMessages HOC + +// */ + +// const mapStateToProps = state => ({ messages: state.messages, }); +// const mapDispatchToProps = dispatch => bindActionCreators(getActions().messages, dispatch); + +// const withMessages = component => connect(mapStateToProps, mapDispatchToProps)(component); + +// export default withMessages; + +const withMessages = (x) => x; +export default withMessages; \ No newline at end of file diff --git a/packages/vulcan-lib/lib/client/auth.js b/packages/vulcan-lib/lib/client/auth.js index 4004321425..c0d8be2d87 100644 --- a/packages/vulcan-lib/lib/client/auth.js +++ b/packages/vulcan-lib/lib/client/auth.js @@ -1,54 +1,54 @@ -import Cookies from 'universal-cookie'; - -import { Meteor } from 'meteor/meteor'; - -import { getRenderContext } from './render_context.js'; - -const cookie = new Cookies(); - -function setToken(loginToken, expires) { - if (loginToken && expires !== -1) { - cookie.set('meteor_login_token', loginToken, { - path: '/', - expires, - }); - } else { - cookie.remove('meteor_login_token', { - path: '/', - }); - } -} - -function resetToken() { - const context = getRenderContext(); - const loginToken = global.localStorage['Meteor.loginToken']; - const loginTokenExpires = new Date(global.localStorage['Meteor.loginTokenExpires']); - - if (loginToken) { - setToken(loginToken, loginTokenExpires); - } else { - setToken(null, -1); - } - - context.loginToken = loginToken; -} - -Meteor.startup(() => { - resetToken(); -}); - -const originalSetItem = Meteor._localStorage.setItem; -Meteor._localStorage.setItem = function setItem(key, value) { - if (key === 'Meteor.loginToken') { - Meteor.defer(resetToken); - } - originalSetItem.call(Meteor._localStorage, key, value); -}; - -const originalRemoveItem = Meteor._localStorage.removeItem; -Meteor._localStorage.removeItem = function removeItem(key) { - if (key === 'Meteor.loginToken') { - Meteor.defer(resetToken); - } - originalRemoveItem.call(Meteor._localStorage, key); -}; \ No newline at end of file +// import Cookies from 'universal-cookie'; + +// import { Meteor } from 'meteor/meteor'; + +// import { getRenderContext } from './render_context.js'; + +// const cookie = new Cookies(); + +// function setToken(loginToken, expires) { +// if (loginToken && expires !== -1) { +// cookie.set('meteor_login_token', loginToken, { +// path: '/', +// expires, +// }); +// } else { +// cookie.remove('meteor_login_token', { +// path: '/', +// }); +// } +// } + +// function resetToken() { +// const context = getRenderContext(); +// const loginToken = global.localStorage['Meteor.loginToken']; +// const loginTokenExpires = new Date(global.localStorage['Meteor.loginTokenExpires']); + +// if (loginToken) { +// setToken(loginToken, loginTokenExpires); +// } else { +// setToken(null, -1); +// } + +// context.loginToken = loginToken; +// } + +// Meteor.startup(() => { +// resetToken(); +// }); + +// const originalSetItem = Meteor._localStorage.setItem; +// Meteor._localStorage.setItem = function setItem(key, value) { +// if (key === 'Meteor.loginToken') { +// Meteor.defer(resetToken); +// } +// originalSetItem.call(Meteor._localStorage, key, value); +// }; + +// const originalRemoveItem = Meteor._localStorage.removeItem; +// Meteor._localStorage.removeItem = function removeItem(key) { +// if (key === 'Meteor.loginToken') { +// Meteor.defer(resetToken); +// } +// originalRemoveItem.call(Meteor._localStorage, key); +// }; \ No newline at end of file diff --git a/packages/vulcan-lib/lib/client/mongo_redux.js b/packages/vulcan-lib/lib/client/mongo_redux.js index a412eadf52..5efde6c33d 100644 --- a/packages/vulcan-lib/lib/client/mongo_redux.js +++ b/packages/vulcan-lib/lib/client/mongo_redux.js @@ -1,12 +1,12 @@ -import { getRenderContext } from './render_context.js'; +// import { getRenderContext } from './render_context.js'; -const { store } = getRenderContext; +// const { store } = getRenderContext; -// use global store -Mongo.Collection.prototype.findRedux = function (selector = {}, options = {}) { - return this.findInStore(store, selector, options); -} +// // use global store +// Mongo.Collection.prototype.findRedux = function (selector = {}, options = {}) { +// return this.findInStore(store, selector, options); +// } -Mongo.Collection.prototype.findOneRedux = function (_idOrObject) { - return this.findOneInStore(store, _idOrObject); -} +// Mongo.Collection.prototype.findOneRedux = function (_idOrObject) { +// return this.findOneInStore(store, _idOrObject); +// } diff --git a/packages/vulcan-lib/lib/client/render_context.js b/packages/vulcan-lib/lib/client/render_context.js index 65edb6fabf..a812c6e4f8 100644 --- a/packages/vulcan-lib/lib/client/render_context.js +++ b/packages/vulcan-lib/lib/client/render_context.js @@ -1,76 +1,76 @@ -import { browserHistory } from 'react-router'; -import { compose } from 'redux'; +// import { browserHistory } from 'react-router'; +// import { compose } from 'redux'; -import { - createApolloClient, - configureStore, - addAction, getActions, addReducer, getReducers, addMiddleware, getMiddlewares, -} from '../modules/index.js'; +// import { +// createApolloClient, +// configureStore, +// addAction, getActions, addReducer, getReducers, addMiddleware, getMiddlewares, +// } from '../modules/index.js'; -let context; +// let context; -export const initContext = () => { +// export const initContext = () => { - // init - const history = browserHistory; - const loginToken = global.localStorage['Meteor.loginToken']; - let apolloClient; +// // init +// const history = browserHistory; +// const loginToken = global.localStorage['Meteor.loginToken']; +// let apolloClient; - // init context - context = { - history, - loginToken, - addAction, // context.addAction same as addAction - getActions, // context.getActions same as getActions - addReducer, // context.addReducer same as addReducer - getReducers, // context.getReducers same as getReducers - addMiddleware, // context.addMiddleware same as addMiddleware - getMiddlewares, // context.getMiddlewares same as getMiddlewares - }; +// // init context +// context = { +// history, +// loginToken, +// addAction, // context.addAction same as addAction +// getActions, // context.getActions same as getActions +// addReducer, // context.addReducer same as addReducer +// getReducers, // context.getReducers same as getReducers +// addMiddleware, // context.addMiddleware same as addMiddleware +// getMiddlewares, // context.getMiddlewares same as getMiddlewares +// }; - // defer creation of apolloClient until it is first used - Object.defineProperty(context, 'apolloClient', { - enumerable: true, - get: () => { - if (!apolloClient) { - apolloClient = createApolloClient(); - addReducer({ apollo: apolloClient.reducer() }); - addMiddleware(apolloClient.middleware()); - } - return apolloClient; - }, - }); +// // defer creation of apolloClient until it is first used +// Object.defineProperty(context, 'apolloClient', { +// enumerable: true, +// get: () => { +// if (!apolloClient) { +// apolloClient = createApolloClient(); +// addReducer({ apollo: apolloClient.reducer() }); +// addMiddleware(apolloClient.middleware()); +// } +// return apolloClient; +// }, +// }); - // init store - context.store = configureStore(context.getReducers, {}, (store) => { - let chain, newDispatch; - return next => (action) => { - if (!chain) { - chain = context.getMiddlewares().map(middleware => middleware(store)); - newDispatch = compose(...chain)(next) - } - return newDispatch(action); - }; - }) -} +// // init store +// context.store = configureStore(context.getReducers, {}, (store) => { +// let chain, newDispatch; +// return next => (action) => { +// if (!chain) { +// chain = context.getMiddlewares().map(middleware => middleware(store)); +// newDispatch = compose(...chain)(next) +// } +// return newDispatch(action); +// }; +// }) +// } -// render context object -export const renderContext = { - get: () => { +// // render context object +// export const renderContext = { +// get: () => { - if (typeof context === 'undefined') { - initContext(); - } +// if (typeof context === 'undefined') { +// initContext(); +// } - return context +// return context - } -}; +// } +// }; -// render context get function -export const getRenderContext = () => renderContext.get(); +// // render context get function +// export const getRenderContext = () => renderContext.get(); -// withRenderContext make it easy to access context -export const withRenderContext = (func) => { - func(context); -}; +// // withRenderContext make it easy to access context +// export const withRenderContext = (func) => { +// func(context); +// }; diff --git a/packages/vulcan-lib/lib/modules/apollo2.js b/packages/vulcan-lib/lib/modules/apollo2.js new file mode 100644 index 0000000000..9dfe1bcbec --- /dev/null +++ b/packages/vulcan-lib/lib/modules/apollo2.js @@ -0,0 +1,12 @@ +import ApolloClient from "apollo-boost"; +import { Accounts } from 'meteor/accounts-base' + +export const apolloClient = new ApolloClient({ + uri: '/graphql', + request: operation => + operation.setContext(() => ({ + headers: { + authorization: Accounts._storedLoginToken() + } + })) +}) \ No newline at end of file diff --git a/packages/vulcan-lib/lib/modules/redux.js b/packages/vulcan-lib/lib/modules/redux.js index 8ab13d4504..eb24a58c75 100644 --- a/packages/vulcan-lib/lib/modules/redux.js +++ b/packages/vulcan-lib/lib/modules/redux.js @@ -1,79 +1,79 @@ -import { createStore, applyMiddleware, compose, combineReducers } from 'redux'; +// import { createStore, applyMiddleware, compose, combineReducers } from 'redux'; -// create store, and implement reload function -export const configureStore = (reducers, initialState = {}, middlewares) => { - let getReducers; - if (typeof reducers === 'function') { - getReducers = reducers; - reducers = getReducers(); - } - reducers = typeof reducers === 'object' ? combineReducers(reducers) : reducers; - middlewares = Array.isArray(middlewares) ? middlewares : [middlewares]; +// // create store, and implement reload function +// export const configureStore = (reducers, initialState = {}, middlewares) => { +// let getReducers; +// if (typeof reducers === 'function') { +// getReducers = reducers; +// reducers = getReducers(); +// } +// reducers = typeof reducers === 'object' ? combineReducers(reducers) : reducers; +// middlewares = Array.isArray(middlewares) ? middlewares : [middlewares]; - const store = createStore( - // reducers - reducers, - // initial state - initialState, - // middlewares - compose( - applyMiddleware(...middlewares), - typeof window !== 'undefined' && window.devToolsExtension ? window.devToolsExtension() : f => f, - ), - ); +// const store = createStore( +// // reducers +// reducers, +// // initial state +// initialState, +// // middlewares +// compose( +// applyMiddleware(...middlewares), +// typeof window !== 'undefined' && window.devToolsExtension ? window.devToolsExtension() : f => f, +// ), +// ); - store.reload = function reload(options = {}) { - if (typeof options.reducers === 'function') { - getReducers = options.reducers; - options.reducers = undefined; - } - if (!options.reducers && getReducers) { - options.reducers = getReducers(); - } - if (options.reducers) { - reducers = typeof options.reducers === 'object' ? combineReducers(options.reducers) : options.reducers; - } - this.replaceReducer(reducers); - return store; - }; +// store.reload = function reload(options = {}) { +// if (typeof options.reducers === 'function') { +// getReducers = options.reducers; +// options.reducers = undefined; +// } +// if (!options.reducers && getReducers) { +// options.reducers = getReducers(); +// } +// if (options.reducers) { +// reducers = typeof options.reducers === 'object' ? combineReducers(options.reducers) : options.reducers; +// } +// this.replaceReducer(reducers); +// return store; +// }; - return store; -}; +// return store; +// }; -// action -// **Notes: client side, addAction to browser** -// **Notes: server side, addAction to server share with every req** -let actions = {}; +// // action +// // **Notes: client side, addAction to browser** +// // **Notes: server side, addAction to server share with every req** +// let actions = {}; -export const addAction = (addedAction) => { - actions = { ...actions, ...addedAction }; - return actions; -}; -export const getActions = () => actions; +// export const addAction = (addedAction) => { +// actions = { ...actions, ...addedAction }; +// return actions; +// }; +// export const getActions = () => actions; -// reducers -// **Notes: client side, addReducer to browser** -// **Notes: server side, addReducer to server share with every req** -let reducers = {}; +// // reducers +// // **Notes: client side, addReducer to browser** +// // **Notes: server side, addReducer to server share with every req** +// let reducers = {}; -export const addReducer = (addedReducer) => { - reducers = { ...reducers, ...addedReducer }; - return reducers; -}; -export const getReducers = () => reducers; +// export const addReducer = (addedReducer) => { +// reducers = { ...reducers, ...addedReducer }; +// return reducers; +// }; +// export const getReducers = () => reducers; -// middlewares -// **Notes: client side, addMiddleware to browser** -// **Notes: server side, addMiddleware to server share with every req** -let middlewares = []; +// // middlewares +// // **Notes: client side, addMiddleware to browser** +// // **Notes: server side, addMiddleware to server share with every req** +// let middlewares = []; -export const addMiddleware = (middlewareOrMiddlewareArray, options = {}) => { - const addedMiddleware = Array.isArray(middlewareOrMiddlewareArray) ? middlewareOrMiddlewareArray : [middlewareOrMiddlewareArray]; - if (options.unshift) { - middlewares = [...addedMiddleware, ...middlewares]; - } else { - middlewares = [...middlewares, ...addedMiddleware]; - } - return middlewares; -}; -export const getMiddlewares = () => middlewares; +// export const addMiddleware = (middlewareOrMiddlewareArray, options = {}) => { +// const addedMiddleware = Array.isArray(middlewareOrMiddlewareArray) ? middlewareOrMiddlewareArray : [middlewareOrMiddlewareArray]; +// if (options.unshift) { +// middlewares = [...addedMiddleware, ...middlewares]; +// } else { +// middlewares = [...middlewares, ...addedMiddleware]; +// } +// return middlewares; +// }; +// export const getMiddlewares = () => middlewares; diff --git a/packages/vulcan-lib/lib/server/render_context.js b/packages/vulcan-lib/lib/server/render_context.js index 2e54ff9573..05e8892c8c 100644 --- a/packages/vulcan-lib/lib/server/render_context.js +++ b/packages/vulcan-lib/lib/server/render_context.js @@ -1,186 +1,186 @@ -import { createMemoryHistory } from 'react-router'; -import { compose } from 'redux'; -import cookieParser from 'cookie-parser'; - -import { Meteor } from 'meteor/meteor'; -import { DDP } from 'meteor/ddp'; -// import { Accounts } from 'meteor/accounts-base'; -import { RoutePolicy } from 'meteor/routepolicy'; -import { WebApp } from 'meteor/webapp'; -import { _hashLoginToken } from './accounts_helpers'; - -import { - createApolloClient, - configureStore, getActions, getReducers, getMiddlewares, - Utils, -} from '../modules/index.js'; - -import { webAppConnectHandlersUse } from './meteor_patch.js'; - -const Fiber = Npm.require('fibers'); - -// check the req url -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 for browsers - // Facebook's scraper uses a request header Accepts: */* - // so allow either - const facebookAcceptsHeader = new RegExp('/*\/*/'); - return /html/.test(req.headers.accept) || facebookAcceptsHeader.test(req.headers.accept); -} - -// for meteor.user -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 && _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; - } - } -}; - -// for req.cookies -webAppConnectHandlersUse(cookieParser(), { order: 10, name: 'cookieParserMiddleware' }); - -// initRenderContextMiddleware -webAppConnectHandlersUse(Meteor.bindEnvironment(function initRenderContextMiddleware(req, res, next) { - // check the req url - if (!isAppUrl(req)) { - next(); - return; - } +// import { createMemoryHistory } from 'react-router'; +// import { compose } from 'redux'; +// import cookieParser from 'cookie-parser'; + +// import { Meteor } from 'meteor/meteor'; +// import { DDP } from 'meteor/ddp'; +// // import { Accounts } from 'meteor/accounts-base'; +// import { RoutePolicy } from 'meteor/routepolicy'; +// import { WebApp } from 'meteor/webapp'; +// import { _hashLoginToken } from './accounts_helpers'; + +// import { +// createApolloClient, +// configureStore, getActions, getReducers, getMiddlewares, +// Utils, +// } from '../modules/index.js'; + +// import { webAppConnectHandlersUse } from './meteor_patch.js'; + +// const Fiber = Npm.require('fibers'); + +// // check the req url +// 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 for browsers +// // Facebook's scraper uses a request header Accepts: */* +// // so allow either +// const facebookAcceptsHeader = new RegExp('/*\/*/'); +// return /html/.test(req.headers.accept) || facebookAcceptsHeader.test(req.headers.accept); +// } + +// // for meteor.user +// 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 && _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; +// } +// } +// }; + +// // for req.cookies +// webAppConnectHandlersUse(cookieParser(), { order: 10, name: 'cookieParserMiddleware' }); + +// // initRenderContextMiddleware +// webAppConnectHandlersUse(Meteor.bindEnvironment(function initRenderContextMiddleware(req, res, next) { +// // check the req url +// if (!isAppUrl(req)) { +// next(); +// return; +// } - // init - const history = createMemoryHistory(req.url); - const loginToken = req.cookies && req.cookies.meteor_login_token; - const locale = req.cookies && req.cookies.locale; - // console.log('// render_context.js locale:', locale); - const apolloClient = createApolloClient({ loginToken, locale }); - let actions = {}; - let reducers = { apollo: apolloClient.reducer() }; - let middlewares = [Utils.defineName(apolloClient.middleware(), 'apolloClientMiddleware')]; - - // renderContext object - req.renderContext = { - locale, - history, - loginToken, - apolloClient, - addAction(addedAction) { // context.addAction: add action to renderContext - actions = { ...actions, ...addedAction }; - return this.getActions(); - }, - getActions() { // SSR actions = server actions + renderContext actions - return { ...getActions(), ...actions }; - }, - addReducer(addedReducer) { // context.addReducer: add reducer to renderContext - reducers = { ...reducers, ...addedReducer }; - return this.getReducers(); - }, - getReducers() { // SSR reducers = server reducers + renderContext reducers - return { ...getReducers(), ...reducers }; - }, - addMiddleware(middlewareOrMiddlewareArray) { // context.addMiddleware: add middleware to renderContext - const addedMiddleware = Array.isArray(middlewareOrMiddlewareArray) ? middlewareOrMiddlewareArray : [middlewareOrMiddlewareArray]; - middlewares = [...middlewares, ...addedMiddleware]; - return this.getMiddlewares(); - }, - getMiddlewares() { // SSR middlewares = server middlewares + renderContext middlewares - return [...getMiddlewares(), ...middlewares]; - }, - }; - - // create store - req.renderContext.store = configureStore(req.renderContext.getReducers, {}, (store) => { - let chain, newDispatch; +// // init +// const history = createMemoryHistory(req.url); +// const loginToken = req.cookies && req.cookies.meteor_login_token; +// const locale = req.cookies && req.cookies.locale; +// // console.log('// render_context.js locale:', locale); +// const apolloClient = createApolloClient({ loginToken, locale }); +// let actions = {}; +// let reducers = { apollo: apolloClient.reducer() }; +// let middlewares = [Utils.defineName(apolloClient.middleware(), 'apolloClientMiddleware')]; + +// // renderContext object +// req.renderContext = { +// locale, +// history, +// loginToken, +// apolloClient, +// addAction(addedAction) { // context.addAction: add action to renderContext +// actions = { ...actions, ...addedAction }; +// return this.getActions(); +// }, +// getActions() { // SSR actions = server actions + renderContext actions +// return { ...getActions(), ...actions }; +// }, +// addReducer(addedReducer) { // context.addReducer: add reducer to renderContext +// reducers = { ...reducers, ...addedReducer }; +// return this.getReducers(); +// }, +// getReducers() { // SSR reducers = server reducers + renderContext reducers +// return { ...getReducers(), ...reducers }; +// }, +// addMiddleware(middlewareOrMiddlewareArray) { // context.addMiddleware: add middleware to renderContext +// const addedMiddleware = Array.isArray(middlewareOrMiddlewareArray) ? middlewareOrMiddlewareArray : [middlewareOrMiddlewareArray]; +// middlewares = [...middlewares, ...addedMiddleware]; +// return this.getMiddlewares(); +// }, +// getMiddlewares() { // SSR middlewares = server middlewares + renderContext middlewares +// return [...getMiddlewares(), ...middlewares]; +// }, +// }; + +// // create store +// req.renderContext.store = configureStore(req.renderContext.getReducers, {}, (store) => { +// let chain, newDispatch; - return next => (action) => { - try { - if (!chain) { - chain = req.renderContext.getMiddlewares().map(middleware => middleware(store)); - } - newDispatch = compose(...chain)(next) - return newDispatch(action); - } catch (error) { - // console.log(error) - return _.identity - } - }; - }) - - // for meteor.user - req.loginContext = new LoginContext(loginToken); - - next(); -}), { order: 20 }); - -// render context object -export const renderContext = new Meteor.EnvironmentVariable(); - -// render context get function -export const getRenderContext = () => renderContext.get(); - -// withRenderContextEnvironment -export const withRenderContextEnvironment = (fn, options = {}) => { - // set newfn - const newfn = (req, res, next) => { - if (!isAppUrl(req)) { - next(); - return; - } - - 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; - - fn(req.renderContext, req, res, next); - - if (options.autoNext) { - next(); - } - }; - - // get evfn - const evfn = Meteor.bindEnvironment(newfn); - - // use it - WebApp.connectHandlers.use(evfn); - - // get handle - const handle = WebApp.connectHandlers.stack[WebApp.connectHandlers.stack.length - 1].handle; - - // copy options to handle - Object.keys(options).forEach((key) => { - handle[key] = options[key]; - }); -}; - -// withRenderContext make it easy to access context -export const withRenderContext = (func, options = {}) => { - withRenderContextEnvironment(func, { ...options, autoNext: true }); -}; +// return next => (action) => { +// try { +// if (!chain) { +// chain = req.renderContext.getMiddlewares().map(middleware => middleware(store)); +// } +// newDispatch = compose(...chain)(next) +// return newDispatch(action); +// } catch (error) { +// // console.log(error) +// return _.identity +// } +// }; +// }) + +// // for meteor.user +// req.loginContext = new LoginContext(loginToken); + +// next(); +// }), { order: 20 }); + +// // render context object +// export const renderContext = new Meteor.EnvironmentVariable(); + +// // render context get function +// export const getRenderContext = () => renderContext.get(); + +// // withRenderContextEnvironment +// export const withRenderContextEnvironment = (fn, options = {}) => { +// // set newfn +// const newfn = (req, res, next) => { +// if (!isAppUrl(req)) { +// next(); +// return; +// } + +// 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; + +// fn(req.renderContext, req, res, next); + +// if (options.autoNext) { +// next(); +// } +// }; + +// // get evfn +// const evfn = Meteor.bindEnvironment(newfn); + +// // use it +// WebApp.connectHandlers.use(evfn); + +// // get handle +// const handle = WebApp.connectHandlers.stack[WebApp.connectHandlers.stack.length - 1].handle; + +// // copy options to handle +// Object.keys(options).forEach((key) => { +// handle[key] = options[key]; +// }); +// }; + +// // withRenderContext make it easy to access context +// export const withRenderContext = (func, options = {}) => { +// withRenderContextEnvironment(func, { ...options, autoNext: true }); +// }; diff --git a/packages/vulcan-routing/lib/server/router.jsx b/packages/vulcan-routing/lib/server/router.jsx index eded83e76b..ddea9691ec 100644 --- a/packages/vulcan-routing/lib/server/router.jsx +++ b/packages/vulcan-routing/lib/server/router.jsx @@ -1,159 +1,159 @@ -import React from 'react'; -import { match, RouterContext, createMemoryHistory } from 'react-router'; -import { renderToString } from 'react-dom/server' -import { ServerStyleSheet } from 'styled-components' -import moment from 'moment'; -import { RoutePolicy } from 'meteor/routepolicy'; - -import { withRenderContextEnvironment, InjectData } from 'meteor/vulcan:lib'; - -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 for browsers - // Facebook's scraper uses a request header Accepts: */* - // so allow either - const facebookAcceptsHeader = new RegExp('/*\/*/'); - return /html/.test(req.headers.accept) || facebookAcceptsHeader.test(req.headers.accept); -} - -function generateSSRData(options, req, res, renderProps) { - let html; - let css; - let styledComponentCss; - - try { - req.css = ''; - - renderProps = { - ...renderProps, - ...options.props, - }; - - const appGenerator = addProps => ; - - let app; - if (typeof options.wrapperHook === 'function') { - app = options.wrapperHook(req, res, appGenerator); - } - - if (options.preRender) { - options.preRender(req, res, app); - } - - if (!options.disableSSR) { - const sheet = new ServerStyleSheet(); - html = renderToString(sheet.collectStyles(app)); - styledComponentCss = sheet.getStyleTags(); - } else if (options.loadingScreen) { - html = options.loadingScreen; - } - - if (typeof options.dehydrateHook === 'function') { - const data = options.dehydrateHook(req, res); - InjectData.pushData(res, 'dehydrated-initial-data', JSON.stringify(data)); - } - - // send server timezone to client - InjectData.pushData(res, 'utcOffset', moment().utcOffset()); - - if (options.postRender) { - options.postRender(req, res); - } - - css = req.css; - } catch (err) { - console.log('url: ', req.url); // eslint-disable-line no-console - console.log(err); // eslint-disable-line no-console - console.error(new Date(), 'error while server-rendering', err.stack); // eslint-disable-line no-console - } - - return { html, css, styledComponentCss }; -} - -function sendSSRHtml(options, req, res, next, renderProps) { - const { css, html, styledComponentCss } = generateSSRData(options, req, res, renderProps); - - req.dynamicHead = req.dynamicHead || ''; - req.dynamicBody = req.dynamicBody || ''; - - // css declared in the project - if (css) { - req.dynamicHead += ``; - } - - // css collected by styled-components - if (styledComponentCss) { - req.dynamicHead += styledComponentCss; - } - - let rootElementAttributes = ''; - const attributes = options.rootElementAttributes instanceof Array ? options.rootElementAttributes : []; - if (attributes[0] instanceof Array) { - for (let i = 0; i < attributes.length; i++) { - rootElementAttributes += ` ${attributes[i][0]}="${attributes[i][1]}"`; - } - } else if (attributes.length > 0) { - rootElementAttributes = ` ${attributes[0]}="${attributes[1]}"`; - } - - req.dynamicBody += `<${options.rootElementType || 'div'} id="${options.rootElement || 'react-app'}"${rootElementAttributes}>${html || ''}`; - - if (typeof options.htmlHook === 'function') { - const { dynamicHead, dynamicBody } = options.htmlHook(req, res, req.dynamicHead, req.dynamicBody); - req.dynamicHead = dynamicHead; - req.dynamicBody = dynamicBody; - } - - next(); -} - -export const RouterServer = { - run(routes, options) { - if (!options) { - options = {}; - } - - withRenderContextEnvironment(function routerMiddleware(context, req, res, next) { - if (!isAppUrl(req)) { - next(); - return; - } - - let history = createMemoryHistory(req.url); - - if (typeof options.historyHook === 'function') { - history = options.historyHook(req, res, history); - } - - match({ history, routes, location: req.url }, (err, redirectLocation, renderProps) => { - if (err) { - res.writeHead(500); - res.write(err.messages); - res.end(); - } else if (redirectLocation) { - res.writeHead(302, { Location: redirectLocation.pathname + redirectLocation.search }); - res.end(); - } else if (renderProps) { - sendSSRHtml(options, req, res, next, renderProps); - } else { - res.writeHead(404); - res.write('Not found'); - res.end(); - } - }); - }, { order: 800 }); - }, -}; +// import React from 'react'; +// import { match, RouterContext, createMemoryHistory } from 'react-router'; +// import { renderToString } from 'react-dom/server' +// import { ServerStyleSheet } from 'styled-components' +// import moment from 'moment'; +// import { RoutePolicy } from 'meteor/routepolicy'; + +// import { withRenderContextEnvironment, InjectData } from 'meteor/vulcan:lib'; + +// 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 for browsers +// // Facebook's scraper uses a request header Accepts: */* +// // so allow either +// const facebookAcceptsHeader = new RegExp('/*\/*/'); +// return /html/.test(req.headers.accept) || facebookAcceptsHeader.test(req.headers.accept); +// } + +// function generateSSRData(options, req, res, renderProps) { +// let html; +// let css; +// let styledComponentCss; + +// try { +// req.css = ''; + +// renderProps = { +// ...renderProps, +// ...options.props, +// }; + +// const appGenerator = addProps => ; + +// let app; +// if (typeof options.wrapperHook === 'function') { +// app = options.wrapperHook(req, res, appGenerator); +// } + +// if (options.preRender) { +// options.preRender(req, res, app); +// } + +// if (!options.disableSSR) { +// const sheet = new ServerStyleSheet(); +// html = renderToString(sheet.collectStyles(app)); +// styledComponentCss = sheet.getStyleTags(); +// } else if (options.loadingScreen) { +// html = options.loadingScreen; +// } + +// if (typeof options.dehydrateHook === 'function') { +// const data = options.dehydrateHook(req, res); +// InjectData.pushData(res, 'dehydrated-initial-data', JSON.stringify(data)); +// } + +// // send server timezone to client +// InjectData.pushData(res, 'utcOffset', moment().utcOffset()); + +// if (options.postRender) { +// options.postRender(req, res); +// } + +// css = req.css; +// } catch (err) { +// console.log('url: ', req.url); // eslint-disable-line no-console +// console.log(err); // eslint-disable-line no-console +// console.error(new Date(), 'error while server-rendering', err.stack); // eslint-disable-line no-console +// } + +// return { html, css, styledComponentCss }; +// } + +// function sendSSRHtml(options, req, res, next, renderProps) { +// const { css, html, styledComponentCss } = generateSSRData(options, req, res, renderProps); + +// req.dynamicHead = req.dynamicHead || ''; +// req.dynamicBody = req.dynamicBody || ''; + +// // css declared in the project +// if (css) { +// req.dynamicHead += ``; +// } + +// // css collected by styled-components +// if (styledComponentCss) { +// req.dynamicHead += styledComponentCss; +// } + +// let rootElementAttributes = ''; +// const attributes = options.rootElementAttributes instanceof Array ? options.rootElementAttributes : []; +// if (attributes[0] instanceof Array) { +// for (let i = 0; i < attributes.length; i++) { +// rootElementAttributes += ` ${attributes[i][0]}="${attributes[i][1]}"`; +// } +// } else if (attributes.length > 0) { +// rootElementAttributes = ` ${attributes[0]}="${attributes[1]}"`; +// } + +// req.dynamicBody += `<${options.rootElementType || 'div'} id="${options.rootElement || 'react-app'}"${rootElementAttributes}>${html || ''}`; + +// if (typeof options.htmlHook === 'function') { +// const { dynamicHead, dynamicBody } = options.htmlHook(req, res, req.dynamicHead, req.dynamicBody); +// req.dynamicHead = dynamicHead; +// req.dynamicBody = dynamicBody; +// } + +// next(); +// } + +// export const RouterServer = { +// run(routes, options) { +// if (!options) { +// options = {}; +// } + +// withRenderContextEnvironment(function routerMiddleware(context, req, res, next) { +// if (!isAppUrl(req)) { +// next(); +// return; +// } + +// let history = createMemoryHistory(req.url); + +// if (typeof options.historyHook === 'function') { +// history = options.historyHook(req, res, history); +// } + +// match({ history, routes, location: req.url }, (err, redirectLocation, renderProps) => { +// if (err) { +// res.writeHead(500); +// res.write(err.messages); +// res.end(); +// } else if (redirectLocation) { +// res.writeHead(302, { Location: redirectLocation.pathname + redirectLocation.search }); +// res.end(); +// } else if (renderProps) { +// sendSSRHtml(options, req, res, next, renderProps); +// } else { +// res.writeHead(404); +// res.write('Not found'); +// res.end(); +// } +// }); +// }, { order: 800 }); +// }, +// }; diff --git a/packages/vulcan-routing/lib/server/routing.jsx b/packages/vulcan-routing/lib/server/routing.jsx index de9668651c..2dcf5d2c69 100644 --- a/packages/vulcan-routing/lib/server/routing.jsx +++ b/packages/vulcan-routing/lib/server/routing.jsx @@ -1,77 +1,77 @@ -import React from 'react'; -import Helmet from 'react-helmet'; -import { getDataFromTree, ApolloProvider } from 'react-apollo'; -import { CookiesProvider } from 'react-cookie'; +// import React from 'react'; +// import Helmet from 'react-helmet'; +// import { getDataFromTree, ApolloProvider } from 'react-apollo'; +// import { CookiesProvider } from 'react-cookie'; -import { Meteor } from 'meteor/meteor'; +// import { Meteor } from 'meteor/meteor'; -import { - Components, - addRoute, - Routes, populateComponentsApp, populateRoutesApp, initializeFragments, - getRenderContext, - runCallbacks, -} from 'meteor/vulcan:lib'; +// import { +// Components, +// addRoute, +// Routes, populateComponentsApp, populateRoutesApp, initializeFragments, +// getRenderContext, +// runCallbacks, +// } from 'meteor/vulcan:lib'; -import { RouterServer } from './router.jsx'; +// import { RouterServer } from './router.jsx'; -Meteor.startup(() => { - // note: route defined here because it "shouldn't be removable" - addRoute({name:'app.notfound', path:'*', componentName: 'Error404'}); +// Meteor.startup(() => { +// // note: route defined here because it "shouldn't be removable" +// addRoute({name:'app.notfound', path:'*', componentName: 'Error404'}); - // init the application components and routes, including components & routes from 3rd-party packages - initializeFragments(); - populateComponentsApp(); - populateRoutesApp(); +// // init the application components and routes, including components & routes from 3rd-party packages +// initializeFragments(); +// populateComponentsApp(); +// populateRoutesApp(); - const indexRoute = _.filter(Routes, route => route.path === '/')[0]; - const childRoutes = _.reject(Routes, route => route.path === '/'); +// const indexRoute = _.filter(Routes, route => route.path === '/')[0]; +// const childRoutes = _.reject(Routes, route => route.path === '/'); - const indexRouteWithoutPath = _.clone(indexRoute); +// const indexRouteWithoutPath = _.clone(indexRoute); - if (indexRouteWithoutPath) { - delete indexRouteWithoutPath.path; // delete path to avoid warning - } +// if (indexRouteWithoutPath) { +// delete indexRouteWithoutPath.path; // delete path to avoid warning +// } - const AppRoutes = { - path: '/', - component: Components.App, - indexRoute: indexRouteWithoutPath, - childRoutes, - }; +// const AppRoutes = { +// path: '/', +// component: Components.App, +// indexRoute: indexRouteWithoutPath, +// childRoutes, +// }; - const options = { - historyHook(req, res, newHistory) { - let { history } = getRenderContext(); - history = runCallbacks('router.server.history', history, { req, res, newHistory }); - return history; - }, - wrapperHook(req, res, appGenerator) { - const { apolloClient, store } = getRenderContext(); - store.reload(); - store.dispatch({ type: '@@nova/INIT' }) // the first dispatch will generate a newDispatch function from middleware - const app = runCallbacks('router.server.wrapper', appGenerator(), { req, res, store, apolloClient }); - return {app}; - }, - preRender(req, res, app) { - runCallbacks('router.server.preRender', { req, res, app }); - return Promise.await(getDataFromTree(app)); - }, - dehydrateHook(req, res) { - const context = runCallbacks('router.server.dehydrate', getRenderContext(), { req, res }); - return context.apolloClient.store.getState(); - }, - postRender(req, res) { - runCallbacks('router.server.postRender', { req, res }); - }, - htmlHook(req, res, dynamicHead, dynamicBody) { - const head = runCallbacks('router.server.html', Helmet.rewind(), { req, res, dynamicHead, dynamicBody }); - return { - dynamicHead: `${head.title}${head.meta}${head.link}${head.script}${dynamicHead}`, - dynamicBody, - }; - }, - }; +// const options = { +// historyHook(req, res, newHistory) { +// let { history } = getRenderContext(); +// history = runCallbacks('router.server.history', history, { req, res, newHistory }); +// return history; +// }, +// wrapperHook(req, res, appGenerator) { +// const { apolloClient, store } = getRenderContext(); +// store.reload(); +// store.dispatch({ type: '@@nova/INIT' }) // the first dispatch will generate a newDispatch function from middleware +// const app = runCallbacks('router.server.wrapper', appGenerator(), { req, res, store, apolloClient }); +// return {app}; +// }, +// preRender(req, res, app) { +// runCallbacks('router.server.preRender', { req, res, app }); +// return Promise.await(getDataFromTree(app)); +// }, +// dehydrateHook(req, res) { +// const context = runCallbacks('router.server.dehydrate', getRenderContext(), { req, res }); +// return context.apolloClient.store.getState(); +// }, +// postRender(req, res) { +// runCallbacks('router.server.postRender', { req, res }); +// }, +// htmlHook(req, res, dynamicHead, dynamicBody) { +// const head = runCallbacks('router.server.html', Helmet.rewind(), { req, res, dynamicHead, dynamicBody }); +// return { +// dynamicHead: `${head.title}${head.meta}${head.link}${head.script}${dynamicHead}`, +// dynamicBody, +// }; +// }, +// }; - RouterServer.run(AppRoutes, options); -}); +// RouterServer.run(AppRoutes, options); +// });