@noony-serverless/core 0.1.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.
Files changed (46) hide show
  1. package/README.md +443 -0
  2. package/build/core/containerPool.d.ts +44 -0
  3. package/build/core/containerPool.js +103 -0
  4. package/build/core/core.d.ts +123 -0
  5. package/build/core/core.js +107 -0
  6. package/build/core/errors.d.ts +25 -0
  7. package/build/core/errors.js +59 -0
  8. package/build/core/handler.d.ts +72 -0
  9. package/build/core/handler.js +151 -0
  10. package/build/core/index.d.ts +8 -0
  11. package/build/core/index.js +24 -0
  12. package/build/core/logger.d.ts +42 -0
  13. package/build/core/logger.js +135 -0
  14. package/build/core/performanceMonitor.d.ts +73 -0
  15. package/build/core/performanceMonitor.js +189 -0
  16. package/build/index.d.ts +3 -0
  17. package/build/index.js +19 -0
  18. package/build/middlewares/authenticationMiddleware.d.ts +52 -0
  19. package/build/middlewares/authenticationMiddleware.js +204 -0
  20. package/build/middlewares/bodyParserMiddleware.d.ts +31 -0
  21. package/build/middlewares/bodyParserMiddleware.js +217 -0
  22. package/build/middlewares/bodyValidationMiddleware.d.ts +12 -0
  23. package/build/middlewares/bodyValidationMiddleware.js +34 -0
  24. package/build/middlewares/dependencyInjectionMiddleware.d.ts +14 -0
  25. package/build/middlewares/dependencyInjectionMiddleware.js +48 -0
  26. package/build/middlewares/errorHandlerMiddleware.d.ts +6 -0
  27. package/build/middlewares/errorHandlerMiddleware.js +64 -0
  28. package/build/middlewares/headerVariablesMiddleware.d.ts +8 -0
  29. package/build/middlewares/headerVariablesMiddleware.js +32 -0
  30. package/build/middlewares/httpAttributesMiddleware.d.ts +10 -0
  31. package/build/middlewares/httpAttributesMiddleware.js +71 -0
  32. package/build/middlewares/index.d.ts +14 -0
  33. package/build/middlewares/index.js +30 -0
  34. package/build/middlewares/queryParametersMiddleware.d.ts +8 -0
  35. package/build/middlewares/queryParametersMiddleware.js +51 -0
  36. package/build/middlewares/rateLimitingMiddleware.d.ts +157 -0
  37. package/build/middlewares/rateLimitingMiddleware.js +237 -0
  38. package/build/middlewares/responseWrapperMiddleware.d.ts +11 -0
  39. package/build/middlewares/responseWrapperMiddleware.js +34 -0
  40. package/build/middlewares/securityAuditMiddleware.d.ts +124 -0
  41. package/build/middlewares/securityAuditMiddleware.js +395 -0
  42. package/build/middlewares/securityHeadersMiddleware.d.ts +128 -0
  43. package/build/middlewares/securityHeadersMiddleware.js +183 -0
  44. package/build/middlewares/validationMiddleware.d.ts +9 -0
  45. package/build/middlewares/validationMiddleware.js +40 -0
  46. package/package.json +73 -0
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.bodyParser = exports.BodyParserMiddleware = void 0;
4
+ const core_1 = require("../core");
5
+ // Enhanced base64 validation with stricter security checks
6
+ const BASE64_REGEX = /^[A-Za-z0-9+/]*={0,2}$/;
7
+ const MAX_BASE64_PADDING = 2;
8
+ const MIN_BASE64_LENGTH = 4; // Base64 minimum valid length
9
+ // Type guard to check if the body is a PubSub message - optimized version
10
+ const isPubSubMessage = (body) => {
11
+ return (!!body &&
12
+ typeof body === 'object' &&
13
+ 'message' in body &&
14
+ typeof body.message === 'object' &&
15
+ 'data' in body.message);
16
+ };
17
+ // Performance constants
18
+ const MAX_JSON_SIZE = 1024 * 1024; // 1MB default limit
19
+ const MAX_BASE64_SIZE = 1024 * 1024 * 1.5; // 1.5MB for base64 (accounts for encoding overhead)
20
+ /**
21
+ * Async JSON parsing using worker threads for large payloads
22
+ * Falls back to synchronous parsing for small payloads
23
+ */
24
+ const parseJsonAsync = async (jsonString) => {
25
+ // Performance optimization: Use sync parsing for small payloads
26
+ if (jsonString.length < 10000) {
27
+ // 10KB threshold
28
+ try {
29
+ return JSON.parse(jsonString);
30
+ }
31
+ catch (error) {
32
+ throw new core_1.ValidationError('Invalid JSON body', error.message);
33
+ }
34
+ }
35
+ // For larger payloads, use async parsing to avoid blocking
36
+ return new Promise((resolve, reject) => {
37
+ // Use setImmediate to make JSON parsing non-blocking
38
+ setImmediate(() => {
39
+ try {
40
+ const result = JSON.parse(jsonString);
41
+ resolve(result);
42
+ }
43
+ catch (error) {
44
+ reject(new core_1.ValidationError('Invalid JSON body', error.message));
45
+ }
46
+ });
47
+ });
48
+ };
49
+ /**
50
+ * Enhanced base64 validation with comprehensive security checks
51
+ */
52
+ const validateBase64Format = (base64Data) => {
53
+ // Check minimum length
54
+ if (base64Data.length < MIN_BASE64_LENGTH) {
55
+ throw new core_1.ValidationError('Base64 data too short');
56
+ }
57
+ // Validate base64 alphabet and padding
58
+ if (!BASE64_REGEX.test(base64Data)) {
59
+ throw new core_1.ValidationError('Invalid base64 format in Pub/Sub message');
60
+ }
61
+ // Validate padding is only at the end
62
+ const paddingIndex = base64Data.indexOf('=');
63
+ if (paddingIndex !== -1) {
64
+ const paddingCount = base64Data.length - paddingIndex;
65
+ if (paddingCount > MAX_BASE64_PADDING) {
66
+ throw new core_1.ValidationError('Invalid base64 padding');
67
+ }
68
+ // Ensure no non-padding characters after padding starts
69
+ const paddingPart = base64Data.substring(paddingIndex);
70
+ if (!/^=+$/.test(paddingPart)) {
71
+ throw new core_1.ValidationError('Invalid characters after base64 padding');
72
+ }
73
+ }
74
+ // Validate length is multiple of 4 (base64 requirement)
75
+ if (base64Data.length % 4 !== 0) {
76
+ throw new core_1.ValidationError('Invalid base64 length - must be multiple of 4');
77
+ }
78
+ };
79
+ /**
80
+ * Secure base64 decoding with comprehensive validation and size limits
81
+ */
82
+ const decodeBase64Async = async (base64Data) => {
83
+ // Perform comprehensive base64 validation
84
+ validateBase64Format(base64Data);
85
+ // Check size limits to prevent memory exhaustion
86
+ if (base64Data.length > MAX_BASE64_SIZE) {
87
+ throw new core_1.TooLargeError('Pub/Sub message too large');
88
+ }
89
+ // For small messages, use sync decoding
90
+ if (base64Data.length < 1000) {
91
+ try {
92
+ const decoded = Buffer.from(base64Data, 'base64').toString('utf8');
93
+ // Validate decoded content is valid UTF-8
94
+ if (decoded.includes('\uFFFD')) {
95
+ throw new core_1.ValidationError('Invalid UTF-8 content in decoded base64');
96
+ }
97
+ return decoded;
98
+ }
99
+ catch (error) {
100
+ if (error instanceof core_1.ValidationError) {
101
+ throw error;
102
+ }
103
+ throw new core_1.ValidationError('Failed to decode base64 data');
104
+ }
105
+ }
106
+ // For larger messages, use async decoding to avoid blocking
107
+ return new Promise((resolve, reject) => {
108
+ setImmediate(() => {
109
+ try {
110
+ const decoded = Buffer.from(base64Data, 'base64').toString('utf8');
111
+ // Validate decoded content is valid UTF-8
112
+ if (decoded.includes('\uFFFD')) {
113
+ reject(new core_1.ValidationError('Invalid UTF-8 content in decoded base64'));
114
+ return;
115
+ }
116
+ resolve(decoded);
117
+ }
118
+ catch (error) {
119
+ reject(new core_1.ValidationError('Failed to decode base64 Pub/Sub message'));
120
+ }
121
+ });
122
+ });
123
+ };
124
+ // Enhanced async body parser with performance optimizations
125
+ const parseBody = async (body) => {
126
+ // Early return for already parsed objects
127
+ if (typeof body === 'object' && body !== null && !isPubSubMessage(body)) {
128
+ return body;
129
+ }
130
+ if (typeof body === 'string') {
131
+ // Size check to prevent DoS attacks
132
+ if (body.length > MAX_JSON_SIZE) {
133
+ throw new core_1.TooLargeError('Request body too large');
134
+ }
135
+ return await parseJsonAsync(body);
136
+ }
137
+ if (isPubSubMessage(body)) {
138
+ try {
139
+ const decoded = await decodeBase64Async(body.message.data);
140
+ return await parseJsonAsync(decoded);
141
+ }
142
+ catch (error) {
143
+ if (error instanceof core_1.ValidationError || error instanceof core_1.TooLargeError) {
144
+ throw error;
145
+ }
146
+ throw new core_1.ValidationError('Invalid Pub/Sub message', error.message);
147
+ }
148
+ }
149
+ return body;
150
+ };
151
+ /**
152
+ * Enhanced BodyParserMiddleware with async parsing and performance optimizations.
153
+ *
154
+ * Features:
155
+ * - Async JSON parsing for large payloads
156
+ * - Size limits to prevent DoS attacks
157
+ * - Base64 decoding for Pub/Sub messages
158
+ * - Non-blocking parsing using setImmediate
159
+ *
160
+ * @template T - The expected type of the parsed body. Defaults to unknown if not specified.
161
+ * @implements {BaseMiddleware}
162
+ */
163
+ class BodyParserMiddleware {
164
+ maxSize;
165
+ constructor(maxSize = MAX_JSON_SIZE) {
166
+ this.maxSize = maxSize;
167
+ }
168
+ async before(context) {
169
+ // Check content-length early to avoid processing oversized requests
170
+ const headers = context.req.headers || {};
171
+ const contentLength = headers['content-length'];
172
+ if (contentLength) {
173
+ const length = Array.isArray(contentLength)
174
+ ? contentLength[0]
175
+ : contentLength;
176
+ if (length && parseInt(length) > this.maxSize) {
177
+ throw new core_1.TooLargeError('Request body too large');
178
+ }
179
+ }
180
+ context.req.parsedBody = await parseBody(context.req.body);
181
+ }
182
+ }
183
+ exports.BodyParserMiddleware = BodyParserMiddleware;
184
+ /**
185
+ * Enhanced middleware function for parsing the request body in specific HTTP methods.
186
+ *
187
+ * Performance optimizations:
188
+ * - Early method validation
189
+ * - Async parsing for large payloads
190
+ * - Size validation
191
+ *
192
+ * @template T - The expected type of the parsed request body.
193
+ * @returns {BaseMiddleware} A middleware object containing a `before` hook.
194
+ */
195
+ const bodyParser = (maxSize = MAX_JSON_SIZE) => ({
196
+ before: async (context) => {
197
+ const { method, body } = context.req;
198
+ // Performance optimization: Early return for methods that don't typically have bodies
199
+ if (!method || !['POST', 'PUT', 'PATCH'].includes(method)) {
200
+ return;
201
+ }
202
+ // Check content-length early
203
+ const headers = context.req.headers || {};
204
+ const contentLength = headers['content-length'];
205
+ if (contentLength) {
206
+ const length = Array.isArray(contentLength)
207
+ ? contentLength[0]
208
+ : contentLength;
209
+ if (length && parseInt(length) > maxSize) {
210
+ throw new core_1.TooLargeError('Request body too large');
211
+ }
212
+ }
213
+ context.req.parsedBody = await parseBody(body);
214
+ },
215
+ });
216
+ exports.bodyParser = bodyParser;
217
+ //# sourceMappingURL=bodyParserMiddleware.js.map
@@ -0,0 +1,12 @@
1
+ import { BaseMiddleware } from '../core/handler';
2
+ import { Context } from '../core/core';
3
+ import { z } from 'zod';
4
+ export declare class BodyValidationMiddleware<T = unknown> implements BaseMiddleware {
5
+ private readonly schema;
6
+ constructor(schema: z.ZodSchema<T>);
7
+ before(context: Context): Promise<void>;
8
+ }
9
+ export declare const bodyValidatorMiddleware: <T>(schema: z.ZodType<T>) => {
10
+ before: (context: Context) => Promise<void>;
11
+ };
12
+ //# sourceMappingURL=bodyValidationMiddleware.d.ts.map
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.bodyValidatorMiddleware = exports.BodyValidationMiddleware = void 0;
4
+ const zod_1 = require("zod");
5
+ const errors_1 = require("../core/errors");
6
+ const validateBody = async (schema, data) => {
7
+ try {
8
+ return await schema.parseAsync(data);
9
+ }
10
+ catch (error) {
11
+ if (error instanceof zod_1.z.ZodError) {
12
+ throw new errors_1.ValidationError('Validation error', error.errors);
13
+ }
14
+ throw error;
15
+ }
16
+ };
17
+ class BodyValidationMiddleware {
18
+ schema;
19
+ constructor(schema) {
20
+ this.schema = schema;
21
+ }
22
+ async before(context) {
23
+ context.req.validatedBody = await validateBody(this.schema, context.req.parsedBody);
24
+ }
25
+ }
26
+ exports.BodyValidationMiddleware = BodyValidationMiddleware;
27
+ // Modified to fix type instantiation error
28
+ const bodyValidatorMiddleware = (schema) => ({
29
+ before: async (context) => {
30
+ context.req.parsedBody = await validateBody(schema, context.req.body);
31
+ },
32
+ });
33
+ exports.bodyValidatorMiddleware = bodyValidatorMiddleware;
34
+ //# sourceMappingURL=bodyValidationMiddleware.js.map
@@ -0,0 +1,14 @@
1
+ import { BaseMiddleware, Context } from '../core';
2
+ export declare class DependencyInjectionMiddleware implements BaseMiddleware {
3
+ private services;
4
+ constructor(services: {
5
+ id: any;
6
+ value: any;
7
+ }[]);
8
+ before(context: Context): Promise<void>;
9
+ }
10
+ export declare const dependencyInjection: (services?: {
11
+ id: any;
12
+ value: any;
13
+ }[]) => BaseMiddleware;
14
+ //# sourceMappingURL=dependencyInjectionMiddleware.d.ts.map
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ /* eslint-disable @typescript-eslint/no-explicit-any */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.dependencyInjection = exports.DependencyInjectionMiddleware = void 0;
5
+ const typedi_1 = require("typedi");
6
+ class DependencyInjectionMiddleware {
7
+ services;
8
+ constructor(services) {
9
+ this.services = services;
10
+ }
11
+ async before(context) {
12
+ this.services.forEach((service) => {
13
+ typedi_1.Container.set(service.id, service.value);
14
+ });
15
+ context.container = typedi_1.Container;
16
+ }
17
+ }
18
+ exports.DependencyInjectionMiddleware = DependencyInjectionMiddleware;
19
+ const dependencyInjection = (services = []) => ({
20
+ before: async (context) => {
21
+ services.forEach((service) => {
22
+ typedi_1.Container.set(service.id, service.value);
23
+ });
24
+ context.container = typedi_1.Container.of();
25
+ },
26
+ });
27
+ exports.dependencyInjection = dependencyInjection;
28
+ /*
29
+ // Initialize services
30
+ const services = [
31
+ { id: 'businessData', value: new Map<string, any>() },
32
+ { id: UserService, value: new UserService(new Map<string, any>()) }
33
+ ];
34
+
35
+ // Create an instance of DependencyInjectionMiddleware with the services
36
+ const diMiddleware = new DependencyInjectionMiddleware(services);
37
+
38
+ // Example handler using the middleware
39
+ const exampleHandler = new Handler()
40
+ .use(diMiddleware)
41
+ .use(errorHandler())
42
+ .use(responseWrapperMiddleware<any>())
43
+ .handle(async (context: Context) => {
44
+ const businessData = context.container?.get('businessData');
45
+ setResponseData(context, { message: 'Dependency Injection Middleware example', businessData });
46
+ });
47
+ */
48
+ //# sourceMappingURL=dependencyInjectionMiddleware.js.map
@@ -0,0 +1,6 @@
1
+ import { BaseMiddleware, Context } from '../core';
2
+ export declare class ErrorHandlerMiddleware implements BaseMiddleware {
3
+ onError(error: Error, context: Context): Promise<void>;
4
+ }
5
+ export declare const errorHandler: () => BaseMiddleware;
6
+ //# sourceMappingURL=errorHandlerMiddleware.d.ts.map
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.errorHandler = exports.ErrorHandlerMiddleware = void 0;
4
+ const core_1 = require("../core");
5
+ const handleError = async (error, context) => {
6
+ const isDevelopment = process.env.NODE_ENV === 'development' || process.env.DEBUG === 'true';
7
+ core_1.logger.error('Error processing request', {
8
+ errorMessage: error?.message,
9
+ errorStack: error?.stack,
10
+ requestId: context.requestId,
11
+ userAgent: context.req.headers?.['user-agent'],
12
+ ip: context.req.ip || 'unknown',
13
+ });
14
+ if (error instanceof core_1.HttpError) {
15
+ const responsePayload = {
16
+ success: false,
17
+ payload: {
18
+ error: error.message,
19
+ },
20
+ timestamp: new Date().toISOString(),
21
+ };
22
+ // Only include sensitive details in development
23
+ if (isDevelopment && error.details) {
24
+ responsePayload.payload.details = error.details;
25
+ }
26
+ // Only include error codes for client errors (4xx), not server errors
27
+ if (error.code && error.status < 500) {
28
+ responsePayload.payload.code = error.code;
29
+ }
30
+ context.res.status(error.status).json(responsePayload);
31
+ }
32
+ else {
33
+ // For non-HttpError exceptions, provide generic error message in production
34
+ const errorMessage = isDevelopment
35
+ ? error.message
36
+ : 'Internal Server Error';
37
+ const responsePayload = {
38
+ error: 'Internal Server Error',
39
+ success: false,
40
+ payload: {
41
+ error: errorMessage,
42
+ },
43
+ timestamp: new Date().toISOString(),
44
+ };
45
+ // Add stack trace in development for non-HTTP errors
46
+ if (isDevelopment && error.stack) {
47
+ responsePayload.payload.stack = error.stack;
48
+ }
49
+ context.res.status(500).json(responsePayload);
50
+ }
51
+ };
52
+ class ErrorHandlerMiddleware {
53
+ async onError(error, context) {
54
+ await handleError(error, context);
55
+ }
56
+ }
57
+ exports.ErrorHandlerMiddleware = ErrorHandlerMiddleware;
58
+ const errorHandler = () => ({
59
+ onError: async (error, context) => {
60
+ await handleError(error, context);
61
+ },
62
+ });
63
+ exports.errorHandler = errorHandler;
64
+ //# sourceMappingURL=errorHandlerMiddleware.js.map
@@ -0,0 +1,8 @@
1
+ import { BaseMiddleware, Context } from '../core';
2
+ export declare class HeaderVariablesMiddleware implements BaseMiddleware {
3
+ private requiredHeaders;
4
+ constructor(requiredHeaders: string[]);
5
+ before(context: Context): Promise<void>;
6
+ }
7
+ export declare const headerVariablesMiddleware: (requiredHeaders: string[]) => BaseMiddleware;
8
+ //# sourceMappingURL=headerVariablesMiddleware.d.ts.map
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.headerVariablesMiddleware = exports.HeaderVariablesMiddleware = void 0;
4
+ const core_1 = require("../core");
5
+ const validateHeaders = (requiredHeaders, headers) => {
6
+ for (const header of requiredHeaders) {
7
+ const headerValue = headers[header.toLowerCase()];
8
+ if (!headerValue ||
9
+ (Array.isArray(headerValue) && headerValue.length === 0)) {
10
+ throw new core_1.ValidationError(`Missing required header: ${header}`);
11
+ }
12
+ }
13
+ };
14
+ class HeaderVariablesMiddleware {
15
+ requiredHeaders;
16
+ constructor(requiredHeaders) {
17
+ this.requiredHeaders = requiredHeaders;
18
+ }
19
+ async before(context) {
20
+ context.req.headers = context.req.headers || {};
21
+ validateHeaders(this.requiredHeaders, context.req.headers);
22
+ }
23
+ }
24
+ exports.HeaderVariablesMiddleware = HeaderVariablesMiddleware;
25
+ const headerVariablesMiddleware = (requiredHeaders) => ({
26
+ async before(context) {
27
+ context.req.headers = context.req.headers || {};
28
+ validateHeaders(requiredHeaders, context.req.headers);
29
+ },
30
+ });
31
+ exports.headerVariablesMiddleware = headerVariablesMiddleware;
32
+ //# sourceMappingURL=headerVariablesMiddleware.js.map
@@ -0,0 +1,10 @@
1
+ import { Context } from '../core/core';
2
+ import { BaseMiddleware } from '../core/handler';
3
+ import { ZodSchema } from 'zod';
4
+ export declare class PathParametersMiddleware implements BaseMiddleware {
5
+ before(context: Context): Promise<void>;
6
+ }
7
+ export declare const pathParameters: () => BaseMiddleware;
8
+ export declare const headerVariablesValidator: (requiredHeaders: string[]) => BaseMiddleware;
9
+ export declare const validatedQueryParameters: (schema: ZodSchema) => BaseMiddleware;
10
+ //# sourceMappingURL=httpAttributesMiddleware.d.ts.map
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validatedQueryParameters = exports.headerVariablesValidator = exports.pathParameters = exports.PathParametersMiddleware = void 0;
4
+ const errors_1 = require("../core/errors");
5
+ const zod_1 = require("zod");
6
+ class PathParametersMiddleware {
7
+ async before(context) {
8
+ const host = (Array.isArray(context.req.headers.host)
9
+ ? context.req.headers.host[0]
10
+ : context.req.headers.host) || 'localhost';
11
+ const url = new URL(context.req.url, `http://${host}`);
12
+ const pathSegments = url.pathname.split('/').filter(Boolean);
13
+ context.req.params = context.req.params || {};
14
+ // Extract path parameters based on your routing configuration
15
+ // This is a simplified example
16
+ pathSegments.forEach((segment, index) => {
17
+ if (segment.startsWith(':')) {
18
+ const paramName = segment.slice(1);
19
+ if (context.req.params) {
20
+ context.req.params[paramName] = pathSegments[index];
21
+ }
22
+ }
23
+ });
24
+ }
25
+ }
26
+ exports.PathParametersMiddleware = PathParametersMiddleware;
27
+ const pathParameters = () => ({
28
+ before: async (context) => {
29
+ const host = (Array.isArray(context.req.headers.host)
30
+ ? context.req.headers.host[0]
31
+ : context.req.headers.host) || 'localhost';
32
+ const url = new URL(context.req.url, `http://${host}`);
33
+ const pathSegments = url.pathname.split('/').filter(Boolean);
34
+ context.req.params = { ...context.req.params };
35
+ pathSegments.forEach((segment, index) => {
36
+ if (segment.startsWith(':')) {
37
+ const paramName = segment.slice(1);
38
+ if (context.req.params) {
39
+ context.req.params[paramName] = pathSegments[index];
40
+ }
41
+ }
42
+ });
43
+ },
44
+ });
45
+ exports.pathParameters = pathParameters;
46
+ const headerVariablesValidator = (requiredHeaders) => ({
47
+ before: async (context) => {
48
+ for (const header of requiredHeaders) {
49
+ if (!context.req.headers?.[header.toLowerCase()]) {
50
+ throw new errors_1.ValidationError(`Missing required header: ${header}`);
51
+ }
52
+ }
53
+ },
54
+ });
55
+ exports.headerVariablesValidator = headerVariablesValidator;
56
+ const validatedQueryParameters = (schema) => ({
57
+ before: async (context) => {
58
+ const queryParams = context.req.query;
59
+ try {
60
+ schema.parse(queryParams);
61
+ }
62
+ catch (error) {
63
+ if (error instanceof zod_1.z.ZodError) {
64
+ throw new errors_1.ValidationError('Validation error', JSON.stringify(error.errors));
65
+ }
66
+ throw error;
67
+ }
68
+ },
69
+ });
70
+ exports.validatedQueryParameters = validatedQueryParameters;
71
+ //# sourceMappingURL=httpAttributesMiddleware.js.map
@@ -0,0 +1,14 @@
1
+ export * from './authenticationMiddleware';
2
+ export * from './bodyParserMiddleware';
3
+ export * from './bodyValidationMiddleware';
4
+ export * from './dependencyInjectionMiddleware';
5
+ export * from './errorHandlerMiddleware';
6
+ export * from './headerVariablesMiddleware';
7
+ export * from './httpAttributesMiddleware';
8
+ export * from './queryParametersMiddleware';
9
+ export * from './rateLimitingMiddleware';
10
+ export * from './responseWrapperMiddleware';
11
+ export * from './securityAuditMiddleware';
12
+ export * from './securityHeadersMiddleware';
13
+ export * from './validationMiddleware';
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./authenticationMiddleware"), exports);
18
+ __exportStar(require("./bodyParserMiddleware"), exports);
19
+ __exportStar(require("./bodyValidationMiddleware"), exports);
20
+ __exportStar(require("./dependencyInjectionMiddleware"), exports);
21
+ __exportStar(require("./errorHandlerMiddleware"), exports);
22
+ __exportStar(require("./headerVariablesMiddleware"), exports);
23
+ __exportStar(require("./httpAttributesMiddleware"), exports);
24
+ __exportStar(require("./queryParametersMiddleware"), exports);
25
+ __exportStar(require("./rateLimitingMiddleware"), exports);
26
+ __exportStar(require("./responseWrapperMiddleware"), exports);
27
+ __exportStar(require("./securityAuditMiddleware"), exports);
28
+ __exportStar(require("./securityHeadersMiddleware"), exports);
29
+ __exportStar(require("./validationMiddleware"), exports);
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,8 @@
1
+ import { BaseMiddleware, Context } from '../core';
2
+ export declare class QueryParametersMiddleware implements BaseMiddleware {
3
+ private readonly requiredParams;
4
+ constructor(requiredParams?: string[]);
5
+ before(context: Context): Promise<void>;
6
+ }
7
+ export declare const queryParametersMiddleware: (requiredParams?: string[]) => BaseMiddleware;
8
+ //# sourceMappingURL=queryParametersMiddleware.d.ts.map
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.queryParametersMiddleware = exports.QueryParametersMiddleware = void 0;
4
+ const core_1 = require("../core");
5
+ const validateQueryParameters = (requiredParams, query) => {
6
+ for (const param of requiredParams) {
7
+ if (!query[param]) {
8
+ throw new core_1.ValidationError(`Missing required query parameter: ${param}`);
9
+ }
10
+ }
11
+ };
12
+ const convertQueryToRecord = (query) => {
13
+ const result = {};
14
+ for (const key in query) {
15
+ if (query[key] !== undefined) {
16
+ result[key] = Array.isArray(query[key])
17
+ ? query[key].map(String)
18
+ : String(query[key]);
19
+ }
20
+ }
21
+ return result;
22
+ };
23
+ class QueryParametersMiddleware {
24
+ requiredParams;
25
+ constructor(requiredParams = []) {
26
+ this.requiredParams = requiredParams;
27
+ }
28
+ async before(context) {
29
+ const host = (Array.isArray(context.req.headers.host)
30
+ ? context.req.headers.host[0]
31
+ : context.req.headers.host) || 'localhost';
32
+ const url = new URL(context.req.url, `http://${host}`);
33
+ context.req.query = Object.fromEntries(url.searchParams);
34
+ const query = convertQueryToRecord(context.req.query);
35
+ validateQueryParameters(this.requiredParams, query);
36
+ }
37
+ }
38
+ exports.QueryParametersMiddleware = QueryParametersMiddleware;
39
+ const queryParametersMiddleware = (requiredParams = []) => ({
40
+ async before(context) {
41
+ const host = (Array.isArray(context.req.headers.host)
42
+ ? context.req.headers.host[0]
43
+ : context.req.headers.host) || 'localhost';
44
+ const url = new URL(context.req.url, `http://${host}`);
45
+ context.req.query = Object.fromEntries(url.searchParams);
46
+ const query = convertQueryToRecord(context.req.query);
47
+ validateQueryParameters(requiredParams, query);
48
+ },
49
+ });
50
+ exports.queryParametersMiddleware = queryParametersMiddleware;
51
+ //# sourceMappingURL=queryParametersMiddleware.js.map