lambder 1.0.103 → 1.0.104

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/Lambder.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { APIGatewayProxyEvent, APIGatewayProxyEventHeaders, Context } from "aws-lambda";
2
2
  import LambderResolver from "./LambderResolver.js";
3
3
  import LambderResponseBuilder, { LambderResolverResponse } from "./LambderResponseBuilder.js";
4
+ import LambderUtils from "./LambderUtils.js";
4
5
  type Path = `/${string}`;
5
6
  type LambderSession = {
6
7
  userId: string;
@@ -37,18 +38,21 @@ type RouteFallbackHandlerFunction = (ctx: LambderRenderContext, resolver: Lambde
37
38
  type ApiFallbackHandlerFunction = (ctx: LambderRenderContext, resolver: LambderResolver) => LambderResolverResponse;
38
39
  export declare const createContext: (event: APIGatewayProxyEvent, lambdaContext: Context, apiPath: string) => LambderRenderContext;
39
40
  export default class Lambder {
40
- private apiPath;
41
- private apiVersion;
42
- private isCorsEnabled;
43
- private publicPath;
41
+ apiPath: string;
42
+ apiVersion: null | string;
43
+ isCorsEnabled: boolean;
44
+ publicPath: string;
45
+ ejsPath: string;
44
46
  private actionList;
45
47
  private hookList;
46
48
  private globalErrorHandler;
47
49
  private routeFallbackHandler;
48
50
  private apiFallbackHandler;
49
- constructor({ publicPath, apiPath, apiVersion, isCorsEnabled, }: {
51
+ utils: LambderUtils;
52
+ constructor({ publicPath, apiPath, ejsPath, apiVersion, isCorsEnabled }: {
50
53
  publicPath: string;
51
54
  apiPath?: string;
55
+ ejsPath?: string;
52
56
  apiVersion?: string;
53
57
  isCorsEnabled?: boolean;
54
58
  });
package/dist/Lambder.js CHANGED
@@ -3,6 +3,7 @@ import cookieParser from "cookie";
3
3
  import { match } from "path-to-regexp";
4
4
  import LambderResolver from "./LambderResolver.js";
5
5
  import LambderResponseBuilder from "./LambderResponseBuilder.js";
6
+ import LambderUtils from "./LambderUtils.js";
6
7
  export const createContext = (event, lambdaContext, apiPath) => {
7
8
  const host = event.headers.Host || event.headers.host || "";
8
9
  const path = event.path;
@@ -35,13 +36,16 @@ export default class Lambder {
35
36
  apiVersion;
36
37
  isCorsEnabled;
37
38
  publicPath;
39
+ ejsPath;
38
40
  actionList;
39
41
  hookList;
40
42
  globalErrorHandler = null;
41
43
  routeFallbackHandler = null;
42
44
  apiFallbackHandler = null;
43
- constructor({ publicPath, apiPath, apiVersion, isCorsEnabled, }) {
45
+ utils;
46
+ constructor({ publicPath, apiPath, ejsPath, apiVersion, isCorsEnabled }) {
44
47
  this.publicPath = publicPath || "/incorrect-path-not-found";
48
+ this.ejsPath = ejsPath || "/incorrect-ejs-path-not-found";
45
49
  this.apiPath = apiPath ?? "/api";
46
50
  this.apiVersion = apiVersion ?? null;
47
51
  this.isCorsEnabled = isCorsEnabled ?? false;
@@ -51,6 +55,7 @@ export default class Lambder {
51
55
  "afterRender": [],
52
56
  "fallback": [],
53
57
  };
58
+ this.utils = new LambderUtils({ ejsPath });
54
59
  }
55
60
  setRouteFallbackHandler(routeFallbackHandler) {
56
61
  this.routeFallbackHandler = routeFallbackHandler;
@@ -192,6 +197,7 @@ export default class Lambder {
192
197
  isCorsEnabled: this.isCorsEnabled,
193
198
  publicPath: this.publicPath,
194
199
  apiVersion: this.apiVersion,
200
+ lambderUtils: this.utils,
195
201
  });
196
202
  }
197
203
  ;
@@ -200,6 +206,7 @@ export default class Lambder {
200
206
  isCorsEnabled: this.isCorsEnabled,
201
207
  publicPath: this.publicPath,
202
208
  apiVersion: this.apiVersion,
209
+ lambderUtils: this.utils,
203
210
  resolve, reject
204
211
  });
205
212
  }
@@ -1,4 +1,5 @@
1
1
  import LambderResponseBuilder, { LambderResolverResponse } from "./LambderResponseBuilder.js";
2
+ import LambderUtils from "./LambderUtils.js";
2
3
  type MethodType<T, M extends keyof T> = T[M] extends (...args: any[]) => any ? T[M] : never;
3
4
  interface DieResolverMethods {
4
5
  raw: MethodType<LambderResponseBuilder, 'raw'>;
@@ -18,10 +19,11 @@ export default class LambderResolver extends LambderResponseBuilder {
18
19
  resolve: (response: LambderResolverResponse) => void;
19
20
  reject: (err: Error) => void;
20
21
  die: DieResolverMethods;
21
- constructor({ isCorsEnabled, publicPath, apiVersion, resolve, reject }: {
22
+ constructor({ isCorsEnabled, publicPath, apiVersion, lambderUtils, resolve, reject }: {
22
23
  isCorsEnabled: boolean;
23
24
  publicPath: string;
24
25
  apiVersion?: string | null;
26
+ lambderUtils: LambderUtils;
25
27
  resolve: (response: LambderResolverResponse) => void;
26
28
  reject: (err: Error) => void;
27
29
  });
@@ -3,8 +3,8 @@ export default class LambderResolver extends LambderResponseBuilder {
3
3
  resolve;
4
4
  reject;
5
5
  die;
6
- constructor({ isCorsEnabled, publicPath, apiVersion, resolve, reject }) {
7
- super({ isCorsEnabled, publicPath, apiVersion });
6
+ constructor({ isCorsEnabled, publicPath, apiVersion, lambderUtils, resolve, reject }) {
7
+ super({ isCorsEnabled, publicPath, apiVersion, lambderUtils });
8
8
  this.resolve = resolve;
9
9
  this.reject = reject;
10
10
  this.die = {
@@ -1,3 +1,4 @@
1
+ import LambderUtils from "./LambderUtils.js";
1
2
  export type LambderResolverResponse = {
2
3
  statusCode: number;
3
4
  multiValueHeaders?: Record<string, string[]>;
@@ -17,18 +18,16 @@ export type LambderApiResponse<T> = LambderApiResponseConfig & {
17
18
  export default class LambderResponseBuilder {
18
19
  private isCorsEnabled;
19
20
  private publicPath;
20
- private ejsPath;
21
21
  private apiVersion;
22
- constructor({ isCorsEnabled, publicPath, apiVersion, ejsPath }: {
22
+ private lambderUtils;
23
+ constructor({ isCorsEnabled, publicPath, apiVersion, lambderUtils }: {
23
24
  isCorsEnabled: boolean;
24
25
  publicPath: string;
25
- ejsPath?: string | null;
26
26
  apiVersion?: string | null;
27
+ lambderUtils: LambderUtils;
27
28
  });
28
29
  private readPublicFileSync;
29
30
  private checkPublicFileExist;
30
- private readEjsFileSync;
31
- private checkEjsFileExist;
32
31
  raw(param: LambderResolverResponse): LambderResolverResponse;
33
32
  json(data: Record<string, any>, headers?: Record<string, string | string[]>): LambderResolverResponse;
34
33
  xml(data: string): LambderResolverResponse;
@@ -1,6 +1,5 @@
1
1
  import fs from "fs";
2
2
  import * as path from "path";
3
- import ejs from "ejs";
4
3
  import mimeTypeResolver from "mime-types";
5
4
  const convertToMultiHeader = (headers) => Object.fromEntries(Object.entries(headers || {}).map(([k, v]) => [k, Array.isArray(v) ? v : [v]]));
6
5
  const CORS_HEADERS = convertToMultiHeader({
@@ -12,13 +11,13 @@ const CORS_HEADERS = convertToMultiHeader({
12
11
  export default class LambderResponseBuilder {
13
12
  isCorsEnabled;
14
13
  publicPath;
15
- ejsPath;
16
14
  apiVersion;
17
- constructor({ isCorsEnabled, publicPath, apiVersion, ejsPath }) {
15
+ lambderUtils;
16
+ constructor({ isCorsEnabled, publicPath, apiVersion, lambderUtils }) {
18
17
  this.isCorsEnabled = isCorsEnabled;
19
18
  this.publicPath = publicPath;
20
- this.ejsPath = ejsPath ?? null;
21
19
  this.apiVersion = apiVersion ?? null;
20
+ this.lambderUtils = lambderUtils;
22
21
  }
23
22
  ;
24
23
  readPublicFileSync(filePath) {
@@ -41,32 +40,6 @@ export default class LambderResponseBuilder {
41
40
  return fs.existsSync(absolutePath) && fs.statSync(absolutePath).isFile();
42
41
  }
43
42
  ;
44
- readEjsFileSync(filePath) {
45
- if (!this.ejsPath) {
46
- return "EJS PATH NOT SET!";
47
- }
48
- const ejsPath = path.resolve(this.ejsPath);
49
- const absolutePath = path.join(ejsPath, filePath);
50
- console.log("readEjsFileSync", { filePath, ejsPath, absolutePath });
51
- if (!absolutePath.includes(ejsPath)) {
52
- return "forbidden-ejs-path";
53
- }
54
- return String(fs.readFileSync(absolutePath));
55
- }
56
- ;
57
- checkEjsFileExist(filePath) {
58
- if (!this.ejsPath) {
59
- return "EJS PATH NOT SET!";
60
- }
61
- const ejsPath = path.resolve(this.ejsPath);
62
- const absolutePath = path.join(this.ejsPath, filePath);
63
- console.log("checkEjsFileExist", { filePath, ejsPath, absolutePath });
64
- if (!absolutePath.includes(ejsPath)) {
65
- return false;
66
- }
67
- return fs.existsSync(absolutePath) && fs.statSync(absolutePath).isFile();
68
- }
69
- ;
70
43
  raw(param) {
71
44
  return param;
72
45
  }
@@ -149,11 +122,7 @@ export default class LambderResponseBuilder {
149
122
  }
150
123
  ;
151
124
  async ejsTemplate(template, pageData, headers) {
152
- const includeRenderedFile = async (filePath, partialData) => {
153
- const template = await this.readEjsFileSync(filePath);
154
- return await ejs.render(template, { page: pageData, partial: partialData, include: includeRenderedFile }, { async: true });
155
- };
156
- const renderedResult = await ejs.render(template, { page: pageData, include: includeRenderedFile }, { async: true });
125
+ const renderedResult = await this.lambderUtils.renderEjs(template, pageData);
157
126
  return this.raw({
158
127
  statusCode: 200,
159
128
  isBase64Encoded: true,
@@ -163,11 +132,13 @@ export default class LambderResponseBuilder {
163
132
  }
164
133
  ;
165
134
  async ejsFile(filePath, pageData, headers) {
166
- if (!this.checkEjsFileExist(filePath)) {
167
- return this.json({ error: "File not found: " + filePath });
168
- }
169
- const template = this.readEjsFileSync(filePath);
170
- return this.ejsTemplate(template, pageData, headers);
135
+ const renderedResult = await this.lambderUtils.renderEjsFile(filePath, pageData);
136
+ return this.raw({
137
+ statusCode: 200,
138
+ isBase64Encoded: true,
139
+ multiValueHeaders: { "Content-Type": ["text/html; charset=utf-8"], ...convertToMultiHeader(headers) },
140
+ body: Buffer.from(renderedResult).toString("base64"),
141
+ });
171
142
  }
172
143
  ;
173
144
  api(payload, { versionExpired, sessionExpired, notAuthorized, message = null, errorMessage = null, } = {
@@ -0,0 +1,10 @@
1
+ export default class LambderUtils {
2
+ private ejsPath?;
3
+ constructor({ ejsPath }?: {
4
+ ejsPath?: string;
5
+ });
6
+ private readEjsFileSync;
7
+ private checkEjsFileExist;
8
+ renderEjs(template: string, pageData: Record<string, any>): Promise<string>;
9
+ renderEjsFile(filePath: string, pageData: Record<string, any>): Promise<string>;
10
+ }
@@ -0,0 +1,54 @@
1
+ import fs from "fs";
2
+ import * as path from "path";
3
+ import ejs from "ejs";
4
+ export default class LambderUtils {
5
+ ejsPath;
6
+ constructor({ ejsPath } = {}) {
7
+ this.ejsPath = ejsPath;
8
+ }
9
+ ;
10
+ readEjsFileSync(filePath) {
11
+ if (!this.ejsPath) {
12
+ return "EJS PATH NOT SET!";
13
+ }
14
+ const ejsPath = path.resolve(this.ejsPath);
15
+ const absolutePath = path.join(ejsPath, filePath);
16
+ console.log("readEjsFileSync", { filePath, ejsPath, absolutePath });
17
+ if (!absolutePath.includes(ejsPath)) {
18
+ return "forbidden-ejs-path";
19
+ }
20
+ return String(fs.readFileSync(absolutePath));
21
+ }
22
+ ;
23
+ checkEjsFileExist(filePath) {
24
+ if (!this.ejsPath) {
25
+ return "EJS PATH NOT SET!";
26
+ }
27
+ const ejsPath = path.resolve(this.ejsPath);
28
+ const absolutePath = path.join(this.ejsPath, filePath);
29
+ console.log("checkEjsFileExist", { filePath, ejsPath, absolutePath });
30
+ if (!absolutePath.includes(ejsPath)) {
31
+ return false;
32
+ }
33
+ return fs.existsSync(absolutePath) && fs.statSync(absolutePath).isFile();
34
+ }
35
+ ;
36
+ async renderEjs(template, pageData) {
37
+ const includeRenderedFile = async (filePath, partialData) => {
38
+ const template = await this.readEjsFileSync(filePath);
39
+ return await ejs.render(template, { page: pageData, partial: partialData, include: includeRenderedFile }, { async: true });
40
+ };
41
+ const renderedResult = await ejs.render(template, { page: pageData, include: includeRenderedFile }, { async: true });
42
+ return renderedResult;
43
+ }
44
+ ;
45
+ async renderEjsFile(filePath, pageData) {
46
+ if (!this.checkEjsFileExist(filePath)) {
47
+ return "File not found: " + filePath;
48
+ }
49
+ const template = this.readEjsFileSync(filePath);
50
+ return this.renderEjs(template, pageData);
51
+ }
52
+ ;
53
+ }
54
+ ;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lambder",
3
- "version": "1.0.103",
3
+ "version": "1.0.104",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/Lambder.ts CHANGED
@@ -5,6 +5,7 @@ import { match } from "path-to-regexp";
5
5
  import type { APIGatewayProxyEvent, APIGatewayProxyEventHeaders, Context } from "aws-lambda";
6
6
  import LambderResolver from "./LambderResolver.js";
7
7
  import LambderResponseBuilder, { LambderResolverResponse } from "./LambderResponseBuilder.js";
8
+ import LambderUtils from "./LambderUtils.js";
8
9
 
9
10
  type Path = `/${string}`;
10
11
 
@@ -35,7 +36,6 @@ type LambderRenderContext = {
35
36
 
36
37
  type LambderModuleFunction = (lambderInstance: Lambder) => void | Promise<void>;
37
38
 
38
-
39
39
  type ConditionFunction = (ctx: LambderRenderContext) => boolean;
40
40
  type ActionFunction = (ctx: LambderRenderContext, resolver: LambderResolver) => LambderResolverResponse|Promise<LambderResolverResponse>;
41
41
  type ActionObject = { conditionFn: ConditionFunction, actionFn: ActionFunction };
@@ -81,10 +81,11 @@ export const createContext = (
81
81
 
82
82
 
83
83
  export default class Lambder {
84
- private apiPath: string;
85
- private apiVersion: null|string;
86
- private isCorsEnabled: boolean;
87
- private publicPath: string;
84
+ public apiPath: string;
85
+ public apiVersion: null|string;
86
+ public isCorsEnabled: boolean;
87
+ public publicPath: string;
88
+ public ejsPath: string;
88
89
 
89
90
  private actionList: ActionObject[];
90
91
  private hookList: {
@@ -96,11 +97,15 @@ export default class Lambder {
96
97
  private routeFallbackHandler: RouteFallbackHandlerFunction|null = null;
97
98
  private apiFallbackHandler: ApiFallbackHandlerFunction|null = null;
98
99
 
100
+ public utils: LambderUtils;
101
+
102
+
99
103
  constructor(
100
- { publicPath, apiPath, apiVersion, isCorsEnabled, }:
101
- { publicPath: string, apiPath?: string, apiVersion?: string, isCorsEnabled?: boolean, }
104
+ { publicPath, apiPath, ejsPath, apiVersion, isCorsEnabled }:
105
+ { publicPath: string, apiPath?: string, ejsPath?: string, apiVersion?: string, isCorsEnabled?: boolean, }
102
106
  ){
103
107
  this.publicPath = publicPath || "/incorrect-path-not-found";
108
+ this.ejsPath = ejsPath || "/incorrect-ejs-path-not-found";
104
109
  this.apiPath = apiPath ?? "/api";
105
110
  this.apiVersion = apiVersion ?? null;
106
111
  this.isCorsEnabled = isCorsEnabled ?? false;
@@ -111,6 +116,8 @@ export default class Lambder {
111
116
  "afterRender": [],
112
117
  "fallback": [],
113
118
  };
119
+
120
+ this.utils = new LambderUtils({ ejsPath });
114
121
  }
115
122
 
116
123
  setRouteFallbackHandler(routeFallbackHandler: RouteFallbackHandlerFunction){
@@ -267,6 +274,7 @@ export default class Lambder {
267
274
  isCorsEnabled: this.isCorsEnabled,
268
275
  publicPath: this.publicPath,
269
276
  apiVersion: this.apiVersion,
277
+ lambderUtils: this.utils,
270
278
  });
271
279
  };
272
280
 
@@ -275,6 +283,7 @@ export default class Lambder {
275
283
  isCorsEnabled: this.isCorsEnabled,
276
284
  publicPath: this.publicPath,
277
285
  apiVersion: this.apiVersion,
286
+ lambderUtils: this.utils,
278
287
  resolve, reject
279
288
  });
280
289
  };
@@ -1,4 +1,5 @@
1
1
  import LambderResponseBuilder, { LambderResolverResponse } from "./LambderResponseBuilder.js";
2
+ import LambderUtils from "./LambderUtils.js";
2
3
 
3
4
  type MethodType<T, M extends keyof T> = T[M] extends (...args: any[]) => any ? T[M] : never;
4
5
 
@@ -23,16 +24,17 @@ export default class LambderResolver extends LambderResponseBuilder {
23
24
  public die: DieResolverMethods;
24
25
 
25
26
  constructor(
26
- { isCorsEnabled, publicPath, apiVersion, resolve, reject }:
27
+ { isCorsEnabled, publicPath, apiVersion, lambderUtils, resolve, reject }:
27
28
  {
28
29
  isCorsEnabled: boolean,
29
30
  publicPath: string,
30
31
  apiVersion?: string|null,
32
+ lambderUtils: LambderUtils
31
33
  resolve: (response: LambderResolverResponse) => void,
32
34
  reject: (err: Error) => void,
33
35
  }
34
36
  ){
35
- super({ isCorsEnabled, publicPath, apiVersion });
37
+ super({ isCorsEnabled, publicPath, apiVersion, lambderUtils });
36
38
  this.resolve = resolve;
37
39
  this.reject = reject;
38
40
 
@@ -2,6 +2,7 @@ import fs from "fs";
2
2
  import * as path from "path";
3
3
  import ejs from "ejs";
4
4
  import mimeTypeResolver from "mime-types";
5
+ import LambderUtils from "./LambderUtils.js";
5
6
 
6
7
  const convertToMultiHeader = (
7
8
  headers: Record<string, string|string[]> | undefined
@@ -38,22 +39,22 @@ export type LambderApiResponse<T> = LambderApiResponseConfig & {
38
39
  export default class LambderResponseBuilder {
39
40
  private isCorsEnabled: boolean;
40
41
  private publicPath: string;
41
- private ejsPath: string|null;
42
42
  private apiVersion: string|null;
43
+ private lambderUtils: LambderUtils;
43
44
 
44
45
  constructor(
45
- { isCorsEnabled, publicPath, apiVersion, ejsPath }:
46
+ { isCorsEnabled, publicPath, apiVersion, lambderUtils }:
46
47
  {
47
48
  isCorsEnabled: boolean,
48
49
  publicPath: string,
49
- ejsPath?: string|null,
50
50
  apiVersion?: string|null,
51
+ lambderUtils: LambderUtils
51
52
  }
52
53
  ){
53
54
  this.isCorsEnabled = isCorsEnabled;
54
55
  this.publicPath = publicPath;
55
- this.ejsPath = ejsPath ?? null;
56
56
  this.apiVersion = apiVersion ?? null;
57
+ this.lambderUtils = lambderUtils;
57
58
  };
58
59
 
59
60
  private readPublicFileSync(filePath: string){
@@ -72,23 +73,6 @@ export default class LambderResponseBuilder {
72
73
  return fs.existsSync(absolutePath) && fs.statSync(absolutePath).isFile();
73
74
  };
74
75
 
75
- private readEjsFileSync(filePath: string){
76
- if(!this.ejsPath){ return "EJS PATH NOT SET!"; }
77
- const ejsPath = path.resolve(this.ejsPath);
78
- const absolutePath = path.join(ejsPath, filePath);
79
- console.log("readEjsFileSync", { filePath, ejsPath, absolutePath });
80
- if(!absolutePath.includes(ejsPath)){ return "forbidden-ejs-path"; }
81
- return String(fs.readFileSync(absolutePath));
82
- };
83
-
84
- private checkEjsFileExist(filePath: string){
85
- if(!this.ejsPath){ return "EJS PATH NOT SET!"; }
86
- const ejsPath = path.resolve(this.ejsPath);
87
- const absolutePath = path.join(this.ejsPath, filePath);
88
- console.log("checkEjsFileExist", { filePath, ejsPath, absolutePath });
89
- if(!absolutePath.includes(ejsPath)){ return false; }
90
- return fs.existsSync(absolutePath) && fs.statSync(absolutePath).isFile();
91
- };
92
76
 
93
77
  raw(param: LambderResolverResponse){
94
78
  return param;
@@ -197,11 +181,7 @@ export default class LambderResponseBuilder {
197
181
  pageData: Record<string, any>,
198
182
  headers?: Record<string, string|string[]>,
199
183
  ):Promise<LambderResolverResponse>{
200
- const includeRenderedFile = async (filePath: string, partialData: Record<string, any>) => {
201
- const template = await this.readEjsFileSync(filePath);
202
- return await ejs.render(template, { page: pageData, partial: partialData, include: includeRenderedFile }, { async: true });
203
- }
204
- const renderedResult = await ejs.render(template, { page: pageData, include: includeRenderedFile }, { async: true });
184
+ const renderedResult = await this.lambderUtils.renderEjs(template, pageData);
205
185
 
206
186
  return this.raw({
207
187
  statusCode: 200,
@@ -216,11 +196,14 @@ export default class LambderResponseBuilder {
216
196
  pageData: Record<string, any>,
217
197
  headers?: Record<string, string|string[]>,
218
198
  ):Promise<LambderResolverResponse>{
219
- if(!this.checkEjsFileExist(filePath)){
220
- return this.json({ error: "File not found: " + filePath })
221
- }
222
- const template = this.readEjsFileSync(filePath);
223
- return this.ejsTemplate(template, pageData, headers);
199
+ const renderedResult = await this.lambderUtils.renderEjsFile(filePath, pageData);
200
+
201
+ return this.raw({
202
+ statusCode: 200,
203
+ isBase64Encoded: true,
204
+ multiValueHeaders: {"Content-Type": ["text/html; charset=utf-8"], ...convertToMultiHeader(headers)},
205
+ body: Buffer.from(renderedResult).toString("base64"),
206
+ });
224
207
  };
225
208
 
226
209
  api<T=any>(
@@ -0,0 +1,58 @@
1
+ import fs from "fs";
2
+ import * as path from "path";
3
+ import ejs from "ejs";
4
+
5
+ export default class LambderUtils {
6
+ private ejsPath?: string;
7
+
8
+ constructor(
9
+ { ejsPath }: {
10
+ ejsPath?: string
11
+ } = {}
12
+ ){
13
+ this.ejsPath = ejsPath;
14
+ };
15
+
16
+ private readEjsFileSync(filePath: string){
17
+ if(!this.ejsPath){ return "EJS PATH NOT SET!"; }
18
+ const ejsPath = path.resolve(this.ejsPath);
19
+ const absolutePath = path.join(ejsPath, filePath);
20
+ console.log("readEjsFileSync", { filePath, ejsPath, absolutePath });
21
+ if(!absolutePath.includes(ejsPath)){ return "forbidden-ejs-path"; }
22
+ return String(fs.readFileSync(absolutePath));
23
+ };
24
+
25
+ private checkEjsFileExist(filePath: string){
26
+ if(!this.ejsPath){ return "EJS PATH NOT SET!"; }
27
+ const ejsPath = path.resolve(this.ejsPath);
28
+ const absolutePath = path.join(this.ejsPath, filePath);
29
+ console.log("checkEjsFileExist", { filePath, ejsPath, absolutePath });
30
+ if(!absolutePath.includes(ejsPath)){ return false; }
31
+ return fs.existsSync(absolutePath) && fs.statSync(absolutePath).isFile();
32
+ };
33
+
34
+ async renderEjs(
35
+ template: string,
36
+ pageData: Record<string, any>,
37
+ ):Promise<string>{
38
+ const includeRenderedFile = async (filePath: string, partialData: Record<string, any>) => {
39
+ const template = await this.readEjsFileSync(filePath);
40
+ return await ejs.render(template, { page: pageData, partial: partialData, include: includeRenderedFile }, { async: true });
41
+ }
42
+ const renderedResult = await ejs.render(template, { page: pageData, include: includeRenderedFile }, { async: true });
43
+
44
+ return renderedResult;
45
+ };
46
+
47
+ async renderEjsFile(
48
+ filePath: string,
49
+ pageData: Record<string, any>,
50
+ ):Promise<string>{
51
+ if(!this.checkEjsFileExist(filePath)){
52
+ return "File not found: " + filePath;
53
+ }
54
+ const template = this.readEjsFileSync(filePath);
55
+ return this.renderEjs(template, pageData);
56
+ };
57
+
58
+ };