@noony-serverless/core 0.1.1 → 0.2.0
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/build/core/core.d.ts +16 -48
- package/build/core/core.js +2 -61
- package/build/core/handler.d.ts +37 -16
- package/build/core/handler.js +131 -42
- package/build/core/index.d.ts +0 -1
- package/build/core/index.js +0 -1
- package/build/middlewares/ConsolidatedValidationMiddleware.d.ts +126 -0
- package/build/middlewares/ConsolidatedValidationMiddleware.js +330 -0
- package/build/middlewares/ProcessingMiddleware.d.ts +138 -0
- package/build/middlewares/ProcessingMiddleware.js +425 -0
- package/build/middlewares/SecurityMiddleware.d.ts +157 -0
- package/build/middlewares/SecurityMiddleware.js +307 -0
- package/build/middlewares/authenticationMiddleware.d.ts +379 -0
- package/build/middlewares/authenticationMiddleware.js +216 -0
- package/build/middlewares/bodyParserMiddleware.d.ts +99 -0
- package/build/middlewares/bodyParserMiddleware.js +99 -0
- package/build/middlewares/bodyValidationMiddleware.d.ts +69 -3
- package/build/middlewares/bodyValidationMiddleware.js +68 -2
- package/build/middlewares/dependencyInjectionMiddleware.d.ts +238 -0
- package/build/middlewares/dependencyInjectionMiddleware.js +238 -0
- package/build/middlewares/errorHandlerMiddleware.d.ts +94 -0
- package/build/middlewares/errorHandlerMiddleware.js +105 -0
- package/build/middlewares/guards/RouteGuards.d.ts +476 -21
- package/build/middlewares/guards/RouteGuards.js +418 -21
- package/build/middlewares/guards/adapters/CustomTokenVerificationPortAdapter.d.ts +271 -0
- package/build/middlewares/guards/adapters/CustomTokenVerificationPortAdapter.js +301 -0
- package/build/middlewares/guards/cache/CacheAdapter.d.ts +369 -28
- package/build/middlewares/guards/cache/CacheAdapter.js +124 -5
- package/build/middlewares/guards/cache/MemoryCacheAdapter.d.ts +113 -4
- package/build/middlewares/guards/cache/MemoryCacheAdapter.js +113 -4
- package/build/middlewares/guards/config/GuardConfiguration.d.ts +568 -18
- package/build/middlewares/guards/config/GuardConfiguration.js +266 -10
- package/build/middlewares/guards/guards/FastAuthGuard.d.ts +5 -5
- package/build/middlewares/guards/guards/PermissionGuardFactory.d.ts +5 -13
- package/build/middlewares/guards/guards/PermissionGuardFactory.js +4 -4
- package/build/middlewares/guards/index.d.ts +43 -1
- package/build/middlewares/guards/index.js +46 -1
- package/build/middlewares/guards/resolvers/ExpressionPermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/resolvers/ExpressionPermissionResolver.js +1 -1
- package/build/middlewares/guards/resolvers/PermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/resolvers/PlainPermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/resolvers/WildcardPermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/services/FastUserContextService.d.ts +20 -33
- package/build/middlewares/guards/services/FastUserContextService.js +19 -5
- package/build/middlewares/headerVariablesMiddleware.d.ts +118 -0
- package/build/middlewares/headerVariablesMiddleware.js +118 -0
- package/build/middlewares/httpAttributesMiddleware.d.ts +235 -0
- package/build/middlewares/httpAttributesMiddleware.js +236 -1
- package/build/middlewares/index.d.ts +3 -1
- package/build/middlewares/index.js +6 -1
- package/build/middlewares/queryParametersMiddleware.d.ts +105 -0
- package/build/middlewares/queryParametersMiddleware.js +105 -0
- package/build/middlewares/rateLimitingMiddleware.d.ts +601 -9
- package/build/middlewares/rateLimitingMiddleware.js +623 -11
- package/build/middlewares/responseWrapperMiddleware.d.ts +170 -1
- package/build/middlewares/responseWrapperMiddleware.js +170 -1
- package/build/middlewares/securityAuditMiddleware.js +5 -5
- package/package.json +11 -9
- package/build/core/containerPool.d.ts +0 -44
- package/build/core/containerPool.js +0 -103
- package/build/middlewares/validationMiddleware.d.ts +0 -9
- package/build/middlewares/validationMiddleware.js +0 -40
|
@@ -1,11 +1,180 @@
|
|
|
1
1
|
import { BaseMiddleware } from '../core/handler';
|
|
2
2
|
import { Context } from '../core/core';
|
|
3
|
+
/**
|
|
4
|
+
* Middleware class that wraps response data in a standardized format.
|
|
5
|
+
* Automatically wraps the response with success flag, payload, and timestamp.
|
|
6
|
+
*
|
|
7
|
+
* @template T - The type of response data being wrapped
|
|
8
|
+
* @implements {BaseMiddleware}
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* Basic response wrapping:
|
|
12
|
+
* ```typescript
|
|
13
|
+
* import { Handler, ResponseWrapperMiddleware, setResponseData } from '@noony-serverless/core';
|
|
14
|
+
*
|
|
15
|
+
* interface UserResponse {
|
|
16
|
+
* id: string;
|
|
17
|
+
* name: string;
|
|
18
|
+
* email: string;
|
|
19
|
+
* }
|
|
20
|
+
*
|
|
21
|
+
* const getUserHandler = new Handler()
|
|
22
|
+
* .use(new ResponseWrapperMiddleware<UserResponse>())
|
|
23
|
+
* .handle(async (context) => {
|
|
24
|
+
* const user = await getUser(context.params.id);
|
|
25
|
+
* setResponseData(context, user);
|
|
26
|
+
* // Response will be: { success: true, payload: user, timestamp: "..." }
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* API response with metadata:
|
|
32
|
+
* ```typescript
|
|
33
|
+
* interface ApiResponse {
|
|
34
|
+
* items: any[];
|
|
35
|
+
* pagination: { page: number; total: number };
|
|
36
|
+
* }
|
|
37
|
+
*
|
|
38
|
+
* const listItemsHandler = new Handler()
|
|
39
|
+
* .use(new ResponseWrapperMiddleware<ApiResponse>())
|
|
40
|
+
* .handle(async (context) => {
|
|
41
|
+
* const items = await getItems();
|
|
42
|
+
* const response: ApiResponse = {
|
|
43
|
+
* items,
|
|
44
|
+
* pagination: { page: 1, total: items.length }
|
|
45
|
+
* };
|
|
46
|
+
* setResponseData(context, response);
|
|
47
|
+
* });
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* Combination with error handling:
|
|
52
|
+
* ```typescript
|
|
53
|
+
* const secureHandler = new Handler()
|
|
54
|
+
* .use(new AuthenticationMiddleware())
|
|
55
|
+
* .use(new ResponseWrapperMiddleware<any>())
|
|
56
|
+
* .use(new ErrorHandlerMiddleware())
|
|
57
|
+
* .handle(async (context) => {
|
|
58
|
+
* const data = await getSecureData(context.user.id);
|
|
59
|
+
* setResponseData(context, data);
|
|
60
|
+
* });
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
3
63
|
export declare class ResponseWrapperMiddleware<T> implements BaseMiddleware {
|
|
4
64
|
after(context: Context): Promise<void>;
|
|
5
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Factory function that creates a response wrapper middleware.
|
|
68
|
+
* Automatically wraps response data in a standardized format with success flag and timestamp.
|
|
69
|
+
*
|
|
70
|
+
* @template T - The type of response data being wrapped
|
|
71
|
+
* @returns BaseMiddleware object with response wrapping logic
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* Simple API endpoint:
|
|
75
|
+
* ```typescript
|
|
76
|
+
* import { Handler, responseWrapperMiddleware, setResponseData } from '@noony-serverless/core';
|
|
77
|
+
*
|
|
78
|
+
* const healthCheckHandler = new Handler()
|
|
79
|
+
* .use(responseWrapperMiddleware<{ status: string; uptime: number }>())
|
|
80
|
+
* .handle(async (context) => {
|
|
81
|
+
* setResponseData(context, {
|
|
82
|
+
* status: 'healthy',
|
|
83
|
+
* uptime: process.uptime()
|
|
84
|
+
* });
|
|
85
|
+
* // Response: { success: true, payload: { status: "healthy", uptime: 12345 }, timestamp: "..." }
|
|
86
|
+
* });
|
|
87
|
+
* ```
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* RESTful CRUD operations:
|
|
91
|
+
* ```typescript
|
|
92
|
+
* const createUserHandler = new Handler()
|
|
93
|
+
* .use(bodyParser())
|
|
94
|
+
* .use(responseWrapperMiddleware<{ id: string; message: string }>())
|
|
95
|
+
* .handle(async (context) => {
|
|
96
|
+
* const userData = context.req.parsedBody;
|
|
97
|
+
* const newUser = await createUser(userData);
|
|
98
|
+
* setResponseData(context, {
|
|
99
|
+
* id: newUser.id,
|
|
100
|
+
* message: 'User created successfully'
|
|
101
|
+
* });
|
|
102
|
+
* });
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* Microservice communication:
|
|
107
|
+
* ```typescript
|
|
108
|
+
* const orderProcessingHandler = new Handler()
|
|
109
|
+
* .use(authenticationMiddleware)
|
|
110
|
+
* .use(responseWrapperMiddleware<{ orderId: string; status: string; estimatedDelivery: string }>())
|
|
111
|
+
* .handle(async (context) => {
|
|
112
|
+
* const order = await processOrder(context.req.parsedBody);
|
|
113
|
+
* setResponseData(context, {
|
|
114
|
+
* orderId: order.id,
|
|
115
|
+
* status: order.status,
|
|
116
|
+
* estimatedDelivery: order.estimatedDelivery
|
|
117
|
+
* });
|
|
118
|
+
* });
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
6
121
|
export declare const responseWrapperMiddleware: <T>() => BaseMiddleware;
|
|
7
122
|
/**
|
|
8
|
-
* Helper function to set response data in context for later wrapping
|
|
123
|
+
* Helper function to set response data in context for later wrapping.
|
|
124
|
+
* This function should be used in handlers when using ResponseWrapperMiddleware.
|
|
125
|
+
*
|
|
126
|
+
* @template T - The type of data being set
|
|
127
|
+
* @param context - The request context
|
|
128
|
+
* @param data - The data to be included in the response payload
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* Setting simple response data:
|
|
132
|
+
* ```typescript
|
|
133
|
+
* import { setResponseData } from '@noony-serverless/core';
|
|
134
|
+
*
|
|
135
|
+
* const handler = new Handler()
|
|
136
|
+
* .use(responseWrapperMiddleware())
|
|
137
|
+
* .handle(async (context) => {
|
|
138
|
+
* const message = "Hello, World!";
|
|
139
|
+
* setResponseData(context, { message, timestamp: new Date().toISOString() });
|
|
140
|
+
* });
|
|
141
|
+
* ```
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* Setting complex response data:
|
|
145
|
+
* ```typescript
|
|
146
|
+
* const dashboardHandler = new Handler()
|
|
147
|
+
* .use(responseWrapperMiddleware())
|
|
148
|
+
* .handle(async (context) => {
|
|
149
|
+
* const stats = await getDashboardStats(context.user.id);
|
|
150
|
+
* const notifications = await getNotifications(context.user.id);
|
|
151
|
+
*
|
|
152
|
+
* setResponseData(context, {
|
|
153
|
+
* user: context.user,
|
|
154
|
+
* stats,
|
|
155
|
+
* notifications,
|
|
156
|
+
* lastLogin: new Date().toISOString()
|
|
157
|
+
* });
|
|
158
|
+
* });
|
|
159
|
+
* ```
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* Conditional response data:
|
|
163
|
+
* ```typescript
|
|
164
|
+
* const userProfileHandler = new Handler()
|
|
165
|
+
* .use(responseWrapperMiddleware())
|
|
166
|
+
* .handle(async (context) => {
|
|
167
|
+
* const userId = context.params.id;
|
|
168
|
+
* const user = await getUser(userId);
|
|
169
|
+
*
|
|
170
|
+
* if (user) {
|
|
171
|
+
* setResponseData(context, { user, found: true });
|
|
172
|
+
* } else {
|
|
173
|
+
* context.res.status(404);
|
|
174
|
+
* setResponseData(context, { message: 'User not found', found: false });
|
|
175
|
+
* }
|
|
176
|
+
* });
|
|
177
|
+
* ```
|
|
9
178
|
*/
|
|
10
179
|
export declare function setResponseData<T>(context: Context, data: T): void;
|
|
11
180
|
//# sourceMappingURL=responseWrapperMiddleware.d.ts.map
|
|
@@ -13,12 +13,127 @@ const wrapResponse = (context) => {
|
|
|
13
13
|
});
|
|
14
14
|
}
|
|
15
15
|
};
|
|
16
|
+
/**
|
|
17
|
+
* Middleware class that wraps response data in a standardized format.
|
|
18
|
+
* Automatically wraps the response with success flag, payload, and timestamp.
|
|
19
|
+
*
|
|
20
|
+
* @template T - The type of response data being wrapped
|
|
21
|
+
* @implements {BaseMiddleware}
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* Basic response wrapping:
|
|
25
|
+
* ```typescript
|
|
26
|
+
* import { Handler, ResponseWrapperMiddleware, setResponseData } from '@noony-serverless/core';
|
|
27
|
+
*
|
|
28
|
+
* interface UserResponse {
|
|
29
|
+
* id: string;
|
|
30
|
+
* name: string;
|
|
31
|
+
* email: string;
|
|
32
|
+
* }
|
|
33
|
+
*
|
|
34
|
+
* const getUserHandler = new Handler()
|
|
35
|
+
* .use(new ResponseWrapperMiddleware<UserResponse>())
|
|
36
|
+
* .handle(async (context) => {
|
|
37
|
+
* const user = await getUser(context.params.id);
|
|
38
|
+
* setResponseData(context, user);
|
|
39
|
+
* // Response will be: { success: true, payload: user, timestamp: "..." }
|
|
40
|
+
* });
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* API response with metadata:
|
|
45
|
+
* ```typescript
|
|
46
|
+
* interface ApiResponse {
|
|
47
|
+
* items: any[];
|
|
48
|
+
* pagination: { page: number; total: number };
|
|
49
|
+
* }
|
|
50
|
+
*
|
|
51
|
+
* const listItemsHandler = new Handler()
|
|
52
|
+
* .use(new ResponseWrapperMiddleware<ApiResponse>())
|
|
53
|
+
* .handle(async (context) => {
|
|
54
|
+
* const items = await getItems();
|
|
55
|
+
* const response: ApiResponse = {
|
|
56
|
+
* items,
|
|
57
|
+
* pagination: { page: 1, total: items.length }
|
|
58
|
+
* };
|
|
59
|
+
* setResponseData(context, response);
|
|
60
|
+
* });
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* Combination with error handling:
|
|
65
|
+
* ```typescript
|
|
66
|
+
* const secureHandler = new Handler()
|
|
67
|
+
* .use(new AuthenticationMiddleware())
|
|
68
|
+
* .use(new ResponseWrapperMiddleware<any>())
|
|
69
|
+
* .use(new ErrorHandlerMiddleware())
|
|
70
|
+
* .handle(async (context) => {
|
|
71
|
+
* const data = await getSecureData(context.user.id);
|
|
72
|
+
* setResponseData(context, data);
|
|
73
|
+
* });
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
16
76
|
class ResponseWrapperMiddleware {
|
|
17
77
|
async after(context) {
|
|
18
78
|
wrapResponse(context);
|
|
19
79
|
}
|
|
20
80
|
}
|
|
21
81
|
exports.ResponseWrapperMiddleware = ResponseWrapperMiddleware;
|
|
82
|
+
/**
|
|
83
|
+
* Factory function that creates a response wrapper middleware.
|
|
84
|
+
* Automatically wraps response data in a standardized format with success flag and timestamp.
|
|
85
|
+
*
|
|
86
|
+
* @template T - The type of response data being wrapped
|
|
87
|
+
* @returns BaseMiddleware object with response wrapping logic
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* Simple API endpoint:
|
|
91
|
+
* ```typescript
|
|
92
|
+
* import { Handler, responseWrapperMiddleware, setResponseData } from '@noony-serverless/core';
|
|
93
|
+
*
|
|
94
|
+
* const healthCheckHandler = new Handler()
|
|
95
|
+
* .use(responseWrapperMiddleware<{ status: string; uptime: number }>())
|
|
96
|
+
* .handle(async (context) => {
|
|
97
|
+
* setResponseData(context, {
|
|
98
|
+
* status: 'healthy',
|
|
99
|
+
* uptime: process.uptime()
|
|
100
|
+
* });
|
|
101
|
+
* // Response: { success: true, payload: { status: "healthy", uptime: 12345 }, timestamp: "..." }
|
|
102
|
+
* });
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* RESTful CRUD operations:
|
|
107
|
+
* ```typescript
|
|
108
|
+
* const createUserHandler = new Handler()
|
|
109
|
+
* .use(bodyParser())
|
|
110
|
+
* .use(responseWrapperMiddleware<{ id: string; message: string }>())
|
|
111
|
+
* .handle(async (context) => {
|
|
112
|
+
* const userData = context.req.parsedBody;
|
|
113
|
+
* const newUser = await createUser(userData);
|
|
114
|
+
* setResponseData(context, {
|
|
115
|
+
* id: newUser.id,
|
|
116
|
+
* message: 'User created successfully'
|
|
117
|
+
* });
|
|
118
|
+
* });
|
|
119
|
+
* ```
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* Microservice communication:
|
|
123
|
+
* ```typescript
|
|
124
|
+
* const orderProcessingHandler = new Handler()
|
|
125
|
+
* .use(authenticationMiddleware)
|
|
126
|
+
* .use(responseWrapperMiddleware<{ orderId: string; status: string; estimatedDelivery: string }>())
|
|
127
|
+
* .handle(async (context) => {
|
|
128
|
+
* const order = await processOrder(context.req.parsedBody);
|
|
129
|
+
* setResponseData(context, {
|
|
130
|
+
* orderId: order.id,
|
|
131
|
+
* status: order.status,
|
|
132
|
+
* estimatedDelivery: order.estimatedDelivery
|
|
133
|
+
* });
|
|
134
|
+
* });
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
22
137
|
const responseWrapperMiddleware = () => ({
|
|
23
138
|
after: async (context) => {
|
|
24
139
|
wrapResponse(context);
|
|
@@ -26,7 +141,61 @@ const responseWrapperMiddleware = () => ({
|
|
|
26
141
|
});
|
|
27
142
|
exports.responseWrapperMiddleware = responseWrapperMiddleware;
|
|
28
143
|
/**
|
|
29
|
-
* Helper function to set response data in context for later wrapping
|
|
144
|
+
* Helper function to set response data in context for later wrapping.
|
|
145
|
+
* This function should be used in handlers when using ResponseWrapperMiddleware.
|
|
146
|
+
*
|
|
147
|
+
* @template T - The type of data being set
|
|
148
|
+
* @param context - The request context
|
|
149
|
+
* @param data - The data to be included in the response payload
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* Setting simple response data:
|
|
153
|
+
* ```typescript
|
|
154
|
+
* import { setResponseData } from '@noony-serverless/core';
|
|
155
|
+
*
|
|
156
|
+
* const handler = new Handler()
|
|
157
|
+
* .use(responseWrapperMiddleware())
|
|
158
|
+
* .handle(async (context) => {
|
|
159
|
+
* const message = "Hello, World!";
|
|
160
|
+
* setResponseData(context, { message, timestamp: new Date().toISOString() });
|
|
161
|
+
* });
|
|
162
|
+
* ```
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* Setting complex response data:
|
|
166
|
+
* ```typescript
|
|
167
|
+
* const dashboardHandler = new Handler()
|
|
168
|
+
* .use(responseWrapperMiddleware())
|
|
169
|
+
* .handle(async (context) => {
|
|
170
|
+
* const stats = await getDashboardStats(context.user.id);
|
|
171
|
+
* const notifications = await getNotifications(context.user.id);
|
|
172
|
+
*
|
|
173
|
+
* setResponseData(context, {
|
|
174
|
+
* user: context.user,
|
|
175
|
+
* stats,
|
|
176
|
+
* notifications,
|
|
177
|
+
* lastLogin: new Date().toISOString()
|
|
178
|
+
* });
|
|
179
|
+
* });
|
|
180
|
+
* ```
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* Conditional response data:
|
|
184
|
+
* ```typescript
|
|
185
|
+
* const userProfileHandler = new Handler()
|
|
186
|
+
* .use(responseWrapperMiddleware())
|
|
187
|
+
* .handle(async (context) => {
|
|
188
|
+
* const userId = context.params.id;
|
|
189
|
+
* const user = await getUser(userId);
|
|
190
|
+
*
|
|
191
|
+
* if (user) {
|
|
192
|
+
* setResponseData(context, { user, found: true });
|
|
193
|
+
* } else {
|
|
194
|
+
* context.res.status(404);
|
|
195
|
+
* setResponseData(context, { message: 'User not found', found: false });
|
|
196
|
+
* }
|
|
197
|
+
* });
|
|
198
|
+
* ```
|
|
30
199
|
*/
|
|
31
200
|
function setResponseData(context, data) {
|
|
32
201
|
context.responseData = data;
|
|
@@ -161,15 +161,15 @@ class SecurityAuditMiddleware {
|
|
|
161
161
|
options;
|
|
162
162
|
constructor(options = {}) {
|
|
163
163
|
this.options = {
|
|
164
|
-
logRequests: false,
|
|
165
|
-
logResponses: false,
|
|
166
|
-
logBodies: false,
|
|
167
|
-
maxBodyLogSize: 1024,
|
|
164
|
+
logRequests: options.logRequests ?? false,
|
|
165
|
+
logResponses: options.logResponses ?? false,
|
|
166
|
+
logBodies: options.logBodies ?? false,
|
|
167
|
+
maxBodyLogSize: options.maxBodyLogSize ?? 1024,
|
|
168
168
|
excludeHeaders: [
|
|
169
169
|
...DEFAULT_EXCLUDE_HEADERS,
|
|
170
170
|
...(options.excludeHeaders || []),
|
|
171
171
|
],
|
|
172
|
-
enableAnomalyDetection: true,
|
|
172
|
+
enableAnomalyDetection: options.enableAnomalyDetection ?? true,
|
|
173
173
|
onSecurityEvent: options.onSecurityEvent,
|
|
174
174
|
suspiciousPatterns: {
|
|
175
175
|
...DEFAULT_SUSPICIOUS_PATTERNS,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noony-serverless/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "A Middy base framework compatible with Firebase and GCP Cloud Functions with TypeScript",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -40,17 +40,19 @@
|
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@google-cloud/firestore": "^7.1.0",
|
|
43
|
-
"@google-cloud/functions-framework": "^
|
|
43
|
+
"@google-cloud/functions-framework": "^4.0.0",
|
|
44
44
|
"@google-cloud/pubsub": "^4.1.0",
|
|
45
|
-
"@types/jsonwebtoken": "^9.0.
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"firebase-
|
|
45
|
+
"@types/jsonwebtoken": "^9.0.10",
|
|
46
|
+
"@types/qs": "^6.14.0",
|
|
47
|
+
"axios": "^1.11.0",
|
|
48
|
+
"fastify": "^5.6.0",
|
|
49
|
+
"firebase-admin": "^13.5.0",
|
|
50
|
+
"firebase-functions": "^6.4.0",
|
|
50
51
|
"jsonwebtoken": "^9.0.2",
|
|
52
|
+
"qs": "^6.14.0",
|
|
51
53
|
"reflect-metadata": "^0.2.2",
|
|
52
54
|
"typedi": "^0.10.0",
|
|
53
|
-
"zod": "^
|
|
55
|
+
"zod": "^4.1.5"
|
|
54
56
|
},
|
|
55
57
|
"devDependencies": {
|
|
56
58
|
"@types/jest": "^29.5.11",
|
|
@@ -58,7 +60,7 @@
|
|
|
58
60
|
"@types/node": "^20.10.5",
|
|
59
61
|
"@typescript-eslint/eslint-plugin": "^6.15.0",
|
|
60
62
|
"@typescript-eslint/parser": "^6.15.0",
|
|
61
|
-
"concurrently": "^
|
|
63
|
+
"concurrently": "^9.2.1",
|
|
62
64
|
"eslint": "^8.56.0",
|
|
63
65
|
"eslint-config-prettier": "^9.1.0",
|
|
64
66
|
"eslint-plugin-prettier": "^5.1.2",
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import Container from 'typedi';
|
|
2
|
-
/**
|
|
3
|
-
* Performance optimization: Container Pool for reusing TypeDI containers
|
|
4
|
-
* This reduces object creation overhead and improves memory efficiency
|
|
5
|
-
*/
|
|
6
|
-
declare class ContainerPool {
|
|
7
|
-
private availableContainers;
|
|
8
|
-
private maxPoolSize;
|
|
9
|
-
private createdContainers;
|
|
10
|
-
constructor(maxPoolSize?: number);
|
|
11
|
-
/**
|
|
12
|
-
* Get a container from the pool or create a new one
|
|
13
|
-
*/
|
|
14
|
-
acquire(): Container;
|
|
15
|
-
/**
|
|
16
|
-
* Return a container to the pool for reuse
|
|
17
|
-
*/
|
|
18
|
-
release(container: Container): void;
|
|
19
|
-
/**
|
|
20
|
-
* Reset container state to prevent cross-request contamination
|
|
21
|
-
* Note: TypeDI containers are isolated by default, so we mainly need
|
|
22
|
-
* to clear any manually set values
|
|
23
|
-
*/
|
|
24
|
-
private resetContainer;
|
|
25
|
-
/**
|
|
26
|
-
* Get pool statistics for monitoring
|
|
27
|
-
*/
|
|
28
|
-
getStats(): {
|
|
29
|
-
available: number;
|
|
30
|
-
created: number;
|
|
31
|
-
maxSize: number;
|
|
32
|
-
};
|
|
33
|
-
/**
|
|
34
|
-
* Warm up the pool by pre-creating containers
|
|
35
|
-
*/
|
|
36
|
-
warmUp(count?: number): void;
|
|
37
|
-
/**
|
|
38
|
-
* Clear all containers from the pool
|
|
39
|
-
*/
|
|
40
|
-
clear(): void;
|
|
41
|
-
}
|
|
42
|
-
declare const containerPool: ContainerPool;
|
|
43
|
-
export { ContainerPool, containerPool };
|
|
44
|
-
//# sourceMappingURL=containerPool.d.ts.map
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.containerPool = exports.ContainerPool = void 0;
|
|
7
|
-
const typedi_1 = __importDefault(require("typedi"));
|
|
8
|
-
/**
|
|
9
|
-
* Performance optimization: Container Pool for reusing TypeDI containers
|
|
10
|
-
* This reduces object creation overhead and improves memory efficiency
|
|
11
|
-
*/
|
|
12
|
-
class ContainerPool {
|
|
13
|
-
availableContainers = [];
|
|
14
|
-
maxPoolSize = 10;
|
|
15
|
-
createdContainers = 0;
|
|
16
|
-
constructor(maxPoolSize = 10) {
|
|
17
|
-
this.maxPoolSize = maxPoolSize;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Get a container from the pool or create a new one
|
|
21
|
-
*/
|
|
22
|
-
acquire() {
|
|
23
|
-
if (this.availableContainers.length > 0) {
|
|
24
|
-
return this.availableContainers.pop();
|
|
25
|
-
}
|
|
26
|
-
// Create new container if pool is empty and under limit
|
|
27
|
-
if (this.createdContainers < this.maxPoolSize) {
|
|
28
|
-
this.createdContainers++;
|
|
29
|
-
return typedi_1.default.of();
|
|
30
|
-
}
|
|
31
|
-
// If pool is at capacity, create a temporary container
|
|
32
|
-
// This should rarely happen in normal usage
|
|
33
|
-
return typedi_1.default.of();
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Return a container to the pool for reuse
|
|
37
|
-
*/
|
|
38
|
-
release(container) {
|
|
39
|
-
if (this.availableContainers.length < this.maxPoolSize) {
|
|
40
|
-
// Reset container state by removing all instances
|
|
41
|
-
// This prevents memory leaks and cross-request contamination
|
|
42
|
-
this.resetContainer(container);
|
|
43
|
-
this.availableContainers.push(container);
|
|
44
|
-
}
|
|
45
|
-
// If pool is full, let the container be garbage collected
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Reset container state to prevent cross-request contamination
|
|
49
|
-
* Note: TypeDI containers are isolated by default, so we mainly need
|
|
50
|
-
* to clear any manually set values
|
|
51
|
-
*/
|
|
52
|
-
resetContainer(_container) {
|
|
53
|
-
try {
|
|
54
|
-
// For TypeDI containers created with Container.of(), each container
|
|
55
|
-
// is already isolated. We just need to ensure no memory leaks.
|
|
56
|
-
// The container will be garbage collected when released from pool
|
|
57
|
-
// if it contains too much data
|
|
58
|
-
// TypeDI containers are self-contained and don't need explicit reset
|
|
59
|
-
// This is a placeholder for future enhancements if needed
|
|
60
|
-
}
|
|
61
|
-
catch (error) {
|
|
62
|
-
// If any issues occur, don't add back to pool
|
|
63
|
-
console.warn('Failed to reset container, discarding:', error);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Get pool statistics for monitoring
|
|
68
|
-
*/
|
|
69
|
-
getStats() {
|
|
70
|
-
return {
|
|
71
|
-
available: this.availableContainers.length,
|
|
72
|
-
created: this.createdContainers,
|
|
73
|
-
maxSize: this.maxPoolSize,
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Warm up the pool by pre-creating containers
|
|
78
|
-
*/
|
|
79
|
-
warmUp(count = 5) {
|
|
80
|
-
const warmUpCount = Math.min(count, this.maxPoolSize);
|
|
81
|
-
for (let i = 0; i < warmUpCount; i++) {
|
|
82
|
-
if (this.createdContainers < this.maxPoolSize) {
|
|
83
|
-
const container = typedi_1.default.of();
|
|
84
|
-
this.createdContainers++;
|
|
85
|
-
this.availableContainers.push(container);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Clear all containers from the pool
|
|
91
|
-
*/
|
|
92
|
-
clear() {
|
|
93
|
-
this.availableContainers = [];
|
|
94
|
-
this.createdContainers = 0;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
exports.ContainerPool = ContainerPool;
|
|
98
|
-
// Global container pool instance
|
|
99
|
-
const containerPool = new ContainerPool(15); // Slightly higher limit for serverless
|
|
100
|
-
exports.containerPool = containerPool;
|
|
101
|
-
// Warm up the pool for better cold start performance
|
|
102
|
-
containerPool.warmUp(3);
|
|
103
|
-
//# sourceMappingURL=containerPool.js.map
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { BaseMiddleware, Context } from '../core';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
export declare class ValidationMiddleware implements BaseMiddleware {
|
|
4
|
-
private readonly schema;
|
|
5
|
-
constructor(schema: z.ZodSchema);
|
|
6
|
-
before(context: Context): Promise<void>;
|
|
7
|
-
}
|
|
8
|
-
export declare const validationMiddleware: (schema: z.ZodSchema) => BaseMiddleware;
|
|
9
|
-
//# sourceMappingURL=validationMiddleware.d.ts.map
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.validationMiddleware = exports.ValidationMiddleware = void 0;
|
|
4
|
-
const core_1 = require("../core");
|
|
5
|
-
const zod_1 = require("zod");
|
|
6
|
-
const validate = async (schema, context) => {
|
|
7
|
-
try {
|
|
8
|
-
const data = context.req.method === 'GET' ? context.req.query : context.req.parsedBody;
|
|
9
|
-
const validated = await schema.parseAsync(data);
|
|
10
|
-
if (context.req.method === 'GET') {
|
|
11
|
-
context.req.query = validated;
|
|
12
|
-
}
|
|
13
|
-
else {
|
|
14
|
-
context.req.validatedBody = validated;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
catch (error) {
|
|
18
|
-
if (error instanceof zod_1.z.ZodError) {
|
|
19
|
-
throw new core_1.ValidationError('Validation error', JSON.stringify(error.errors));
|
|
20
|
-
}
|
|
21
|
-
throw error;
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
class ValidationMiddleware {
|
|
25
|
-
schema;
|
|
26
|
-
constructor(schema) {
|
|
27
|
-
this.schema = schema;
|
|
28
|
-
}
|
|
29
|
-
async before(context) {
|
|
30
|
-
await validate(this.schema, context);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
exports.ValidationMiddleware = ValidationMiddleware;
|
|
34
|
-
const validationMiddleware = (schema) => ({
|
|
35
|
-
before: async (context) => {
|
|
36
|
-
await validate(schema, context);
|
|
37
|
-
},
|
|
38
|
-
});
|
|
39
|
-
exports.validationMiddleware = validationMiddleware;
|
|
40
|
-
//# sourceMappingURL=validationMiddleware.js.map
|