2015-07-04 00:40:12 +00:00
|
|
|
import React from 'react';
|
2015-09-14 01:12:22 +00:00
|
|
|
import { RoutingContext } from 'react-router';
|
2015-07-25 00:52:07 +00:00
|
|
|
import Fetchr from 'fetchr';
|
2015-09-14 01:12:22 +00:00
|
|
|
import { createLocation } from 'history';
|
2015-06-29 19:01:56 +00:00
|
|
|
import debugFactory from 'debug';
|
2015-12-23 03:28:07 +00:00
|
|
|
import { dehydrate } from 'thundercats';
|
|
|
|
import { renderToString$ } from 'thundercats-react';
|
|
|
|
|
2015-07-03 06:44:34 +00:00
|
|
|
import { app$ } from '../../common/app';
|
2015-06-29 16:50:25 +00:00
|
|
|
|
2015-07-25 00:52:07 +00:00
|
|
|
const debug = debugFactory('freecc:react-server');
|
2015-07-01 22:14:10 +00:00
|
|
|
|
|
|
|
// add routes here as they slowly get reactified
|
|
|
|
// remove their individual controllers
|
2015-06-29 19:01:56 +00:00
|
|
|
const routes = [
|
2015-08-31 16:53:25 +00:00
|
|
|
'/jobs',
|
2015-12-23 03:28:07 +00:00
|
|
|
'/jobs/*',
|
2015-10-20 06:16:56 +00:00
|
|
|
'/hikes',
|
|
|
|
'/hikes/*'
|
|
|
|
];
|
|
|
|
|
2015-12-23 03:28:07 +00:00
|
|
|
const devRoutes = [];
|
|
|
|
|
2015-06-29 19:01:56 +00:00
|
|
|
export default function reactSubRouter(app) {
|
2015-07-03 06:44:34 +00:00
|
|
|
var router = app.loopback.Router();
|
2015-06-29 16:50:25 +00:00
|
|
|
|
2015-10-30 00:55:42 +00:00
|
|
|
// These routes are in production
|
|
|
|
routes.forEach((route) => {
|
|
|
|
router.get(route, serveReactApp);
|
|
|
|
});
|
2015-10-20 06:16:56 +00:00
|
|
|
|
2015-08-13 18:09:34 +00:00
|
|
|
if (process.env.NODE_ENV === 'development') {
|
2015-10-20 06:16:56 +00:00
|
|
|
devRoutes.forEach(function(route) {
|
2015-08-13 18:09:34 +00:00
|
|
|
router.get(route, serveReactApp);
|
|
|
|
});
|
|
|
|
}
|
2015-06-29 16:50:25 +00:00
|
|
|
|
|
|
|
app.use(router);
|
|
|
|
|
|
|
|
function serveReactApp(req, res, next) {
|
2015-07-25 00:52:07 +00:00
|
|
|
const services = new Fetchr({ req });
|
2015-09-14 01:12:22 +00:00
|
|
|
const location = createLocation(req.path);
|
2015-06-29 16:50:25 +00:00
|
|
|
|
|
|
|
// returns a router wrapped app
|
2015-09-14 01:12:22 +00:00
|
|
|
app$({ location })
|
2015-06-29 16:50:25 +00:00
|
|
|
// if react-router does not find a route send down the chain
|
2015-10-20 06:16:56 +00:00
|
|
|
.filter(function({ props }) {
|
2015-09-14 01:12:22 +00:00
|
|
|
if (!props) {
|
2015-07-16 04:00:51 +00:00
|
|
|
debug('react tried to find %s but got 404', location.pathname);
|
2015-07-04 04:46:22 +00:00
|
|
|
return next();
|
2015-06-29 16:50:25 +00:00
|
|
|
}
|
2015-09-14 01:12:22 +00:00
|
|
|
return !!props;
|
2015-06-29 16:50:25 +00:00
|
|
|
})
|
2015-09-14 01:12:22 +00:00
|
|
|
.flatMap(function({ props, AppCat }) {
|
2015-12-23 03:28:07 +00:00
|
|
|
const cat = AppCat(null, services);
|
|
|
|
debug('render react markup and pre-fetch data');
|
2016-01-04 03:40:49 +00:00
|
|
|
const store = cat.getStore('appStore');
|
|
|
|
|
|
|
|
// primes store to observe action changes
|
|
|
|
// cleaned up by cat.dispose further down
|
|
|
|
store.subscribe(() => {});
|
|
|
|
|
2015-12-23 03:28:07 +00:00
|
|
|
return renderToString$(
|
|
|
|
cat,
|
2015-09-14 01:12:22 +00:00
|
|
|
React.createElement(RoutingContext, props)
|
2015-12-23 03:28:07 +00:00
|
|
|
)
|
|
|
|
.flatMap(
|
|
|
|
dehydrate(cat),
|
|
|
|
({ markup }, data) => ({ markup, data, cat })
|
|
|
|
);
|
2015-06-29 16:50:25 +00:00
|
|
|
})
|
2015-12-23 03:28:07 +00:00
|
|
|
.flatMap(function({ data, markup, cat }) {
|
|
|
|
debug('react markup rendered, data fetched');
|
|
|
|
cat.dispose();
|
2015-07-29 17:16:48 +00:00
|
|
|
const { title } = data.AppStore;
|
2015-07-04 00:40:12 +00:00
|
|
|
res.expose(data, 'data');
|
2015-07-29 17:16:48 +00:00
|
|
|
return res.render$(
|
|
|
|
'layout-react',
|
|
|
|
{ markup, title }
|
|
|
|
);
|
2015-06-29 16:50:25 +00:00
|
|
|
})
|
|
|
|
.subscribe(
|
|
|
|
function(markup) {
|
2015-12-23 03:28:07 +00:00
|
|
|
debug('html rendered and ready to send');
|
2015-06-29 16:50:25 +00:00
|
|
|
res.send(markup);
|
|
|
|
},
|
|
|
|
next
|
|
|
|
);
|
|
|
|
}
|
2015-06-29 19:01:56 +00:00
|
|
|
}
|