import { _, inject, Kernel, state } from "oly-core";
import { IKoaContext } from "oly-http";
import { AppContext, View } from "oly-react";
import * as React from "react";
import { createElement } from "react";
import { renderToString } from "react-dom/server";
export class ReactServerRenderer {
/**
* List of POST transformation of template.
* You can see an example on {@see PixieServerProvider}.
*
* @type {Array}
*/
@state()
public templateTransforms: Array<(template: string, context: Kernel) => string> = [];
@inject(Kernel)
protected kernel: Kernel;
/**
* This is useless if you use ReactStatic or ReactProxy.
*
* @param prefix
* @param mountId
*/
public generateIndex(prefix: string, mountId: string) {
return `
${this.kernel.env("APP_NAME")}
`;
}
/**
* Make the react rendering.
*
* @param ctx IKoaContext
* @param template index.html
* @param mountId
*/
public render(ctx: IKoaContext, template: string, mountId: string): string {
const markup = renderToString(this.rootElement);
template = template.replace(
``,
`${markup}
`);
// apply transformations
this.templateTransforms.forEach((func) => template = func(template, ctx.kernel));
return template;
}
/**
* In very few cases, SSR can failed.
*
* @param ctx Koa Context with Kernel
* @param mountId
* @param template App template with styles + scripts
* @param error The holy error
* @returns {string}
*/
public renderError(ctx: IKoaContext, template: string, mountId: string, error: Error): string {
return template.replace(/[\s\S]*<\/body>/igm, `
Looks like something went wrong!
${!_.isProduction()
? `
${error.stack || error.message || error}`
: ""}
`);
}
/**
*
*/
public get rootElement(): JSX.Element {
return createElement(AppContext, {kernel: this.kernel}, createElement(View, {index: 0}));
}
}