@travi/hapi-react-router
Version:
hapi route to delegate routing for html content to react-router
155 lines (133 loc) • 4.43 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var Boom = require('@hapi/boom');
var httpStatusCodes = require('http-status-codes');
var reactRouter = require('react-router');
var redial = require('redial');
var React = require('react');
var server = require('react-dom/server');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var Boom__default = /*#__PURE__*/_interopDefaultLegacy(Boom);
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
function determineStatusFrom(components) {
if (components && components.map(function (component) {
return component.displayName;
}).includes('NotFound')) {
return httpStatusCodes.StatusCodes.NOT_FOUND;
}
return httpStatusCodes.StatusCodes.OK;
}
function matchRoute(url, routes) {
return new Promise(function (resolve, reject) {
var history = reactRouter.createMemoryHistory();
reactRouter.match({
routes: routes,
location: history.createLocation(url)
}, function (err, redirectLocation, renderProps) {
if (err) reject(err);
resolve({
redirectLocation: redirectLocation,
renderProps: renderProps,
status: determineStatusFrom(renderProps && renderProps.components)
});
});
});
}
function fetchData (_ref) {
var renderProps = _ref.renderProps,
store = _ref.store;
var getState = store.getState;
return redial.trigger('fetch', renderProps.components, {
params: renderProps.params,
dispatch: store.dispatch,
state: getState(),
getState: getState,
store: store
});
}
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
function defaultRenderFactory (request, store, renderProps, Root) {
return function (otherProps) {
return server.renderToString( /*#__PURE__*/React__default["default"].createElement(Root, _extends({
request: request,
store: store
}, otherProps), /*#__PURE__*/React__default["default"].createElement(reactRouter.RouterContext, renderProps)));
};
}
async function renderThroughReactRouter(request, h, _ref) {
var render = _ref.render,
routes = _ref.routes,
respond = _ref.respond,
Root = _ref.Root,
store = _ref.store;
try {
var _await$matchRoute = await matchRoute(request.raw.req.url, routes),
renderProps = _await$matchRoute.renderProps,
status = _await$matchRoute.status,
redirectLocation = _await$matchRoute.redirectLocation;
if (redirectLocation) {
var state = redirectLocation.state || {};
switch (state.status) {
case httpStatusCodes.StatusCodes.MOVED_PERMANENTLY:
return h.redirect(redirectLocation.pathname).permanent();
case httpStatusCodes.StatusCodes.MOVED_TEMPORARILY:
return h.redirect(redirectLocation.pathname).temporary();
default:
return h.redirect(redirectLocation.pathname).temporary();
}
} else {
await fetchData({
renderProps: renderProps,
store: store
});
var defaultRender = defaultRenderFactory(request, store, renderProps, Root);
return respond(h, {
store: store,
status: status,
renderedContent: render ? render(defaultRender, request) : {
html: defaultRender()
}
});
}
} catch (e) {
throw Boom__default["default"].boomify(e);
}
}
/* eslint import/prefer-default-export: "off" */
var plugin = {
pkg: require('../package.json'),
register: async function register(server, options) {
server.route({
method: 'GET',
path: '/html',
handler: function handler(request, h) {
return renderThroughReactRouter(request, h, {
render: options.render,
routes: options.routes,
respond: options.respond,
Root: options.Root,
store: options.configureStore({
session: {
auth: request.auth.credentials
},
server: server
})
});
}
});
}
};
exports.plugin = plugin;