lambder 1.0.103 → 1.0.105
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 +9 -5
- package/dist/Lambder.js +8 -1
- package/dist/LambderResolver.d.ts +3 -1
- package/dist/LambderResolver.js +2 -2
- package/dist/LambderResponseBuilder.d.ts +4 -5
- package/dist/LambderResponseBuilder.js +11 -40
- package/dist/LambderUtils.d.ts +10 -0
- package/dist/LambderUtils.js +54 -0
- package/package.json +1 -1
- package/src/Lambder.ts +16 -7
- package/src/LambderResolver.ts +4 -2
- package/src/LambderResponseBuilder.ts +14 -31
- package/src/LambderUtils.ts +58 -0
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
});
|
package/dist/LambderResolver.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
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
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
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
};
|
package/src/LambderResolver.ts
CHANGED
|
@@ -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,
|
|
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
|
|
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
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
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
|
+
};
|