framework: add multiple renderers support

This commit is contained in:
undefined committed 2025-02-21 05:48:13 +08:00
1 parent c48c9f9cf3
commit 4d2b8dfd93
2 files changed
+29 -10

No files matched your search

+21 -7
View File
@@ -73,7 +73,6 @@ export interface HydroResponse {
attachment: (name: string, stream?: any) => void;
addHeader: (name: string, value: string) => void;
}
export type RendererFunction = (name: string, context: Record<string, any>) => string | Promise<string>;
type HydroContext = {
request: HydroRequest;
response: HydroResponse;
@@ -90,6 +89,21 @@ export type KoaContext = Koa.Context & {
holdFiles: (string | File)[];
};
export type TextRenderer = {
output: 'html' | 'json' | 'text';
render: (name: string, args: Record<string, any>, context: Record<string, any>) => string | Promise<string>;
};
export type BinaryRenderer = {
output: 'binary';
render: (name: string, args: Record<string, any>, context: Record<string, any>) => Buffer | Promise<Buffer>;
};
export type Renderer = (BinaryRenderer | TextRenderer) & {
name: string;
accept: readonly string[];
priority: number;
asFallback: boolean;
};
const logger = new Logger('server');
/** @deprecated */
export const koa = new Koa<Koa.DefaultState, KoaContext>({
@@ -170,14 +184,14 @@ export class HandlerCommon {
}
renderHTML(templateName: string, args: Record<string, any>) {
const type = templateName.split('.')[1];
const engine = this.ctx.server.renderers[type] || (() => JSON.stringify(args, serializer(false, this)));
return engine(templateName, {
const renderers = Object.values(this.ctx.server.renderers).filter((r) => r.accept.includes(templateName) || r.asFallback);
const topPrio = renderers.sort((a, b) => b.priority - a.priority)[0];
const engine = topPrio?.render || (() => JSON.stringify(args, serializer(false, this)));
return engine(templateName, args, {
handler: this,
UserContext: this.user,
url: this.url,
_: this.translate,
...args,
});
}
}
@@ -338,7 +352,7 @@ export class WebService extends Service {
private wsLayers = [];
private captureAllRoutes = Object.create(null);
renderers: Record<string, RendererFunction> = Object.create(null);
renderers: Record<string, Renderer> = Object.create(null);
server = koa;
router = router;
HandlerCommon = HandlerCommon;
@@ -730,7 +744,7 @@ ${c.response.status} ${endTime - startTime}ms ${c.response.length}`);
}
}
public registerRenderer(name: string, func: RendererFunction) {
public registerRenderer(name: string, func: Renderer) {
if (this.renderers[name]) logger.warn('Renderer %s already exists.', name);
this.ctx.effect(() => {
this.renderers[name] = func;
+8 -3
View File
@@ -199,7 +199,12 @@ const render = (name: string, state: any) => new Promise<string>((resolve, rejec
export const inject = ['server'];
export async function apply(ctx: Context) {
ctx.server.registerRenderer('html', render);
ctx.server.registerRenderer('yaml', render);
ctx.server.registerRenderer('md', render);
ctx.server.registerRenderer('ui-default', {
name: 'ui-default',
output: 'html',
accept: [],
asFallback: true,
priority: 1,
render: (name, args, context) => render(name, { ...context, ...args }),
});
}