@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.
- package/README.md +443 -0
- package/build/core/containerPool.d.ts +44 -0
- package/build/core/containerPool.js +103 -0
- package/build/core/core.d.ts +123 -0
- package/build/core/core.js +107 -0
- package/build/core/errors.d.ts +25 -0
- package/build/core/errors.js +59 -0
- package/build/core/handler.d.ts +72 -0
- package/build/core/handler.js +151 -0
- package/build/core/index.d.ts +8 -0
- package/build/core/index.js +24 -0
- package/build/core/logger.d.ts +42 -0
- package/build/core/logger.js +135 -0
- package/build/core/performanceMonitor.d.ts +73 -0
- package/build/core/performanceMonitor.js +189 -0
- package/build/index.d.ts +3 -0
- package/build/index.js +19 -0
- package/build/middlewares/authenticationMiddleware.d.ts +52 -0
- package/build/middlewares/authenticationMiddleware.js +204 -0
- package/build/middlewares/bodyParserMiddleware.d.ts +31 -0
- package/build/middlewares/bodyParserMiddleware.js +217 -0
- package/build/middlewares/bodyValidationMiddleware.d.ts +12 -0
- package/build/middlewares/bodyValidationMiddleware.js +34 -0
- package/build/middlewares/dependencyInjectionMiddleware.d.ts +14 -0
- package/build/middlewares/dependencyInjectionMiddleware.js +48 -0
- package/build/middlewares/errorHandlerMiddleware.d.ts +6 -0
- package/build/middlewares/errorHandlerMiddleware.js +64 -0
- package/build/middlewares/headerVariablesMiddleware.d.ts +8 -0
- package/build/middlewares/headerVariablesMiddleware.js +32 -0
- package/build/middlewares/httpAttributesMiddleware.d.ts +10 -0
- package/build/middlewares/httpAttributesMiddleware.js +71 -0
- package/build/middlewares/index.d.ts +14 -0
- package/build/middlewares/index.js +30 -0
- package/build/middlewares/queryParametersMiddleware.d.ts +8 -0
- package/build/middlewares/queryParametersMiddleware.js +51 -0
- package/build/middlewares/rateLimitingMiddleware.d.ts +157 -0
- package/build/middlewares/rateLimitingMiddleware.js +237 -0
- package/build/middlewares/responseWrapperMiddleware.d.ts +11 -0
- package/build/middlewares/responseWrapperMiddleware.js +34 -0
- package/build/middlewares/securityAuditMiddleware.d.ts +124 -0
- package/build/middlewares/securityAuditMiddleware.js +395 -0
- package/build/middlewares/securityHeadersMiddleware.d.ts +128 -0
- package/build/middlewares/securityHeadersMiddleware.js +183 -0
- package/build/middlewares/validationMiddleware.d.ts +9 -0
- package/build/middlewares/validationMiddleware.js +40 -0
- package/package.json +73 -0
|
@@ -0,0 +1,107 @@
|
|
|
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.HttpMethod = void 0;
|
|
7
|
+
exports.generateRequestId = generateRequestId;
|
|
8
|
+
exports.adaptGCPRequest = adaptGCPRequest;
|
|
9
|
+
exports.adaptGCPResponse = adaptGCPResponse;
|
|
10
|
+
exports.createContext = createContext;
|
|
11
|
+
const typedi_1 = __importDefault(require("typedi"));
|
|
12
|
+
/**
|
|
13
|
+
* Framework-agnostic HTTP method enum
|
|
14
|
+
*/
|
|
15
|
+
var HttpMethod;
|
|
16
|
+
(function (HttpMethod) {
|
|
17
|
+
HttpMethod["GET"] = "GET";
|
|
18
|
+
HttpMethod["POST"] = "POST";
|
|
19
|
+
HttpMethod["PUT"] = "PUT";
|
|
20
|
+
HttpMethod["DELETE"] = "DELETE";
|
|
21
|
+
HttpMethod["PATCH"] = "PATCH";
|
|
22
|
+
HttpMethod["OPTIONS"] = "OPTIONS";
|
|
23
|
+
HttpMethod["HEAD"] = "HEAD";
|
|
24
|
+
})(HttpMethod || (exports.HttpMethod = HttpMethod = {}));
|
|
25
|
+
/**
|
|
26
|
+
* Utility function to generate unique request IDs
|
|
27
|
+
*/
|
|
28
|
+
function generateRequestId() {
|
|
29
|
+
return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Adapter to convert GCP Functions Request to GenericRequest
|
|
33
|
+
*/
|
|
34
|
+
function adaptGCPRequest(gcpRequest) {
|
|
35
|
+
return {
|
|
36
|
+
method: gcpRequest.method || HttpMethod.GET,
|
|
37
|
+
url: gcpRequest.url || '/',
|
|
38
|
+
path: gcpRequest.path,
|
|
39
|
+
headers: gcpRequest.headers || {},
|
|
40
|
+
query: gcpRequest.query || {},
|
|
41
|
+
params: gcpRequest.params || {},
|
|
42
|
+
body: gcpRequest.body,
|
|
43
|
+
rawBody: gcpRequest.rawBody,
|
|
44
|
+
ip: gcpRequest.ip,
|
|
45
|
+
userAgent: gcpRequest.get?.('user-agent'),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Adapter to convert GCP Functions Response to GenericResponse
|
|
50
|
+
*/
|
|
51
|
+
function adaptGCPResponse(gcpResponse) {
|
|
52
|
+
let currentStatusCode = 200;
|
|
53
|
+
let isHeadersSent = false;
|
|
54
|
+
return {
|
|
55
|
+
status: (code) => {
|
|
56
|
+
currentStatusCode = code;
|
|
57
|
+
gcpResponse.status(code);
|
|
58
|
+
return adaptGCPResponse(gcpResponse);
|
|
59
|
+
},
|
|
60
|
+
json: (data) => {
|
|
61
|
+
isHeadersSent = true;
|
|
62
|
+
gcpResponse.json(data);
|
|
63
|
+
},
|
|
64
|
+
send: (data) => {
|
|
65
|
+
isHeadersSent = true;
|
|
66
|
+
gcpResponse.send(data);
|
|
67
|
+
},
|
|
68
|
+
header: (name, value) => {
|
|
69
|
+
gcpResponse.header(name, value);
|
|
70
|
+
return adaptGCPResponse(gcpResponse);
|
|
71
|
+
},
|
|
72
|
+
headers: (headers) => {
|
|
73
|
+
Object.entries(headers).forEach(([key, value]) => {
|
|
74
|
+
gcpResponse.header(key, value);
|
|
75
|
+
});
|
|
76
|
+
return adaptGCPResponse(gcpResponse);
|
|
77
|
+
},
|
|
78
|
+
end: () => {
|
|
79
|
+
isHeadersSent = true;
|
|
80
|
+
gcpResponse.end();
|
|
81
|
+
},
|
|
82
|
+
get statusCode() {
|
|
83
|
+
return gcpResponse.statusCode || currentStatusCode;
|
|
84
|
+
},
|
|
85
|
+
get headersSent() {
|
|
86
|
+
return gcpResponse.headersSent || isHeadersSent;
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Creates a context object for framework-agnostic handlers
|
|
92
|
+
*/
|
|
93
|
+
function createContext(req, res, options = {}) {
|
|
94
|
+
return {
|
|
95
|
+
req,
|
|
96
|
+
res,
|
|
97
|
+
container: options.container || typedi_1.default.of(),
|
|
98
|
+
error: options.error || null,
|
|
99
|
+
businessData: options.businessData || new Map(),
|
|
100
|
+
user: options.user,
|
|
101
|
+
startTime: options.startTime || Date.now(),
|
|
102
|
+
requestId: options.requestId || generateRequestId(),
|
|
103
|
+
timeoutSignal: options.timeoutSignal,
|
|
104
|
+
responseData: options.responseData,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=core.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export declare class HttpError extends Error {
|
|
2
|
+
status: number;
|
|
3
|
+
code?: string;
|
|
4
|
+
details?: unknown;
|
|
5
|
+
constructor(status: number, message: string, code?: string, details?: unknown);
|
|
6
|
+
}
|
|
7
|
+
export declare class ValidationError extends HttpError {
|
|
8
|
+
constructor(message: string, details?: unknown);
|
|
9
|
+
}
|
|
10
|
+
export declare class AuthenticationError extends HttpError {
|
|
11
|
+
constructor(message?: string);
|
|
12
|
+
}
|
|
13
|
+
export declare class BusinessError extends HttpError {
|
|
14
|
+
constructor(message: string, status?: number, details?: unknown);
|
|
15
|
+
}
|
|
16
|
+
export declare class SecurityError extends HttpError {
|
|
17
|
+
constructor(message?: string, details?: unknown);
|
|
18
|
+
}
|
|
19
|
+
export declare class TimeoutError extends HttpError {
|
|
20
|
+
constructor(message?: string, details?: unknown);
|
|
21
|
+
}
|
|
22
|
+
export declare class TooLargeError extends HttpError {
|
|
23
|
+
constructor(message?: string, details?: unknown);
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TooLargeError = exports.TimeoutError = exports.SecurityError = exports.BusinessError = exports.AuthenticationError = exports.ValidationError = exports.HttpError = void 0;
|
|
4
|
+
class HttpError extends Error {
|
|
5
|
+
status;
|
|
6
|
+
code;
|
|
7
|
+
details;
|
|
8
|
+
constructor(status, message, code, details) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.status = status;
|
|
11
|
+
this.code = code;
|
|
12
|
+
this.details = details;
|
|
13
|
+
this.name = 'HttpError';
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.HttpError = HttpError;
|
|
17
|
+
class ValidationError extends HttpError {
|
|
18
|
+
constructor(message, details) {
|
|
19
|
+
super(400, message, 'VALIDATION_ERROR', details);
|
|
20
|
+
this.name = 'ValidationError';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.ValidationError = ValidationError;
|
|
24
|
+
class AuthenticationError extends HttpError {
|
|
25
|
+
constructor(message = 'Unauthorized') {
|
|
26
|
+
super(401, message, 'AUTHENTICATION_ERROR');
|
|
27
|
+
this.name = 'AuthenticationError';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.AuthenticationError = AuthenticationError;
|
|
31
|
+
class BusinessError extends HttpError {
|
|
32
|
+
constructor(message, status = 500, details) {
|
|
33
|
+
super(status, message, 'BUSINESS_ERROR', details);
|
|
34
|
+
this.name = 'BusinessError';
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.BusinessError = BusinessError;
|
|
38
|
+
class SecurityError extends HttpError {
|
|
39
|
+
constructor(message = 'Security violation detected', details) {
|
|
40
|
+
super(403, message, 'SECURITY_ERROR', details);
|
|
41
|
+
this.name = 'SecurityError';
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
exports.SecurityError = SecurityError;
|
|
45
|
+
class TimeoutError extends HttpError {
|
|
46
|
+
constructor(message = 'Request timeout', details) {
|
|
47
|
+
super(408, message, 'TIMEOUT_ERROR', details);
|
|
48
|
+
this.name = 'TimeoutError';
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.TimeoutError = TimeoutError;
|
|
52
|
+
class TooLargeError extends HttpError {
|
|
53
|
+
constructor(message = 'Request entity too large', details) {
|
|
54
|
+
super(413, message, 'TOO_LARGE_ERROR', details);
|
|
55
|
+
this.name = 'TooLargeError';
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.TooLargeError = TooLargeError;
|
|
59
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Context, CustomRequest, CustomResponse, GenericRequest, GenericResponse } from './core';
|
|
2
|
+
/**
|
|
3
|
+
* Interface representing a base structure for middleware with optional lifecycle methods.
|
|
4
|
+
*
|
|
5
|
+
* This interface is designed to provide hooks for execution during different
|
|
6
|
+
* stages of a middleware's lifecycle. It allows for defining logic to be
|
|
7
|
+
* executed before and after a process, as well as handling errors that
|
|
8
|
+
* occur during the process.
|
|
9
|
+
*
|
|
10
|
+
* @template T - The type of the request or input context. Defaults to unknown.
|
|
11
|
+
* @template U - The type of the response or output context. Defaults to unknown.
|
|
12
|
+
*/
|
|
13
|
+
export interface BaseMiddleware<T = unknown, U = unknown> {
|
|
14
|
+
before?: (context: Context<T, U>) => Promise<void>;
|
|
15
|
+
after?: (context: Context<T, U>) => Promise<void>;
|
|
16
|
+
onError?: (error: Error, context: Context<T, U>) => Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The Handler class is responsible for managing and executing middleware functions
|
|
20
|
+
* and a main handler function in a sequential and controlled manner.
|
|
21
|
+
*
|
|
22
|
+
* This class provides a mechanism for registering middlewares that can
|
|
23
|
+
* process a request/response flow either before the main handler (via `before`),
|
|
24
|
+
* after the main handler (via `after`), or handle errors (via `onError`).
|
|
25
|
+
*
|
|
26
|
+
* interface MessagePayload {
|
|
27
|
+
* action: string;
|
|
28
|
+
* data: Record<string, unknown>;
|
|
29
|
+
* }
|
|
30
|
+
*
|
|
31
|
+
* const handler = new Handler<MessagePayload>()
|
|
32
|
+
* .use(errorHandler())
|
|
33
|
+
* .use(bodyParser())
|
|
34
|
+
* .handle(async (context) => {
|
|
35
|
+
* const { req } = context;
|
|
36
|
+
* // Handle the request
|
|
37
|
+
* });
|
|
38
|
+
* @template T Type for the input request data.
|
|
39
|
+
* @template U Type for the additional context or response data.
|
|
40
|
+
*/
|
|
41
|
+
export declare class Handler<T = unknown, U = unknown> {
|
|
42
|
+
private baseMiddlewares;
|
|
43
|
+
private handler;
|
|
44
|
+
private reversedMiddlewares;
|
|
45
|
+
private errorMiddlewares;
|
|
46
|
+
private middlewaresPrecomputed;
|
|
47
|
+
static use<T = unknown, U = unknown>(middleware: BaseMiddleware<T, U>): Handler<T, U>;
|
|
48
|
+
use<NewT = T, NewU = U>(middleware: BaseMiddleware<NewT, NewU>): Handler<NewT, NewU>;
|
|
49
|
+
handle(handler: (context: Context<T, U>) => Promise<void>): Handler<T, U>;
|
|
50
|
+
/**
|
|
51
|
+
* Performance optimization: Pre-compute middleware arrays to avoid runtime array operations
|
|
52
|
+
*/
|
|
53
|
+
private precomputeMiddlewareArrays;
|
|
54
|
+
execute(req: CustomRequest<T>, res: CustomResponse): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Execute before middlewares with optimized batching for independent middlewares
|
|
57
|
+
*/
|
|
58
|
+
private executeBeforeMiddlewares;
|
|
59
|
+
/**
|
|
60
|
+
* Execute after middlewares using pre-computed reversed array
|
|
61
|
+
*/
|
|
62
|
+
private executeAfterMiddlewares;
|
|
63
|
+
/**
|
|
64
|
+
* Execute error middlewares using pre-computed array
|
|
65
|
+
*/
|
|
66
|
+
private executeErrorMiddlewares;
|
|
67
|
+
/**
|
|
68
|
+
* Framework-agnostic execute method that works with GenericRequest/GenericResponse
|
|
69
|
+
*/
|
|
70
|
+
executeGeneric(req: GenericRequest<T>, res: GenericResponse): Promise<void>;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=handler.d.ts.map
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Handler = void 0;
|
|
4
|
+
// Container import removed - now using containerPool for performance
|
|
5
|
+
const core_1 = require("./core");
|
|
6
|
+
const containerPool_1 = require("./containerPool");
|
|
7
|
+
/**
|
|
8
|
+
* The Handler class is responsible for managing and executing middleware functions
|
|
9
|
+
* and a main handler function in a sequential and controlled manner.
|
|
10
|
+
*
|
|
11
|
+
* This class provides a mechanism for registering middlewares that can
|
|
12
|
+
* process a request/response flow either before the main handler (via `before`),
|
|
13
|
+
* after the main handler (via `after`), or handle errors (via `onError`).
|
|
14
|
+
*
|
|
15
|
+
* interface MessagePayload {
|
|
16
|
+
* action: string;
|
|
17
|
+
* data: Record<string, unknown>;
|
|
18
|
+
* }
|
|
19
|
+
*
|
|
20
|
+
* const handler = new Handler<MessagePayload>()
|
|
21
|
+
* .use(errorHandler())
|
|
22
|
+
* .use(bodyParser())
|
|
23
|
+
* .handle(async (context) => {
|
|
24
|
+
* const { req } = context;
|
|
25
|
+
* // Handle the request
|
|
26
|
+
* });
|
|
27
|
+
* @template T Type for the input request data.
|
|
28
|
+
* @template U Type for the additional context or response data.
|
|
29
|
+
*/
|
|
30
|
+
class Handler {
|
|
31
|
+
baseMiddlewares = [];
|
|
32
|
+
handler;
|
|
33
|
+
// Performance optimization: Pre-computed middleware arrays
|
|
34
|
+
reversedMiddlewares = [];
|
|
35
|
+
errorMiddlewares = [];
|
|
36
|
+
middlewaresPrecomputed = false;
|
|
37
|
+
static use(middleware) {
|
|
38
|
+
const handler = new Handler();
|
|
39
|
+
handler.baseMiddlewares.push(middleware);
|
|
40
|
+
return handler;
|
|
41
|
+
}
|
|
42
|
+
use(middleware) {
|
|
43
|
+
const handler = new Handler();
|
|
44
|
+
handler.baseMiddlewares = [
|
|
45
|
+
...this.baseMiddlewares,
|
|
46
|
+
middleware,
|
|
47
|
+
];
|
|
48
|
+
return handler;
|
|
49
|
+
}
|
|
50
|
+
handle(handler) {
|
|
51
|
+
this.handler = handler;
|
|
52
|
+
this.precomputeMiddlewareArrays();
|
|
53
|
+
return this;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Performance optimization: Pre-compute middleware arrays to avoid runtime array operations
|
|
57
|
+
*/
|
|
58
|
+
precomputeMiddlewareArrays() {
|
|
59
|
+
if (this.middlewaresPrecomputed)
|
|
60
|
+
return;
|
|
61
|
+
// Pre-compute reversed array for after/error middlewares
|
|
62
|
+
this.reversedMiddlewares = [...this.baseMiddlewares].reverse();
|
|
63
|
+
this.errorMiddlewares = this.reversedMiddlewares.filter((m) => m.onError);
|
|
64
|
+
this.middlewaresPrecomputed = true;
|
|
65
|
+
}
|
|
66
|
+
async execute(req, res) {
|
|
67
|
+
const genericReq = (0, core_1.adaptGCPRequest)(req);
|
|
68
|
+
const genericRes = (0, core_1.adaptGCPResponse)(res);
|
|
69
|
+
// Performance optimization: Use container pool instead of creating new containers
|
|
70
|
+
const container = containerPool_1.containerPool.acquire();
|
|
71
|
+
const context = (0, core_1.createContext)(genericReq, genericRes, {
|
|
72
|
+
container,
|
|
73
|
+
});
|
|
74
|
+
try {
|
|
75
|
+
// Execute before middlewares with performance optimizations
|
|
76
|
+
await this.executeBeforeMiddlewares(context);
|
|
77
|
+
await this.handler(context);
|
|
78
|
+
// Execute after middlewares in reverse order using pre-computed array
|
|
79
|
+
await this.executeAfterMiddlewares(context);
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
context.error = error;
|
|
83
|
+
// Execute error handlers using pre-computed array
|
|
84
|
+
await this.executeErrorMiddlewares(error, context);
|
|
85
|
+
}
|
|
86
|
+
finally {
|
|
87
|
+
// Always return container to pool for reuse
|
|
88
|
+
containerPool_1.containerPool.release(container);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Execute before middlewares with optimized batching for independent middlewares
|
|
93
|
+
*/
|
|
94
|
+
async executeBeforeMiddlewares(context) {
|
|
95
|
+
// For backward compatibility and simpler logic, execute all before middlewares in order
|
|
96
|
+
for (const middleware of this.baseMiddlewares) {
|
|
97
|
+
if (middleware.before) {
|
|
98
|
+
await middleware.before(context);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Execute after middlewares using pre-computed reversed array
|
|
104
|
+
*/
|
|
105
|
+
async executeAfterMiddlewares(context) {
|
|
106
|
+
// For backward compatibility and simpler logic, execute all after middlewares in reverse order
|
|
107
|
+
for (const middleware of this.reversedMiddlewares) {
|
|
108
|
+
if (middleware.after) {
|
|
109
|
+
await middleware.after(context);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Execute error middlewares using pre-computed array
|
|
115
|
+
*/
|
|
116
|
+
async executeErrorMiddlewares(error, context) {
|
|
117
|
+
for (const middleware of this.errorMiddlewares) {
|
|
118
|
+
if (middleware.onError) {
|
|
119
|
+
await middleware.onError(error, context);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Framework-agnostic execute method that works with GenericRequest/GenericResponse
|
|
125
|
+
*/
|
|
126
|
+
async executeGeneric(req, res) {
|
|
127
|
+
// Performance optimization: Use container pool instead of creating new containers
|
|
128
|
+
const container = containerPool_1.containerPool.acquire();
|
|
129
|
+
const context = (0, core_1.createContext)(req, res, {
|
|
130
|
+
container,
|
|
131
|
+
});
|
|
132
|
+
try {
|
|
133
|
+
// Execute before middlewares with performance optimizations
|
|
134
|
+
await this.executeBeforeMiddlewares(context);
|
|
135
|
+
await this.handler(context);
|
|
136
|
+
// Execute after middlewares in reverse order using pre-computed array
|
|
137
|
+
await this.executeAfterMiddlewares(context);
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
context.error = error;
|
|
141
|
+
// Execute error handlers using pre-computed array
|
|
142
|
+
await this.executeErrorMiddlewares(error, context);
|
|
143
|
+
}
|
|
144
|
+
finally {
|
|
145
|
+
// Always return container to pool for reuse
|
|
146
|
+
containerPool_1.containerPool.release(container);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
exports.Handler = Handler;
|
|
151
|
+
//# sourceMappingURL=handler.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
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("./core"), exports);
|
|
18
|
+
__exportStar(require("./errors"), exports);
|
|
19
|
+
__exportStar(require("./handler"), exports);
|
|
20
|
+
__exportStar(require("./logger"), exports);
|
|
21
|
+
__exportStar(require("./containerPool"), exports);
|
|
22
|
+
__exportStar(require("./performanceMonitor"), exports);
|
|
23
|
+
__exportStar(require("../middlewares"), exports);
|
|
24
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface LogOptions {
|
|
2
|
+
structuredData?: boolean;
|
|
3
|
+
[key: string]: boolean | string | number | object | undefined;
|
|
4
|
+
}
|
|
5
|
+
declare class Logger {
|
|
6
|
+
private logDataPool;
|
|
7
|
+
private isDebugEnabled;
|
|
8
|
+
private timestampCache;
|
|
9
|
+
private lastTimestamp;
|
|
10
|
+
constructor();
|
|
11
|
+
/**
|
|
12
|
+
* Performance optimized timestamp generation with caching
|
|
13
|
+
* Cache timestamps for up to 1 second to reduce Date object creation
|
|
14
|
+
*/
|
|
15
|
+
private getTimestamp;
|
|
16
|
+
/**
|
|
17
|
+
* Optimized log method with object pooling and lazy evaluation
|
|
18
|
+
*/
|
|
19
|
+
private log;
|
|
20
|
+
/**
|
|
21
|
+
* Performance optimized logging methods with level checks
|
|
22
|
+
*/
|
|
23
|
+
info(message: string, options?: LogOptions): void;
|
|
24
|
+
error(message: string, options?: LogOptions): void;
|
|
25
|
+
warn(message: string, options?: LogOptions): void;
|
|
26
|
+
debug(message: string, options?: LogOptions): void;
|
|
27
|
+
/**
|
|
28
|
+
* Performance monitoring method for internal framework use
|
|
29
|
+
*/
|
|
30
|
+
logPerformance(operation: string, duration: number, metadata?: Record<string, unknown>): void;
|
|
31
|
+
/**
|
|
32
|
+
* Get logger statistics for monitoring
|
|
33
|
+
*/
|
|
34
|
+
getStats(): {
|
|
35
|
+
poolSize: number;
|
|
36
|
+
maxPoolSize: number;
|
|
37
|
+
debugEnabled: boolean;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export declare const logger: Logger;
|
|
41
|
+
export { Logger };
|
|
42
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Logger = exports.logger = void 0;
|
|
4
|
+
// Performance optimization: Object pool for log data to reduce GC pressure
|
|
5
|
+
class LogDataPool {
|
|
6
|
+
pool = [];
|
|
7
|
+
maxPoolSize = 50;
|
|
8
|
+
acquire() {
|
|
9
|
+
return (this.pool.pop() || {
|
|
10
|
+
timestamp: '',
|
|
11
|
+
level: 'info',
|
|
12
|
+
message: '',
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
release(logData) {
|
|
16
|
+
if (this.pool.length < this.maxPoolSize) {
|
|
17
|
+
// Reset object properties
|
|
18
|
+
logData.timestamp = '';
|
|
19
|
+
logData.level = 'info';
|
|
20
|
+
logData.message = '';
|
|
21
|
+
// Remove any additional properties
|
|
22
|
+
const keys = Object.keys(logData);
|
|
23
|
+
for (let i = 3; i < keys.length; i++) {
|
|
24
|
+
delete logData[keys[i]];
|
|
25
|
+
}
|
|
26
|
+
this.pool.push(logData);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// Performance optimization: Dynamic method references for testing compatibility
|
|
31
|
+
const getLogMethod = (level) => {
|
|
32
|
+
switch (level) {
|
|
33
|
+
case 'error':
|
|
34
|
+
return console.error;
|
|
35
|
+
case 'warn':
|
|
36
|
+
return console.warn;
|
|
37
|
+
case 'debug':
|
|
38
|
+
return console.debug;
|
|
39
|
+
default:
|
|
40
|
+
return console.log;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
class Logger {
|
|
44
|
+
logDataPool = new LogDataPool();
|
|
45
|
+
isDebugEnabled;
|
|
46
|
+
timestampCache = '';
|
|
47
|
+
lastTimestamp = 0;
|
|
48
|
+
constructor() {
|
|
49
|
+
// Performance optimization: Cache debug mode check
|
|
50
|
+
this.isDebugEnabled =
|
|
51
|
+
process.env.NODE_ENV === 'development' ||
|
|
52
|
+
process.env.DEBUG === 'true' ||
|
|
53
|
+
process.env.LOG_LEVEL === 'debug';
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Performance optimized timestamp generation with caching
|
|
57
|
+
* Cache timestamps for up to 1 second to reduce Date object creation
|
|
58
|
+
*/
|
|
59
|
+
getTimestamp() {
|
|
60
|
+
const now = Date.now();
|
|
61
|
+
// Cache timestamp for 1 second to reduce object creation
|
|
62
|
+
if (now - this.lastTimestamp > 1000) {
|
|
63
|
+
this.timestampCache = new Date(now).toISOString();
|
|
64
|
+
this.lastTimestamp = now;
|
|
65
|
+
}
|
|
66
|
+
return this.timestampCache;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Optimized log method with object pooling and lazy evaluation
|
|
70
|
+
*/
|
|
71
|
+
log(level, message, options) {
|
|
72
|
+
// Performance optimization: Early return for debug logs in production
|
|
73
|
+
if (level === 'debug' && !this.isDebugEnabled) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const logData = this.logDataPool.acquire();
|
|
77
|
+
// Performance optimization: Lazy timestamp generation
|
|
78
|
+
logData.timestamp = this.getTimestamp();
|
|
79
|
+
logData.level = level;
|
|
80
|
+
logData.message = message;
|
|
81
|
+
// Add options if provided
|
|
82
|
+
if (options) {
|
|
83
|
+
Object.assign(logData, options);
|
|
84
|
+
}
|
|
85
|
+
// Use dynamic method reference for testing compatibility
|
|
86
|
+
const logMethod = getLogMethod(level);
|
|
87
|
+
// For testing: create a copy of the data to avoid pool interference
|
|
88
|
+
const logDataCopy = { ...logData };
|
|
89
|
+
logMethod(logDataCopy);
|
|
90
|
+
// Always return object to pool
|
|
91
|
+
this.logDataPool.release(logData);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Performance optimized logging methods with level checks
|
|
95
|
+
*/
|
|
96
|
+
info(message, options) {
|
|
97
|
+
this.log('info', message, options);
|
|
98
|
+
}
|
|
99
|
+
error(message, options) {
|
|
100
|
+
this.log('error', message, options);
|
|
101
|
+
}
|
|
102
|
+
warn(message, options) {
|
|
103
|
+
this.log('warn', message, options);
|
|
104
|
+
}
|
|
105
|
+
debug(message, options) {
|
|
106
|
+
// Performance optimization: Early return for debug in production
|
|
107
|
+
if (!this.isDebugEnabled)
|
|
108
|
+
return;
|
|
109
|
+
this.log('debug', message, options);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Performance monitoring method for internal framework use
|
|
113
|
+
*/
|
|
114
|
+
logPerformance(operation, duration, metadata) {
|
|
115
|
+
if (this.isDebugEnabled) {
|
|
116
|
+
this.debug(`Performance: ${operation}`, {
|
|
117
|
+
duration: `${duration}ms`,
|
|
118
|
+
...metadata,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Get logger statistics for monitoring
|
|
124
|
+
*/
|
|
125
|
+
getStats() {
|
|
126
|
+
return {
|
|
127
|
+
poolSize: this.logDataPool['pool'].length,
|
|
128
|
+
maxPoolSize: this.logDataPool['maxPoolSize'],
|
|
129
|
+
debugEnabled: this.isDebugEnabled,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
exports.Logger = Logger;
|
|
134
|
+
exports.logger = new Logger();
|
|
135
|
+
//# sourceMappingURL=logger.js.map
|