@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,157 @@
1
+ import { BaseMiddleware, Context } from '../core';
2
+ export interface RateLimitOptions {
3
+ /**
4
+ * Maximum number of requests per window
5
+ * @default 100
6
+ */
7
+ maxRequests?: number;
8
+ /**
9
+ * Time window in milliseconds
10
+ * @default 60000 (1 minute)
11
+ */
12
+ windowMs?: number;
13
+ /**
14
+ * Function to generate rate limiting key
15
+ * @default Uses IP address
16
+ */
17
+ keyGenerator?: (context: Context) => string;
18
+ /**
19
+ * Custom error message
20
+ * @default 'Too many requests, please try again later'
21
+ */
22
+ message?: string;
23
+ /**
24
+ * HTTP status code for rate limit exceeded
25
+ * @default 429
26
+ */
27
+ statusCode?: number;
28
+ /**
29
+ * Skip rate limiting for certain requests
30
+ */
31
+ skip?: (context: Context) => boolean;
32
+ /**
33
+ * Headers to include in response
34
+ */
35
+ headers?: boolean;
36
+ /**
37
+ * Different limits for different request types
38
+ */
39
+ dynamicLimits?: {
40
+ [key: string]: {
41
+ maxRequests: number;
42
+ windowMs: number;
43
+ matcher: (context: Context) => boolean;
44
+ };
45
+ };
46
+ /**
47
+ * Storage backend (default: in-memory)
48
+ * Use Redis or other persistent storage in production
49
+ */
50
+ store?: RateLimitStore;
51
+ }
52
+ export interface RateLimitStore {
53
+ increment(key: string, windowMs: number): Promise<{
54
+ count: number;
55
+ resetTime: number;
56
+ }>;
57
+ get(key: string): Promise<{
58
+ count: number;
59
+ resetTime: number;
60
+ } | null>;
61
+ reset(key: string): Promise<void>;
62
+ }
63
+ export interface RateLimitInfo {
64
+ limit: number;
65
+ current: number;
66
+ remaining: number;
67
+ resetTime: number;
68
+ }
69
+ /**
70
+ * In-memory rate limit store (use Redis in production)
71
+ */
72
+ declare class MemoryStore implements RateLimitStore {
73
+ private store;
74
+ private cleanupInterval;
75
+ constructor();
76
+ increment(key: string, windowMs: number): Promise<{
77
+ count: number;
78
+ resetTime: number;
79
+ }>;
80
+ get(key: string): Promise<{
81
+ count: number;
82
+ resetTime: number;
83
+ } | null>;
84
+ reset(key: string): Promise<void>;
85
+ private cleanup;
86
+ destroy(): void;
87
+ }
88
+ /**
89
+ * Rate Limiting Middleware
90
+ * Implements sliding window rate limiting with comprehensive features
91
+ */
92
+ export declare class RateLimitingMiddleware implements BaseMiddleware {
93
+ private store;
94
+ private options;
95
+ constructor(options?: RateLimitOptions);
96
+ before(context: Context): Promise<void>;
97
+ }
98
+ /**
99
+ * Rate Limiting Middleware Factory
100
+ * @param options Rate limiting configuration
101
+ * @returns BaseMiddleware
102
+ */
103
+ export declare const rateLimiting: (options?: RateLimitOptions) => BaseMiddleware;
104
+ /**
105
+ * Predefined rate limit configurations
106
+ */
107
+ export declare const RateLimitPresets: {
108
+ /**
109
+ * Very strict limits for sensitive endpoints
110
+ */
111
+ readonly STRICT: {
112
+ maxRequests: number;
113
+ windowMs: number;
114
+ message: string;
115
+ };
116
+ /**
117
+ * Standard API limits
118
+ */
119
+ readonly API: {
120
+ maxRequests: number;
121
+ windowMs: number;
122
+ dynamicLimits: {
123
+ authenticated: {
124
+ maxRequests: number;
125
+ windowMs: number;
126
+ matcher: (context: Context) => boolean;
127
+ };
128
+ };
129
+ };
130
+ /**
131
+ * Authentication endpoint limits
132
+ */
133
+ readonly AUTH: {
134
+ maxRequests: number;
135
+ windowMs: number;
136
+ message: string;
137
+ };
138
+ /**
139
+ * Public endpoint limits
140
+ */
141
+ readonly PUBLIC: {
142
+ maxRequests: number;
143
+ windowMs: number;
144
+ };
145
+ /**
146
+ * Development mode - very permissive
147
+ */
148
+ readonly DEVELOPMENT: {
149
+ maxRequests: number;
150
+ windowMs: number;
151
+ };
152
+ };
153
+ /**
154
+ * Export memory store for testing and custom implementations
155
+ */
156
+ export { MemoryStore };
157
+ //# sourceMappingURL=rateLimitingMiddleware.d.ts.map
@@ -0,0 +1,237 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MemoryStore = exports.RateLimitPresets = exports.rateLimiting = exports.RateLimitingMiddleware = void 0;
4
+ const core_1 = require("../core");
5
+ const logger_1 = require("../core/logger");
6
+ /**
7
+ * In-memory rate limit store (use Redis in production)
8
+ */
9
+ class MemoryStore {
10
+ store = new Map();
11
+ cleanupInterval;
12
+ constructor() {
13
+ // Cleanup expired entries every 5 minutes
14
+ this.cleanupInterval = setInterval(() => {
15
+ this.cleanup();
16
+ }, 5 * 60 * 1000);
17
+ }
18
+ async increment(key, windowMs) {
19
+ const now = Date.now();
20
+ const resetTime = now + windowMs;
21
+ const existing = this.store.get(key);
22
+ if (existing && now < existing.resetTime) {
23
+ existing.count++;
24
+ return existing;
25
+ }
26
+ else {
27
+ const newEntry = { count: 1, resetTime };
28
+ this.store.set(key, newEntry);
29
+ return newEntry;
30
+ }
31
+ }
32
+ async get(key) {
33
+ const entry = this.store.get(key);
34
+ if (entry && Date.now() < entry.resetTime) {
35
+ return entry;
36
+ }
37
+ if (entry) {
38
+ this.store.delete(key);
39
+ }
40
+ return null;
41
+ }
42
+ async reset(key) {
43
+ this.store.delete(key);
44
+ }
45
+ cleanup() {
46
+ const now = Date.now();
47
+ for (const [key, entry] of this.store.entries()) {
48
+ if (now >= entry.resetTime) {
49
+ this.store.delete(key);
50
+ }
51
+ }
52
+ }
53
+ destroy() {
54
+ clearInterval(this.cleanupInterval);
55
+ this.store.clear();
56
+ }
57
+ }
58
+ exports.MemoryStore = MemoryStore;
59
+ /**
60
+ * Default key generator using IP address with user identification
61
+ */
62
+ const defaultKeyGenerator = (context) => {
63
+ const ip = context.req.ip ||
64
+ (Array.isArray(context.req.headers?.['x-forwarded-for'])
65
+ ? context.req.headers['x-forwarded-for'][0]
66
+ : context.req.headers?.['x-forwarded-for']) ||
67
+ 'unknown';
68
+ // Include user ID if authenticated for per-user limits
69
+ const userId = context.user && typeof context.user === 'object' && 'sub' in context.user
70
+ ? context.user.sub
71
+ : null;
72
+ return userId ? `user:${userId}` : `ip:${ip}`;
73
+ };
74
+ /**
75
+ * Apply rate limit headers to response
76
+ */
77
+ const setRateLimitHeaders = (context, info) => {
78
+ context.res.header('X-RateLimit-Limit', String(info.limit));
79
+ context.res.header('X-RateLimit-Remaining', String(Math.max(0, info.remaining)));
80
+ context.res.header('X-RateLimit-Reset', String(Math.ceil(info.resetTime / 1000)));
81
+ context.res.header('Retry-After', String(Math.ceil((info.resetTime - Date.now()) / 1000)));
82
+ };
83
+ /**
84
+ * Determine the appropriate rate limit for the request
85
+ */
86
+ const getRateLimit = (context, options) => {
87
+ // Check dynamic limits first
88
+ if (options.dynamicLimits) {
89
+ for (const [name, config] of Object.entries(options.dynamicLimits)) {
90
+ if (config.matcher(context)) {
91
+ logger_1.logger.debug('Applied dynamic rate limit', {
92
+ limitName: name,
93
+ maxRequests: config.maxRequests,
94
+ windowMs: config.windowMs,
95
+ });
96
+ return { maxRequests: config.maxRequests, windowMs: config.windowMs };
97
+ }
98
+ }
99
+ }
100
+ // Default limits
101
+ return {
102
+ maxRequests: options.maxRequests || 100,
103
+ windowMs: options.windowMs || 60000,
104
+ };
105
+ };
106
+ /**
107
+ * Rate Limiting Middleware
108
+ * Implements sliding window rate limiting with comprehensive features
109
+ */
110
+ class RateLimitingMiddleware {
111
+ store;
112
+ options;
113
+ constructor(options = {}) {
114
+ this.store = options.store || new MemoryStore();
115
+ this.options = {
116
+ maxRequests: 100,
117
+ windowMs: 60000,
118
+ message: 'Too many requests, please try again later',
119
+ statusCode: 429,
120
+ headers: true,
121
+ keyGenerator: options.keyGenerator || defaultKeyGenerator,
122
+ skip: options.skip,
123
+ dynamicLimits: options.dynamicLimits,
124
+ store: options.store,
125
+ };
126
+ }
127
+ async before(context) {
128
+ // Skip rate limiting if configured
129
+ if (this.options.skip && this.options.skip(context)) {
130
+ return;
131
+ }
132
+ const key = this.options.keyGenerator(context);
133
+ const { maxRequests, windowMs } = getRateLimit(context, this.options);
134
+ try {
135
+ const result = await this.store.increment(key, windowMs);
136
+ const rateLimitInfo = {
137
+ limit: maxRequests,
138
+ current: result.count,
139
+ remaining: Math.max(0, maxRequests - result.count),
140
+ resetTime: result.resetTime,
141
+ };
142
+ // Set rate limit headers
143
+ if (this.options.headers) {
144
+ setRateLimitHeaders(context, rateLimitInfo);
145
+ }
146
+ // Check if limit exceeded
147
+ if (result.count > maxRequests) {
148
+ logger_1.logger.warn('Rate limit exceeded', {
149
+ key,
150
+ count: result.count,
151
+ limit: maxRequests,
152
+ resetTime: new Date(result.resetTime).toISOString(),
153
+ userAgent: context.req.headers?.['user-agent'],
154
+ endpoint: context.req.path || context.req.url,
155
+ });
156
+ throw new core_1.SecurityError(this.options.message);
157
+ }
158
+ // Log approaching limit
159
+ if (result.count > maxRequests * 0.8) {
160
+ logger_1.logger.debug('Approaching rate limit', {
161
+ key,
162
+ count: result.count,
163
+ limit: maxRequests,
164
+ percentage: Math.round((result.count / maxRequests) * 100),
165
+ });
166
+ }
167
+ }
168
+ catch (error) {
169
+ if (error instanceof core_1.SecurityError) {
170
+ throw error;
171
+ }
172
+ // Log store errors but don't block requests
173
+ logger_1.logger.error('Rate limiting store error', {
174
+ error: error instanceof Error ? error.message : 'Unknown error',
175
+ key,
176
+ });
177
+ }
178
+ }
179
+ }
180
+ exports.RateLimitingMiddleware = RateLimitingMiddleware;
181
+ /**
182
+ * Rate Limiting Middleware Factory
183
+ * @param options Rate limiting configuration
184
+ * @returns BaseMiddleware
185
+ */
186
+ const rateLimiting = (options = {}) => new RateLimitingMiddleware(options);
187
+ exports.rateLimiting = rateLimiting;
188
+ /**
189
+ * Predefined rate limit configurations
190
+ */
191
+ exports.RateLimitPresets = {
192
+ /**
193
+ * Very strict limits for sensitive endpoints
194
+ */
195
+ STRICT: {
196
+ maxRequests: 5,
197
+ windowMs: 60000, // 1 minute
198
+ message: 'Too many requests to sensitive endpoint',
199
+ },
200
+ /**
201
+ * Standard API limits
202
+ */
203
+ API: {
204
+ maxRequests: 100,
205
+ windowMs: 60000, // 1 minute
206
+ dynamicLimits: {
207
+ authenticated: {
208
+ maxRequests: 1000,
209
+ windowMs: 60000,
210
+ matcher: (context) => !!context.user,
211
+ },
212
+ },
213
+ },
214
+ /**
215
+ * Authentication endpoint limits
216
+ */
217
+ AUTH: {
218
+ maxRequests: 10,
219
+ windowMs: 60000, // 1 minute
220
+ message: 'Too many authentication attempts',
221
+ },
222
+ /**
223
+ * Public endpoint limits
224
+ */
225
+ PUBLIC: {
226
+ maxRequests: 50,
227
+ windowMs: 60000, // 1 minute
228
+ },
229
+ /**
230
+ * Development mode - very permissive
231
+ */
232
+ DEVELOPMENT: {
233
+ maxRequests: 10000,
234
+ windowMs: 60000, // 1 minute
235
+ },
236
+ };
237
+ //# sourceMappingURL=rateLimitingMiddleware.js.map
@@ -0,0 +1,11 @@
1
+ import { BaseMiddleware } from '../core/handler';
2
+ import { Context } from '../core/core';
3
+ export declare class ResponseWrapperMiddleware<T> implements BaseMiddleware {
4
+ after(context: Context): Promise<void>;
5
+ }
6
+ export declare const responseWrapperMiddleware: <T>() => BaseMiddleware;
7
+ /**
8
+ * Helper function to set response data in context for later wrapping
9
+ */
10
+ export declare function setResponseData<T>(context: Context, data: T): void;
11
+ //# sourceMappingURL=responseWrapperMiddleware.d.ts.map
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.responseWrapperMiddleware = exports.ResponseWrapperMiddleware = void 0;
4
+ exports.setResponseData = setResponseData;
5
+ const wrapResponse = (context) => {
6
+ if (!context.res.headersSent) {
7
+ const statusCode = context.res.statusCode || 200;
8
+ const body = context.responseData;
9
+ context.res.status(statusCode).json({
10
+ success: true,
11
+ payload: body,
12
+ timestamp: new Date().toISOString(),
13
+ });
14
+ }
15
+ };
16
+ class ResponseWrapperMiddleware {
17
+ async after(context) {
18
+ wrapResponse(context);
19
+ }
20
+ }
21
+ exports.ResponseWrapperMiddleware = ResponseWrapperMiddleware;
22
+ const responseWrapperMiddleware = () => ({
23
+ after: async (context) => {
24
+ wrapResponse(context);
25
+ },
26
+ });
27
+ exports.responseWrapperMiddleware = responseWrapperMiddleware;
28
+ /**
29
+ * Helper function to set response data in context for later wrapping
30
+ */
31
+ function setResponseData(context, data) {
32
+ context.responseData = data;
33
+ }
34
+ //# sourceMappingURL=responseWrapperMiddleware.js.map
@@ -0,0 +1,124 @@
1
+ import { BaseMiddleware, Context } from '../core';
2
+ export interface SecurityEvent {
3
+ type: SecurityEventType;
4
+ severity: SecuritySeverity;
5
+ timestamp: string;
6
+ requestId: string;
7
+ clientIP: string;
8
+ userAgent?: string;
9
+ userId?: string;
10
+ endpoint: string;
11
+ method: string;
12
+ details: Record<string, unknown>;
13
+ }
14
+ export type SecurityEventType = 'SUSPICIOUS_REQUEST' | 'AUTHENTICATION_FAILURE' | 'AUTHORIZATION_FAILURE' | 'RATE_LIMIT_EXCEEDED' | 'INVALID_INPUT' | 'TOKEN_MANIPULATION' | 'UNUSUAL_BEHAVIOR' | 'SECURITY_HEADER_VIOLATION' | 'INJECTION_ATTEMPT' | 'MALFORMED_REQUEST';
15
+ export type SecuritySeverity = 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
16
+ export interface SecurityAuditOptions {
17
+ /**
18
+ * Enable detailed request logging
19
+ * @default false
20
+ */
21
+ logRequests?: boolean;
22
+ /**
23
+ * Enable response logging
24
+ * @default false
25
+ */
26
+ logResponses?: boolean;
27
+ /**
28
+ * Log request/response bodies (be careful with sensitive data)
29
+ * @default false
30
+ */
31
+ logBodies?: boolean;
32
+ /**
33
+ * Maximum body size to log (in bytes)
34
+ * @default 1024
35
+ */
36
+ maxBodyLogSize?: number;
37
+ /**
38
+ * Headers to exclude from logging (security headers, auth tokens, etc.)
39
+ */
40
+ excludeHeaders?: string[];
41
+ /**
42
+ * Custom security event handler
43
+ */
44
+ onSecurityEvent?: (event: SecurityEvent) => Promise<void> | void;
45
+ /**
46
+ * Enable anomaly detection
47
+ * @default true
48
+ */
49
+ enableAnomalyDetection?: boolean;
50
+ /**
51
+ * Suspicious patterns to detect
52
+ */
53
+ suspiciousPatterns?: {
54
+ sqlInjection?: RegExp[];
55
+ xss?: RegExp[];
56
+ pathTraversal?: RegExp[];
57
+ commandInjection?: RegExp[];
58
+ };
59
+ }
60
+ /**
61
+ * Security event tracking for anomaly detection
62
+ */
63
+ declare class SecurityEventTracker {
64
+ private events;
65
+ private readonly maxEventsPerClient;
66
+ private readonly timeWindow;
67
+ addEvent(event: SecurityEvent): void;
68
+ getClientEvents(clientIP: string, minutes?: number): SecurityEvent[];
69
+ detectAnomalies(clientIP: string): SecurityEvent[];
70
+ }
71
+ declare const securityEventTracker: SecurityEventTracker;
72
+ /**
73
+ * Security Audit Middleware
74
+ * Provides comprehensive security event logging and monitoring
75
+ */
76
+ export declare class SecurityAuditMiddleware implements BaseMiddleware {
77
+ private options;
78
+ constructor(options?: SecurityAuditOptions);
79
+ before(context: Context): Promise<void>;
80
+ after(context: Context): Promise<void>;
81
+ onError(error: Error, context: Context): Promise<void>;
82
+ private logSecurityEvent;
83
+ private sanitizeHeaders;
84
+ }
85
+ /**
86
+ * Security Audit Middleware Factory
87
+ * @param options Security audit configuration
88
+ * @returns BaseMiddleware
89
+ */
90
+ export declare const securityAudit: (options?: SecurityAuditOptions) => BaseMiddleware;
91
+ /**
92
+ * Predefined security audit configurations
93
+ */
94
+ export declare const SecurityAuditPresets: {
95
+ /**
96
+ * Full monitoring with detailed logging
97
+ */
98
+ readonly COMPREHENSIVE: {
99
+ logRequests: true;
100
+ logResponses: true;
101
+ logBodies: false;
102
+ enableAnomalyDetection: true;
103
+ };
104
+ /**
105
+ * Security events only
106
+ */
107
+ readonly SECURITY_ONLY: {
108
+ logRequests: false;
109
+ logResponses: false;
110
+ logBodies: false;
111
+ enableAnomalyDetection: true;
112
+ };
113
+ /**
114
+ * Development mode with full logging
115
+ */
116
+ readonly DEVELOPMENT: {
117
+ logRequests: true;
118
+ logResponses: true;
119
+ logBodies: true;
120
+ enableAnomalyDetection: false;
121
+ };
122
+ };
123
+ export { securityEventTracker };
124
+ //# sourceMappingURL=securityAuditMiddleware.d.ts.map