UNPKG

@foxpage/foxpage-node-sdk

Version:

foxpage node sdk

245 lines (244 loc) 8.31 kB
"use strict"; 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'; }