lambder 1.0.122 → 1.0.124
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 +10 -2
- package/dist/Lambder.js +18 -11
- package/dist/LambderCaller.js +5 -0
- package/dist/LambderResolver.d.ts +3 -1
- package/dist/LambderResolver.js +2 -2
- package/dist/LambderResponseBuilder.d.ts +9 -2
- package/dist/LambderResponseBuilder.js +33 -3
- package/dist/LambderSessionController.js +6 -18
- package/package.json +1 -1
- package/src/Lambder.ts +31 -14
- package/src/LambderCaller.ts +5 -0
- package/src/LambderResolver.ts +5 -3
- package/src/LambderResponseBuilder.ts +34 -4
- package/src/LambderSessionController.ts +6 -18
- /package/{deploy.sh → deploy} +0 -0
package/dist/Lambder.d.ts
CHANGED
|
@@ -20,7 +20,15 @@ export type LambderRenderContext = {
|
|
|
20
20
|
lambdaContext: Context;
|
|
21
21
|
_otherInternal: {
|
|
22
22
|
isApiCall: boolean;
|
|
23
|
-
|
|
23
|
+
setHeaderFnAccumulator: {
|
|
24
|
+
key: string;
|
|
25
|
+
value: string | string[];
|
|
26
|
+
}[];
|
|
27
|
+
addHeaderFnAccumulator: {
|
|
28
|
+
key: string;
|
|
29
|
+
value: string;
|
|
30
|
+
}[];
|
|
31
|
+
logToApiResponseAccumulator: any[];
|
|
24
32
|
};
|
|
25
33
|
};
|
|
26
34
|
type LambderModuleFunction = (lambderInstance: Lambder) => void | Promise<void>;
|
|
@@ -30,7 +38,7 @@ type HookCreatedFunction = (lambderInstance: Lambder) => Promise<void>;
|
|
|
30
38
|
type HookBeforeRenderFunction = (ctx: LambderRenderContext, resolver: LambderResolver) => LambderRenderContext | Error | Promise<LambderRenderContext | Error>;
|
|
31
39
|
type HookAfterRenderFunction = (ctx: LambderRenderContext, resolver: LambderResolver, response: LambderResolverResponse) => LambderResolverResponse | Error | Promise<LambderResolverResponse | Error>;
|
|
32
40
|
type HookFallbackFunction = (ctx: LambderRenderContext, resolver: LambderResolver) => void | Promise<void>;
|
|
33
|
-
type GlobalErrorHandlerFunction = (err: Error, ctx: LambderRenderContext | null, response: LambderResponseBuilder) => LambderResolverResponse | Promise<LambderResolverResponse>;
|
|
41
|
+
type GlobalErrorHandlerFunction = (err: Error, ctx: LambderRenderContext | null, response: LambderResponseBuilder, logListToApiResponse?: any[]) => LambderResolverResponse | Promise<LambderResolverResponse>;
|
|
34
42
|
type RouteFallbackHandlerFunction = (ctx: LambderRenderContext, resolver: LambderResolver) => LambderResolverResponse;
|
|
35
43
|
type ApiFallbackHandlerFunction = (ctx: LambderRenderContext, resolver: LambderResolver) => LambderResolverResponse;
|
|
36
44
|
export declare const createContext: (event: APIGatewayProxyEvent, lambdaContext: Context, apiPath: string) => LambderRenderContext;
|
package/dist/Lambder.js
CHANGED
|
@@ -36,7 +36,12 @@ export const createContext = (event, lambdaContext, apiPath) => {
|
|
|
36
36
|
get, post, cookie,
|
|
37
37
|
apiName, apiPayload,
|
|
38
38
|
headers, session, lambdaContext,
|
|
39
|
-
_otherInternal: {
|
|
39
|
+
_otherInternal: {
|
|
40
|
+
isApiCall,
|
|
41
|
+
setHeaderFnAccumulator: [],
|
|
42
|
+
addHeaderFnAccumulator: [],
|
|
43
|
+
logToApiResponseAccumulator: [],
|
|
44
|
+
}
|
|
40
45
|
};
|
|
41
46
|
};
|
|
42
47
|
export default class Lambder {
|
|
@@ -207,13 +212,13 @@ export default class Lambder {
|
|
|
207
212
|
});
|
|
208
213
|
}
|
|
209
214
|
;
|
|
210
|
-
getResolver(resolve, reject) {
|
|
215
|
+
getResolver(ctx, resolve, reject) {
|
|
211
216
|
return new LambderResolver({
|
|
212
217
|
isCorsEnabled: this.isCorsEnabled,
|
|
213
218
|
publicPath: this.publicPath,
|
|
214
219
|
apiVersion: this.apiVersion,
|
|
215
220
|
lambderUtils: this.utils,
|
|
216
|
-
resolve, reject
|
|
221
|
+
ctx, resolve, reject
|
|
217
222
|
});
|
|
218
223
|
}
|
|
219
224
|
;
|
|
@@ -224,7 +229,7 @@ export default class Lambder {
|
|
|
224
229
|
eventRenderContext = ctx;
|
|
225
230
|
return await new Promise(async (resolve, reject) => {
|
|
226
231
|
try {
|
|
227
|
-
const resolver = this.getResolver(resolve, reject);
|
|
232
|
+
const resolver = this.getResolver(ctx, resolve, reject);
|
|
228
233
|
if (ctx.method === "OPTIONS")
|
|
229
234
|
return resolver.cors();
|
|
230
235
|
const firstMatchedAction = this.actionList.find(action => action.conditionFn(ctx));
|
|
@@ -247,12 +252,14 @@ export default class Lambder {
|
|
|
247
252
|
}
|
|
248
253
|
response = hookResponse;
|
|
249
254
|
}
|
|
250
|
-
// Apply
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
255
|
+
// Apply setHeader, addHeader values.
|
|
256
|
+
response.multiValueHeaders = response.multiValueHeaders || {};
|
|
257
|
+
for (const header of ctx._otherInternal.setHeaderFnAccumulator) {
|
|
258
|
+
response.multiValueHeaders[header.key] = Array.isArray(header.value) ? header.value : [header.value];
|
|
259
|
+
}
|
|
260
|
+
for (const header of ctx._otherInternal.addHeaderFnAccumulator) {
|
|
261
|
+
response.multiValueHeaders[header.key] = response.multiValueHeaders[header.key] || [];
|
|
262
|
+
response.multiValueHeaders[header.key].push(header.value);
|
|
256
263
|
}
|
|
257
264
|
resolve(response);
|
|
258
265
|
}
|
|
@@ -270,7 +277,7 @@ export default class Lambder {
|
|
|
270
277
|
if (this.globalErrorHandler) {
|
|
271
278
|
const wrappedError = err instanceof Error ? err : new Error("Error: " + String(err));
|
|
272
279
|
const responseBuilder = this.getResponseBuilder();
|
|
273
|
-
return this.globalErrorHandler(wrappedError, eventRenderContext, responseBuilder);
|
|
280
|
+
return this.globalErrorHandler(wrappedError, eventRenderContext, responseBuilder, eventRenderContext?._otherInternal.logToApiResponseAccumulator);
|
|
274
281
|
}
|
|
275
282
|
return { statusCode: 500, body: "Internal Server Error.", };
|
|
276
283
|
}
|
package/dist/LambderCaller.js
CHANGED
|
@@ -65,6 +65,11 @@ export default class LambderCaller {
|
|
|
65
65
|
activeFetchList: this.fetchTrackerList.filter(v => !v.done),
|
|
66
66
|
});
|
|
67
67
|
}
|
|
68
|
+
if (data && data.logList?.length) {
|
|
69
|
+
for (const record of data.logList) {
|
|
70
|
+
console.log("LogToApiResponse:", record);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
68
73
|
if (data && data.versionExpired) {
|
|
69
74
|
if (this.versionExpiredHandler) {
|
|
70
75
|
await this.versionExpiredHandler();
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { LambderRenderContext } from "./Lambder.js";
|
|
1
2
|
import LambderResponseBuilder, { LambderResolverResponse } from "./LambderResponseBuilder.js";
|
|
2
3
|
import LambderUtils from "./LambderUtils.js";
|
|
3
4
|
type MethodType<T, M extends keyof T> = T[M] extends (...args: any[]) => any ? T[M] : never;
|
|
@@ -19,11 +20,12 @@ export default class LambderResolver extends LambderResponseBuilder {
|
|
|
19
20
|
resolve: (response: LambderResolverResponse) => void;
|
|
20
21
|
reject: (err: Error) => void;
|
|
21
22
|
die: DieResolverMethods;
|
|
22
|
-
constructor({ isCorsEnabled, publicPath, apiVersion, lambderUtils, resolve, reject }: {
|
|
23
|
+
constructor({ isCorsEnabled, publicPath, apiVersion, lambderUtils, ctx, resolve, reject }: {
|
|
23
24
|
isCorsEnabled: boolean;
|
|
24
25
|
publicPath: string;
|
|
25
26
|
apiVersion?: string | null;
|
|
26
27
|
lambderUtils: LambderUtils;
|
|
28
|
+
ctx: LambderRenderContext;
|
|
27
29
|
resolve: (response: LambderResolverResponse) => void;
|
|
28
30
|
reject: (err: Error) => void;
|
|
29
31
|
});
|
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, lambderUtils, resolve, reject }) {
|
|
7
|
-
super({ isCorsEnabled, publicPath, apiVersion, lambderUtils });
|
|
6
|
+
constructor({ isCorsEnabled, publicPath, apiVersion, lambderUtils, ctx, resolve, reject }) {
|
|
7
|
+
super({ isCorsEnabled, publicPath, apiVersion, lambderUtils, ctx, });
|
|
8
8
|
this.resolve = resolve;
|
|
9
9
|
this.reject = reject;
|
|
10
10
|
this.die = {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import LambderUtils from "./LambderUtils.js";
|
|
2
|
+
import { LambderRenderContext } from "./Lambder.js";
|
|
2
3
|
export type LambderResolverResponse = {
|
|
3
4
|
statusCode: number;
|
|
4
5
|
multiValueHeaders?: Record<string, string[]>;
|
|
@@ -11,6 +12,7 @@ export type LambderApiResponseConfig = {
|
|
|
11
12
|
notAuthorized?: boolean;
|
|
12
13
|
message?: any;
|
|
13
14
|
errorMessage?: any;
|
|
15
|
+
logList?: any[];
|
|
14
16
|
};
|
|
15
17
|
export type LambderApiResponse<T> = LambderApiResponseConfig & {
|
|
16
18
|
payload?: T | null;
|
|
@@ -20,14 +22,19 @@ export default class LambderResponseBuilder {
|
|
|
20
22
|
private publicPath;
|
|
21
23
|
private apiVersion;
|
|
22
24
|
private lambderUtils;
|
|
23
|
-
|
|
25
|
+
private ctx?;
|
|
26
|
+
constructor({ isCorsEnabled, publicPath, apiVersion, lambderUtils, ctx }: {
|
|
24
27
|
isCorsEnabled: boolean;
|
|
25
28
|
publicPath: string;
|
|
26
29
|
apiVersion?: string | null;
|
|
27
30
|
lambderUtils: LambderUtils;
|
|
31
|
+
ctx?: LambderRenderContext;
|
|
28
32
|
});
|
|
29
33
|
private readPublicFileSync;
|
|
30
34
|
private checkPublicFileExist;
|
|
35
|
+
addHeader(key: string, value: string): void;
|
|
36
|
+
setHeader(key: string, value: string | string[]): void;
|
|
37
|
+
logToApiResponse(input: any): void;
|
|
31
38
|
raw(param: LambderResolverResponse): LambderResolverResponse;
|
|
32
39
|
json(data: Record<string, any>, headers?: Record<string, string | string[]>): LambderResolverResponse;
|
|
33
40
|
xml(data: string): LambderResolverResponse;
|
|
@@ -39,5 +46,5 @@ export default class LambderResponseBuilder {
|
|
|
39
46
|
file(filePath: string, headers?: Record<string, string | string[]>, fallbackFilePath?: string): LambderResolverResponse;
|
|
40
47
|
ejsTemplate(template: string, pageData: Record<string, any>, headers?: Record<string, string | string[]>): Promise<LambderResolverResponse>;
|
|
41
48
|
ejsFile(filePath: string, pageData: Record<string, any>, headers?: Record<string, string | string[]>): Promise<LambderResolverResponse>;
|
|
42
|
-
api<T = any>(payload: T | null, { versionExpired, sessionExpired, notAuthorized, message, errorMessage, }?: LambderApiResponseConfig, headers?: Record<string, string | string[]>): LambderResolverResponse;
|
|
49
|
+
api<T = any>(payload: T | null, { versionExpired, sessionExpired, notAuthorized, message, errorMessage, logList, }?: LambderApiResponseConfig, headers?: Record<string, string | string[]>): LambderResolverResponse;
|
|
43
50
|
}
|
|
@@ -13,11 +13,13 @@ export default class LambderResponseBuilder {
|
|
|
13
13
|
publicPath;
|
|
14
14
|
apiVersion;
|
|
15
15
|
lambderUtils;
|
|
16
|
-
|
|
16
|
+
ctx;
|
|
17
|
+
constructor({ isCorsEnabled, publicPath, apiVersion, lambderUtils, ctx }) {
|
|
17
18
|
this.isCorsEnabled = isCorsEnabled;
|
|
18
19
|
this.publicPath = publicPath;
|
|
19
20
|
this.apiVersion = apiVersion ?? null;
|
|
20
21
|
this.lambderUtils = lambderUtils;
|
|
22
|
+
this.ctx = ctx;
|
|
21
23
|
}
|
|
22
24
|
;
|
|
23
25
|
readPublicFileSync(filePath) {
|
|
@@ -40,6 +42,32 @@ export default class LambderResponseBuilder {
|
|
|
40
42
|
return fs.existsSync(absolutePath) && fs.statSync(absolutePath).isFile();
|
|
41
43
|
}
|
|
42
44
|
;
|
|
45
|
+
addHeader(key, value) {
|
|
46
|
+
if (!this.ctx)
|
|
47
|
+
throw new Error(".addHeader function is not available within this hook");
|
|
48
|
+
else {
|
|
49
|
+
this.ctx._otherInternal.addHeaderFnAccumulator.push({ key, value });
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
;
|
|
53
|
+
setHeader(key, value) {
|
|
54
|
+
if (!this.ctx)
|
|
55
|
+
throw new Error(".setHeader function is not available within this hook");
|
|
56
|
+
else {
|
|
57
|
+
this.ctx._otherInternal.addHeaderFnAccumulator = this.ctx._otherInternal.addHeaderFnAccumulator
|
|
58
|
+
.filter(header => header.key !== key);
|
|
59
|
+
this.ctx._otherInternal.setHeaderFnAccumulator.push({ key, value });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
;
|
|
63
|
+
logToApiResponse(input) {
|
|
64
|
+
if (!this.ctx)
|
|
65
|
+
throw new Error(".logToResponse function is not available within this hook");
|
|
66
|
+
else {
|
|
67
|
+
this.ctx._otherInternal.logToApiResponseAccumulator.push(input);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
;
|
|
43
71
|
raw(param) {
|
|
44
72
|
return param;
|
|
45
73
|
}
|
|
@@ -141,10 +169,11 @@ export default class LambderResponseBuilder {
|
|
|
141
169
|
});
|
|
142
170
|
}
|
|
143
171
|
;
|
|
144
|
-
api(payload, { versionExpired, sessionExpired, notAuthorized, message
|
|
172
|
+
api(payload, { versionExpired, sessionExpired, notAuthorized, message, errorMessage, logList, } = {
|
|
145
173
|
versionExpired: undefined, sessionExpired: undefined, notAuthorized: undefined,
|
|
146
|
-
message: null, errorMessage: null,
|
|
174
|
+
message: null, errorMessage: null, logList: undefined
|
|
147
175
|
}, headers) {
|
|
176
|
+
const finalLogList = logList || this.ctx?._otherInternal?.logToApiResponseAccumulator;
|
|
148
177
|
return this.json({
|
|
149
178
|
apiVersion: this.apiVersion,
|
|
150
179
|
payload,
|
|
@@ -153,6 +182,7 @@ export default class LambderResponseBuilder {
|
|
|
153
182
|
...(notAuthorized ? { notAuthorized } : {}),
|
|
154
183
|
...(message ? { message } : {}),
|
|
155
184
|
...(errorMessage ? { errorMessage } : {}),
|
|
185
|
+
...(finalLogList?.length ? { logList: finalLogList } : {}),
|
|
156
186
|
}, headers);
|
|
157
187
|
}
|
|
158
188
|
;
|
|
@@ -25,12 +25,8 @@ export default class LambderSessionController {
|
|
|
25
25
|
;
|
|
26
26
|
async createSession(sessionKey, data, ttlInSeconds) {
|
|
27
27
|
const session = await this.lambderSessionManager.createSession(sessionKey, data, ttlInSeconds);
|
|
28
|
-
this.ctx._otherInternal.
|
|
29
|
-
|
|
30
|
-
`${this.sessionTokenCookieKey}=${session.sessionToken}; Expires=${new Date(session.expiresAt * 1000).toUTCString()}; Path=/; HttpOnly; SameSite=Lax; Secure`,
|
|
31
|
-
`${this.sessionCsrfCookieKey}=${session.csrfToken}; Expires=${new Date(session.expiresAt * 1000).toUTCString()}; Path=/; SameSite=Lax; Secure`,
|
|
32
|
-
],
|
|
33
|
-
};
|
|
28
|
+
this.ctx._otherInternal.addHeaderFnAccumulator.push({ key: "Set-Cookie", value: `${this.sessionTokenCookieKey}=${session.sessionToken}; Expires=${new Date(session.expiresAt * 1000).toUTCString()}; Path=/; HttpOnly; SameSite=Lax; Secure` });
|
|
29
|
+
this.ctx._otherInternal.addHeaderFnAccumulator.push({ key: "Set-Cookie", value: `${this.sessionCsrfCookieKey}=${session.csrfToken}; Expires=${new Date(session.expiresAt * 1000).toUTCString()}; Path=/; SameSite=Lax; Secure` });
|
|
34
30
|
this.ctx.session = session;
|
|
35
31
|
return this.ctx.session;
|
|
36
32
|
}
|
|
@@ -83,12 +79,8 @@ export default class LambderSessionController {
|
|
|
83
79
|
if (!this.ctx.session)
|
|
84
80
|
throw new Error("Session not found.");
|
|
85
81
|
await this.lambderSessionManager.deleteSession(this.ctx.session);
|
|
86
|
-
this.ctx._otherInternal.
|
|
87
|
-
|
|
88
|
-
`${this.sessionTokenCookieKey}=0; Expires=${new Date(Date.now() - 100000).toUTCString()}; Path=/; HttpOnly; SameSite=Lax; Secure`,
|
|
89
|
-
`${this.sessionCsrfCookieKey}=0; Expires=${new Date(Date.now() - 100000).toUTCString()}; Path=/; SameSite=Lax; Secure`,
|
|
90
|
-
],
|
|
91
|
-
};
|
|
82
|
+
this.ctx._otherInternal.addHeaderFnAccumulator.push({ key: "Set-Cookie", value: `${this.sessionTokenCookieKey}=0; Expires=${new Date(Date.now() - 100000).toUTCString()}; Path=/; HttpOnly; SameSite=Lax; Secure` });
|
|
83
|
+
this.ctx._otherInternal.addHeaderFnAccumulator.push({ key: "Set-Cookie", value: `${this.sessionCsrfCookieKey}=0; Expires=${new Date(Date.now() - 100000).toUTCString()}; Path=/; SameSite=Lax; Secure` });
|
|
92
84
|
this.ctx.session = null;
|
|
93
85
|
}
|
|
94
86
|
;
|
|
@@ -96,12 +88,8 @@ export default class LambderSessionController {
|
|
|
96
88
|
if (!this.ctx.session)
|
|
97
89
|
throw new Error("Session not found.");
|
|
98
90
|
await this.lambderSessionManager.deleteSessionAll(this.ctx.session);
|
|
99
|
-
this.ctx._otherInternal.
|
|
100
|
-
|
|
101
|
-
`${this.sessionTokenCookieKey}=0; Expires=${new Date(Date.now() - 100000).toUTCString()}; Path=/; HttpOnly; SameSite=Lax; Secure`,
|
|
102
|
-
`${this.sessionCsrfCookieKey}=0; Expires=${new Date(Date.now() - 100000).toUTCString()}; Path=/; SameSite=Lax; Secure`,
|
|
103
|
-
],
|
|
104
|
-
};
|
|
91
|
+
this.ctx._otherInternal.addHeaderFnAccumulator.push({ key: "Set-Cookie", value: `${this.sessionTokenCookieKey}=0; Expires=${new Date(Date.now() - 100000).toUTCString()}; Path=/; HttpOnly; SameSite=Lax; Secure` });
|
|
92
|
+
this.ctx._otherInternal.addHeaderFnAccumulator.push({ key: "Set-Cookie", value: `${this.sessionCsrfCookieKey}=0; Expires=${new Date(Date.now() - 100000).toUTCString()}; Path=/; SameSite=Lax; Secure` });
|
|
105
93
|
this.ctx.session = null;
|
|
106
94
|
}
|
|
107
95
|
;
|
package/package.json
CHANGED
package/src/Lambder.ts
CHANGED
|
@@ -26,7 +26,9 @@ export type LambderRenderContext = {
|
|
|
26
26
|
lambdaContext: Context;
|
|
27
27
|
_otherInternal: {
|
|
28
28
|
isApiCall: boolean,
|
|
29
|
-
|
|
29
|
+
setHeaderFnAccumulator: { key:string, value:string|string[] }[];
|
|
30
|
+
addHeaderFnAccumulator: { key:string, value:string }[];
|
|
31
|
+
logToApiResponseAccumulator: any[];
|
|
30
32
|
};
|
|
31
33
|
};
|
|
32
34
|
|
|
@@ -42,7 +44,7 @@ type HookBeforeRenderFunction = (ctx: LambderRenderContext, resolver: LambderRes
|
|
|
42
44
|
type HookAfterRenderFunction = (ctx: LambderRenderContext, resolver: LambderResolver, response: LambderResolverResponse) => LambderResolverResponse|Error|Promise<LambderResolverResponse|Error>;
|
|
43
45
|
type HookFallbackFunction = (ctx: LambderRenderContext, resolver: LambderResolver) => void|Promise<void>;
|
|
44
46
|
|
|
45
|
-
type GlobalErrorHandlerFunction = (err: Error, ctx: LambderRenderContext|null, response: LambderResponseBuilder) => LambderResolverResponse|Promise<LambderResolverResponse>;
|
|
47
|
+
type GlobalErrorHandlerFunction = (err: Error, ctx: LambderRenderContext|null, response: LambderResponseBuilder, logListToApiResponse?: any[]) => LambderResolverResponse|Promise<LambderResolverResponse>;
|
|
46
48
|
type RouteFallbackHandlerFunction = (ctx:LambderRenderContext, resolver: LambderResolver) => LambderResolverResponse;
|
|
47
49
|
type ApiFallbackHandlerFunction = (ctx:LambderRenderContext, resolver: LambderResolver) => LambderResolverResponse;
|
|
48
50
|
|
|
@@ -79,7 +81,12 @@ export const createContext = (
|
|
|
79
81
|
get, post, cookie,
|
|
80
82
|
apiName, apiPayload,
|
|
81
83
|
headers, session, lambdaContext,
|
|
82
|
-
_otherInternal: {
|
|
84
|
+
_otherInternal: {
|
|
85
|
+
isApiCall,
|
|
86
|
+
setHeaderFnAccumulator: [],
|
|
87
|
+
addHeaderFnAccumulator: [],
|
|
88
|
+
logToApiResponseAccumulator: [],
|
|
89
|
+
}
|
|
83
90
|
};
|
|
84
91
|
}
|
|
85
92
|
|
|
@@ -296,13 +303,17 @@ export default class Lambder {
|
|
|
296
303
|
});
|
|
297
304
|
};
|
|
298
305
|
|
|
299
|
-
private getResolver(
|
|
306
|
+
private getResolver(
|
|
307
|
+
ctx: LambderRenderContext,
|
|
308
|
+
resolve: (response: LambderResolverResponse) => void,
|
|
309
|
+
reject: (err: Error) => void
|
|
310
|
+
){
|
|
300
311
|
return new LambderResolver({
|
|
301
312
|
isCorsEnabled: this.isCorsEnabled,
|
|
302
313
|
publicPath: this.publicPath,
|
|
303
314
|
apiVersion: this.apiVersion,
|
|
304
315
|
lambderUtils: this.utils,
|
|
305
|
-
resolve, reject
|
|
316
|
+
ctx, resolve, reject
|
|
306
317
|
});
|
|
307
318
|
};
|
|
308
319
|
|
|
@@ -313,7 +324,6 @@ export default class Lambder {
|
|
|
313
324
|
let eventRenderContext:LambderRenderContext|null = null;
|
|
314
325
|
|
|
315
326
|
try {
|
|
316
|
-
|
|
317
327
|
let ctx = createContext(event, lambdaContext, this.apiPath);
|
|
318
328
|
eventRenderContext = ctx;
|
|
319
329
|
|
|
@@ -322,7 +332,7 @@ export default class Lambder {
|
|
|
322
332
|
reject:(err: Error)=>void
|
|
323
333
|
)=> {
|
|
324
334
|
try{
|
|
325
|
-
const resolver = this.getResolver(resolve, reject);
|
|
335
|
+
const resolver = this.getResolver(ctx, resolve, reject);
|
|
326
336
|
if(ctx.method === "OPTIONS") return resolver.cors();
|
|
327
337
|
|
|
328
338
|
const firstMatchedAction = this.actionList.find(action => action.conditionFn(ctx));
|
|
@@ -341,12 +351,14 @@ export default class Lambder {
|
|
|
341
351
|
if(hookResponse instanceof Error){ throw hookResponse; }
|
|
342
352
|
response = hookResponse;
|
|
343
353
|
}
|
|
344
|
-
// Apply
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
354
|
+
// Apply setHeader, addHeader values.
|
|
355
|
+
response.multiValueHeaders = response.multiValueHeaders || {};
|
|
356
|
+
for(const header of ctx._otherInternal.setHeaderFnAccumulator){
|
|
357
|
+
response.multiValueHeaders[header.key] = Array.isArray(header.value) ? header.value: [header.value];
|
|
358
|
+
}
|
|
359
|
+
for(const header of ctx._otherInternal.addHeaderFnAccumulator){
|
|
360
|
+
response.multiValueHeaders[header.key] = response.multiValueHeaders[header.key] || [];
|
|
361
|
+
response.multiValueHeaders[header.key].push(header.value);
|
|
350
362
|
}
|
|
351
363
|
resolve(response);
|
|
352
364
|
}else{
|
|
@@ -362,7 +374,12 @@ export default class Lambder {
|
|
|
362
374
|
if(this.globalErrorHandler){
|
|
363
375
|
const wrappedError = err instanceof Error ? err : new Error("Error: " + String(err));
|
|
364
376
|
const responseBuilder = this.getResponseBuilder();
|
|
365
|
-
return this.globalErrorHandler(
|
|
377
|
+
return this.globalErrorHandler(
|
|
378
|
+
wrappedError,
|
|
379
|
+
eventRenderContext,
|
|
380
|
+
responseBuilder,
|
|
381
|
+
eventRenderContext?._otherInternal.logToApiResponseAccumulator
|
|
382
|
+
);
|
|
366
383
|
}
|
|
367
384
|
return { statusCode: 500, body: "Internal Server Error.", }
|
|
368
385
|
|
package/src/LambderCaller.ts
CHANGED
|
@@ -130,6 +130,11 @@ export default class LambderCaller {
|
|
|
130
130
|
activeFetchList: this.fetchTrackerList.filter(v=>!v.done),
|
|
131
131
|
});
|
|
132
132
|
}
|
|
133
|
+
if(data && data.logList?.length){
|
|
134
|
+
for(const record of data.logList){
|
|
135
|
+
console.log("LogToApiResponse:", record);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
133
138
|
if(data && data.versionExpired){
|
|
134
139
|
if(this.versionExpiredHandler){
|
|
135
140
|
await this.versionExpiredHandler();
|
package/src/LambderResolver.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { LambderRenderContext } from "./Lambder.js";
|
|
1
2
|
import LambderResponseBuilder, { LambderResolverResponse } from "./LambderResponseBuilder.js";
|
|
2
3
|
import LambderUtils from "./LambderUtils.js";
|
|
3
4
|
|
|
@@ -24,17 +25,18 @@ export default class LambderResolver extends LambderResponseBuilder {
|
|
|
24
25
|
public die: DieResolverMethods;
|
|
25
26
|
|
|
26
27
|
constructor(
|
|
27
|
-
{ isCorsEnabled, publicPath, apiVersion, lambderUtils, resolve, reject }:
|
|
28
|
+
{ isCorsEnabled, publicPath, apiVersion, lambderUtils, ctx, resolve, reject }:
|
|
28
29
|
{
|
|
29
30
|
isCorsEnabled: boolean,
|
|
30
31
|
publicPath: string,
|
|
31
32
|
apiVersion?: string|null,
|
|
32
|
-
lambderUtils: LambderUtils
|
|
33
|
+
lambderUtils: LambderUtils,
|
|
34
|
+
ctx: LambderRenderContext,
|
|
33
35
|
resolve: (response: LambderResolverResponse) => void,
|
|
34
36
|
reject: (err: Error) => void,
|
|
35
37
|
}
|
|
36
38
|
){
|
|
37
|
-
super({ isCorsEnabled, publicPath, apiVersion, lambderUtils });
|
|
39
|
+
super({ isCorsEnabled, publicPath, apiVersion, lambderUtils, ctx, });
|
|
38
40
|
this.resolve = resolve;
|
|
39
41
|
this.reject = reject;
|
|
40
42
|
|
|
@@ -3,6 +3,7 @@ import * as path from "path";
|
|
|
3
3
|
import ejs from "ejs";
|
|
4
4
|
import mimeTypeResolver from "mime-types";
|
|
5
5
|
import LambderUtils from "./LambderUtils.js";
|
|
6
|
+
import { LambderRenderContext } from "./Lambder.js";
|
|
6
7
|
|
|
7
8
|
const convertToMultiHeader = (
|
|
8
9
|
headers: Record<string, string|string[]> | undefined
|
|
@@ -29,6 +30,7 @@ export type LambderApiResponseConfig = {
|
|
|
29
30
|
notAuthorized?: boolean;
|
|
30
31
|
message?: any;
|
|
31
32
|
errorMessage?: any;
|
|
33
|
+
logList?: any[];
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
|
|
@@ -41,20 +43,23 @@ export default class LambderResponseBuilder {
|
|
|
41
43
|
private publicPath: string;
|
|
42
44
|
private apiVersion: string|null;
|
|
43
45
|
private lambderUtils: LambderUtils;
|
|
46
|
+
private ctx?: LambderRenderContext;
|
|
44
47
|
|
|
45
48
|
constructor(
|
|
46
|
-
{ isCorsEnabled, publicPath, apiVersion, lambderUtils }:
|
|
49
|
+
{ isCorsEnabled, publicPath, apiVersion, lambderUtils, ctx }:
|
|
47
50
|
{
|
|
48
51
|
isCorsEnabled: boolean,
|
|
49
52
|
publicPath: string,
|
|
50
53
|
apiVersion?: string|null,
|
|
51
|
-
lambderUtils: LambderUtils
|
|
54
|
+
lambderUtils: LambderUtils,
|
|
55
|
+
ctx?: LambderRenderContext,
|
|
52
56
|
}
|
|
53
57
|
){
|
|
54
58
|
this.isCorsEnabled = isCorsEnabled;
|
|
55
59
|
this.publicPath = publicPath;
|
|
56
60
|
this.apiVersion = apiVersion ?? null;
|
|
57
61
|
this.lambderUtils = lambderUtils;
|
|
62
|
+
this.ctx = ctx;
|
|
58
63
|
};
|
|
59
64
|
|
|
60
65
|
private readPublicFileSync(filePath: string){
|
|
@@ -73,6 +78,29 @@ export default class LambderResponseBuilder {
|
|
|
73
78
|
return fs.existsSync(absolutePath) && fs.statSync(absolutePath).isFile();
|
|
74
79
|
};
|
|
75
80
|
|
|
81
|
+
addHeader(key: string, value: string){
|
|
82
|
+
if(!this.ctx) throw new Error(".addHeader function is not available within this hook");
|
|
83
|
+
else{
|
|
84
|
+
this.ctx._otherInternal.addHeaderFnAccumulator.push({ key, value });
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
setHeader(key: string, value: string|string[]){
|
|
89
|
+
if(!this.ctx) throw new Error(".setHeader function is not available within this hook");
|
|
90
|
+
else{
|
|
91
|
+
this.ctx._otherInternal.addHeaderFnAccumulator = this.ctx._otherInternal.addHeaderFnAccumulator
|
|
92
|
+
.filter(header=>header.key !== key);
|
|
93
|
+
this.ctx._otherInternal.setHeaderFnAccumulator.push({ key, value });
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
logToApiResponse(input:any){
|
|
98
|
+
if(!this.ctx) throw new Error(".logToResponse function is not available within this hook");
|
|
99
|
+
else{
|
|
100
|
+
this.ctx._otherInternal.logToApiResponseAccumulator.push(input);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
76
104
|
|
|
77
105
|
raw(param: LambderResolverResponse){
|
|
78
106
|
return param;
|
|
@@ -210,13 +238,14 @@ export default class LambderResponseBuilder {
|
|
|
210
238
|
payload: T | null,
|
|
211
239
|
{
|
|
212
240
|
versionExpired, sessionExpired, notAuthorized,
|
|
213
|
-
message
|
|
241
|
+
message, errorMessage, logList,
|
|
214
242
|
}: LambderApiResponseConfig = {
|
|
215
243
|
versionExpired: undefined, sessionExpired: undefined, notAuthorized: undefined,
|
|
216
|
-
message: null, errorMessage: null,
|
|
244
|
+
message: null, errorMessage: null, logList: undefined
|
|
217
245
|
},
|
|
218
246
|
headers?: Record<string, string|string[]>,
|
|
219
247
|
): LambderResolverResponse {
|
|
248
|
+
const finalLogList = logList || this.ctx?._otherInternal?.logToApiResponseAccumulator;
|
|
220
249
|
return this.json({
|
|
221
250
|
apiVersion: this.apiVersion,
|
|
222
251
|
payload,
|
|
@@ -225,6 +254,7 @@ export default class LambderResponseBuilder {
|
|
|
225
254
|
...(notAuthorized ? {notAuthorized} : {}),
|
|
226
255
|
...(message ? {message} : {}),
|
|
227
256
|
...(errorMessage ? {errorMessage} : {}),
|
|
257
|
+
...(finalLogList?.length ? {logList: finalLogList} : {}),
|
|
228
258
|
}, headers);
|
|
229
259
|
};
|
|
230
260
|
|
|
@@ -42,12 +42,8 @@ export default class LambderSessionController {
|
|
|
42
42
|
|
|
43
43
|
async createSession (sessionKey: string, data?: any, ttlInSeconds?: number): Promise<LambderSessionContext> {
|
|
44
44
|
const session = await this.lambderSessionManager.createSession(sessionKey, data, ttlInSeconds);
|
|
45
|
-
this.ctx._otherInternal.
|
|
46
|
-
|
|
47
|
-
`${this.sessionTokenCookieKey}=${session.sessionToken}; Expires=${new Date(session.expiresAt * 1000).toUTCString()}; Path=/; HttpOnly; SameSite=Lax; Secure`,
|
|
48
|
-
`${this.sessionCsrfCookieKey}=${session.csrfToken}; Expires=${new Date(session.expiresAt * 1000).toUTCString()}; Path=/; SameSite=Lax; Secure`,
|
|
49
|
-
],
|
|
50
|
-
};
|
|
45
|
+
this.ctx._otherInternal.addHeaderFnAccumulator.push({ key: "Set-Cookie", value: `${this.sessionTokenCookieKey}=${session.sessionToken}; Expires=${new Date(session.expiresAt * 1000).toUTCString()}; Path=/; HttpOnly; SameSite=Lax; Secure` });
|
|
46
|
+
this.ctx._otherInternal.addHeaderFnAccumulator.push({ key: "Set-Cookie", value: `${this.sessionCsrfCookieKey}=${session.csrfToken}; Expires=${new Date(session.expiresAt * 1000).toUTCString()}; Path=/; SameSite=Lax; Secure` });
|
|
51
47
|
this.ctx.session = session;
|
|
52
48
|
return this.ctx.session;
|
|
53
49
|
};
|
|
@@ -94,24 +90,16 @@ export default class LambderSessionController {
|
|
|
94
90
|
async endSession (){
|
|
95
91
|
if(!this.ctx.session) throw new Error("Session not found.");
|
|
96
92
|
await this.lambderSessionManager.deleteSession(this.ctx.session);
|
|
97
|
-
this.ctx._otherInternal.
|
|
98
|
-
|
|
99
|
-
`${this.sessionTokenCookieKey}=0; Expires=${new Date(Date.now() - 100000).toUTCString()}; Path=/; HttpOnly; SameSite=Lax; Secure`,
|
|
100
|
-
`${this.sessionCsrfCookieKey}=0; Expires=${new Date(Date.now() - 100000).toUTCString()}; Path=/; SameSite=Lax; Secure`,
|
|
101
|
-
],
|
|
102
|
-
};
|
|
93
|
+
this.ctx._otherInternal.addHeaderFnAccumulator.push({ key: "Set-Cookie", value: `${this.sessionTokenCookieKey}=0; Expires=${new Date(Date.now() - 100000).toUTCString()}; Path=/; HttpOnly; SameSite=Lax; Secure` });
|
|
94
|
+
this.ctx._otherInternal.addHeaderFnAccumulator.push({ key: "Set-Cookie", value: `${this.sessionCsrfCookieKey}=0; Expires=${new Date(Date.now() - 100000).toUTCString()}; Path=/; SameSite=Lax; Secure` });
|
|
103
95
|
this.ctx.session = null
|
|
104
96
|
};
|
|
105
97
|
|
|
106
98
|
async endSessionAll (){
|
|
107
99
|
if(!this.ctx.session) throw new Error("Session not found.");
|
|
108
100
|
await this.lambderSessionManager.deleteSessionAll(this.ctx.session);
|
|
109
|
-
this.ctx._otherInternal.
|
|
110
|
-
|
|
111
|
-
`${this.sessionTokenCookieKey}=0; Expires=${new Date(Date.now() - 100000).toUTCString()}; Path=/; HttpOnly; SameSite=Lax; Secure`,
|
|
112
|
-
`${this.sessionCsrfCookieKey}=0; Expires=${new Date(Date.now() - 100000).toUTCString()}; Path=/; SameSite=Lax; Secure`,
|
|
113
|
-
],
|
|
114
|
-
};
|
|
101
|
+
this.ctx._otherInternal.addHeaderFnAccumulator.push({ key: "Set-Cookie", value: `${this.sessionTokenCookieKey}=0; Expires=${new Date(Date.now() - 100000).toUTCString()}; Path=/; HttpOnly; SameSite=Lax; Secure` });
|
|
102
|
+
this.ctx._otherInternal.addHeaderFnAccumulator.push({ key: "Set-Cookie", value: `${this.sessionCsrfCookieKey}=0; Expires=${new Date(Date.now() - 100000).toUTCString()}; Path=/; SameSite=Lax; Secure` });
|
|
115
103
|
this.ctx.session = null
|
|
116
104
|
};
|
|
117
105
|
};
|
/package/{deploy.sh → deploy}
RENAMED
|
File without changes
|