Skip to content

Commit fea95d1

Browse files
authored
Merge pull request #66 from expressots/343-support-for-render-engines
343 support for render engines
2 parents b7965d2 + a699bd4 commit fea95d1

12 files changed

+422
-38
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@
7575
"@codecov/vite-plugin": "^0.0.1-beta.6",
7676
"@commitlint/cli": "19.2.1",
7777
"@commitlint/config-conventional": "19.2.2",
78-
"@expressots/core": "latest",
78+
"@expressots/core": "2.15.0",
7979
"@release-it/conventional-changelog": "8.0.1",
8080
"@types/express": "4.17.21",
8181
"@types/node": "20.14.10",

src/adapter-express/application-express.interface.ts

+1-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
import { IApplicationMessageToConsole } from "@expressots/core";
12
import express from "express";
2-
import { IApplicationMessageToConsole, RenderTemplateOptions } from "@expressots/core";
33
import { ServerEnvironment } from "./application-express.types";
44

55
/**
@@ -18,19 +18,6 @@ export interface IWebServerPublic {
1818
consoleMessage?: IApplicationMessageToConsole,
1919
): Promise<void>;
2020

21-
/**
22-
* Configures the application's view engine based on the provided configuration options.
23-
*
24-
* @public
25-
* @method setEngine
26-
* @template T - A generic type extending from RenderTemplateOptions.
27-
*
28-
* @param {T} options - An object of type T (must be an object that extends RenderTemplateOptions)
29-
* that provides the configuration options for setting the view engine.
30-
* This includes the extension name, view path, and the engine function itself.
31-
*/
32-
setEngine<T extends RenderTemplateOptions>(options: T): void;
33-
3421
/**
3522
* Get the underlying HTTP server. (default: Express.js)
3623
* @returns The underlying HTTP server after initialization.

src/adapter-express/application-express.ts

+39-18
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
1-
import {
2-
Console,
3-
IApplicationMessageToConsole,
4-
IHandlebars,
5-
Logger,
6-
Middleware,
7-
RenderTemplateOptions,
8-
} from "@expressots/core";
1+
import { Console, IApplicationMessageToConsole, Logger, Middleware } from "@expressots/core";
92
import express from "express";
103
import { Container } from "inversify";
114
import { provide } from "inversify-binding-decorators";
@@ -18,8 +11,12 @@ import {
1811
MiddlewareConfig,
1912
ServerEnvironment,
2013
} from "./application-express.types";
21-
import { InversifyExpressServer } from "./express-utils/inversify-express-server";
2214
import { HttpStatusCodeMiddleware } from "./express-utils/http-status-middleware";
15+
import { InversifyExpressServer } from "./express-utils/inversify-express-server";
16+
import { EjsOptions, setEngineEjs } from "./render/ejs/ejs.config";
17+
import { Engine, EngineOptions, RenderOptions } from "./render/engine";
18+
import { HandlebarsOptions, setEngineHandlebars } from "./render/handlebars/hbs.config";
19+
import { packageResolver } from "./render/resolve-render";
2320

2421
/**
2522
* The AppExpress class provides methods for configuring and running an Express application.
@@ -42,6 +39,7 @@ class AppExpress extends ApplicationBase implements IWebServer {
4239
private globalPrefix: string = "/";
4340
private middlewares: Array<ExpressHandler | MiddlewareConfig | ExpressoMiddleware> = [];
4441
private console: Console;
42+
private renderOptions: RenderOptions = {} as RenderOptions;
4543

4644
protected configureServices(): void | Promise<void> {}
4745
protected postServerInitialization(): void | Promise<void> {}
@@ -146,6 +144,7 @@ class AppExpress extends ApplicationBase implements IWebServer {
146144
consoleMessage?: IApplicationMessageToConsole,
147145
): Promise<void> {
148146
await this.init();
147+
await this.configEngine();
149148

150149
this.port = port || 3000;
151150
this.environment = environment;
@@ -177,23 +176,45 @@ class AppExpress extends ApplicationBase implements IWebServer {
177176
this.globalPrefix = prefix;
178177
}
179178

179+
/**
180+
* Configures the application's view engine based on the provided configuration options.
181+
*/
182+
private async configEngine(): Promise<void> {
183+
if (this.renderOptions.engine) {
184+
switch (this.renderOptions.engine) {
185+
case Engine.HBS:
186+
await setEngineHandlebars(this.app, this.renderOptions.options as HandlebarsOptions);
187+
break;
188+
case Engine.EJS:
189+
await setEngineEjs(this.app, this.renderOptions.options as EjsOptions);
190+
break;
191+
default:
192+
throw new Error("Unsupported engine type!");
193+
}
194+
}
195+
}
196+
180197
/**
181198
* Configures the application's view engine based on the provided configuration options.
182199
*
183200
* @public
184201
* @method setEngine
185202
* @template T - A generic type extending from RenderTemplateOptions.
186203
*
187-
* @param {T} options - An object of type T (must be an object that extends RenderTemplateOptions)
188-
* that provides the configuration options for setting the view engine.
189-
* This includes the extension name, view path, and the engine function itself.
204+
* @param {Engine} engine - The view engine to set
205+
* @param {EngineOptions} [options] - The configuration options for the view engine
190206
*/
191-
public setEngine<T extends RenderTemplateOptions>(options: T): void {
192-
if ("extName" in options) {
193-
const { extName, viewPath, engine } = options as IHandlebars;
194-
this.app.engine(extName, engine);
195-
this.app.set("view engine", extName);
196-
this.app.set("views", viewPath);
207+
public async setEngine<T extends EngineOptions>(engine: Engine, options?: T): Promise<void> {
208+
packageResolver(engine, options);
209+
210+
try {
211+
if (options) {
212+
this.renderOptions = { engine, options };
213+
} else {
214+
this.renderOptions = { engine };
215+
}
216+
} catch (error: unknown) {
217+
this.logger.error((error as Error).message, "adapter-express");
197218
}
198219
}
199220

src/adapter-express/application-express.types.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import express, { Request, Response, NextFunction } from "express";
2-
import { IApplicationMessageToConsole, RenderTemplateOptions } from "@expressots/core";
2+
import { IApplicationMessageToConsole } from "@expressots/core";
33
import { Container } from "inversify";
4+
import { Engine, EngineOptions } from "./render/engine";
45

56
/**
67
* Interface for the WebServer application implementation.
@@ -12,7 +13,7 @@ export interface IWebServer {
1213
environment: ServerEnvironment,
1314
consoleMessage?: IApplicationMessageToConsole,
1415
): Promise<void>;
15-
setEngine<T extends RenderTemplateOptions>(options: T): void;
16+
setEngine<T extends EngineOptions>(engine: Engine, options?: T): Promise<void>;
1617
}
1718

1819
/**

src/adapter-express/express-utils/inversify-express-server.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -267,10 +267,9 @@ export class InversifyExpressServer {
267267
} else if (value instanceof Function) {
268268
value();
269269
} else if (!res.headersSent) {
270-
if (value === undefined) {
271-
res.status(204);
270+
if (value !== undefined) {
271+
res.send(value);
272272
}
273-
res.send(value);
274273
}
275274
} catch (err) {
276275
next(err);

src/adapter-express/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export * from "./express-utils";
22
export { AppExpress } from "./application-express";
33
export { IWebServerPublic } from "./application-express.interface";
44
export { IWebServer, IWebServerConstructor, ServerEnvironment } from "./application-express.types";
5+
export * from "./render";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { Application } from "express";
2+
import { join } from "path";
3+
import { Options } from "./ejs.types";
4+
5+
/**
6+
* Ejs options
7+
* @typedef {Object} EjsOptions
8+
* @property {string | Array<string>} viewsDir - The path to the views folder
9+
* @property {string} viewEngine - The view engine
10+
* @property {ejs.Options} [serverOptions] - The server options
11+
*
12+
*/
13+
export type EjsOptions = {
14+
viewsDir?: string | Array<string>;
15+
viewEngine?: string;
16+
serverOptions?: Options;
17+
};
18+
19+
/**
20+
* Ejs defaults
21+
* @type {EjsOptions}
22+
* @constant
23+
* @default
24+
*/
25+
const EJS_DEFAULTS: EjsOptions = {
26+
viewsDir: join(process.cwd(), "views"),
27+
viewEngine: "ejs",
28+
serverOptions: {},
29+
};
30+
31+
/**
32+
* Set Ejs as the view engine
33+
* @param {Application} app - The express application
34+
* @param {EjsOptions} [options=EJS_DEFAULTS] - The ejs options
35+
*/
36+
export async function setEngineEjs(
37+
app: Application,
38+
options: EjsOptions = EJS_DEFAULTS,
39+
): Promise<void> {
40+
app.set("view engine", options.viewEngine || EJS_DEFAULTS.viewEngine);
41+
app.set("views", options.viewsDir || EJS_DEFAULTS.viewsDir);
42+
43+
if (Array.isArray(options.viewsDir)) {
44+
options.viewsDir.forEach((dir) => {
45+
app.set("views", dir);
46+
});
47+
}
48+
49+
if (options.serverOptions) {
50+
app.locals = {
51+
...app.locals,
52+
...options.serverOptions,
53+
};
54+
}
55+
}

0 commit comments

Comments
 (0)