@sanpjs/runtime
Version:
San Pro Runtime
167 lines • 5.49 kB
JavaScript
;
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