@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
|
@@ -3,6 +3,61 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.validatedQueryParameters = exports.headerVariablesValidator = exports.pathParameters = exports.PathParametersMiddleware = void 0;
|
|
4
4
|
const errors_1 = require("../core/errors");
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
|
+
/**
|
|
7
|
+
* Middleware class that extracts path parameters from the URL.
|
|
8
|
+
* Parses URL segments and extracts parameters based on colon-prefixed patterns.
|
|
9
|
+
*
|
|
10
|
+
* @implements {BaseMiddleware}
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* Basic path parameter extraction:
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { Handler, PathParametersMiddleware } from '@noony-serverless/core';
|
|
16
|
+
*
|
|
17
|
+
* // For URL: /users/123/posts/456
|
|
18
|
+
* const userPostHandler = new Handler()
|
|
19
|
+
* .use(new PathParametersMiddleware())
|
|
20
|
+
* .handle(async (context) => {
|
|
21
|
+
* // Assuming your routing pattern is /users/:userId/posts/:postId
|
|
22
|
+
* const { userId, postId } = context.req.params || {};
|
|
23
|
+
*
|
|
24
|
+
* const user = await getUserById(userId);
|
|
25
|
+
* const post = await getPostById(postId);
|
|
26
|
+
*
|
|
27
|
+
* return { success: true, user, post };
|
|
28
|
+
* });
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* RESTful API with multiple parameters:
|
|
33
|
+
* ```typescript
|
|
34
|
+
* // For URL: /api/v1/organizations/org-123/projects/proj-456/tasks/task-789
|
|
35
|
+
* const taskHandler = new Handler()
|
|
36
|
+
* .use(new PathParametersMiddleware())
|
|
37
|
+
* .handle(async (context) => {
|
|
38
|
+
* const { organizationId, projectId, taskId } = context.req.params || {};
|
|
39
|
+
*
|
|
40
|
+
* const task = await getTask(organizationId, projectId, taskId);
|
|
41
|
+
* return { success: true, task };
|
|
42
|
+
* });
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* E-commerce product details:
|
|
47
|
+
* ```typescript
|
|
48
|
+
* // For URL: /categories/electronics/products/laptop-123
|
|
49
|
+
* const productHandler = new Handler()
|
|
50
|
+
* .use(new PathParametersMiddleware())
|
|
51
|
+
* .handle(async (context) => {
|
|
52
|
+
* const { category, productId } = context.req.params || {};
|
|
53
|
+
*
|
|
54
|
+
* const product = await getProductByCategory(category, productId);
|
|
55
|
+
* const recommendations = await getRecommendations(category, productId);
|
|
56
|
+
*
|
|
57
|
+
* return { success: true, product, recommendations };
|
|
58
|
+
* });
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
6
61
|
class PathParametersMiddleware {
|
|
7
62
|
async before(context) {
|
|
8
63
|
const host = (Array.isArray(context.req.headers.host)
|
|
@@ -24,6 +79,54 @@ class PathParametersMiddleware {
|
|
|
24
79
|
}
|
|
25
80
|
}
|
|
26
81
|
exports.PathParametersMiddleware = PathParametersMiddleware;
|
|
82
|
+
/**
|
|
83
|
+
* Factory function that creates a path parameters extraction middleware.
|
|
84
|
+
* Extracts URL path segments and sets them in context.req.params.
|
|
85
|
+
*
|
|
86
|
+
* @returns BaseMiddleware object with path parameter extraction logic
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* Simple product API:
|
|
90
|
+
* ```typescript
|
|
91
|
+
* import { Handler, pathParameters } from '@noony-serverless/core';
|
|
92
|
+
*
|
|
93
|
+
* // For URL: /products/123
|
|
94
|
+
* const getProductHandler = new Handler()
|
|
95
|
+
* .use(pathParameters())
|
|
96
|
+
* .handle(async (context) => {
|
|
97
|
+
* const productId = context.req.params?.id;
|
|
98
|
+
* const product = await getProduct(productId);
|
|
99
|
+
* return { success: true, product };
|
|
100
|
+
* });
|
|
101
|
+
* ```
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* Blog post with category:
|
|
105
|
+
* ```typescript
|
|
106
|
+
* // For URL: /blog/technology/post-123
|
|
107
|
+
* const blogPostHandler = new Handler()
|
|
108
|
+
* .use(pathParameters())
|
|
109
|
+
* .handle(async (context) => {
|
|
110
|
+
* const { category, postId } = context.req.params || {};
|
|
111
|
+
* const post = await getBlogPost(category, postId);
|
|
112
|
+
* const relatedPosts = await getRelatedPosts(category);
|
|
113
|
+
* return { success: true, post, relatedPosts };
|
|
114
|
+
* });
|
|
115
|
+
* ```
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* Nested resource API:
|
|
119
|
+
* ```typescript
|
|
120
|
+
* // For URL: /users/user-123/orders/order-456/items
|
|
121
|
+
* const orderItemsHandler = new Handler()
|
|
122
|
+
* .use(pathParameters())
|
|
123
|
+
* .handle(async (context) => {
|
|
124
|
+
* const { userId, orderId } = context.req.params || {};
|
|
125
|
+
* const orderItems = await getOrderItems(userId, orderId);
|
|
126
|
+
* return { success: true, items: orderItems };
|
|
127
|
+
* });
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
27
130
|
const pathParameters = () => ({
|
|
28
131
|
before: async (context) => {
|
|
29
132
|
const host = (Array.isArray(context.req.headers.host)
|
|
@@ -43,6 +146,60 @@ const pathParameters = () => ({
|
|
|
43
146
|
},
|
|
44
147
|
});
|
|
45
148
|
exports.pathParameters = pathParameters;
|
|
149
|
+
/**
|
|
150
|
+
* Factory function that creates a header validation middleware.
|
|
151
|
+
* Validates that all required headers are present in the request.
|
|
152
|
+
*
|
|
153
|
+
* @param requiredHeaders - Array of header names that must be present
|
|
154
|
+
* @returns BaseMiddleware object with header validation logic
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* API authentication headers:
|
|
158
|
+
* ```typescript
|
|
159
|
+
* import { Handler, headerVariablesValidator } from '@noony-serverless/core';
|
|
160
|
+
*
|
|
161
|
+
* const secureApiHandler = new Handler()
|
|
162
|
+
* .use(headerVariablesValidator(['authorization', 'x-api-key']))
|
|
163
|
+
* .handle(async (context) => {
|
|
164
|
+
* const authToken = context.req.headers.authorization;
|
|
165
|
+
* const apiKey = context.req.headers['x-api-key'];
|
|
166
|
+
*
|
|
167
|
+
* const isValid = await validateCredentials(authToken, apiKey);
|
|
168
|
+
* return { success: isValid, message: 'Access granted' };
|
|
169
|
+
* });
|
|
170
|
+
* ```
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* Content type validation:
|
|
174
|
+
* ```typescript
|
|
175
|
+
* const uploadHandler = new Handler()
|
|
176
|
+
* .use(headerVariablesValidator(['content-type', 'content-length']))
|
|
177
|
+
* .handle(async (context) => {
|
|
178
|
+
* const contentType = context.req.headers['content-type'];
|
|
179
|
+
* const contentLength = context.req.headers['content-length'];
|
|
180
|
+
*
|
|
181
|
+
* if (contentType !== 'application/json') {
|
|
182
|
+
* throw new Error('Only JSON content is accepted');
|
|
183
|
+
* }
|
|
184
|
+
*
|
|
185
|
+
* return { success: true, received: contentLength };
|
|
186
|
+
* });
|
|
187
|
+
* ```
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* Multi-tenant application:
|
|
191
|
+
* ```typescript
|
|
192
|
+
* const tenantHandler = new Handler()
|
|
193
|
+
* .use(headerVariablesValidator(['x-tenant-id', 'x-client-version']))
|
|
194
|
+
* .handle(async (context) => {
|
|
195
|
+
* const tenantId = context.req.headers['x-tenant-id'];
|
|
196
|
+
* const clientVersion = context.req.headers['x-client-version'];
|
|
197
|
+
*
|
|
198
|
+
* const tenantConfig = await getTenantConfig(tenantId);
|
|
199
|
+
* return { success: true, config: tenantConfig, version: clientVersion };
|
|
200
|
+
* });
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
46
203
|
const headerVariablesValidator = (requiredHeaders) => ({
|
|
47
204
|
before: async (context) => {
|
|
48
205
|
for (const header of requiredHeaders) {
|
|
@@ -53,6 +210,84 @@ const headerVariablesValidator = (requiredHeaders) => ({
|
|
|
53
210
|
},
|
|
54
211
|
});
|
|
55
212
|
exports.headerVariablesValidator = headerVariablesValidator;
|
|
213
|
+
/**
|
|
214
|
+
* Factory function that creates a query parameter validation middleware using Zod schema.
|
|
215
|
+
* Validates query parameters against a provided schema and throws ValidationError if invalid.
|
|
216
|
+
*
|
|
217
|
+
* @param schema - Zod schema to validate query parameters against
|
|
218
|
+
* @returns BaseMiddleware object with query parameter validation logic
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* Pagination parameters validation:
|
|
222
|
+
* ```typescript
|
|
223
|
+
* import { z } from 'zod';
|
|
224
|
+
* import { Handler, validatedQueryParameters } from '@noony-serverless/core';
|
|
225
|
+
*
|
|
226
|
+
* const paginationSchema = z.object({
|
|
227
|
+
* page: z.string().regex(/^\d+$/).transform(Number).default('1'),
|
|
228
|
+
* limit: z.string().regex(/^\d+$/).transform(Number).default('10'),
|
|
229
|
+
* sort: z.enum(['asc', 'desc']).default('asc')
|
|
230
|
+
* });
|
|
231
|
+
*
|
|
232
|
+
* const listUsersHandler = new Handler()
|
|
233
|
+
* .use(validatedQueryParameters(paginationSchema))
|
|
234
|
+
* .handle(async (context) => {
|
|
235
|
+
* const { page, limit, sort } = context.req.query;
|
|
236
|
+
* const users = await getUsersPaginated(page, limit, sort);
|
|
237
|
+
* return { success: true, users, pagination: { page, limit, sort } };
|
|
238
|
+
* });
|
|
239
|
+
* ```
|
|
240
|
+
*
|
|
241
|
+
* @example
|
|
242
|
+
* Search and filter parameters:
|
|
243
|
+
* ```typescript
|
|
244
|
+
* const searchSchema = z.object({
|
|
245
|
+
* q: z.string().min(1),
|
|
246
|
+
* category: z.string().optional(),
|
|
247
|
+
* price_min: z.string().regex(/^\d+(\.\d{2})?$/).optional(),
|
|
248
|
+
* price_max: z.string().regex(/^\d+(\.\d{2})?$/).optional(),
|
|
249
|
+
* in_stock: z.enum(['true', 'false']).optional()
|
|
250
|
+
* });
|
|
251
|
+
*
|
|
252
|
+
* const searchProductsHandler = new Handler()
|
|
253
|
+
* .use(validatedQueryParameters(searchSchema))
|
|
254
|
+
* .handle(async (context) => {
|
|
255
|
+
* const { q, category, price_min, price_max, in_stock } = context.req.query;
|
|
256
|
+
* const filters = {
|
|
257
|
+
* query: q,
|
|
258
|
+
* category,
|
|
259
|
+
* priceRange: { min: price_min, max: price_max },
|
|
260
|
+
* inStock: in_stock === 'true'
|
|
261
|
+
* };
|
|
262
|
+
* const products = await searchProducts(filters);
|
|
263
|
+
* return { success: true, products, filters };
|
|
264
|
+
* });
|
|
265
|
+
* ```
|
|
266
|
+
*
|
|
267
|
+
* @example
|
|
268
|
+
* Date range and reporting parameters:
|
|
269
|
+
* ```typescript
|
|
270
|
+
* const reportSchema = z.object({
|
|
271
|
+
* start_date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
|
|
272
|
+
* end_date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
|
|
273
|
+
* granularity: z.enum(['day', 'week', 'month']).default('day'),
|
|
274
|
+
* metrics: z.string().transform(val => val.split(',')).optional()
|
|
275
|
+
* });
|
|
276
|
+
*
|
|
277
|
+
* const analyticsHandler = new Handler()
|
|
278
|
+
* .use(validatedQueryParameters(reportSchema))
|
|
279
|
+
* .handle(async (context) => {
|
|
280
|
+
* const { start_date, end_date, granularity, metrics } = context.req.query;
|
|
281
|
+
* const report = await generateReport({
|
|
282
|
+
* startDate: new Date(start_date),
|
|
283
|
+
* endDate: new Date(end_date),
|
|
284
|
+
* granularity,
|
|
285
|
+
* metrics
|
|
286
|
+
* });
|
|
287
|
+
* return { success: true, report };
|
|
288
|
+
* });
|
|
289
|
+
* ```
|
|
290
|
+
*/
|
|
56
291
|
const validatedQueryParameters = (schema) => ({
|
|
57
292
|
before: async (context) => {
|
|
58
293
|
const queryParams = context.req.query;
|
|
@@ -61,7 +296,7 @@ const validatedQueryParameters = (schema) => ({
|
|
|
61
296
|
}
|
|
62
297
|
catch (error) {
|
|
63
298
|
if (error instanceof zod_1.z.ZodError) {
|
|
64
|
-
throw new errors_1.ValidationError('Validation error', JSON.stringify(error.
|
|
299
|
+
throw new errors_1.ValidationError('Validation error', JSON.stringify(error.issues));
|
|
65
300
|
}
|
|
66
301
|
throw error;
|
|
67
302
|
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
export * from './SecurityMiddleware';
|
|
2
|
+
export * from './ConsolidatedValidationMiddleware';
|
|
3
|
+
export * from './ProcessingMiddleware';
|
|
1
4
|
export * from './authenticationMiddleware';
|
|
2
5
|
export * from './bodyParserMiddleware';
|
|
3
6
|
export * from './bodyValidationMiddleware';
|
|
@@ -10,6 +13,5 @@ export * from './rateLimitingMiddleware';
|
|
|
10
13
|
export * from './responseWrapperMiddleware';
|
|
11
14
|
export * from './securityAuditMiddleware';
|
|
12
15
|
export * from './securityHeadersMiddleware';
|
|
13
|
-
export * from './validationMiddleware';
|
|
14
16
|
export * from './guards';
|
|
15
17
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -14,6 +14,11 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
// === NEW CONSOLIDATED MIDDLEWARES ===
|
|
18
|
+
__exportStar(require("./SecurityMiddleware"), exports);
|
|
19
|
+
__exportStar(require("./ConsolidatedValidationMiddleware"), exports);
|
|
20
|
+
__exportStar(require("./ProcessingMiddleware"), exports);
|
|
21
|
+
// === EXISTING INDIVIDUAL MIDDLEWARES (for backward compatibility) ===
|
|
17
22
|
__exportStar(require("./authenticationMiddleware"), exports);
|
|
18
23
|
__exportStar(require("./bodyParserMiddleware"), exports);
|
|
19
24
|
__exportStar(require("./bodyValidationMiddleware"), exports);
|
|
@@ -26,6 +31,6 @@ __exportStar(require("./rateLimitingMiddleware"), exports);
|
|
|
26
31
|
__exportStar(require("./responseWrapperMiddleware"), exports);
|
|
27
32
|
__exportStar(require("./securityAuditMiddleware"), exports);
|
|
28
33
|
__exportStar(require("./securityHeadersMiddleware"), exports);
|
|
29
|
-
|
|
34
|
+
// NOTE: validationMiddleware export removed due to naming conflict with new ValidationMiddleware
|
|
30
35
|
__exportStar(require("./guards"), exports);
|
|
31
36
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,8 +1,113 @@
|
|
|
1
1
|
import { BaseMiddleware, Context } from '../core';
|
|
2
|
+
/**
|
|
3
|
+
* Middleware class that validates and processes query parameters from the request URL.
|
|
4
|
+
* Extracts query parameters and validates that required parameters are present.
|
|
5
|
+
*
|
|
6
|
+
* @implements {BaseMiddleware}
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* Basic query parameter validation:
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { Handler, QueryParametersMiddleware } from '@noony-serverless/core';
|
|
12
|
+
*
|
|
13
|
+
* const searchHandler = new Handler()
|
|
14
|
+
* .use(new QueryParametersMiddleware(['q', 'type']))
|
|
15
|
+
* .handle(async (context) => {
|
|
16
|
+
* const { q, type } = context.req.query;
|
|
17
|
+
* const results = await search(q, type);
|
|
18
|
+
* return { success: true, results, query: q, type };
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* Pagination with required parameters:
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const listHandler = new Handler()
|
|
26
|
+
* .use(new QueryParametersMiddleware(['page', 'limit']))
|
|
27
|
+
* .handle(async (context) => {
|
|
28
|
+
* const { page, limit, sort } = context.req.query;
|
|
29
|
+
* const items = await getItems(parseInt(page), parseInt(limit), sort);
|
|
30
|
+
* return { success: true, items, pagination: { page, limit } };
|
|
31
|
+
* });
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* Optional parameters (empty required array):
|
|
36
|
+
* ```typescript
|
|
37
|
+
* const flexibleHandler = new Handler()
|
|
38
|
+
* .use(new QueryParametersMiddleware([])) // No required parameters
|
|
39
|
+
* .handle(async (context) => {
|
|
40
|
+
* const { filter, sort, category } = context.req.query || {};
|
|
41
|
+
* const data = await getData({ filter, sort, category });
|
|
42
|
+
* return { success: true, data };
|
|
43
|
+
* });
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
2
46
|
export declare class QueryParametersMiddleware implements BaseMiddleware {
|
|
3
47
|
private readonly requiredParams;
|
|
4
48
|
constructor(requiredParams?: string[]);
|
|
5
49
|
before(context: Context): Promise<void>;
|
|
6
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Factory function that creates a query parameter processing middleware.
|
|
53
|
+
* Extracts and validates query parameters from the request URL.
|
|
54
|
+
*
|
|
55
|
+
* @param requiredParams - Array of parameter names that must be present (default: empty array)
|
|
56
|
+
* @returns BaseMiddleware object with query parameter processing logic
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* API endpoint with required search parameters:
|
|
60
|
+
* ```typescript
|
|
61
|
+
* import { Handler, queryParametersMiddleware } from '@noony-serverless/core';
|
|
62
|
+
*
|
|
63
|
+
* const searchApiHandler = new Handler()
|
|
64
|
+
* .use(queryParametersMiddleware(['q'])) // 'q' parameter is required
|
|
65
|
+
* .handle(async (context) => {
|
|
66
|
+
* const { q, category, sort } = context.req.query;
|
|
67
|
+
* const searchResults = await performSearch(q, { category, sort });
|
|
68
|
+
* return { success: true, results: searchResults };
|
|
69
|
+
* });
|
|
70
|
+
* ```
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* E-commerce product listing with filters:
|
|
74
|
+
* ```typescript
|
|
75
|
+
* const productListHandler = new Handler()
|
|
76
|
+
* .use(queryParametersMiddleware(['category'])) // Category is required
|
|
77
|
+
* .handle(async (context) => {
|
|
78
|
+
* const { category, price_min, price_max, brand, sort } = context.req.query;
|
|
79
|
+
* const products = await getProducts({
|
|
80
|
+
* category,
|
|
81
|
+
* priceRange: { min: price_min, max: price_max },
|
|
82
|
+
* brand,
|
|
83
|
+
* sortBy: sort || 'name'
|
|
84
|
+
* });
|
|
85
|
+
* return { success: true, products, filters: { category, brand, sort } };
|
|
86
|
+
* });
|
|
87
|
+
* ```
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* Flexible API with optional parameters:
|
|
91
|
+
* ```typescript
|
|
92
|
+
* const dataHandler = new Handler()
|
|
93
|
+
* .use(queryParametersMiddleware()) // No required parameters
|
|
94
|
+
* .handle(async (context) => {
|
|
95
|
+
* const queryParams = context.req.query || {};
|
|
96
|
+
* const {
|
|
97
|
+
* page = '1',
|
|
98
|
+
* limit = '10',
|
|
99
|
+
* sort = 'created_at',
|
|
100
|
+
* order = 'desc'
|
|
101
|
+
* } = queryParams;
|
|
102
|
+
*
|
|
103
|
+
* const data = await fetchData({
|
|
104
|
+
* pagination: { page: parseInt(page), limit: parseInt(limit) },
|
|
105
|
+
* sorting: { field: sort, order }
|
|
106
|
+
* });
|
|
107
|
+
*
|
|
108
|
+
* return { success: true, data, meta: { page, limit, sort, order } };
|
|
109
|
+
* });
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
7
112
|
export declare const queryParametersMiddleware: (requiredParams?: string[]) => BaseMiddleware;
|
|
8
113
|
//# sourceMappingURL=queryParametersMiddleware.d.ts.map
|
|
@@ -20,6 +20,50 @@ const convertQueryToRecord = (query) => {
|
|
|
20
20
|
}
|
|
21
21
|
return result;
|
|
22
22
|
};
|
|
23
|
+
/**
|
|
24
|
+
* Middleware class that validates and processes query parameters from the request URL.
|
|
25
|
+
* Extracts query parameters and validates that required parameters are present.
|
|
26
|
+
*
|
|
27
|
+
* @implements {BaseMiddleware}
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* Basic query parameter validation:
|
|
31
|
+
* ```typescript
|
|
32
|
+
* import { Handler, QueryParametersMiddleware } from '@noony-serverless/core';
|
|
33
|
+
*
|
|
34
|
+
* const searchHandler = new Handler()
|
|
35
|
+
* .use(new QueryParametersMiddleware(['q', 'type']))
|
|
36
|
+
* .handle(async (context) => {
|
|
37
|
+
* const { q, type } = context.req.query;
|
|
38
|
+
* const results = await search(q, type);
|
|
39
|
+
* return { success: true, results, query: q, type };
|
|
40
|
+
* });
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* Pagination with required parameters:
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const listHandler = new Handler()
|
|
47
|
+
* .use(new QueryParametersMiddleware(['page', 'limit']))
|
|
48
|
+
* .handle(async (context) => {
|
|
49
|
+
* const { page, limit, sort } = context.req.query;
|
|
50
|
+
* const items = await getItems(parseInt(page), parseInt(limit), sort);
|
|
51
|
+
* return { success: true, items, pagination: { page, limit } };
|
|
52
|
+
* });
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* Optional parameters (empty required array):
|
|
57
|
+
* ```typescript
|
|
58
|
+
* const flexibleHandler = new Handler()
|
|
59
|
+
* .use(new QueryParametersMiddleware([])) // No required parameters
|
|
60
|
+
* .handle(async (context) => {
|
|
61
|
+
* const { filter, sort, category } = context.req.query || {};
|
|
62
|
+
* const data = await getData({ filter, sort, category });
|
|
63
|
+
* return { success: true, data };
|
|
64
|
+
* });
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
23
67
|
class QueryParametersMiddleware {
|
|
24
68
|
requiredParams;
|
|
25
69
|
constructor(requiredParams = []) {
|
|
@@ -36,6 +80,67 @@ class QueryParametersMiddleware {
|
|
|
36
80
|
}
|
|
37
81
|
}
|
|
38
82
|
exports.QueryParametersMiddleware = QueryParametersMiddleware;
|
|
83
|
+
/**
|
|
84
|
+
* Factory function that creates a query parameter processing middleware.
|
|
85
|
+
* Extracts and validates query parameters from the request URL.
|
|
86
|
+
*
|
|
87
|
+
* @param requiredParams - Array of parameter names that must be present (default: empty array)
|
|
88
|
+
* @returns BaseMiddleware object with query parameter processing logic
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* API endpoint with required search parameters:
|
|
92
|
+
* ```typescript
|
|
93
|
+
* import { Handler, queryParametersMiddleware } from '@noony-serverless/core';
|
|
94
|
+
*
|
|
95
|
+
* const searchApiHandler = new Handler()
|
|
96
|
+
* .use(queryParametersMiddleware(['q'])) // 'q' parameter is required
|
|
97
|
+
* .handle(async (context) => {
|
|
98
|
+
* const { q, category, sort } = context.req.query;
|
|
99
|
+
* const searchResults = await performSearch(q, { category, sort });
|
|
100
|
+
* return { success: true, results: searchResults };
|
|
101
|
+
* });
|
|
102
|
+
* ```
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* E-commerce product listing with filters:
|
|
106
|
+
* ```typescript
|
|
107
|
+
* const productListHandler = new Handler()
|
|
108
|
+
* .use(queryParametersMiddleware(['category'])) // Category is required
|
|
109
|
+
* .handle(async (context) => {
|
|
110
|
+
* const { category, price_min, price_max, brand, sort } = context.req.query;
|
|
111
|
+
* const products = await getProducts({
|
|
112
|
+
* category,
|
|
113
|
+
* priceRange: { min: price_min, max: price_max },
|
|
114
|
+
* brand,
|
|
115
|
+
* sortBy: sort || 'name'
|
|
116
|
+
* });
|
|
117
|
+
* return { success: true, products, filters: { category, brand, sort } };
|
|
118
|
+
* });
|
|
119
|
+
* ```
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* Flexible API with optional parameters:
|
|
123
|
+
* ```typescript
|
|
124
|
+
* const dataHandler = new Handler()
|
|
125
|
+
* .use(queryParametersMiddleware()) // No required parameters
|
|
126
|
+
* .handle(async (context) => {
|
|
127
|
+
* const queryParams = context.req.query || {};
|
|
128
|
+
* const {
|
|
129
|
+
* page = '1',
|
|
130
|
+
* limit = '10',
|
|
131
|
+
* sort = 'created_at',
|
|
132
|
+
* order = 'desc'
|
|
133
|
+
* } = queryParams;
|
|
134
|
+
*
|
|
135
|
+
* const data = await fetchData({
|
|
136
|
+
* pagination: { page: parseInt(page), limit: parseInt(limit) },
|
|
137
|
+
* sorting: { field: sort, order }
|
|
138
|
+
* });
|
|
139
|
+
*
|
|
140
|
+
* return { success: true, data, meta: { page, limit, sort, order } };
|
|
141
|
+
* });
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
39
144
|
const queryParametersMiddleware = (requiredParams = []) => ({
|
|
40
145
|
async before(context) {
|
|
41
146
|
const host = (Array.isArray(context.req.headers.host)
|