UNPKG

@travi/hapi-react-router

Version:

hapi route to delegate routing for html content to react-router

155 lines (133 loc) 4.43 kB
'use strict'; 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;