lambder 2.0.5 → 2.0.8

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,43 +1,12 @@
1
1
  import { z } from "zod";
2
- import type { APIGatewayProxyEvent, APIGatewayProxyEventHeaders, Context } from "aws-lambda";
2
+ import type { APIGatewayProxyEvent, Context } from "aws-lambda";
3
3
  import LambderResolver from "./LambderResolver.js";
4
4
  import LambderResponseBuilder, { LambderResolverResponse } from "./LambderResponseBuilder.js";
5
5
  import LambderUtils from "./LambderUtils.js";
6
- import { type LambderSessionContext } from "./LambderSessionManager.js";
7
6
  import LambderSessionController from "./LambderSessionController.js";
8
7
  import type { MergeContract } from "./LambderApiContract.js";
8
+ import { type LambderRenderContext, type LambderSessionRenderContext } from "./LambderContext.js";
9
9
  type Path = `/${string}`;
10
- export type LambderRenderContext<TApiPayload = any> = {
11
- host: string;
12
- path: string;
13
- pathParams: Record<string, any> | null;
14
- method: string;
15
- get: Record<string, any>;
16
- post: Record<string, any>;
17
- cookie: Record<string, any>;
18
- session: null;
19
- apiName: string;
20
- apiPayload: TApiPayload;
21
- headers: APIGatewayProxyEventHeaders;
22
- event: APIGatewayProxyEvent;
23
- lambdaContext: Context;
24
- _otherInternal: {
25
- isApiCall: boolean;
26
- requestVersion: string | null;
27
- setHeaderFnAccumulator: {
28
- key: string;
29
- value: string | string[];
30
- }[];
31
- addHeaderFnAccumulator: {
32
- key: string;
33
- value: string;
34
- }[];
35
- logToApiResponseAccumulator: any[];
36
- };
37
- };
38
- export type LambderSessionRenderContext<TApiPayload = any, SessionData = any> = Omit<LambderRenderContext<TApiPayload>, 'session'> & {
39
- session: LambderSessionContext<SessionData>;
40
- };
41
10
  type ConditionFunction = (ctx: LambderRenderContext<any>) => boolean;
42
11
  type ActionFunction = (ctx: LambderRenderContext<any>, resolver: LambderResolver) => LambderResolverResponse | Promise<LambderResolverResponse>;
43
12
  type SessionActionFunction<SessionData = any> = (ctx: LambderSessionRenderContext<any, SessionData>, resolver: LambderResolver) => LambderResolverResponse | Promise<LambderResolverResponse>;
@@ -48,7 +17,7 @@ type HookFallbackFunction = (ctx: LambderRenderContext<any>, resolver: LambderRe
48
17
  type GlobalErrorHandlerFunction = (err: Error, ctx: LambderRenderContext<any> | null, response: LambderResponseBuilder, logListToApiResponse?: any[]) => LambderResolverResponse | Promise<LambderResolverResponse>;
49
18
  type RouteFallbackHandlerFunction = (ctx: LambderRenderContext<any>, resolver: LambderResolver) => LambderResolverResponse;
50
19
  type ApiFallbackHandlerFunction = (ctx: LambderRenderContext<any>, resolver: LambderResolver) => LambderResolverResponse;
51
- export declare const createContext: (event: APIGatewayProxyEvent, lambdaContext: Context, apiPath: string) => LambderRenderContext<any>;
20
+ type ApiInputValidationErrorHandlerFunction = (ctx: LambderRenderContext<any>, resolver: LambderResolver, zodError: z.ZodError) => LambderResolverResponse | Promise<LambderResolverResponse>;
52
21
  /**
53
22
  * Main Lambder class for building type-safe serverless APIs
54
23
  *
@@ -86,6 +55,7 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
86
55
  private globalErrorHandler;
87
56
  private routeFallbackHandler;
88
57
  private apiFallbackHandler;
58
+ private apiInputValidationErrorHandler;
89
59
  utils: LambderUtils;
90
60
  private lambderSessionManager?;
91
61
  private sessionTokenCookieKey;
@@ -109,6 +79,7 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
109
79
  setSessionCookieKey(sessionTokenCookieKey: string, sessionCsrfCookieKey: string): this;
110
80
  setRouteFallbackHandler(routeFallbackHandler: RouteFallbackHandlerFunction): this;
111
81
  setApiFallbackHandler(apiFallbackHandler: ApiFallbackHandlerFunction): this;
82
+ setApiInputValidationErrorHandler(apiInputValidationErrorHandler: ApiInputValidationErrorHandlerFunction): this;
112
83
  setGlobalErrorHandler(globalErrorHandler: GlobalErrorHandlerFunction): this;
113
84
  private getPatternMatch;
114
85
  private testPatternMatch;
package/dist/Lambder.js CHANGED
@@ -1,53 +1,10 @@
1
- import cookieParser from "cookie";
2
1
  import { match } from "path-to-regexp";
3
2
  import LambderResolver from "./LambderResolver.js";
4
3
  import LambderResponseBuilder from "./LambderResponseBuilder.js";
5
4
  import LambderUtils from "./LambderUtils.js";
6
5
  import LambderSessionManager from "./LambderSessionManager.js";
7
6
  import LambderSessionController from "./LambderSessionController.js";
8
- export const createContext = (event, lambdaContext, apiPath) => {
9
- const host = event.headers.Host || event.headers.host || "";
10
- const path = event.path;
11
- const pathParams = null;
12
- const get = event.queryStringParameters || {};
13
- const method = event.httpMethod;
14
- const cookie = cookieParser.parse(event.headers.Cookie || event.headers.cookie || "");
15
- const headers = event.headers;
16
- // Decode body for the post
17
- let post = {};
18
- try {
19
- const decodedBody = event.isBase64Encoded ? (event.body ? Buffer.from(event.body, "base64").toString() : "{}") : (event.body || "{}");
20
- try {
21
- post = JSON.parse(decodedBody) || {};
22
- }
23
- catch (e) {
24
- const params = new URLSearchParams(decodedBody);
25
- post = {};
26
- for (const [key, value] of params.entries()) {
27
- post[key] = value;
28
- }
29
- }
30
- }
31
- catch (e) { }
32
- // Parse api variables
33
- const isApiCall = method === "POST" && apiPath && path === apiPath && post.apiName;
34
- const apiName = isApiCall ? post.apiName : null;
35
- const apiPayload = isApiCall ? post.payload : null;
36
- const requestVersion = isApiCall ? post.version : null;
37
- return {
38
- host, path, pathParams, method,
39
- get, post, cookie, event,
40
- session: null,
41
- apiName, apiPayload,
42
- headers, lambdaContext,
43
- _otherInternal: {
44
- isApiCall, requestVersion,
45
- setHeaderFnAccumulator: [],
46
- addHeaderFnAccumulator: [],
47
- logToApiResponseAccumulator: [],
48
- }
49
- };
50
- };
7
+ import { createContext } from "./LambderContext.js";
51
8
  /**
52
9
  * Main Lambder class for building type-safe serverless APIs
53
10
  *
@@ -85,6 +42,7 @@ export default class Lambder {
85
42
  globalErrorHandler = null;
86
43
  routeFallbackHandler = null;
87
44
  apiFallbackHandler = null;
45
+ apiInputValidationErrorHandler = null;
88
46
  utils;
89
47
  lambderSessionManager;
90
48
  sessionTokenCookieKey = "LMDRSESSIONTKID";
@@ -125,6 +83,10 @@ export default class Lambder {
125
83
  this.apiFallbackHandler = apiFallbackHandler;
126
84
  return this;
127
85
  }
86
+ setApiInputValidationErrorHandler(apiInputValidationErrorHandler) {
87
+ this.apiInputValidationErrorHandler = apiInputValidationErrorHandler;
88
+ return this;
89
+ }
128
90
  setGlobalErrorHandler(globalErrorHandler) {
129
91
  this.globalErrorHandler = globalErrorHandler;
130
92
  return this;
@@ -211,6 +173,9 @@ export default class Lambder {
211
173
  // Validate Input
212
174
  const inputResult = schema.input.safeParse(ctx.apiPayload);
213
175
  if (!inputResult.success) {
176
+ if (this.apiInputValidationErrorHandler) {
177
+ return await this.apiInputValidationErrorHandler(ctx, resolver, inputResult.error);
178
+ }
214
179
  return resolver.raw({
215
180
  statusCode: 400,
216
181
  body: JSON.stringify({ error: "Input validation failed", zodError: inputResult.error }),
@@ -237,6 +202,9 @@ export default class Lambder {
237
202
  // Validate Input
238
203
  const inputResult = schema.input.safeParse(ctx.apiPayload);
239
204
  if (!inputResult.success) {
205
+ if (this.apiInputValidationErrorHandler) {
206
+ return await this.apiInputValidationErrorHandler(ctx, resolver, inputResult.error);
207
+ }
240
208
  return resolver.raw({
241
209
  statusCode: 400,
242
210
  body: JSON.stringify({ error: "Input validation failed", zodError: inputResult.error }),
@@ -0,0 +1,34 @@
1
+ import type { APIGatewayProxyEvent, APIGatewayProxyEventHeaders, Context } from "aws-lambda";
2
+ import type { LambderSessionContext } from "./LambderSessionManager.js";
3
+ export type LambderRenderContext<TApiPayload = any> = {
4
+ host: string;
5
+ path: string;
6
+ pathParams: Record<string, any> | null;
7
+ method: string;
8
+ get: Record<string, any>;
9
+ post: Record<string, any>;
10
+ cookie: Record<string, any>;
11
+ session: null;
12
+ apiName: string;
13
+ apiPayload: TApiPayload;
14
+ headers: APIGatewayProxyEventHeaders;
15
+ event: APIGatewayProxyEvent;
16
+ lambdaContext: Context;
17
+ _otherInternal: {
18
+ isApiCall: boolean;
19
+ requestVersion: string | null;
20
+ setHeaderFnAccumulator: {
21
+ key: string;
22
+ value: string | string[];
23
+ }[];
24
+ addHeaderFnAccumulator: {
25
+ key: string;
26
+ value: string;
27
+ }[];
28
+ logToApiResponseAccumulator: any[];
29
+ };
30
+ };
31
+ export type LambderSessionRenderContext<TApiPayload = any, SessionData = any> = Omit<LambderRenderContext<TApiPayload>, 'session'> & {
32
+ session: LambderSessionContext<SessionData>;
33
+ };
34
+ export declare const createContext: (event: APIGatewayProxyEvent, lambdaContext: Context, apiPath: string) => LambderRenderContext<any>;
@@ -0,0 +1,44 @@
1
+ import cookieParser from "cookie";
2
+ export const createContext = (event, lambdaContext, apiPath) => {
3
+ const host = event.headers.Host || event.headers.host || "";
4
+ const path = event.path;
5
+ const pathParams = null;
6
+ const get = event.queryStringParameters || {};
7
+ const method = event.httpMethod;
8
+ const cookie = cookieParser.parse(event.headers.Cookie || event.headers.cookie || "");
9
+ const headers = event.headers;
10
+ // Decode body for the post
11
+ let post = {};
12
+ try {
13
+ const decodedBody = event.isBase64Encoded ? (event.body ? Buffer.from(event.body, "base64").toString() : "{}") : (event.body || "{}");
14
+ try {
15
+ post = JSON.parse(decodedBody) || {};
16
+ }
17
+ catch (e) {
18
+ const params = new URLSearchParams(decodedBody);
19
+ post = {};
20
+ for (const [key, value] of params.entries()) {
21
+ post[key] = value;
22
+ }
23
+ }
24
+ }
25
+ catch (e) { }
26
+ // Parse api variables
27
+ const isApiCall = method === "POST" && apiPath && path === apiPath && post.apiName;
28
+ const apiName = isApiCall ? post.apiName : null;
29
+ const apiPayload = isApiCall ? post.payload : null;
30
+ const requestVersion = isApiCall ? post.version : null;
31
+ return {
32
+ host, path, pathParams, method,
33
+ get, post, cookie, event,
34
+ session: null,
35
+ apiName, apiPayload,
36
+ headers, lambdaContext,
37
+ _otherInternal: {
38
+ isApiCall, requestVersion,
39
+ setHeaderFnAccumulator: [],
40
+ addHeaderFnAccumulator: [],
41
+ logToApiResponseAccumulator: [],
42
+ }
43
+ };
44
+ };
@@ -1,4 +1,4 @@
1
- import type { LambderRenderContext } from "./Lambder.js";
1
+ import type { LambderRenderContext } from "./LambderContext.js";
2
2
  import LambderResponseBuilder, { LambderResolverResponse } from "./LambderResponseBuilder.js";
3
3
  import LambderUtils from "./LambderUtils.js";
4
4
  type MethodType<T, M extends keyof T> = T[M] extends (...args: any[]) => any ? T[M] : never;
@@ -1,5 +1,5 @@
1
1
  import LambderUtils from "./LambderUtils.js";
2
- import { LambderRenderContext } from "./Lambder.js";
2
+ import { LambderRenderContext } from "./LambderContext.js";
3
3
  export type LambderResolverResponse = {
4
4
  statusCode: number;
5
5
  multiValueHeaders?: Record<string, string[]>;
@@ -68,7 +68,7 @@ export default class LambderResponseBuilder {
68
68
  throw new Error(".setHeader function is not available within this hook");
69
69
  else {
70
70
  this.ctx._otherInternal.addHeaderFnAccumulator = this.ctx._otherInternal.addHeaderFnAccumulator
71
- .filter(header => header.key !== key);
71
+ .filter((header) => header.key !== key);
72
72
  this.ctx._otherInternal.setHeaderFnAccumulator.push({ key, value });
73
73
  }
74
74
  }
@@ -154,10 +154,12 @@ export default class LambderResponseBuilder {
154
154
  ;
155
155
  async file(filePath, headers, fallbackFilePath) {
156
156
  const doesFileExist = await this.checkPublicFileExist(filePath);
157
- if (!doesFileExist && fallbackFilePath) {
158
- const doesFallbackExist = await this.checkPublicFileExist(fallbackFilePath);
159
- if (doesFallbackExist) {
160
- return await this.file(fallbackFilePath, headers);
157
+ if (!doesFileExist) {
158
+ if (fallbackFilePath) {
159
+ const doesFallbackExist = await this.checkPublicFileExist(fallbackFilePath);
160
+ if (doesFallbackExist) {
161
+ return await this.file(fallbackFilePath, headers);
162
+ }
161
163
  }
162
164
  return this.json({ error: "File not found: " + filePath });
163
165
  }
@@ -1,4 +1,4 @@
1
- import { LambderRenderContext, LambderSessionRenderContext } from "./Lambder.js";
1
+ import { LambderRenderContext, LambderSessionRenderContext } from "./LambderContext.js";
2
2
  import type LambderSessionManager from "./LambderSessionManager.js";
3
3
  import type { LambderSessionContext } from "./LambderSessionManager.js";
4
4
  export default class LambderSessionController<TSessionData = any> {
package/dist/index.d.ts CHANGED
@@ -6,3 +6,5 @@ export { default as LambderResolver } from "./LambderResolver.js";
6
6
  export { default as LambderSessionManager } from "./LambderSessionManager.js";
7
7
  export { default as LambderMSW } from "./LambderMSW.js";
8
8
  export { type ApiContractShape, } from "./LambderApiContract.js";
9
+ export type { LambderRenderContext, LambderSessionRenderContext } from "./LambderContext.js";
10
+ export { createContext } from "./LambderContext.js";
package/dist/index.js CHANGED
@@ -5,3 +5,4 @@ export { default as LambderResponseBuilder } from "./LambderResponseBuilder.js";
5
5
  export { default as LambderResolver } from "./LambderResolver.js";
6
6
  export { default as LambderSessionManager } from "./LambderSessionManager.js";
7
7
  export { default as LambderMSW } from "./LambderMSW.js";
8
+ export { createContext } from "./LambderContext.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lambder",
3
- "version": "2.0.5",
3
+ "version": "2.0.8",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/Lambder.ts CHANGED
@@ -1,44 +1,17 @@
1
- import cookieParser from "cookie";
2
1
  import { match } from "path-to-regexp";
3
2
  import { z } from "zod";
4
3
 
5
- import type { APIGatewayProxyEvent, APIGatewayProxyEventHeaders, Context } from "aws-lambda";
4
+ import type { APIGatewayProxyEvent, Context } from "aws-lambda";
6
5
  import LambderResolver from "./LambderResolver.js";
7
6
  import LambderResponseBuilder, { LambderResolverResponse } from "./LambderResponseBuilder.js";
8
7
  import LambderUtils from "./LambderUtils.js";
9
- import LambderSessionManager, { type LambderSessionContext } from "./LambderSessionManager.js";
8
+ import LambderSessionManager from "./LambderSessionManager.js";
10
9
  import LambderSessionController from "./LambderSessionController.js";
11
10
  import type { MergeContract } from "./LambderApiContract.js";
11
+ import { createContext, type LambderRenderContext, type LambderSessionRenderContext } from "./LambderContext.js";
12
12
 
13
13
  type Path = `/${string}`;
14
14
 
15
- export type LambderRenderContext<TApiPayload = any> = {
16
- host: string;
17
- path: string;
18
- pathParams: Record<string, any> | null;
19
- method: string;
20
- get: Record<string, any>;
21
- post: Record<string, any>;
22
- cookie: Record<string, any>;
23
- session: null;
24
- apiName: string;
25
- apiPayload: TApiPayload;
26
- headers: APIGatewayProxyEventHeaders;
27
- event: APIGatewayProxyEvent;
28
- lambdaContext: Context;
29
- _otherInternal: {
30
- isApiCall: boolean,
31
- requestVersion: string|null;
32
- setHeaderFnAccumulator: { key:string, value:string|string[] }[];
33
- addHeaderFnAccumulator: { key:string, value:string }[];
34
- logToApiResponseAccumulator: any[];
35
- };
36
- };
37
-
38
- export type LambderSessionRenderContext<
39
- TApiPayload = any, SessionData = any
40
- > = Omit<LambderRenderContext<TApiPayload>, 'session'> & { session: LambderSessionContext<SessionData> };
41
-
42
15
  type ConditionFunction = (ctx: LambderRenderContext<any>) => boolean;
43
16
  type ActionFunction = (ctx: LambderRenderContext<any>, resolver: LambderResolver) => LambderResolverResponse|Promise<LambderResolverResponse>;
44
17
  type SessionActionFunction<SessionData = any> = (ctx: LambderSessionRenderContext<any, SessionData>, resolver: LambderResolver) => LambderResolverResponse|Promise<LambderResolverResponse>;
@@ -54,55 +27,7 @@ type HookFallbackFunction = (ctx: LambderRenderContext<any>, resolver: LambderRe
54
27
  type GlobalErrorHandlerFunction = (err: Error, ctx: LambderRenderContext<any>|null, response: LambderResponseBuilder, logListToApiResponse?: any[]) => LambderResolverResponse|Promise<LambderResolverResponse>;
55
28
  type RouteFallbackHandlerFunction = (ctx:LambderRenderContext<any>, resolver: LambderResolver) => LambderResolverResponse;
56
29
  type ApiFallbackHandlerFunction = (ctx:LambderRenderContext<any>, resolver: LambderResolver) => LambderResolverResponse;
57
-
58
-
59
- export const createContext = (
60
- event: APIGatewayProxyEvent,
61
- lambdaContext: Context,
62
- apiPath: string,
63
- ):LambderRenderContext<any> => {
64
- const host = event.headers.Host || event.headers.host || "";
65
- const path = event.path;
66
- const pathParams = null;
67
- const get: Record<string, any> = event.queryStringParameters || {};
68
- const method = event.httpMethod;
69
- const cookie = cookieParser.parse(event.headers.Cookie || event.headers.cookie || "");
70
- const headers = event.headers;
71
-
72
- // Decode body for the post
73
- let post: Record<string, any> = {};
74
- try {
75
- const decodedBody = event.isBase64Encoded ? ( event.body ? Buffer.from(event.body,"base64").toString() : "{}" ) : ( event.body || "{}" );
76
- try { post = JSON.parse(decodedBody) || {}; }
77
- catch(e){
78
- const params = new URLSearchParams(decodedBody);
79
- post = {};
80
- for(const [key, value] of params.entries()){
81
- post[key] = value;
82
- }
83
- }
84
- }catch(e){}
85
- // Parse api variables
86
-
87
- const isApiCall = method === "POST" && apiPath && path === apiPath && post.apiName;
88
- const apiName:string = isApiCall ? post.apiName : null;
89
- const apiPayload:string = isApiCall ? post.payload : null;
90
- const requestVersion:string = isApiCall ? post.version : null;
91
-
92
- return {
93
- host, path, pathParams, method,
94
- get, post, cookie, event,
95
- session: null,
96
- apiName, apiPayload,
97
- headers, lambdaContext,
98
- _otherInternal: {
99
- isApiCall, requestVersion,
100
- setHeaderFnAccumulator: [],
101
- addHeaderFnAccumulator: [],
102
- logToApiResponseAccumulator: [],
103
- }
104
- };
105
- }
30
+ type ApiInputValidationErrorHandlerFunction = (ctx: LambderRenderContext<any>, resolver: LambderResolver, zodError: z.ZodError) => LambderResolverResponse|Promise<LambderResolverResponse>;
106
31
 
107
32
  /**
108
33
  * Main Lambder class for building type-safe serverless APIs
@@ -147,6 +72,7 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
147
72
  private globalErrorHandler: GlobalErrorHandlerFunction|null = null;
148
73
  private routeFallbackHandler: RouteFallbackHandlerFunction|null = null;
149
74
  private apiFallbackHandler: ApiFallbackHandlerFunction|null = null;
75
+ private apiInputValidationErrorHandler: ApiInputValidationErrorHandlerFunction|null = null;
150
76
 
151
77
  public utils: LambderUtils;
152
78
 
@@ -202,6 +128,10 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
202
128
  this.apiFallbackHandler = apiFallbackHandler;
203
129
  return this;
204
130
  }
131
+ setApiInputValidationErrorHandler(apiInputValidationErrorHandler: ApiInputValidationErrorHandlerFunction): this {
132
+ this.apiInputValidationErrorHandler = apiInputValidationErrorHandler;
133
+ return this;
134
+ }
205
135
  setGlobalErrorHandler(globalErrorHandler: GlobalErrorHandlerFunction): this {
206
136
  this.globalErrorHandler = globalErrorHandler;
207
137
  return this;
@@ -308,6 +238,9 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
308
238
  // Validate Input
309
239
  const inputResult = schema.input.safeParse(ctx.apiPayload);
310
240
  if (!inputResult.success) {
241
+ if (this.apiInputValidationErrorHandler) {
242
+ return await this.apiInputValidationErrorHandler(ctx, resolver, inputResult.error);
243
+ }
311
244
  return resolver.raw({
312
245
  statusCode: 400,
313
246
  body: JSON.stringify({ error: "Input validation failed", zodError: inputResult.error }),
@@ -346,6 +279,9 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
346
279
  // Validate Input
347
280
  const inputResult = schema.input.safeParse(ctx.apiPayload);
348
281
  if (!inputResult.success) {
282
+ if (this.apiInputValidationErrorHandler) {
283
+ return await this.apiInputValidationErrorHandler(ctx, resolver, inputResult.error);
284
+ }
349
285
  return resolver.raw({
350
286
  statusCode: 400,
351
287
  body: JSON.stringify({ error: "Input validation failed", zodError: inputResult.error }),
@@ -0,0 +1,78 @@
1
+ import cookieParser from "cookie";
2
+ import type { APIGatewayProxyEvent, APIGatewayProxyEventHeaders, Context } from "aws-lambda";
3
+ import type { LambderSessionContext } from "./LambderSessionManager.js";
4
+
5
+ export type LambderRenderContext<TApiPayload = any> = {
6
+ host: string;
7
+ path: string;
8
+ pathParams: Record<string, any> | null;
9
+ method: string;
10
+ get: Record<string, any>;
11
+ post: Record<string, any>;
12
+ cookie: Record<string, any>;
13
+ session: null;
14
+ apiName: string;
15
+ apiPayload: TApiPayload;
16
+ headers: APIGatewayProxyEventHeaders;
17
+ event: APIGatewayProxyEvent;
18
+ lambdaContext: Context;
19
+ _otherInternal: {
20
+ isApiCall: boolean,
21
+ requestVersion: string|null;
22
+ setHeaderFnAccumulator: { key:string, value:string|string[] }[];
23
+ addHeaderFnAccumulator: { key:string, value:string }[];
24
+ logToApiResponseAccumulator: any[];
25
+ };
26
+ };
27
+
28
+ export type LambderSessionRenderContext<
29
+ TApiPayload = any, SessionData = any
30
+ > = Omit<LambderRenderContext<TApiPayload>, 'session'> & { session: LambderSessionContext<SessionData> };
31
+
32
+ export const createContext = (
33
+ event: APIGatewayProxyEvent,
34
+ lambdaContext: Context,
35
+ apiPath: string,
36
+ ):LambderRenderContext<any> => {
37
+ const host = event.headers.Host || event.headers.host || "";
38
+ const path = event.path;
39
+ const pathParams = null;
40
+ const get: Record<string, any> = event.queryStringParameters || {};
41
+ const method = event.httpMethod;
42
+ const cookie = cookieParser.parse(event.headers.Cookie || event.headers.cookie || "");
43
+ const headers = event.headers;
44
+
45
+ // Decode body for the post
46
+ let post: Record<string, any> = {};
47
+ try {
48
+ const decodedBody = event.isBase64Encoded ? ( event.body ? Buffer.from(event.body,"base64").toString() : "{}" ) : ( event.body || "{}" );
49
+ try { post = JSON.parse(decodedBody) || {}; }
50
+ catch(e){
51
+ const params = new URLSearchParams(decodedBody);
52
+ post = {};
53
+ for(const [key, value] of params.entries()){
54
+ post[key] = value;
55
+ }
56
+ }
57
+ }catch(e){}
58
+ // Parse api variables
59
+
60
+ const isApiCall = method === "POST" && apiPath && path === apiPath && post.apiName;
61
+ const apiName:string = isApiCall ? post.apiName : null;
62
+ const apiPayload:string = isApiCall ? post.payload : null;
63
+ const requestVersion:string = isApiCall ? post.version : null;
64
+
65
+ return {
66
+ host, path, pathParams, method,
67
+ get, post, cookie, event,
68
+ session: null,
69
+ apiName, apiPayload,
70
+ headers, lambdaContext,
71
+ _otherInternal: {
72
+ isApiCall, requestVersion,
73
+ setHeaderFnAccumulator: [],
74
+ addHeaderFnAccumulator: [],
75
+ logToApiResponseAccumulator: [],
76
+ }
77
+ };
78
+ }
@@ -1,4 +1,4 @@
1
- import type { LambderRenderContext } from "./Lambder.js";
1
+ import type { LambderRenderContext } from "./LambderContext.js";
2
2
  import LambderResponseBuilder, { LambderResolverResponse } from "./LambderResponseBuilder.js";
3
3
  import LambderUtils from "./LambderUtils.js";
4
4
 
@@ -1,6 +1,6 @@
1
1
  import mimeTypeResolver from "mime-types";
2
2
  import LambderUtils from "./LambderUtils.js";
3
- import { LambderRenderContext } from "./Lambder.js";
3
+ import { LambderRenderContext } from "./LambderContext.js";
4
4
  import { getFS, getPath } from "./node-polyfills.js";
5
5
 
6
6
  const convertToMultiHeader = (
@@ -102,7 +102,7 @@ export default class LambderResponseBuilder<TResponse = any> {
102
102
  if(!this.ctx) throw new Error(".setHeader function is not available within this hook");
103
103
  else{
104
104
  this.ctx._otherInternal.addHeaderFnAccumulator = this.ctx._otherInternal.addHeaderFnAccumulator
105
- .filter(header=>header.key !== key);
105
+ .filter((header: { key: string, value: string }) => header.key !== key);
106
106
  this.ctx._otherInternal.setHeaderFnAccumulator.push({ key, value });
107
107
  }
108
108
  };
@@ -211,10 +211,12 @@ export default class LambderResponseBuilder<TResponse = any> {
211
211
  fallbackFilePath?: string,
212
212
  ):Promise<LambderResolverResponse>{
213
213
  const doesFileExist = await this.checkPublicFileExist(filePath);
214
- if(!doesFileExist && fallbackFilePath){
215
- const doesFallbackExist = await this.checkPublicFileExist(fallbackFilePath);
216
- if(doesFallbackExist){
217
- return await this.file(fallbackFilePath, headers);
214
+ if(!doesFileExist){
215
+ if(fallbackFilePath){
216
+ const doesFallbackExist = await this.checkPublicFileExist(fallbackFilePath);
217
+ if(doesFallbackExist){
218
+ return await this.file(fallbackFilePath, headers);
219
+ }
218
220
  }
219
221
  return this.json({ error: "File not found: " + filePath })
220
222
  }
@@ -1,4 +1,4 @@
1
- import { LambderRenderContext, LambderSessionRenderContext } from "./Lambder.js";
1
+ import { LambderRenderContext, LambderSessionRenderContext } from "./LambderContext.js";
2
2
  import type LambderSessionManager from "./LambderSessionManager.js";
3
3
  import type { LambderSessionContext } from "./LambderSessionManager.js";
4
4
 
package/src/index.ts CHANGED
@@ -11,3 +11,7 @@ export { default as LambderMSW } from "./LambderMSW.js";
11
11
  export {
12
12
  type ApiContractShape,
13
13
  } from "./LambderApiContract.js";
14
+
15
+ // Context types and utilities
16
+ export type { LambderRenderContext, LambderSessionRenderContext } from "./LambderContext.js";
17
+ export { createContext } from "./LambderContext.js";