@hazeljs/core 0.3.1 → 0.4.1
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 +14 -2
- package/dist/__tests__/container.test.js +176 -366
- package/dist/__tests__/enhanced-errors.test.d.ts +2 -0
- package/dist/__tests__/enhanced-errors.test.d.ts.map +1 -0
- package/dist/__tests__/enhanced-errors.test.js +315 -0
- package/dist/__tests__/performance.test.d.ts +2 -0
- package/dist/__tests__/performance.test.d.ts.map +1 -0
- package/dist/__tests__/performance.test.js +324 -0
- package/dist/container.d.ts +1 -0
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +31 -9
- package/dist/decorators.d.ts +4 -0
- package/dist/decorators.d.ts.map +1 -1
- package/dist/decorators.js +10 -0
- package/dist/enhanced-errors.d.ts +30 -0
- package/dist/enhanced-errors.d.ts.map +1 -0
- package/dist/enhanced-errors.js +227 -0
- package/dist/hazel-app.d.ts +10 -0
- package/dist/hazel-app.d.ts.map +1 -1
- package/dist/hazel-app.js +35 -6
- package/dist/hazel-module.d.ts +1 -0
- package/dist/hazel-module.d.ts.map +1 -1
- package/dist/hazel-module.js +14 -3
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -3
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +28 -0
- package/dist/performance.d.ts +49 -0
- package/dist/performance.d.ts.map +1 -0
- package/dist/performance.js +140 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -7,9 +7,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
7
7
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
8
|
};
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.
|
|
11
|
-
exports.
|
|
12
|
-
exports.escapeHtml = exports.sanitizeObject = void 0;
|
|
10
|
+
exports.Scope = exports.Container = exports.CUSTOM_METADATA_PREFIX = exports.Lazy = exports.createParamDecorator = exports.getMetadata = exports.SetMetadata = exports.ApiOperation = exports.ApiTags = exports.Retry = exports.Session = exports.Optional = exports.Timeout = exports.AITask = exports.SkipAuth = exports.Public = exports.UseGuards = exports.UseInterceptors = exports.UsePipes = exports.Inject = exports.Redirect = exports.Header = exports.HttpCode = exports.Headers = exports.Host = exports.Ip = exports.Res = exports.Req = exports.Query = exports.Param = exports.Body = exports.Patch = exports.Delete = exports.Put = exports.Post = exports.Get = exports.Service = exports.Injectable = exports.Controller = exports.TimeoutMiddleware = exports.BuiltInHealthChecks = exports.HealthCheckManager = exports.ShutdownManager = exports.collectControllersFromModule = exports.collectModulesFromModule = exports.getModuleMetadata = exports.HazelModuleInstance = exports.Module = exports.HazelModule = exports.HazelApp = void 0;
|
|
11
|
+
exports.sanitizeEmail = exports.sanitizeUrl = exports.sanitizeString = exports.sanitizeHtml = exports.RequestParser = exports.Router = exports.Validator = exports.default = exports.logger = exports.UploadedFiles = exports.UploadedFile = exports.FileUploadInterceptor = exports.CsrfMiddleware = exports.RateLimitMiddleware = exports.SecurityHeadersMiddleware = exports.LoggerMiddleware = exports.CorsMiddleware = exports.GlobalMiddlewareManager = exports.extractVersion = exports.matchVersion = exports.getVersionMetadata = exports.VersioningType = exports.Version = exports.RouteMatcher = exports.TestingModuleBuilder = exports.TestingModule = exports.Test = exports.HttpExceptionFilter = exports.getFilterExceptions = exports.Catch = exports.ArgumentsHostImpl = exports.RetryInterceptor = exports.ValidationPipe = exports.ParseIntPipe = exports.ValidationError = exports.RequestTimeoutError = exports.InternalServerErrorException = exports.ConflictException = exports.NotFoundException = exports.ForbiddenException = exports.UnauthorizedException = exports.BadRequestException = exports.HttpException = exports.InternalServerError = exports.ConflictError = exports.NotFoundError = exports.ForbiddenError = exports.UnauthorizedError = exports.BadRequestError = exports.HttpError = void 0;
|
|
12
|
+
exports.EnhancedErrors = exports.createEnhancedError = exports.ErrorHandler = exports.BuiltinPerformanceHooks = exports.PerformanceMonitor = exports.escapeHtml = exports.sanitizeObject = exports.sanitizeSql = void 0;
|
|
13
13
|
// Import reflect-metadata to enable decorator metadata
|
|
14
14
|
// Users don't need to import this manually
|
|
15
15
|
require("reflect-metadata");
|
|
@@ -69,6 +69,7 @@ Object.defineProperty(exports, "ApiOperation", { enumerable: true, get: function
|
|
|
69
69
|
Object.defineProperty(exports, "SetMetadata", { enumerable: true, get: function () { return decorators_1.SetMetadata; } });
|
|
70
70
|
Object.defineProperty(exports, "getMetadata", { enumerable: true, get: function () { return decorators_1.getMetadata; } });
|
|
71
71
|
Object.defineProperty(exports, "createParamDecorator", { enumerable: true, get: function () { return decorators_1.createParamDecorator; } });
|
|
72
|
+
Object.defineProperty(exports, "Lazy", { enumerable: true, get: function () { return decorators_1.Lazy; } });
|
|
72
73
|
Object.defineProperty(exports, "CUSTOM_METADATA_PREFIX", { enumerable: true, get: function () { return decorators_1.CUSTOM_METADATA_PREFIX; } });
|
|
73
74
|
// Container & DI
|
|
74
75
|
var container_1 = require("./container");
|
|
@@ -160,3 +161,12 @@ Object.defineProperty(exports, "sanitizeEmail", { enumerable: true, get: functio
|
|
|
160
161
|
Object.defineProperty(exports, "sanitizeSql", { enumerable: true, get: function () { return sanitize_1.sanitizeSql; } });
|
|
161
162
|
Object.defineProperty(exports, "sanitizeObject", { enumerable: true, get: function () { return sanitize_1.sanitizeObject; } });
|
|
162
163
|
Object.defineProperty(exports, "escapeHtml", { enumerable: true, get: function () { return sanitize_1.escapeHtml; } });
|
|
164
|
+
// Performance monitoring
|
|
165
|
+
var performance_1 = require("./performance");
|
|
166
|
+
Object.defineProperty(exports, "PerformanceMonitor", { enumerable: true, get: function () { return performance_1.PerformanceMonitor; } });
|
|
167
|
+
Object.defineProperty(exports, "BuiltinPerformanceHooks", { enumerable: true, get: function () { return performance_1.BuiltinPerformanceHooks; } });
|
|
168
|
+
// Enhanced error handling
|
|
169
|
+
var enhanced_errors_1 = require("./enhanced-errors");
|
|
170
|
+
Object.defineProperty(exports, "ErrorHandler", { enumerable: true, get: function () { return enhanced_errors_1.ErrorHandler; } });
|
|
171
|
+
Object.defineProperty(exports, "createEnhancedError", { enumerable: true, get: function () { return enhanced_errors_1.createEnhancedError; } });
|
|
172
|
+
Object.defineProperty(exports, "EnhancedErrors", { enumerable: true, get: function () { return enhanced_errors_1.EnhancedErrors; } });
|
package/dist/logger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAK9B,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAK9B,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAoSvD,eAAO,MAAM,aAAa,GACxB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,MAAM,MAAM,IAAI,KACf,IAyBF,CAAC;AAQF,QAAA,MAAM,cAAc;0BALO,OAAO;CAOhC,CAAC;AAGH,eAAe,cAAc,CAAC"}
|
package/dist/logger.js
CHANGED
|
@@ -178,10 +178,24 @@ if (logEnabled) {
|
|
|
178
178
|
const { level, message, timestamp, ...metadata } = info;
|
|
179
179
|
let msg = `${timestamp} [${String(level).toUpperCase()}] ${message}`;
|
|
180
180
|
if (Object.keys(metadata).length > 0) {
|
|
181
|
+
// Use the same comprehensive circular reference handling as console logger
|
|
182
|
+
const seen = new WeakSet();
|
|
181
183
|
msg += ` | ${JSON.stringify(metadata, (key, val) => {
|
|
184
|
+
// Skip known circular references
|
|
182
185
|
if (key === 'socket' || key === 'parser' || key === 'res' || key === 'req') {
|
|
183
186
|
return '[Circular]';
|
|
184
187
|
}
|
|
188
|
+
// Skip Node.js internal objects
|
|
189
|
+
if (key === '_idlePrev' || key === '_idleNext' || key === 'cleanupInterval') {
|
|
190
|
+
return '[Internal]';
|
|
191
|
+
}
|
|
192
|
+
// Handle circular references
|
|
193
|
+
if (typeof val === 'object' && val !== null) {
|
|
194
|
+
if (seen.has(val)) {
|
|
195
|
+
return '[Circular]';
|
|
196
|
+
}
|
|
197
|
+
seen.add(val);
|
|
198
|
+
}
|
|
185
199
|
return val;
|
|
186
200
|
})}`;
|
|
187
201
|
}
|
|
@@ -194,10 +208,24 @@ if (logEnabled) {
|
|
|
194
208
|
const { level, message, timestamp, ...metadata } = info;
|
|
195
209
|
let msg = `${timestamp} [${String(level).toUpperCase()}] ${message}`;
|
|
196
210
|
if (Object.keys(metadata).length > 0) {
|
|
211
|
+
// Use the same comprehensive circular reference handling as console logger
|
|
212
|
+
const seen = new WeakSet();
|
|
197
213
|
msg += ` | ${JSON.stringify(metadata, (key, val) => {
|
|
214
|
+
// Skip known circular references
|
|
198
215
|
if (key === 'socket' || key === 'parser' || key === 'res' || key === 'req') {
|
|
199
216
|
return '[Circular]';
|
|
200
217
|
}
|
|
218
|
+
// Skip Node.js internal objects
|
|
219
|
+
if (key === '_idlePrev' || key === '_idleNext' || key === 'cleanupInterval') {
|
|
220
|
+
return '[Internal]';
|
|
221
|
+
}
|
|
222
|
+
// Handle circular references
|
|
223
|
+
if (typeof val === 'object' && val !== null) {
|
|
224
|
+
if (seen.has(val)) {
|
|
225
|
+
return '[Circular]';
|
|
226
|
+
}
|
|
227
|
+
seen.add(val);
|
|
228
|
+
}
|
|
201
229
|
return val;
|
|
202
230
|
})}`;
|
|
203
231
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Request } from './types';
|
|
2
|
+
export interface PerformanceMetrics {
|
|
3
|
+
requestId: string;
|
|
4
|
+
method: string;
|
|
5
|
+
path: string;
|
|
6
|
+
startTime: number;
|
|
7
|
+
endTime?: number;
|
|
8
|
+
duration?: number;
|
|
9
|
+
statusCode?: number;
|
|
10
|
+
memoryUsage?: NodeJS.MemoryUsage;
|
|
11
|
+
cpuUsage?: NodeJS.CpuUsage;
|
|
12
|
+
error?: Error;
|
|
13
|
+
}
|
|
14
|
+
export interface PerformanceHook {
|
|
15
|
+
name: string;
|
|
16
|
+
onRequest?: (metrics: PerformanceMetrics) => void | Promise<void>;
|
|
17
|
+
onResponse?: (metrics: PerformanceMetrics) => void | Promise<void>;
|
|
18
|
+
onError?: (metrics: PerformanceMetrics) => void | Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
export interface PerformanceOptions {
|
|
21
|
+
enableMetrics?: boolean;
|
|
22
|
+
slowRequestThreshold?: number;
|
|
23
|
+
maxRequestsWindow?: number;
|
|
24
|
+
rateLimitWindow?: number;
|
|
25
|
+
}
|
|
26
|
+
export declare class PerformanceMonitor {
|
|
27
|
+
private hooks;
|
|
28
|
+
private activeRequests;
|
|
29
|
+
constructor();
|
|
30
|
+
addHook(hook: PerformanceHook): void;
|
|
31
|
+
removeHook(name: string): void;
|
|
32
|
+
startRequest(req: Request): string;
|
|
33
|
+
endRequest(requestId: string, statusCode: number, error?: Error): void;
|
|
34
|
+
getActiveRequests(): PerformanceMetrics[];
|
|
35
|
+
getMetrics(): {
|
|
36
|
+
activeRequests: number;
|
|
37
|
+
totalHooks: number;
|
|
38
|
+
averageResponseTime?: number;
|
|
39
|
+
};
|
|
40
|
+
private generateRequestId;
|
|
41
|
+
private executeHooks;
|
|
42
|
+
}
|
|
43
|
+
export declare const BuiltinPerformanceHooks: {
|
|
44
|
+
slowRequestLogger: (threshold?: number) => PerformanceHook;
|
|
45
|
+
memoryMonitor: () => PerformanceHook;
|
|
46
|
+
rateLimiter: (maxRequests?: number, windowMs?: number) => PerformanceHook;
|
|
47
|
+
metricsCollector: () => PerformanceHook;
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=performance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"performance.d.ts","sourceRoot":"","sources":["../src/performance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGlC,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC,WAAW,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClE,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjE;AAED,MAAM,WAAW,kBAAkB;IACjC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,cAAc,CAA8C;;IAMpE,OAAO,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI;IAKpC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAK9B,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM;IAmBlC,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI;IAmBtE,iBAAiB,IAAI,kBAAkB,EAAE;IAIzC,UAAU,IAAI;QACZ,cAAc,EAAE,MAAM,CAAC;QACvB,UAAU,EAAE,MAAM,CAAC;QACnB,mBAAmB,CAAC,EAAE,MAAM,CAAC;KAC9B;IAOD,OAAO,CAAC,iBAAiB;YAIX,YAAY;CAgB3B;AAGD,eAAO,MAAM,uBAAuB;oCAEH,MAAM,KAAU,eAAe;yBAY3C,eAAe;gCAaP,MAAM,aAAkB,MAAM,KAAW,eAAe;4BA0B7D,eAAe;CAwBtC,CAAC"}
|
|
@@ -0,0 +1,140 @@
|
|
|
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.BuiltinPerformanceHooks = exports.PerformanceMonitor = void 0;
|
|
7
|
+
const logger_1 = __importDefault(require("./logger"));
|
|
8
|
+
class PerformanceMonitor {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.hooks = [];
|
|
11
|
+
this.activeRequests = new Map();
|
|
12
|
+
logger_1.default.debug('PerformanceMonitor initialized');
|
|
13
|
+
}
|
|
14
|
+
addHook(hook) {
|
|
15
|
+
this.hooks.push(hook);
|
|
16
|
+
logger_1.default.debug(`Added performance hook: ${hook.name}`);
|
|
17
|
+
}
|
|
18
|
+
removeHook(name) {
|
|
19
|
+
this.hooks = this.hooks.filter(hook => hook.name !== name);
|
|
20
|
+
logger_1.default.debug(`Removed performance hook: ${name}`);
|
|
21
|
+
}
|
|
22
|
+
startRequest(req) {
|
|
23
|
+
const requestId = this.generateRequestId();
|
|
24
|
+
const metrics = {
|
|
25
|
+
requestId,
|
|
26
|
+
method: req.method || 'GET',
|
|
27
|
+
path: req.url || '/',
|
|
28
|
+
startTime: Date.now(),
|
|
29
|
+
memoryUsage: process.memoryUsage(),
|
|
30
|
+
cpuUsage: process.cpuUsage(),
|
|
31
|
+
};
|
|
32
|
+
this.activeRequests.set(requestId, metrics);
|
|
33
|
+
// Execute request hooks
|
|
34
|
+
this.executeHooks('onRequest', metrics);
|
|
35
|
+
return requestId;
|
|
36
|
+
}
|
|
37
|
+
endRequest(requestId, statusCode, error) {
|
|
38
|
+
const metrics = this.activeRequests.get(requestId);
|
|
39
|
+
if (!metrics)
|
|
40
|
+
return;
|
|
41
|
+
metrics.endTime = Date.now();
|
|
42
|
+
metrics.duration = metrics.endTime - metrics.startTime;
|
|
43
|
+
metrics.statusCode = statusCode;
|
|
44
|
+
metrics.error = error;
|
|
45
|
+
// Execute response or error hooks
|
|
46
|
+
if (error) {
|
|
47
|
+
this.executeHooks('onError', metrics);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
this.executeHooks('onResponse', metrics);
|
|
51
|
+
}
|
|
52
|
+
this.activeRequests.delete(requestId);
|
|
53
|
+
}
|
|
54
|
+
getActiveRequests() {
|
|
55
|
+
return Array.from(this.activeRequests.values());
|
|
56
|
+
}
|
|
57
|
+
getMetrics() {
|
|
58
|
+
return {
|
|
59
|
+
activeRequests: this.activeRequests.size,
|
|
60
|
+
totalHooks: this.hooks.length,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
generateRequestId() {
|
|
64
|
+
return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
65
|
+
}
|
|
66
|
+
async executeHooks(hookType, metrics) {
|
|
67
|
+
const promises = this.hooks
|
|
68
|
+
.filter(hook => hook[hookType])
|
|
69
|
+
.map(async (hook) => {
|
|
70
|
+
try {
|
|
71
|
+
await hook[hookType](metrics);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
logger_1.default.error(`Error in performance hook ${hook.name}:`, error);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
await Promise.allSettled(promises);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
exports.PerformanceMonitor = PerformanceMonitor;
|
|
81
|
+
// Built-in performance hooks
|
|
82
|
+
exports.BuiltinPerformanceHooks = {
|
|
83
|
+
// Log slow requests
|
|
84
|
+
slowRequestLogger: (threshold = 1000) => ({
|
|
85
|
+
name: 'slow-request-logger',
|
|
86
|
+
onResponse: (metrics) => {
|
|
87
|
+
if (metrics.duration && metrics.duration > threshold) {
|
|
88
|
+
logger_1.default.warn(`Slow request detected: ${metrics.method} ${metrics.path} took ${metrics.duration}ms`);
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
}),
|
|
92
|
+
// Memory usage monitoring
|
|
93
|
+
memoryMonitor: () => ({
|
|
94
|
+
name: 'memory-monitor',
|
|
95
|
+
onRequest: (metrics) => {
|
|
96
|
+
const memUsage = metrics.memoryUsage;
|
|
97
|
+
if (memUsage.heapUsed > 100 * 1024 * 1024) { // 100MB
|
|
98
|
+
logger_1.default.warn(`High memory usage during request ${metrics.requestId}: ${Math.round(memUsage.heapUsed / 1024 / 1024)}MB`);
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
}),
|
|
102
|
+
// Request rate limiting
|
|
103
|
+
rateLimiter: (maxRequests = 100, windowMs = 60000) => {
|
|
104
|
+
const requests = [];
|
|
105
|
+
return {
|
|
106
|
+
name: 'rate-limiter',
|
|
107
|
+
onRequest: (_metrics) => {
|
|
108
|
+
const now = Date.now();
|
|
109
|
+
const windowStart = now - windowMs;
|
|
110
|
+
// Remove old requests
|
|
111
|
+
while (requests.length > 0 && requests[0] < windowStart) {
|
|
112
|
+
requests.shift();
|
|
113
|
+
}
|
|
114
|
+
requests.push(now);
|
|
115
|
+
if (requests.length > maxRequests) {
|
|
116
|
+
logger_1.default.warn(`Rate limit exceeded: ${requests.length} requests in ${windowMs}ms`);
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
},
|
|
121
|
+
// Performance metrics collector
|
|
122
|
+
metricsCollector: () => {
|
|
123
|
+
const metrics = [];
|
|
124
|
+
return {
|
|
125
|
+
name: 'metrics-collector',
|
|
126
|
+
onResponse: (metricsData) => {
|
|
127
|
+
metrics.push(metricsData);
|
|
128
|
+
// Keep only last 1000 metrics
|
|
129
|
+
if (metrics.length > 1000) {
|
|
130
|
+
metrics.splice(0, 100);
|
|
131
|
+
}
|
|
132
|
+
// Calculate average response time
|
|
133
|
+
const avgTime = metrics.reduce((sum, m) => sum + (m.duration || 0), 0) / metrics.length;
|
|
134
|
+
if (metrics.length % 100 === 0) {
|
|
135
|
+
logger_1.default.debug(`Performance metrics - Avg response time: ${Math.round(avgTime)}ms, Requests: ${metrics.length}`);
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
},
|
|
140
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hazeljs/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Core HazelJS framework - Dependency injection, routing, decorators, and base functionality",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -63,5 +63,5 @@
|
|
|
63
63
|
"url": "https://github.com/hazeljs/hazel-js/issues"
|
|
64
64
|
},
|
|
65
65
|
"homepage": "https://hazeljs.ai",
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "151d5678aa2aeddd75fb75b1b5c55fabe8cb8050"
|
|
67
67
|
}
|