react-middleware
Version:
Connect middleware for serving React components from a standard folder structure.
141 lines (111 loc) • 4.22 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _ramda = require("ramda");
var _ramda2 = _interopRequireDefault(_ramda);
var _react = require("react");
var _react2 = _interopRequireDefault(_react);
var _server = require("react-dom/server");
var _server2 = _interopRequireDefault(_server);
var _fsExtra = require("fs-extra");
var _fsExtra2 = _interopRequireDefault(_fsExtra);
var _path = require("path");
var _path2 = _interopRequireDefault(_path);
var _url = require("url");
var _url2 = _interopRequireDefault(_url);
var _jsUtil = require("js-util");
var util = _interopRequireWildcard(_jsUtil);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var NODE_ENV = process.env.NODE_ENV || "development";
var asValues = function asValues(obj, args) {
var result = _ramda2.default.clone(obj);
Object.keys(obj).forEach(function (key) {
var value = obj[key];
if (_ramda2.default.is(Function, value)) {
result[key] = value(args); // Convert the function into a value.
} else if (_ramda2.default.is(Object, value)) {
result[key] = asValues(value, args); // <== RECURSION.
}
});
return result;
};
var getFilePath = function getFilePath(basePath, name, extension) {
var path = undefined;
name = name.charAt(0).toUpperCase() + name.slice(1); // Capitalize the file/folder name.
// Look first for the existence of a stand-alone file.
path = _path2.default.join(basePath, name + "." + extension);
if (_fsExtra2.default.existsSync(path)) {
return path;
}
// Look for the file within a folder.
path = _path2.default.join(basePath, name, name + "." + extension);
if (_fsExtra2.default.existsSync(path)) {
return path;
}
};
exports.default = function (middleware, paths, routes, data) {
var getLayout = function getLayout(route) {
var layoutName = route.layout || "Html";
var path = getFilePath(paths.layouts, layoutName, "jsx");
if (!path) {
throw new Error("A layout named '" + layoutName + "' does not exist.");
}
return require(path).default;
};
var getPage = function getPage(route) {
var pageName = route.page;
var path = getFilePath(paths.pages, pageName, "jsx");
if (!path) {
throw new Error("A page named '" + pageName + "' does not exist.");
}
return require(path).default;
};
var getData = function getData(route, url) {
return _ramda2.default.is(Function, data) ? data({ route: route, url: url }) : data;
};
var render = function render(req, res, route) {
// Setup initial conditions.
var params = Object.keys(req.params).map(function (key) {
req.params[key] = util.toType(req.params[key]);
});
var url = {
path: req.url,
pathname: _url2.default.parse(req.url).pathname,
query: req.query,
pattern: route.pattern,
params: params
};
var args = { url: url };
route = asValues(route, args);
// Prepare the page body.
var layoutData = getData(route, url);
var pageProps = route.props || {};
var pageData = pageProps.data || layoutData;
if (pageData) {
pageProps.data = pageData;
}
var pageBody = _react2.default.createElement(getPage(route), pageProps);
// Prepare the root <Html> page props.
var layoutProps = {
title: route.title,
body: pageBody,
data: layoutData,
env: NODE_ENV,
page: { name: route.page }
};
// Convert the page-layout into HTML.
var layout = _react2.default.createElement(getLayout(route), layoutProps);
var html = _server2.default.renderToStaticMarkup(layout);
res.send(html);
};
// Regsiter each route as a GET handler.
Object.keys(routes).forEach(function (pattern) {
var route = routes[pattern];
route.pattern = pattern;
middleware.get(pattern, function (req, res) {
render(req, res, route);
});
});
};