@foxpage/foxpage-node-sdk
Version:
foxpage node sdk
245 lines (244 loc) • 8.31 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.preprocess = void 0;
const lodash_1 = __importDefault(require("lodash"));
const foxpage_shared_1 = require("@foxpage/foxpage-shared");
const logger_1 = require("../logger");
/**
* pre render
* for data formate, preprocess
*/
async function preprocess(dsl = [], ctx, opt) {
const { componentMap = new Map(), appConfigs = {}, logger = (0, logger_1.loggerCreate)('render'), locale = '', origin, structureMap = new Map(), hooks, } = ctx;
withNoSSRNode(componentMap, ctx);
initCSRRootId(structureMap, componentMap, ctx);
const { beforePreprocess, afterPreprocess } = hooks || {};
if (typeof beforePreprocess === 'function') {
await beforePreprocess(ctx);
}
const _opt = Object.assign(Object.assign({}, opt), { componentMap,
structureMap,
appConfigs,
logger,
locale, csrRootId: ctx.csrRootId, originPage: origin.page || {} });
// data preprocess of structure
await Promise.all(dsl.map(item => dataProcess(item, ctx, _opt)));
if (typeof afterPreprocess === 'function') {
await afterPreprocess(ctx);
}
}
exports.preprocess = preprocess;
/**
* data process
* @param node
* @param ctx
* @param opt
*/
async function dataProcess(node, ctx, opt) {
const { structureMap, errorThrow, logger } = opt;
const { id, name, type, version, props = {} } = node;
try {
const component = opt.componentMap.get(id);
if (!component) {
const msg = `node ${name}@${id} component is empty`;
logger.warn(msg);
if (errorThrow) {
throw new Error(msg);
}
return null;
}
const structure = structureMap.get(id);
if (structure) {
// injector
const injector = {
id,
type,
name,
version,
};
// inject props
const injectProps = initInjectProps(node, ctx, opt);
node.props = Object.assign(Object.assign({}, injectProps), props);
// hook props
const hookProps = await getHookProps(node, component, ctx, opt);
// important: merge props
// for update final props to component
// for csr render get the right data
structure.props = Object.assign(Object.assign(Object.assign({ $injector: injector }, injectProps), props), lodash_1.default.cloneDeep(hookProps || {}));
}
}
catch (e) {
logger.error(`Data preprocess ${node.name}@${node.id} failed.`, e);
throw e;
}
}
/**
* get hook props
* @param node node data
* @param component component data
* @param ctx render context
* @param opt options
* @returns hook props
*/
async function getHookProps(node, component, ctx, opt) {
const { children = [] } = node;
const { factory } = component;
let hookProps = {};
const hookEnable = getHookEnable(node, component, opt);
if (hookEnable) {
const hooksResults = await Promise.all([
doHook(ctx, node, opt, factory),
...children.map(item => dataProcess(item, ctx, opt)),
]);
hookProps = hooksResults[0];
}
else {
await Promise.all(children.map(item => dataProcess(item, ctx, opt)));
}
return hookProps;
}
/**
* get hook enable
* @param node node data
* @param component component data
* @param opt options
* @returns hook enable
*/
function getHookEnable(node, component, opt) {
const structure = opt.structureMap.get(node.id);
if (!structure) {
return true;
}
const { isCSREntry, supportSSR = true, supportSSRHook = true } = component.meta || {};
if (isCSREntry) {
// start with csr entry
const { enable = true, hookEnable = true } = opt.appConfigs.ssr || {};
const { ssrEnable: nodeSSREnable = true, ssrHookEnable: nodeSSRHookEnable = true } = node.props || {};
const _ssrEnable = isTrue(enable) ? nodeSSREnable : enable;
const _ssrHookEnable = isTrue(hookEnable) ? nodeSSRHookEnable : hookEnable;
// cache ssr state
structure.ssrEnable = _ssrEnable;
structure.ssrHookEnable = _ssrHookEnable;
return true;
}
const { parentId } = node.extension || {};
if (parentId) {
let parent = opt.structureMap.get(parentId);
if (!parent) {
// use csr node as parent
parent = opt.structureMap.get(opt.csrRootId || '');
}
if (parent) {
const { ssrEnable = true, ssrHookEnable = true } = parent || {};
const _ssrEnable = isTrue(ssrEnable) ? supportSSR : ssrEnable;
const _ssrHookEnable = isTrue(ssrHookEnable) ? supportSSRHook : ssrHookEnable;
// cache ssr state
structure.ssrEnable = _ssrEnable;
structure.ssrHookEnable = _ssrHookEnable;
return !!_ssrHookEnable;
}
else {
//
}
}
// cache ssr state
structure.ssrEnable = supportSSR;
structure.ssrHookEnable = supportSSRHook;
return !!supportSSRHook;
}
// do getInitialProps hook
async function doHook(ctx, node, opt, factory) {
var _a;
const { appConfigs, logger } = opt;
const { nodeBuildHookTimeout = 0 } = appConfigs.ssr || {};
let buildHookProps;
if (factory && typeof factory.beforeNodeBuild === 'function') {
const hookCost = (_a = ctx.performanceLogger) === null || _a === void 0 ? void 0 : _a.call(ctx, 'nodePerformance', node);
try {
if (nodeBuildHookTimeout > 0) {
buildHookProps = await (0, foxpage_shared_1.timeout)(factory.beforeNodeBuild(ctx, node), nodeBuildHookTimeout);
}
else {
buildHookProps = await factory.beforeNodeBuild(ctx, node);
}
logger.info(`Hook [ buildHookProps ][ ${node.name}@${node.id} ] success.`);
}
catch (e) {
const msg = `Hook [ buildHookProps ][ ${node.name}@${node.id} ] run failed,`;
logger.warn(msg, e);
if (opt.errorThrow) {
throw new Error(msg);
}
}
finally {
hookCost();
}
}
return buildHookProps;
}
// init inject props
function initInjectProps(node, ctx, opt) {
const comp = node && opt.componentMap.get(node.id);
return {
$locale: ctx.locale,
$runtime: {
isServer: true,
isBrowser: false,
clientType: 'server',
},
$eid: node.id,
$ename: node.name,
$elabel: node.label,
$etype: node.type,
$dsl: {
appId: ctx.appId,
id: ctx.page.id,
name: opt.originPage.name,
fileId: opt.originPage.fileId,
version: opt.originPage.versionNumber,
structure: {
id: node.id,
name: node.name,
label: node.label,
type: node.type,
version: comp === null || comp === void 0 ? void 0 : comp.version,
},
},
};
}
/**
* check noSSR node
* @param ctx context
* @param opt options
*/
function withNoSSRNode(componentMap = new Map(), ctx) {
const existNoSSRNode = Array.from(componentMap.values()).findIndex(item => !item.meta.isCSREntry && item.meta.supportSSR === false);
if (existNoSSRNode > -1) {
// no noSSR node
ctx.setRenderMethod(true);
}
}
/**
* init csr root id
* @param structureMap structure map
* @param componentMap component map
* @param ctx context
*/
function initCSRRootId(structureMap = new Map(), componentMap = new Map(), ctx) {
const csrNode = Array.from(structureMap.values()).find(item => {
const comp = componentMap.get(item.id);
return !!(comp && comp.meta.isCSREntry);
});
if (csrNode) {
ctx.csrRootId = csrNode.id;
}
}
function isTrue(value) {
return value === true || isUndefined(value);
}
function isUndefined(value) {
return typeof value === 'undefined';
}