neweb
Version:
[![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Dependency Status][daviddm-image]][daviddm-url] [![Coverage percentage][coveralls-image]][coveralls-url] [ • 3.87 kB
text/typescript
import { exists, readFile } from "fs";
import { IPackInfo } from "neweb-pack";
import { join, resolve } from "path";
import { promisify } from "util";
import withError from "with-error";
import { INITIAL_VAR } from "../common";
import { IApplication, IPageMetaInfo, IRouterClass } from "../typings";
import ClassicRouter from "./ClassicRouter";
import FrameController from "./FrameController";
export interface IApplicationConfig {
environment: "production" | "development";
appPath: string;
modulePacker: {
addLocalPackage(path: string): Promise<IPackInfo>;
};
}
class Application implements IApplication {
protected template = `<!doctype><html>
<head><title>{%title%}</title>{%meta%}
<meta charset="utf8" /></head><body>
<div id="root">{%html%}</div>
<script>{%script%}</script>
<script async src="/bundle.js"></script>
</body></html>`;
protected context: any;
protected config: {};
protected environment = "development";
protected appPath: string;
constructor(protected configuration: IApplicationConfig) {
this.appPath = configuration.appPath;
this.environment = configuration.environment;
}
public async requireModule(modulePath: string) {
const { error, result: path } = withError(() => require.resolve(join(this.appPath, modulePath)));
if (error) {
return;
}
if (this.environment === "development") {
delete require.cache[path];
}
return require(path).default;
}
public async getRouterClass(): Promise<IRouterClass> {
return (await this.requireModule("Router")) || ClassicRouter;
}
public async hasFrame(frameName: string) {
return promisify(exists)(resolve(this.appPath, "frames", frameName));
}
public async getContext() {
if (typeof (this.context) !== "undefined") {
return this.context;
}
const ContextClass = await this.requireModule("Context");
this.context = ContextClass ? new ContextClass({
config: await this.getConfig(),
}) : {};
return this.context;
}
public async getConfig() {
if (typeof (this.config) !== "undefined") {
return this.config;
}
const ConfigClass = await this.requireModule("Config." + this.environment);
this.config = ConfigClass ? new ConfigClass() : {};
return this.config;
}
public async getFrameControllerClass(frameName: string) {
return (await this.requireModule("frames/" + frameName + "/controller")) || FrameController;
}
public async getFrameViewClass(frameName: string) {
return (await this.requireModule("frames/" + frameName + "/view")) || (() => null);
}
public async getFrameViewModulePackInfo(frameName: string): Promise<IPackInfo> {
return this.configuration.modulePacker.addLocalPackage(
join(this.appPath, "frames", frameName, "view.js"),
);
}
public async fillTemplate(html: string, meta: IPageMetaInfo, initialInfo: any) {
const templatePath = join(this.appPath, "template.html");
const template = await promisify(exists)(templatePath) ?
(await promisify(readFile)(templatePath)).toString()
: this.template;
return template
.replace("{%html%}", html)
.replace("{%title%}", meta.title || "")
.replace("{%meta%}", "<!--__page_meta_start__-->" + (meta.meta ? meta.meta.map((m) =>
`<meta name="${m.name}" content="${m.content}" />`).join("") : "") + "<!--__page_meta_end__-->")
.replace("{%script%}", `window["${INITIAL_VAR}"]=${JSON.stringify(initialInfo)}`);
}
}
export default Application;