@hemia/core 0.0.10 → 0.0.13
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/dist/hemia-core.esm.js +139 -6
- package/dist/hemia-core.js +136 -3
- package/dist/types/guards/auth.guard.d.ts +8 -0
- package/dist/types/guards/index.d.ts +2 -0
- package/dist/types/guards/public-client.guard.d.ts +7 -0
- package/dist/types/guards/throttle.guard.d.ts +13 -0
- package/package.json +3 -3
package/dist/hemia-core.esm.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import 'reflect-metadata';
|
|
2
2
|
import express, { Router } from 'express';
|
|
3
|
-
import { METADATA_KEYS, ParamType, ApiResponse, isRedirectResponse, ControllerRegistry } from '@hemia/common';
|
|
3
|
+
import { METADATA_KEYS, ParamType, ApiResponse, isRedirectResponse, ControllerRegistry, CustomHttpError } from '@hemia/common';
|
|
4
4
|
import { TRACE_METADATA_KEY } from '@hemia/trace-manager';
|
|
5
5
|
import { traceMiddleware } from '@hemia/app-context';
|
|
6
6
|
import { plainToInstance } from 'class-transformer';
|
|
7
7
|
import multer from 'multer';
|
|
8
8
|
import { injectable, inject } from 'inversify';
|
|
9
|
-
import { AUTH_SERVICE_ID, AuthService } from '@hemia/auth-sdk';
|
|
9
|
+
import { AUTH_SERVICE_ID, AuthService, OAuthService } from '@hemia/auth-sdk';
|
|
10
10
|
|
|
11
11
|
class GuardsConsumer {
|
|
12
12
|
/**
|
|
@@ -338,9 +338,9 @@ class AppFactory {
|
|
|
338
338
|
const defaultHeaders = {
|
|
339
339
|
'Access-Control-Allow-Origin': req.headers.origin || '*',
|
|
340
340
|
'Access-Control-Allow-Methods': 'GET,POST,PUT,DELETE,PATCH,OPTIONS',
|
|
341
|
-
'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-Api-Key, Language, X-No-Cookies, x-session',
|
|
341
|
+
'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-Api-Key, Language, X-No-Cookies, x-session, x-client-id, X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After',
|
|
342
342
|
'Access-Control-Allow-Credentials': 'true',
|
|
343
|
-
'Access-Control-Expose-Headers': 'Authorization, X-Correlation-Id, X-Trace-Id, x-session',
|
|
343
|
+
'Access-Control-Expose-Headers': 'Authorization, X-Correlation-Id, X-Trace-Id, x-session, X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After',
|
|
344
344
|
};
|
|
345
345
|
const headers = { ...defaultHeaders, ...(options.corsHeaders || {}) };
|
|
346
346
|
Object.entries(headers).forEach(([key, value]) => {
|
|
@@ -392,6 +392,7 @@ class AppFactory {
|
|
|
392
392
|
/**
|
|
393
393
|
* Guardia de autorización que verifica roles y permisos definidos en los controladores y métodos.
|
|
394
394
|
* Utiliza los metadatos definidos con los decoradores @Roles y @Permissions.
|
|
395
|
+
* Soporta wildcards en permisos jerárquicos (ej: account:*, account:email:*)
|
|
395
396
|
*/
|
|
396
397
|
let AuthGuard = class AuthGuard {
|
|
397
398
|
constructor(reflector) {
|
|
@@ -422,12 +423,36 @@ let AuthGuard = class AuthGuard {
|
|
|
422
423
|
}
|
|
423
424
|
if (requiredPermissions) {
|
|
424
425
|
const userPermissions = Array.isArray(permissions) ? permissions : [];
|
|
425
|
-
const hasPermission = requiredPermissions.some((
|
|
426
|
+
const hasPermission = requiredPermissions.some((requiredPerm) => this.checkPermission(requiredPerm, userPermissions));
|
|
426
427
|
if (!hasPermission)
|
|
427
428
|
return false;
|
|
428
429
|
}
|
|
429
430
|
return true;
|
|
430
431
|
}
|
|
432
|
+
/**
|
|
433
|
+
* Verifica si el usuario tiene un permiso requerido, soportando wildcards
|
|
434
|
+
* @param requiredPermission Permiso requerido (ej: account:email:update)
|
|
435
|
+
* @param userPermissions Array de permisos del usuario
|
|
436
|
+
* @returns true si el usuario tiene el permiso
|
|
437
|
+
*/
|
|
438
|
+
checkPermission(requiredPermission, userPermissions) {
|
|
439
|
+
const requiredParts = requiredPermission.split(':');
|
|
440
|
+
return userPermissions.some(userPerm => {
|
|
441
|
+
const userParts = userPerm.split(':');
|
|
442
|
+
for (let i = 0; i < requiredParts.length; i++) {
|
|
443
|
+
if (userParts[i] === '*') {
|
|
444
|
+
return true;
|
|
445
|
+
}
|
|
446
|
+
if (i >= userParts.length) {
|
|
447
|
+
return false;
|
|
448
|
+
}
|
|
449
|
+
if (userParts[i] !== requiredParts[i]) {
|
|
450
|
+
return false;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
return true;
|
|
454
|
+
});
|
|
455
|
+
}
|
|
431
456
|
};
|
|
432
457
|
AuthGuard = __decorate([
|
|
433
458
|
injectable(),
|
|
@@ -500,4 +525,112 @@ JWTGuard = __decorate([
|
|
|
500
525
|
__metadata("design:paramtypes", [AuthService])
|
|
501
526
|
], JWTGuard);
|
|
502
527
|
|
|
503
|
-
|
|
528
|
+
let PublicClientGuard = class PublicClientGuard {
|
|
529
|
+
constructor(oauthService) {
|
|
530
|
+
this.oauthService = oauthService;
|
|
531
|
+
}
|
|
532
|
+
async canActivate(context) {
|
|
533
|
+
const request = context.switchToHttp().getRequest();
|
|
534
|
+
const clientId = request.headers['x-client-id'] || request.body.client_id;
|
|
535
|
+
if (!clientId) {
|
|
536
|
+
return false;
|
|
537
|
+
}
|
|
538
|
+
const client = await this.oauthService.getByClientId(clientId);
|
|
539
|
+
if (!client || !client.isActive) {
|
|
540
|
+
return false;
|
|
541
|
+
}
|
|
542
|
+
request.oauthClient = client;
|
|
543
|
+
return true;
|
|
544
|
+
}
|
|
545
|
+
};
|
|
546
|
+
PublicClientGuard = __decorate([
|
|
547
|
+
injectable(),
|
|
548
|
+
__param(0, inject(OAuthService)),
|
|
549
|
+
__metadata("design:paramtypes", [OAuthService])
|
|
550
|
+
], PublicClientGuard);
|
|
551
|
+
|
|
552
|
+
var ThrottleGuard_1;
|
|
553
|
+
let ThrottleGuard = ThrottleGuard_1 = class ThrottleGuard {
|
|
554
|
+
constructor() {
|
|
555
|
+
if (!ThrottleGuard_1.cleanupInterval) {
|
|
556
|
+
ThrottleGuard_1.cleanupInterval = setInterval(() => {
|
|
557
|
+
this.cleanup();
|
|
558
|
+
}, 60000);
|
|
559
|
+
ThrottleGuard_1.cleanupInterval.unref();
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
async canActivate(context) {
|
|
563
|
+
const request = context.switchToHttp().getRequest();
|
|
564
|
+
const handler = context.getHandler();
|
|
565
|
+
const options = Reflect.getMetadata(METADATA_KEYS.THROTTLE, handler);
|
|
566
|
+
if (!options) {
|
|
567
|
+
return true;
|
|
568
|
+
}
|
|
569
|
+
if (options.skipIf && options.skipIf(context)) {
|
|
570
|
+
return true;
|
|
571
|
+
}
|
|
572
|
+
const ip = this.getClientIp(request);
|
|
573
|
+
const endpointKey = `${context.getClass().name}:${handler.name}`;
|
|
574
|
+
const key = `throttle:${endpointKey}:${ip}`;
|
|
575
|
+
const now = Date.now();
|
|
576
|
+
const ttlMs = options.ttl * 1000;
|
|
577
|
+
let record = ThrottleGuard_1.storage.get(key);
|
|
578
|
+
if (!record || record.expiresAt < now) {
|
|
579
|
+
record = {
|
|
580
|
+
hits: 0,
|
|
581
|
+
expiresAt: now + ttlMs
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
record.hits++;
|
|
585
|
+
ThrottleGuard_1.storage.set(key, record);
|
|
586
|
+
if (record.hits > options.limit) {
|
|
587
|
+
const response = context.switchToHttp().getResponse();
|
|
588
|
+
const retryAfter = Math.ceil((record.expiresAt - now) / 1000);
|
|
589
|
+
this.setHeaders(response, options.limit, 0, retryAfter);
|
|
590
|
+
throw new CustomHttpError('Too Many Requests', 429, 'rate_limit_exceeded');
|
|
591
|
+
}
|
|
592
|
+
const response = context.switchToHttp().getResponse();
|
|
593
|
+
const remaining = Math.max(0, options.limit - record.hits);
|
|
594
|
+
this.setHeaders(response, options.limit, remaining, options.ttl);
|
|
595
|
+
return true;
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* Limpia las entradas expiradas para evitar fugas de memoria
|
|
599
|
+
*/
|
|
600
|
+
cleanup() {
|
|
601
|
+
const now = Date.now();
|
|
602
|
+
ThrottleGuard_1.storage.forEach((value, key) => {
|
|
603
|
+
if (value.expiresAt < now) {
|
|
604
|
+
ThrottleGuard_1.storage.delete(key);
|
|
605
|
+
}
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
getClientIp(request) {
|
|
609
|
+
const headers = request.headers;
|
|
610
|
+
if (headers['cf-connecting-ip'])
|
|
611
|
+
return headers['cf-connecting-ip'];
|
|
612
|
+
if (headers['x-forwarded-for']) {
|
|
613
|
+
return headers['x-forwarded-for'].split(',')[0].trim();
|
|
614
|
+
}
|
|
615
|
+
if (headers['x-real-ip'])
|
|
616
|
+
return headers['x-real-ip'];
|
|
617
|
+
return request.socket?.remoteAddress || request.ip || 'unknown';
|
|
618
|
+
}
|
|
619
|
+
setHeaders(res, limit, remaining, resetOrRetry) {
|
|
620
|
+
if (res && typeof res.setHeader === 'function') {
|
|
621
|
+
res.setHeader('X-RateLimit-Limit', limit);
|
|
622
|
+
res.setHeader('X-RateLimit-Remaining', remaining);
|
|
623
|
+
if (remaining === 0) {
|
|
624
|
+
res.setHeader('Retry-After', resetOrRetry);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
};
|
|
629
|
+
ThrottleGuard.storage = new Map();
|
|
630
|
+
ThrottleGuard.cleanupInterval = null;
|
|
631
|
+
ThrottleGuard = ThrottleGuard_1 = __decorate([
|
|
632
|
+
injectable(),
|
|
633
|
+
__metadata("design:paramtypes", [])
|
|
634
|
+
], ThrottleGuard);
|
|
635
|
+
|
|
636
|
+
export { ApiKeyGuard, AppFactory, AuthGuard, GuardsConsumer, HemiaExecutionContext, JWTGuard, PublicClientGuard, Reflector, ResponseSerializer, ThrottleGuard, registerRoutes };
|
package/dist/hemia-core.js
CHANGED
|
@@ -340,9 +340,9 @@ class AppFactory {
|
|
|
340
340
|
const defaultHeaders = {
|
|
341
341
|
'Access-Control-Allow-Origin': req.headers.origin || '*',
|
|
342
342
|
'Access-Control-Allow-Methods': 'GET,POST,PUT,DELETE,PATCH,OPTIONS',
|
|
343
|
-
'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-Api-Key, Language, X-No-Cookies, x-session',
|
|
343
|
+
'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-Api-Key, Language, X-No-Cookies, x-session, x-client-id, X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After',
|
|
344
344
|
'Access-Control-Allow-Credentials': 'true',
|
|
345
|
-
'Access-Control-Expose-Headers': 'Authorization, X-Correlation-Id, X-Trace-Id, x-session',
|
|
345
|
+
'Access-Control-Expose-Headers': 'Authorization, X-Correlation-Id, X-Trace-Id, x-session, X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After',
|
|
346
346
|
};
|
|
347
347
|
const headers = { ...defaultHeaders, ...(options.corsHeaders || {}) };
|
|
348
348
|
Object.entries(headers).forEach(([key, value]) => {
|
|
@@ -394,6 +394,7 @@ class AppFactory {
|
|
|
394
394
|
/**
|
|
395
395
|
* Guardia de autorización que verifica roles y permisos definidos en los controladores y métodos.
|
|
396
396
|
* Utiliza los metadatos definidos con los decoradores @Roles y @Permissions.
|
|
397
|
+
* Soporta wildcards en permisos jerárquicos (ej: account:*, account:email:*)
|
|
397
398
|
*/
|
|
398
399
|
exports.AuthGuard = class AuthGuard {
|
|
399
400
|
constructor(reflector) {
|
|
@@ -424,12 +425,36 @@ exports.AuthGuard = class AuthGuard {
|
|
|
424
425
|
}
|
|
425
426
|
if (requiredPermissions) {
|
|
426
427
|
const userPermissions = Array.isArray(permissions) ? permissions : [];
|
|
427
|
-
const hasPermission = requiredPermissions.some((
|
|
428
|
+
const hasPermission = requiredPermissions.some((requiredPerm) => this.checkPermission(requiredPerm, userPermissions));
|
|
428
429
|
if (!hasPermission)
|
|
429
430
|
return false;
|
|
430
431
|
}
|
|
431
432
|
return true;
|
|
432
433
|
}
|
|
434
|
+
/**
|
|
435
|
+
* Verifica si el usuario tiene un permiso requerido, soportando wildcards
|
|
436
|
+
* @param requiredPermission Permiso requerido (ej: account:email:update)
|
|
437
|
+
* @param userPermissions Array de permisos del usuario
|
|
438
|
+
* @returns true si el usuario tiene el permiso
|
|
439
|
+
*/
|
|
440
|
+
checkPermission(requiredPermission, userPermissions) {
|
|
441
|
+
const requiredParts = requiredPermission.split(':');
|
|
442
|
+
return userPermissions.some(userPerm => {
|
|
443
|
+
const userParts = userPerm.split(':');
|
|
444
|
+
for (let i = 0; i < requiredParts.length; i++) {
|
|
445
|
+
if (userParts[i] === '*') {
|
|
446
|
+
return true;
|
|
447
|
+
}
|
|
448
|
+
if (i >= userParts.length) {
|
|
449
|
+
return false;
|
|
450
|
+
}
|
|
451
|
+
if (userParts[i] !== requiredParts[i]) {
|
|
452
|
+
return false;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
return true;
|
|
456
|
+
});
|
|
457
|
+
}
|
|
433
458
|
};
|
|
434
459
|
exports.AuthGuard = __decorate([
|
|
435
460
|
inversify.injectable(),
|
|
@@ -502,6 +527,114 @@ exports.JWTGuard = __decorate([
|
|
|
502
527
|
__metadata("design:paramtypes", [authSdk.AuthService])
|
|
503
528
|
], exports.JWTGuard);
|
|
504
529
|
|
|
530
|
+
exports.PublicClientGuard = class PublicClientGuard {
|
|
531
|
+
constructor(oauthService) {
|
|
532
|
+
this.oauthService = oauthService;
|
|
533
|
+
}
|
|
534
|
+
async canActivate(context) {
|
|
535
|
+
const request = context.switchToHttp().getRequest();
|
|
536
|
+
const clientId = request.headers['x-client-id'] || request.body.client_id;
|
|
537
|
+
if (!clientId) {
|
|
538
|
+
return false;
|
|
539
|
+
}
|
|
540
|
+
const client = await this.oauthService.getByClientId(clientId);
|
|
541
|
+
if (!client || !client.isActive) {
|
|
542
|
+
return false;
|
|
543
|
+
}
|
|
544
|
+
request.oauthClient = client;
|
|
545
|
+
return true;
|
|
546
|
+
}
|
|
547
|
+
};
|
|
548
|
+
exports.PublicClientGuard = __decorate([
|
|
549
|
+
inversify.injectable(),
|
|
550
|
+
__param(0, inversify.inject(authSdk.OAuthService)),
|
|
551
|
+
__metadata("design:paramtypes", [authSdk.OAuthService])
|
|
552
|
+
], exports.PublicClientGuard);
|
|
553
|
+
|
|
554
|
+
var ThrottleGuard_1;
|
|
555
|
+
exports.ThrottleGuard = ThrottleGuard_1 = class ThrottleGuard {
|
|
556
|
+
constructor() {
|
|
557
|
+
if (!ThrottleGuard_1.cleanupInterval) {
|
|
558
|
+
ThrottleGuard_1.cleanupInterval = setInterval(() => {
|
|
559
|
+
this.cleanup();
|
|
560
|
+
}, 60000);
|
|
561
|
+
ThrottleGuard_1.cleanupInterval.unref();
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
async canActivate(context) {
|
|
565
|
+
const request = context.switchToHttp().getRequest();
|
|
566
|
+
const handler = context.getHandler();
|
|
567
|
+
const options = Reflect.getMetadata(common.METADATA_KEYS.THROTTLE, handler);
|
|
568
|
+
if (!options) {
|
|
569
|
+
return true;
|
|
570
|
+
}
|
|
571
|
+
if (options.skipIf && options.skipIf(context)) {
|
|
572
|
+
return true;
|
|
573
|
+
}
|
|
574
|
+
const ip = this.getClientIp(request);
|
|
575
|
+
const endpointKey = `${context.getClass().name}:${handler.name}`;
|
|
576
|
+
const key = `throttle:${endpointKey}:${ip}`;
|
|
577
|
+
const now = Date.now();
|
|
578
|
+
const ttlMs = options.ttl * 1000;
|
|
579
|
+
let record = ThrottleGuard_1.storage.get(key);
|
|
580
|
+
if (!record || record.expiresAt < now) {
|
|
581
|
+
record = {
|
|
582
|
+
hits: 0,
|
|
583
|
+
expiresAt: now + ttlMs
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
record.hits++;
|
|
587
|
+
ThrottleGuard_1.storage.set(key, record);
|
|
588
|
+
if (record.hits > options.limit) {
|
|
589
|
+
const response = context.switchToHttp().getResponse();
|
|
590
|
+
const retryAfter = Math.ceil((record.expiresAt - now) / 1000);
|
|
591
|
+
this.setHeaders(response, options.limit, 0, retryAfter);
|
|
592
|
+
throw new common.CustomHttpError('Too Many Requests', 429, 'rate_limit_exceeded');
|
|
593
|
+
}
|
|
594
|
+
const response = context.switchToHttp().getResponse();
|
|
595
|
+
const remaining = Math.max(0, options.limit - record.hits);
|
|
596
|
+
this.setHeaders(response, options.limit, remaining, options.ttl);
|
|
597
|
+
return true;
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* Limpia las entradas expiradas para evitar fugas de memoria
|
|
601
|
+
*/
|
|
602
|
+
cleanup() {
|
|
603
|
+
const now = Date.now();
|
|
604
|
+
ThrottleGuard_1.storage.forEach((value, key) => {
|
|
605
|
+
if (value.expiresAt < now) {
|
|
606
|
+
ThrottleGuard_1.storage.delete(key);
|
|
607
|
+
}
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
getClientIp(request) {
|
|
611
|
+
const headers = request.headers;
|
|
612
|
+
if (headers['cf-connecting-ip'])
|
|
613
|
+
return headers['cf-connecting-ip'];
|
|
614
|
+
if (headers['x-forwarded-for']) {
|
|
615
|
+
return headers['x-forwarded-for'].split(',')[0].trim();
|
|
616
|
+
}
|
|
617
|
+
if (headers['x-real-ip'])
|
|
618
|
+
return headers['x-real-ip'];
|
|
619
|
+
return request.socket?.remoteAddress || request.ip || 'unknown';
|
|
620
|
+
}
|
|
621
|
+
setHeaders(res, limit, remaining, resetOrRetry) {
|
|
622
|
+
if (res && typeof res.setHeader === 'function') {
|
|
623
|
+
res.setHeader('X-RateLimit-Limit', limit);
|
|
624
|
+
res.setHeader('X-RateLimit-Remaining', remaining);
|
|
625
|
+
if (remaining === 0) {
|
|
626
|
+
res.setHeader('Retry-After', resetOrRetry);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
};
|
|
631
|
+
exports.ThrottleGuard.storage = new Map();
|
|
632
|
+
exports.ThrottleGuard.cleanupInterval = null;
|
|
633
|
+
exports.ThrottleGuard = ThrottleGuard_1 = __decorate([
|
|
634
|
+
inversify.injectable(),
|
|
635
|
+
__metadata("design:paramtypes", [])
|
|
636
|
+
], exports.ThrottleGuard);
|
|
637
|
+
|
|
505
638
|
exports.AppFactory = AppFactory;
|
|
506
639
|
exports.GuardsConsumer = GuardsConsumer;
|
|
507
640
|
exports.HemiaExecutionContext = HemiaExecutionContext;
|
|
@@ -3,9 +3,17 @@ import { Reflector } from '../services';
|
|
|
3
3
|
/**
|
|
4
4
|
* Guardia de autorización que verifica roles y permisos definidos en los controladores y métodos.
|
|
5
5
|
* Utiliza los metadatos definidos con los decoradores @Roles y @Permissions.
|
|
6
|
+
* Soporta wildcards en permisos jerárquicos (ej: account:*, account:email:*)
|
|
6
7
|
*/
|
|
7
8
|
export declare class AuthGuard implements CanActivate {
|
|
8
9
|
private reflector;
|
|
9
10
|
constructor(reflector: Reflector);
|
|
10
11
|
canActivate(context: ExecutionContext): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Verifica si el usuario tiene un permiso requerido, soportando wildcards
|
|
14
|
+
* @param requiredPermission Permiso requerido (ej: account:email:update)
|
|
15
|
+
* @param userPermissions Array de permisos del usuario
|
|
16
|
+
* @returns true si el usuario tiene el permiso
|
|
17
|
+
*/
|
|
18
|
+
private checkPermission;
|
|
11
19
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { CanActivate, ExecutionContext } from "@hemia/common";
|
|
2
|
+
import { OAuthService } from "@hemia/auth-sdk";
|
|
3
|
+
export declare class PublicClientGuard implements CanActivate {
|
|
4
|
+
private readonly oauthService;
|
|
5
|
+
constructor(oauthService: OAuthService);
|
|
6
|
+
canActivate(context: ExecutionContext): Promise<boolean>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { CanActivate, ExecutionContext } from "@hemia/common";
|
|
2
|
+
export declare class ThrottleGuard implements CanActivate {
|
|
3
|
+
private static storage;
|
|
4
|
+
private static cleanupInterval;
|
|
5
|
+
constructor();
|
|
6
|
+
canActivate(context: ExecutionContext): Promise<boolean>;
|
|
7
|
+
/**
|
|
8
|
+
* Limpia las entradas expiradas para evitar fugas de memoria
|
|
9
|
+
*/
|
|
10
|
+
private cleanup;
|
|
11
|
+
private getClientIp;
|
|
12
|
+
private setHeaders;
|
|
13
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hemia/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.13",
|
|
4
4
|
"description": "Core utilities for Hemia projects",
|
|
5
5
|
"main": "dist/hemia-core.js",
|
|
6
6
|
"module": "dist/hemia-core.esm.js",
|
|
@@ -18,10 +18,10 @@
|
|
|
18
18
|
"@rollup/plugin-commonjs": "^26.0.1",
|
|
19
19
|
"@rollup/plugin-json": "^6.1.0",
|
|
20
20
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
21
|
-
"@hemia/common": "^0.0.
|
|
21
|
+
"@hemia/common": "^0.0.15",
|
|
22
22
|
"@hemia/app-context": "^0.0.6",
|
|
23
23
|
"@hemia/trace-manager": "^0.0.9",
|
|
24
|
-
"@hemia/auth-sdk": "^0.0.
|
|
24
|
+
"@hemia/auth-sdk": "^0.0.16",
|
|
25
25
|
"@types/express": "^5.0.5",
|
|
26
26
|
"express": "^5.1.0",
|
|
27
27
|
"inversify": "^7.10.4",
|