UNPKG

@sanpjs/runtime

Version:

San Pro Runtime

167 lines 5.49 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); /** * @file * @author gkiwi */ const san_ssr_1 = require("san-ssr"); const Page_1 = __importDefault(require("./Page")); const path = __importStar(require("path")); const fs = __importStar(require("fs")); const project = new san_ssr_1.SanProject(); const renderCache = {}; class Controller { context; page; layout; headers; status; body; Component; logger; html; constructor(context) { // this.page = import.meta.url; this.headers = {}; this.layout = {}; this.page = new Page_1.default(); this.status = 200; this.context = context; this.logger = context.sanp.logger; let componentPath = context.request.path || '/'; if (componentPath === '/') { componentPath = '/index'; } const componentAbsPath = path.join(context.sanp.config.root, 'pages', componentPath); try { // eslint-disable-next-line @typescript-eslint/no-require-imports,@typescript-eslint/no-var-requires const { default: Component } = require(componentAbsPath); this.Component = Component; } catch (e) { this.logger.error('require page component fail, try resolve path: ' + componentAbsPath); throw e; } } setPage(page) { this.page = page; } setLayout(layout) { this.layout = layout; } setStatus(status) { this.status = status; } setBody(body) { this.body = body; } runAction(context) { this.context = context; const method = context.request.method; const action = this[`${method.toLowerCase()}Action`]; if (action) { action(this); } else if (this.allAction) { this.allAction(); } else { throw new Error(`Not supported method: ${context.method}`); } } allAction() { throw new Error('Should Implement this method [allAction]'); } postAction() { throw new Error('Should Implement this method [postAction]'); } putAction() { throw new Error('Should Implement this method [putAction]'); } deleteAction() { throw new Error('Should Implement this method [deleteAction]'); } getAction() { throw new Error('Should Implement this method [deleteAction]'); } async render() { const renderFn = this._getSSRRender(); const data = await this._getData(); const content = await renderFn(data); return await this._replacePlacehoder(content, data); } async _replacePlacehoder(content, data) { let finalHtml = await this._getHtml(); const ssrData = `<script id="__DATA__" type="application/json">${JSON.stringify(data)}</script>`; finalHtml = finalHtml.replace('<!----hydration-html---->', () => content); finalHtml = finalHtml.replace('<!----hydration-data---->', () => ssrData); return finalHtml; } async _getHtml() { if (!this.html) { const htmlAbsPath = path.join(this.context.sanp.config.root, 'output', 'index.html'); try { this.html = fs.readFileSync(htmlAbsPath, 'utf8'); } catch (e) { this.logger.error('get Html Template Fail, try resolve path:', htmlAbsPath); throw e; } } return this.html; } async _getData() { if (this.Component.fetchData) { const fetchData = this.Component.fetchData; return await fetchData(this.context); } return {}; } _getSSRRender() { const rPath = this.context.request.path; let render = renderCache[rPath]; if (!render) { // @ts-ignore render = project.compileToRenderer(this.Component); renderCache[rPath] = render; } return render; } redirect(url, options) { let qs = ''; if (options && options.query) { qs = encodeURI(Object.entries(options.query).map(([k, v]) => `${k}=${v}`).join('&')); } if (url.indexOf('?')) { url += `&${qs}`; } else { url += `?${qs}`; } this.context.redirect(url); } } exports.default = Controller; //# sourceMappingURL=Controller.js.map