falconhub-apilibrary 1.2.3-dev.70 → 1.2.4-dev.71

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/index.d.mts CHANGED
@@ -396,6 +396,47 @@ interface UserBasicResponse {
396
396
  securityLevel: number;
397
397
  }
398
398
 
399
+ interface AdminUser {
400
+ userId: number;
401
+ username: string;
402
+ firstName: string;
403
+ lastName: string;
404
+ email: string;
405
+ phone: string;
406
+ areaCodeId: number | null;
407
+ birthday: string | null;
408
+ referrerUserId: number | null;
409
+ userReferralCode: string;
410
+ genderId: number | null;
411
+ roleId: number | null;
412
+ userTypeId: number | null;
413
+ isActive: boolean;
414
+ createdAt: string;
415
+ updatedAt: string | null;
416
+ deleted: boolean;
417
+ }
418
+ interface AdminAuthentication {
419
+ userAuthenticationId: number;
420
+ userId: number;
421
+ securityLevel: number;
422
+ clientId: string;
423
+ isTwoFactorEnabled: boolean;
424
+ failedLoginAttempts: number;
425
+ lastLogin: string | null;
426
+ isActive: boolean;
427
+ isLocked: boolean;
428
+ emailVerified: boolean;
429
+ phoneVerified: boolean;
430
+ mustChangePassword: boolean;
431
+ passwordLastChanged: string | null;
432
+ passwordExpiresAt: string | null;
433
+ lastLoginIP: string | null;
434
+ lastLoginDevice: string | null;
435
+ lastActivityAt: string | null;
436
+ createdAt: string;
437
+ updatedAt: string | null;
438
+ }
439
+
399
440
  interface UserAdminRequest {
400
441
  username: string;
401
442
  firstName: string;
@@ -577,12 +618,12 @@ declare class UserService {
577
618
  * Crea un nuevo usuario administrador.
578
619
  * @param request - Datos del nuevo administrador
579
620
  */
580
- newAdminUser(request: UserAdminRequest): Promise<ResponseModel>;
621
+ newAdminUser(request: UserAdminRequest): Promise<ResponseModel<AdminUser>>;
581
622
  /**
582
623
  * Crea la autenticación para un usuario.
583
624
  * @param request - Datos de autenticación del usuario
584
625
  */
585
- createUserAuthentication(request: UserAuthAdminRequest): Promise<ResponseModel>;
626
+ createUserAuthentication(request: UserAuthAdminRequest): Promise<ResponseModel<AdminAuthentication>>;
586
627
  /**
587
628
  * Cambia la contraseña de un administrador.
588
629
  * @param id - ID del usuario
@@ -593,7 +634,7 @@ declare class UserService {
593
634
  * Obtiene todos los administradores con filtros opcionales.
594
635
  * @param filter - Filtros opcionales para la búsqueda
595
636
  */
596
- getAllAdmins(filter?: UserAdminFilter): Promise<ResponseModel>;
637
+ getAllAdmins(filter?: UserAdminFilter): Promise<ResponseModel<AdminUser[]>>;
597
638
  /**
598
639
  * Obtiene el modelo de filtros disponibles para administradores.
599
640
  */
@@ -602,29 +643,29 @@ declare class UserService {
602
643
  * Obtiene un administrador por su ID.
603
644
  * @param id - ID del administrador
604
645
  */
605
- getAdminById(id: number): Promise<ResponseModel>;
646
+ getAdminById(id: number): Promise<ResponseModel<AdminUser>>;
606
647
  /**
607
648
  * Obtiene la autenticación de un administrador.
608
649
  * @param id - ID del usuario
609
650
  */
610
- getAdminAuthentication(id: number): Promise<ResponseModel>;
651
+ getAdminAuthentication(id: number): Promise<ResponseModel<AdminAuthentication>>;
611
652
  /**
612
653
  * Actualiza un administrador existente.
613
654
  * @param id - ID del administrador
614
655
  * @param request - Nuevos datos del administrador
615
656
  */
616
- updateAdmin(id: number, request: UserAdminUpdateRequest): Promise<ResponseModel>;
657
+ updateAdmin(id: number, request: UserAdminUpdateRequest): Promise<ResponseModel<AdminUser>>;
617
658
  /**
618
659
  * Activa o desactiva un administrador.
619
660
  * @param id - ID del administrador
620
661
  */
621
- toggleAdminStatus(id: number): Promise<ResponseModel>;
662
+ toggleAdminStatus(id: number): Promise<ResponseModel<AdminUser>>;
622
663
  /**
623
664
  * Actualiza la autenticación de un administrador.
624
665
  * @param id - ID del usuario
625
666
  * @param request - Nuevos datos de autenticación
626
667
  */
627
- updateAdminAuthentication(id: number, request: UserAuthUpdateRequest): Promise<ResponseModel>;
668
+ updateAdminAuthentication(id: number, request: UserAuthUpdateRequest): Promise<ResponseModel<AdminAuthentication>>;
628
669
  }
629
670
 
630
671
  /**
@@ -880,6 +921,23 @@ declare class SystemService {
880
921
  deleteUIRoute(id: number): Promise<ResponseModel<void>>;
881
922
  }
882
923
 
924
+ interface Location {
925
+ locationId: number;
926
+ locationName: string;
927
+ address1: string;
928
+ address2: string;
929
+ city: string;
930
+ state: string;
931
+ country: string;
932
+ postalCode: string;
933
+ contactName: string;
934
+ contactPhone: string;
935
+ contactEmail: string;
936
+ isActive: boolean | null;
937
+ createdAt: string | null;
938
+ updatedAt: string | null;
939
+ deleted: boolean | null;
940
+ }
883
941
  interface LocationsRequest {
884
942
  locationName: string;
885
943
  address1: string;
@@ -902,6 +960,14 @@ interface LocationsFilter {
902
960
  IsActive?: boolean;
903
961
  }
904
962
 
963
+ interface InventoryStatus {
964
+ inventoryStatusId: number;
965
+ inventoryStatus: string;
966
+ description: string;
967
+ createdAt: string | null;
968
+ updatedAt: string | null;
969
+ deleted: boolean | null;
970
+ }
905
971
  interface InventoryStatusRequest {
906
972
  inventoryStatusId?: number;
907
973
  inventoryStatus: string;
@@ -927,7 +993,7 @@ declare class InventoryService {
927
993
  * Obtiene todas las ubicaciones con filtros opcionales.
928
994
  * @param filter - Filtros opcionales para la búsqueda
929
995
  */
930
- getLocations(filter?: LocationsFilter): Promise<ResponseModel>;
996
+ getLocations(filter?: LocationsFilter): Promise<ResponseModel<Location[]>>;
931
997
  /**
932
998
  * Obtiene el modelo de filtros disponibles para ubicaciones.
933
999
  */
@@ -936,23 +1002,23 @@ declare class InventoryService {
936
1002
  * Obtiene una ubicación por su ID.
937
1003
  * @param id - ID de la ubicación
938
1004
  */
939
- getLocationById(id: number): Promise<ResponseModel>;
1005
+ getLocationById(id: number): Promise<ResponseModel<Location>>;
940
1006
  /**
941
1007
  * Crea una nueva ubicación.
942
1008
  * @param request - Datos de la ubicación a crear
943
1009
  */
944
- createLocation(request: LocationsRequest): Promise<ResponseModel>;
1010
+ createLocation(request: LocationsRequest): Promise<ResponseModel<Location>>;
945
1011
  /**
946
1012
  * Actualiza una ubicación existente.
947
1013
  * @param id - ID de la ubicación a actualizar
948
1014
  * @param request - Nuevos datos de la ubicación
949
1015
  */
950
- updateLocation(id: number, request: LocationsRequest): Promise<ResponseModel>;
1016
+ updateLocation(id: number, request: LocationsRequest): Promise<ResponseModel<Location>>;
951
1017
  /**
952
1018
  * Activa o desactiva una ubicación.
953
1019
  * @param id - ID de la ubicación
954
1020
  */
955
- toggleLocationStatus(id: number): Promise<ResponseModel>;
1021
+ toggleLocationStatus(id: number): Promise<ResponseModel<Location>>;
956
1022
  /**
957
1023
  * Elimina una ubicación.
958
1024
  * @param id - ID de la ubicación a eliminar
@@ -962,7 +1028,7 @@ declare class InventoryService {
962
1028
  * Obtiene todos los estatus de inventario con filtros opcionales.
963
1029
  * @param filter - Filtros opcionales para la búsqueda
964
1030
  */
965
- getStatuses(filter?: InventoryStatusesFilter): Promise<ResponseModel>;
1031
+ getStatuses(filter?: InventoryStatusesFilter): Promise<ResponseModel<InventoryStatus[]>>;
966
1032
  /**
967
1033
  * Obtiene el modelo de filtros disponibles para estatus de inventario.
968
1034
  */
@@ -971,23 +1037,23 @@ declare class InventoryService {
971
1037
  * Obtiene un estatus de inventario por su ID.
972
1038
  * @param id - ID del estatus
973
1039
  */
974
- getStatusById(id: number): Promise<ResponseModel>;
1040
+ getStatusById(id: number): Promise<ResponseModel<InventoryStatus>>;
975
1041
  /**
976
1042
  * Crea un nuevo estatus de inventario.
977
1043
  * @param request - Datos del estatus a crear
978
1044
  */
979
- createStatus(request: InventoryStatusRequest): Promise<ResponseModel>;
1045
+ createStatus(request: InventoryStatusRequest): Promise<ResponseModel<InventoryStatus>>;
980
1046
  /**
981
1047
  * Actualiza un estatus de inventario existente.
982
1048
  * @param id - ID del estatus a actualizar
983
1049
  * @param request - Nuevos datos del estatus
984
1050
  */
985
- updateStatus(id: number, request: InventoryStatusRequest): Promise<ResponseModel>;
1051
+ updateStatus(id: number, request: InventoryStatusRequest): Promise<ResponseModel<InventoryStatus>>;
986
1052
  /**
987
1053
  * Activa o desactiva un estatus de inventario.
988
1054
  * @param id - ID del estatus
989
1055
  */
990
- toggleStatusActive(id: number): Promise<ResponseModel>;
1056
+ toggleStatusActive(id: number): Promise<ResponseModel<InventoryStatus>>;
991
1057
  /**
992
1058
  * Elimina un estatus de inventario.
993
1059
  * @param id - ID del estatus a eliminar
@@ -1035,4 +1101,4 @@ declare class FalconHUBSDK {
1035
1101
 
1036
1102
  declare function decrypt(encryptedBase64: string, secret: string, timestamp: string): string;
1037
1103
 
1038
- export { API, AuthInterceptor, type AuthInterceptorConfig, AuthService, type ChangePasswordAdminRequest, type ChangePasswordRequest, type ConfirmEmailRequest, CryptoService, type Endpoint, type EndpointRequest, type EndpointsFilter, ErrorResponse, FalconHUBSDK, FilterBuilder, type FilterFieldMetadata, type FilterGroup, type FilterGroupOption, type FilterGroupsModel, type FilterMetadataModel, type FilterModel, type HttpMethodType, type InterceptorContext, InventoryService, type InventoryStatusRequest, type InventoryStatusesFilter, type LocationsFilter, type LocationsRequest, type LoginRequest, type LoginResponse, type MethodTypes, type Module, type ModuleRequest, type ModulesFilter, type RefreshTokenRequest, type RefreshTokenResponse, type RequestConfig, type RequestInterceptor, type RequestOptions, type ResponseModel, type SendOtpRequest, type ServiceProperties, SystemService, type TokenData, TokenManager, type UIRoute, type UIRouteRequest, type UIRoutesFilter, type UserAdminFilter, type UserAdminRequest, type UserAdminUpdateRequest, type UserAuthAdminRequest, type UserAuthUpdateRequest, type UserBasicResponse, type UserProfileResponse, UserService, type ValidateOtpRequest, type ValidateSessionRenewedResponse, type ValidateSessionResponse, decrypt };
1104
+ export { API, type AdminAuthentication, type AdminUser, AuthInterceptor, type AuthInterceptorConfig, AuthService, type ChangePasswordAdminRequest, type ChangePasswordRequest, type ConfirmEmailRequest, CryptoService, type Endpoint, type EndpointRequest, type EndpointsFilter, ErrorResponse, FalconHUBSDK, FilterBuilder, type FilterFieldMetadata, type FilterGroup, type FilterGroupOption, type FilterGroupsModel, type FilterMetadataModel, type FilterModel, type HttpMethodType, type InterceptorContext, InventoryService, type InventoryStatus, type InventoryStatusRequest, type InventoryStatusesFilter, type Location, type LocationsFilter, type LocationsRequest, type LoginRequest, type LoginResponse, type MethodTypes, type Module, type ModuleRequest, type ModulesFilter, type RefreshTokenRequest, type RefreshTokenResponse, type RequestConfig, type RequestInterceptor, type RequestOptions, type ResponseModel, type SendOtpRequest, type ServiceProperties, SystemService, type TokenData, TokenManager, type UIRoute, type UIRouteRequest, type UIRoutesFilter, type UserAdminFilter, type UserAdminRequest, type UserAdminUpdateRequest, type UserAuthAdminRequest, type UserAuthUpdateRequest, type UserBasicResponse, type UserProfileResponse, UserService, type ValidateOtpRequest, type ValidateSessionRenewedResponse, type ValidateSessionResponse, decrypt };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/API.ts","../src/core/CryptoService.ts","../src/core/TokenManager.ts","../src/core/interceptors/AuthInterceptor.ts","../src/types/ErrorResponse.ts","../src/services/AuthService.ts","../src/utils/FilterBuilder.ts","../src/services/UserService.ts","../src/services/SystemService.ts","../src/services/InventoryService.ts","../src/FalconHUBSDK.ts","../src/core/Encryption.ts"],"sourcesContent":["import { ServiceProperties } from \"@/types/ServiceProperties\";\nimport { CryptoService } from \"./CryptoService\";\nimport { MethodTypes, RequestOptions } from \"@/types/RequestOptions\";\nimport { ErrorResponse } from \"@/types/ErrorResponse\";\nimport { RequestConfig } from \"@/types/RequestConfig\";\nimport { AuthInterceptor } from \"./interceptors/AuthInterceptor\";\nimport { InterceptorContext } from \"@/core/interceptors/types/InterceptorContext\";\nimport { ResponseModel } from \"@/types/ResponseModel\";\n\n\n/**\n * Clase base para la ejecución de request HTTP al API\n */\nexport class API {\n private properties: ServiceProperties;\n private cryptoService: CryptoService;\n private authInterceptor: AuthInterceptor | null;\n\n private getAccessToken: () => string | null;\n private getRefreshToken: () => string | null;\n\n constructor(\n properties: ServiceProperties,\n cryptoService: CryptoService,\n authInterceptor: AuthInterceptor | null,\n getAccessToken: () => string | null,\n getRefreshToken: () => string | null\n ) {\n this.properties = properties;\n this.cryptoService = cryptoService;\n this.getAccessToken = getAccessToken;\n this.getRefreshToken = getRefreshToken;\n this.authInterceptor = authInterceptor;\n };\n\n /**\n * Ejecuta una request HTTP al API\n *\n * @param options - Opciones de la request\n * @returns Respuesta del tipo ResponseModel\n */\n private async apiExecute<T>(options: RequestOptions): Promise<ResponseModel<T>> {\n const {\n endpoint,\n method,\n body,\n requiresAuth,\n timeStamp\n } = options;\n\n const context: InterceptorContext = {\n requestId: this.cryptoService.generateUniqueId(),\n startTime: Date.now(),\n retryCount: 0,\n metadata: {}\n };\n\n try {\n const url = `${this.properties.url}/${endpoint}`;\n\n const headers: Record<string, string> = {};\n\n if (body && method !== 'GET') {\n headers['Content-Type'] = 'application/json';\n };\n\n const accessToken = this.getAccessToken();\n\n if (accessToken) {\n headers['Authorization'] = `Bearer ${accessToken}`;\n };\n\n const newTimeStamp = timeStamp || new Date().toString();\n\n headers[\"X-Origin-Request\"] = this.properties.originRequest;\n headers['X-Timestamp'] = newTimeStamp;\n headers[\"X-Domain\"] = this.properties.domain;\n headers[\"X-Device\"] = this.properties.device;\n headers[\"X-Source\"] = this.properties.source;\n\n let bodyString: string | undefined;\n\n if (body && method !== 'GET') {\n bodyString = JSON.stringify(body);\n };\n\n const requestConfig: RequestConfig = {\n url,\n method,\n headers,\n body: bodyString,\n requiresAuth\n };\n\n const modifiedConfig = this.authInterceptor\n ? await this.authInterceptor.onRequest(requestConfig, context)\n : requestConfig;\n\n const requestInit: RequestInit = {\n method: modifiedConfig.method,\n headers: modifiedConfig.headers,\n mode: 'cors',\n credentials: 'omit'\n };\n\n if (bodyString) {\n requestInit.body = bodyString;\n };\n\n const response = await fetch(\n modifiedConfig.url,\n requestInit\n );\n\n const newAccessToken = response.headers.get('X-New-Access-Token');\n const newRefreshToken = response.headers.get('X-New-Refresh-Token');\n\n if (newAccessToken || newRefreshToken) {\n this.properties.onTokensRefreshed?.({\n accessToken: newAccessToken,\n refreshToken: newRefreshToken\n });\n };\n\n const contentType = response.headers.get('Content-Type');\n\n if (contentType && contentType.includes('application/json')) {\n const responseText = await response.text();\n return JSON.parse(responseText) as ResponseModel<T>;\n };\n\n return {\n success: false,\n message: 'Response is not JSON',\n data: null,\n responseTime: null\n };\n } catch (error) {\n return {\n success: false,\n message: error instanceof Error ? error.message : 'Unexpected error occurred during API request.',\n data: null,\n responseTime: null\n };\n };\n };\n\n\n //#region REQUEST METHODS\n\n async executeGET<T>(\n endpoint: string,\n requiresAuth: boolean = false\n ): Promise<ResponseModel<T>> {\n return this.apiExecute<T>({\n endpoint,\n method: 'GET',\n requiresAuth: requiresAuth\n });\n };\n\n async executePOST<T>(\n endpoint: string,\n body?: any,\n requiresAuth: boolean = true,\n ): Promise<ResponseModel<T>> {\n return this.apiExecute<T>({\n endpoint,\n method: 'POST',\n body,\n requiresAuth: requiresAuth\n });\n };\n\n async executePATCH<T>(\n endpoint: string,\n body?: any,\n requiresAuth: boolean = true,\n ): Promise<ResponseModel<T>> {\n return this.apiExecute<T>({\n endpoint,\n method: 'PATCH',\n body,\n requiresAuth: requiresAuth\n });\n };\n\n async executeDELETE<T>(\n endpoint: string,\n body?: any,\n requiresAuth: boolean = true,\n ): Promise<ResponseModel<T>> {\n return this.apiExecute<T>({\n endpoint,\n method: 'DELETE',\n body,\n requiresAuth: requiresAuth\n });\n };\n\n async executePUT<T>(\n endpoint: string,\n body?: any,\n requiresAuth: boolean = true\n ): Promise<ResponseModel<T>> {\n return this.apiExecute<T>({\n endpoint,\n method: 'PUT',\n body,\n requiresAuth: requiresAuth,\n });\n };\n\n async executePublicRequest<T>(\n endpoint: string,\n method: MethodTypes,\n body?: any,\n timestamp?: string\n ): Promise<ResponseModel<T>> {\n return this.apiExecute<T>({\n endpoint,\n method,\n body,\n requiresAuth: false,\n timeStamp: timestamp\n });\n };\n\n //#endregion\n}\n","import * as CryptoJS from \"crypto-js\";\n\nexport class CryptoService {\n /**\n * Genera un hash SHA256 de un texto (útil para fingerprints)\n *\n * @param text - Texto a hashear\n * @returns Hash en formato hexadecimal\n */\n sha256(text: string): string {\n return CryptoJS.SHA256(text).toString(CryptoJS.enc.Hex);\n }\n\n /**\n * Genera un identificador único basado en timestamp y random\n * (útil para request IDs)\n *\n * @returns ID único\n */\n generateUniqueId(): string {\n const timestamp = Date.now().toString(36);\n const randomPart = Math.random().toString(36).substring(2, 15);\n return `${timestamp}-${randomPart}`;\n }\n}\n","import { TokenData } from \"@/types/TokenData\";\n\n/**\n * Manages authentication tokens.\n */\nexport class TokenManager {\n private tokens: TokenData | null = null;\n private onTokensChanged?: (tokens: TokenData | null) => void;\n private sessionCheckInterval: NodeJS.Timeout | null = null;\n private autoRefreshTimeout: NodeJS.Timeout | null = null;\n private onSessionExpiring?: (remainingMinutes: number) => void;\n private onSessionExpired?: () => Promise<void>;\n private onSessionRecovery?: () => Promise<boolean>;\n private hasNotifiedExpiring: boolean = false;\n private autoRefreshThresholdMinutes: number = 5;\n\n constructor(\n onTokensChanged?: (tokens: TokenData | null) => void,\n onSessionExpiring?: (remainingMinutes: number) => void,\n onSessionExpired?: () => Promise<void>,\n onSessionRecovery?: () => Promise<boolean>,\n autoRefreshThresholdMinutes?: number\n ) {\n this.onTokensChanged = onTokensChanged;\n this.onSessionExpiring = onSessionExpiring;\n this.onSessionExpired = onSessionExpired;\n this.onSessionRecovery = onSessionRecovery;\n this.autoRefreshThresholdMinutes = autoRefreshThresholdMinutes ?? 5;\n };\n\n /**\n * Guarda los tokens de autenticación y dispara el callback onTokensChanged.\n */\n setTokens(tokens: TokenData) {\n this.tokens = tokens;\n this.hasNotifiedExpiring = false;\n\n this.onTokensChanged?.(this.tokens);\n\n if (!tokens.rememberMe) {\n this.startExpirationCheck();\n this.stopAutoRefreshTimer();\n } else {\n this.stopExpirationCheck();\n this.scheduleAutoRefresh();\n };\n };\n\n /**\n * Guarda los tokens sin disparar el callback onTokensChanged.\n * Usar para inyectar tokens desde storage externo (cookies/localStorage).\n */\n setTokensSilent(tokens: TokenData) {\n this.tokens = tokens;\n this.hasNotifiedExpiring = false;\n\n if (!tokens.rememberMe) {\n this.startExpirationCheck();\n this.stopAutoRefreshTimer();\n } else {\n this.stopExpirationCheck();\n this.scheduleAutoRefresh();\n };\n };\n\n /**\n * Obtiene los tokens de autenticación almacenados.\n */\n getTokens(): TokenData | null {\n return this.tokens;\n };\n\n /**\n * Limpia los tokens de autenticación almacenados y dispara el callback onTokensChanged.\n */\n clearTokens() {\n this.stopExpirationCheck();\n this.stopAutoRefreshTimer();\n this.tokens = null;\n this.onTokensChanged?.(this.tokens);\n };\n\n /**\n * Valida si existen tokens y si el access token no ha expirado.\n */\n hasValidTokens(): boolean {\n if (!this.tokens) return false;\n\n return Date.now() < this.tokens.expiresAt;\n };\n\n /**\n * Valida si el access token expirará dentro del umbral especificado (en minutos).\n */\n isTokenExpiringSoon(thresholdMinutes: number): boolean {\n if (!this.tokens) return false;\n\n const thresholdMs = thresholdMinutes * 60 * 1000;\n const timeLeft = this.tokens.expiresAt - Date.now();\n\n return timeLeft > 0 && timeLeft <= thresholdMs;\n };\n\n /**\n * Obtiene el tiempo restante hasta la expiración del access token en milisegundos.\n */\n getTimeUntilExpiry(): number | null {\n if (!this.tokens) return null;\n\n return Math.max(0, this.tokens.expiresAt - Date.now());\n };\n\n /**\n * Obtiene el access token almacenado.\n */\n getAccessToken(): string | null {\n return this.tokens ? this.tokens.accessToken : null;\n };\n\n /**\n * Obtiene el refresh token almacenado.\n */\n getRefreshToken(): string | null {\n return this.tokens ? this.tokens.refreshToken : null;\n };\n\n /**\n * Verifica si el auto-refresh debe ejecutarse\n * Solo si el usuario activó \"rememberMe\" durante el login\n */\n shouldAutoRefresh(): boolean {\n if (!this.tokens) return false;\n\n return this.tokens.rememberMe === true;\n }\n\n /**\n * Inicia el monitoreo de expiración para sesiones sin rememberMe\n * - Notifica cuando quedan 5 minutos (onSessionExpiring)\n */\n private startExpirationCheck(): void {\n this.stopExpirationCheck();\n\n this.sessionCheckInterval = setInterval(async () => {\n if (!this.tokens) {\n this.stopExpirationCheck();\n return;\n };\n\n const timeLeft = this.getTimeUntilExpiry();\n if (timeLeft === null) return;\n\n const minutesLeft = Math.floor(timeLeft / (60 * 1000));\n\n if (minutesLeft <= 5 && minutesLeft > 1 && !this.hasNotifiedExpiring) {\n this.hasNotifiedExpiring = true;\n this.onSessionExpiring?.(minutesLeft);\n };\n\n if (minutesLeft <= 1) {\n this.stopExpirationCheck();\n\n if (this.onSessionRecovery) {\n try {\n const recovered = await this.onSessionRecovery();\n if (recovered) return;\n } catch (error) {\n }\n }\n\n if (this.onSessionExpired) {\n await this.onSessionExpired();\n };\n };\n }, 60000);\n }\n\n /**\n * Programa un auto-refresh proactivo para sesiones con rememberMe.\n * Se ejecuta X minutos antes de que expire el token\n */\n private scheduleAutoRefresh(): void {\n this.stopAutoRefreshTimer();\n\n if (!this.tokens || !this.tokens.rememberMe) return;\n\n const timeLeft = this.getTimeUntilExpiry();\n if (timeLeft === null || timeLeft <= 0) return;\n\n const thresholdMs = this.autoRefreshThresholdMinutes * 60 * 1000;\n const delay = Math.max(0, timeLeft - thresholdMs);\n\n this.autoRefreshTimeout = setTimeout(async () => {\n if (!this.tokens || !this.tokens.rememberMe) return;\n\n if (this.onSessionRecovery) {\n try {\n const recovered = await this.onSessionRecovery();\n if (recovered) return;\n } catch (error) {\n }\n }\n\n if (this.onSessionExpired) {\n await this.onSessionExpired();\n }\n }, delay);\n }\n\n /**\n * Detiene el monitoreo de expiración\n */\n private stopExpirationCheck(): void {\n if (this.sessionCheckInterval) {\n clearInterval(this.sessionCheckInterval);\n this.sessionCheckInterval = null;\n };\n }\n\n /**\n * Detiene el timer de auto-refresh proactivo\n */\n private stopAutoRefreshTimer(): void {\n if (this.autoRefreshTimeout) {\n clearTimeout(this.autoRefreshTimeout);\n this.autoRefreshTimeout = null;\n };\n }\n};\n","import { AuthInterceptorConfig } from \"./types/AuthInterceptorConfig\";\nimport { InterceptorContext } from \"@/core/interceptors/types/InterceptorContext\";\nimport { RequestConfig } from \"@/types/RequestConfig\";\nimport { RequestInterceptor } from \"./types/RequestInterceptor\";\n\nexport class AuthInterceptor implements RequestInterceptor {\n readonly name = \"AuthInterceptor\";\n\n private config: Required<AuthInterceptorConfig>;\n private refreshPromise: Promise<void> | null = null;\n private isRefreshing = false;\n\n constructor(config: AuthInterceptorConfig) {\n this.config = {\n enabled: config.enabled ?? true,\n thresholdMinutes: config.thresholdMinutes ?? 5,\n isTokenExpiringSoon: config.isTokenExpiringSoon,\n hasValidTokens: config.hasValidTokens,\n shouldAutoRefresh: config.shouldAutoRefresh,\n refreshSession: config.refreshSession\n };\n };\n\n async onRequest(\n config: RequestConfig,\n context: InterceptorContext\n ): Promise<RequestConfig> {\n\n //Actua en solicitudes que requieren autenticación\n if (!config.requiresAuth || !this.config.enabled) {\n return config;\n };\n\n //Actúa SOLO si los tokens son válidos\n if (!this.config.hasValidTokens()) {\n return config;\n };\n\n if (!this.config.shouldAutoRefresh()) {\n return config;\n };\n\n if (this.config.isTokenExpiringSoon()) {\n try {\n //Evita múltiples llamadas de actualización simultáneas\n if (this.isRefreshing && this.refreshPromise) {\n await this.refreshPromise;\n } else {\n this.isRefreshing = true;\n this.refreshPromise = this.config.refreshSession();\n await this.refreshPromise;\n this.isRefreshing = false;\n this.refreshPromise = null;\n };\n } catch (error) {\n this.isRefreshing = false;\n this.refreshPromise = null;\n };\n };\n\n return config;\n };\n\n updateConfig(config: Partial<AuthInterceptorConfig>): void {\n this.config = {\n ...this.config,\n ...config\n } as Required<AuthInterceptorConfig>;\n };\n\n reset(): void {\n this.isRefreshing = false;\n this.refreshPromise = null;\n };\n};\n","export class ErrorResponse extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n public responseData?: any\n ){\n super(message);\n this.name = \"FalconHUB API Error\";\n };\n};\n","import { API } from \"@/core/API\";\nimport { CryptoService } from \"@/core/CryptoService\";\nimport { TokenManager } from \"@/core/TokenManager\";\nimport { LoginRequest } from \"@/interfaces/Auth/Login/LoginRequest\";\nimport { LoginResponse } from \"@/interfaces/Auth/Login/LoginResponse\";\nimport { RefreshTokenRequest } from \"@/interfaces/Auth/RefreshTokens/RefreshTokenRequest\";\nimport { RefreshTokenResponse } from \"@/interfaces/Auth/RefreshTokens/RefreshTokenResponse\";\nimport { ValidateSessionRenewedResponse, ValidateSessionResponse } from \"@/interfaces/Auth/ValidateSession/ValidateSessionResponse\";\nimport { ConfirmEmailRequest } from \"@/interfaces/Auth/ConfirmEmail/ConfirmEmailRequest\";\nimport { SendOtpRequest } from \"@/interfaces/Auth/SendOtp/SendOtpRequest\";\nimport { ValidateOtpRequest } from \"@/interfaces/Auth/ValidateOtp/ValidateOtpRequest\";\nimport { ChangePasswordRequest } from \"@/interfaces/Auth/ChangePassword/ChangePasswordRequest\";\nimport { ErrorResponse } from \"@/types/ErrorResponse\";\nimport { ResponseModel } from \"@/types/ResponseModel\";\nimport { ServiceProperties } from \"@/types/ServiceProperties\";\nimport { TokenData } from \"@/types/TokenData\";\n\nexport class AuthService {\n private api: API;\n private crytpoService: CryptoService;\n private tokenManager: TokenManager;\n private serviceProperties: ServiceProperties;\n\n constructor(\n serviceProperties: ServiceProperties,\n tokenManager: TokenManager,\n cryptoService: CryptoService,\n api: API\n ) {\n this.api = api;\n this.crytpoService = cryptoService;\n this.tokenManager = tokenManager;\n this.serviceProperties = serviceProperties;\n };\n\n /**\n * Login con las credenciales proporcionadas\n * @param credentials - Objeto con email, password y rememberMe\n * @returns Retorna el cuerpo de respuesta del login.\n */\n async login(credentials: LoginRequest): Promise<ResponseModel<LoginResponse>> {\n const timestamp = Date.now().toString();\n\n const loginData: LoginRequest = {\n email: credentials.email,\n password: credentials.password,\n rememberMe: credentials.rememberMe\n };\n\n const response = await this.api.executePublicRequest<LoginResponse>(\n 'oauth/login',\n 'POST',\n loginData,\n timestamp\n );\n\n if (!response) {\n throw new ErrorResponse('No response from server');\n };\n\n if (response.success && response.data) {\n const data: LoginResponse = response.data;\n\n const expiresIn = parseInt(data.expiresIn.replace('s', ''));\n const expiresAt = Date.now() + expiresIn * 1000;\n\n const tokens: TokenData = {\n accessToken: data.accessToken,\n refreshToken: data.refreshToken,\n expiresAt,\n rememberMe: credentials.rememberMe\n };\n\n await this.tokenManager.setTokens(tokens);\n\n this.serviceProperties.onTokensUpdated?.(tokens);\n }\n\n return response;\n };\n\n /**\n * Valida la sesión actual y retorna información de expiración\n *\n * El servidor puede responder de 2 formas:\n * 1. Sesión renovada (sliding window): retorna nuevos tokens\n * 2. Sesión válida: retorna info de expiración sin renovar\n */\n async validateSession(): Promise<ResponseModel<ValidateSessionRenewedResponse | ValidateSessionResponse>> {\n const response = await this.api.executePOST<ValidateSessionRenewedResponse | ValidateSessionResponse>(\n 'oauth/validateSession'\n );\n\n if (!response) {\n throw new ErrorResponse('No response from server');\n };\n\n if (response.success && response.data) {\n const respData = response.data;\n\n if ('expiresIn' in respData && respData.expiresIn) {\n const sessionData = respData as ValidateSessionRenewedResponse;\n const expiresIn = parseInt(sessionData.expiresIn.replace('s', ''));\n const expiresAt = Date.now() + expiresIn * 1000;\n\n const currentTokens = this.tokenManager.getTokens();\n const rememberMe = currentTokens?.rememberMe ?? sessionData.isRemembered;\n\n const tokens: TokenData = {\n accessToken: sessionData.accessToken,\n refreshToken: sessionData.refreshToken,\n expiresAt,\n rememberMe\n };\n\n this.tokenManager.setTokens(tokens);\n this.serviceProperties.onTokensUpdated?.(tokens);\n }\n else if ('expiresAt' in respData && respData.expiresAt) {\n const sessionData = respData as ValidateSessionResponse;\n\n if (sessionData.remainingMinutes <= 5 && sessionData.remainingMinutes > 1) {\n this.serviceProperties.onSessionExpiring?.(sessionData.remainingMinutes);\n } else if (sessionData.remainingMinutes <= 1) {\n if (this.serviceProperties.onSessionExpired) {\n await this.serviceProperties.onSessionExpired();\n }\n }\n }\n };\n\n return response;\n };\n\n /**\n * Refresca los tokens usando el refresh token\n */\n async refreshTokens(refreshRequest: RefreshTokenRequest): Promise<ResponseModel<RefreshTokenResponse>> {\n const currentTokens = this.tokenManager.getTokens();\n const refreshToken = this.tokenManager.getRefreshToken() ?? refreshRequest.refreshToken;\n\n if (!refreshToken) {\n throw new ErrorResponse('No refresh token available');\n };\n\n const refreshRequestData: RefreshTokenRequest = {\n refreshToken: refreshToken,\n rememberMe: refreshRequest.rememberMe ?? currentTokens?.rememberMe\n }\n\n const response = await this.api.executePublicRequest<RefreshTokenResponse>(\n 'oauth/refresh',\n 'POST',\n refreshRequestData\n );\n\n if (!response) {\n throw new ErrorResponse('No response from server');\n };\n\n if (response.success && response.data) {\n const sessionData: RefreshTokenResponse = response.data;\n\n\n const shouldRemember = refreshRequest.rememberMe ?? currentTokens?.rememberMe ?? false;\n const expiresIn = parseInt(sessionData.expiresIn.replace('s', ''));\n const expiresAt = Date.now() + expiresIn * 1000;\n\n const tokens: TokenData = {\n accessToken: sessionData.accessToken,\n refreshToken: sessionData.refreshToken,\n expiresAt,\n rememberMe: shouldRemember\n };\n\n this.tokenManager.setTokens(tokens);\n this.serviceProperties.onTokensUpdated?.(tokens);\n };\n\n return response;\n };\n\n /**\n * Cierra sesión: notifica al servidor y limpia tokens\n */\n async logout(): Promise<ResponseModel> {\n const res = await this.api.executePOST('oauth/logout');\n\n if (res.success) {\n this.tokenManager.clearTokens();\n this.serviceProperties.onTokensUpdated?.(null);\n }\n\n return res;\n }\n\n // #region Email & OTP & Password (public - no auth)\n\n /**\n * Confirma el correo electrónico de un usuario.\n * @param request - Email y expiresAt\n */\n async confirmEmail(request: ConfirmEmailRequest): Promise<ResponseModel> {\n return this.api.executePublicRequest('oauth/email/confirm', 'PUT', request);\n }\n\n /**\n * Envía un código OTP al correo electrónico.\n * @param request - Email del usuario\n */\n async sendOtp(request: SendOtpRequest): Promise<ResponseModel> {\n return this.api.executePublicRequest('oauth/otp', 'POST', request);\n }\n\n /**\n * Valida un código OTP.\n * @param request - Email y código OTP\n */\n async validateOtp(request: ValidateOtpRequest): Promise<ResponseModel> {\n return this.api.executePublicRequest('oauth/otp/verify', 'POST', request);\n }\n\n /**\n * Cambia la contraseña del usuario (flujo público, sin sesión).\n * @param request - Email, contraseña actual y nueva contraseña\n */\n async changePassword(request: ChangePasswordRequest): Promise<ResponseModel> {\n return this.api.executePublicRequest('oauth/password', 'PUT', request);\n }\n\n // #endregion\n\n /**\n * Verifica si el usuario está autenticado\n */\n isAuthenticated(): boolean {\n return this.tokenManager.hasValidTokens();\n };\n\n /**\n * Obtiene los tokens actuales\n */\n getTokens(): TokenData | null {\n return this.tokenManager.getTokens();\n };\n\n}\n","/**\n * Utilidad para construir query params a partir de objetos de filtro.\n *\n * @example\n * ```typescript\n * const filter: EndpointsFilter = { HttpMethod: 'GET', IsActive: true };\n * const queryString = FilterBuilder.toQueryString(filter);\n * // Result: \"HttpMethod=GET&IsActive=true\"\n * ```\n */\nexport class FilterBuilder {\n /**\n * Convierte un objeto de filtro a query string.\n * Ignora valores null, undefined y strings vacíos.\n *\n * @param filter - Objeto con los filtros a aplicar\n * @returns Query string sin el \"?\" inicial\n */\n static toQueryString<T extends Record<string, any>>(filter: T): string {\n const params = new URLSearchParams();\n\n for (const [key, value] of Object.entries(filter)) {\n if (value !== null && value !== undefined && value !== '') {\n params.append(key, String(value));\n }\n }\n\n return params.toString();\n }\n\n /**\n * Construye la URL completa con filtros aplicados.\n *\n * @param baseEndpoint - Endpoint base sin query params\n * @param filter - Objeto con los filtros a aplicar\n * @returns Endpoint con query params si hay filtros, o el endpoint base si no hay\n */\n static buildEndpoint<T extends Record<string, any>>(baseEndpoint: string, filter?: T): string {\n if (!filter) return baseEndpoint;\n\n const queryString = this.toQueryString(filter);\n\n if (!queryString) return baseEndpoint;\n\n return `${baseEndpoint}?${queryString}`;\n }\n\n /**\n * Verifica si un objeto de filtro tiene al menos un valor válido.\n *\n * @param filter - Objeto con los filtros a verificar\n * @returns true si hay al menos un filtro con valor válido\n */\n static hasFilters<T extends Record<string, any>>(filter?: T): boolean {\n if (!filter) return false;\n\n return Object.values(filter).some(\n value => value !== null && value !== undefined && value !== ''\n );\n }\n\n /**\n * Limpia un objeto de filtro removiendo valores vacíos.\n * Útil para normalizar filtros antes de enviarlos.\n *\n * @param filter - Objeto con los filtros\n * @returns Nuevo objeto solo con valores válidos\n */\n static clean<T extends Record<string, any>>(filter: T): Partial<T> {\n const cleaned: Partial<T> = {};\n\n for (const [key, value] of Object.entries(filter)) {\n if (value !== null && value !== undefined && value !== '') {\n (cleaned as any)[key] = value;\n }\n }\n\n return cleaned;\n }\n}\n\n/**\n * Tipo base para modelos de filtro.\n * Todos los campos son opcionales y pueden ser string, number, boolean o null.\n */\nexport type FilterModel = Record<string, string | number | boolean | null | undefined>;\n\n/**\n * Tipo para definir metadatos de un campo de filtro.\n */\nexport interface FilterFieldMetadata {\n /** Tipo de filtro */\n type: 'search' | 'string' | 'boolean' | 'number' | 'select' | 'multiselect' | 'date' | 'daterange';\n /** Descripción / label del filtro */\n description: string;\n /** Orden de renderizado (menor = primero, default 99) */\n order?: number;\n /** Opciones para select / multiselect */\n options?: string[];\n /** Labels personalizados para boolean (default: Activo/Inactivo) */\n labels?: { true: string; false: string };\n /** Campos en los que busca el backend (solo para type: 'search') */\n searchIn?: string[];\n /** Valor mínimo (para number) */\n min?: number;\n /** Valor máximo (para number) */\n max?: number;\n /** Fecha mínima (para date / daterange) */\n minDate?: string;\n /** Fecha máxima (para date / daterange) */\n maxDate?: string;\n}\n\n/**\n * Tipo para el modelo de filtros retornado por el endpoint /filters.\n */\nexport type FilterMetadataModel = Record<string, FilterFieldMetadata>;\n\n// ── Filter Groups (array-based format) ──\n\n/**\n * Opción dentro de un grupo de filtros.\n */\nexport interface FilterGroupOption {\n /** Campo del backend (e.g. \"Module\", \"IsActive\") */\n key: string;\n /** Label visible en el frontend */\n label: string;\n /** Placeholder del input (solo para string) */\n placeholder?: string;\n /** Opciones disponibles (solo para select) */\n values?: string[];\n /** Label cuando el valor es true (solo para boolean) */\n trueLabel?: string;\n /** Label cuando el valor es false (solo para boolean) */\n falseLabel?: string;\n}\n\n/**\n * Grupo de filtros agrupados por tipo.\n * El frontend renderiza cada grupo de forma diferente.\n */\nexport interface FilterGroup {\n /** Tipo de filtro: \"string\" | \"boolean\" | \"select\" | \"date\" */\n type: 'string' | 'boolean' | 'select' | 'date';\n /** Label del grupo */\n label: string;\n /** Opciones del grupo */\n options: FilterGroupOption[];\n}\n\n/**\n * Modelo retornado por el endpoint /filters (formato array-based).\n */\nexport type FilterGroupsModel = FilterGroup[];\n","import { API } from \"@/core/API\";\nimport { UserProfileResponse } from \"@/interfaces/User/UserProfileResponse\";\nimport { UserBasicResponse } from \"@/interfaces/User/UserBasicResponse\";\nimport {\n UserAdminRequest,\n UserAuthAdminRequest,\n ChangePasswordAdminRequest,\n UserAdminFilter,\n UserAdminUpdateRequest,\n UserAuthUpdateRequest\n} from \"@/interfaces/User/Admin\";\nimport { ResponseModel } from \"@/types/ResponseModel\";\nimport { FilterBuilder, type FilterGroupsModel } from \"@/utils/FilterBuilder\";\n\nexport class UserService {\n private api: API;\n private readonly BASE_PATH = 'users';\n\n constructor(\n api: API,\n ){\n this.api = api;\n };\n\n async me(): Promise<ResponseModel<UserBasicResponse>> {\n const response: ResponseModel<UserBasicResponse> = await this.api.executeGET(\n `${this.BASE_PATH}/me`,\n true,\n );\n\n return response;\n };\n\n async profile(): Promise<ResponseModel<UserProfileResponse>>{\n const response: ResponseModel<UserProfileResponse> = await this.api.executeGET(\n `${this.BASE_PATH}/profile`,\n true\n );\n\n return response;\n }\n\n // #region Admin CRUD\n\n /**\n * Crea un nuevo usuario administrador.\n * @param request - Datos del nuevo administrador\n */\n async newAdminUser(request: UserAdminRequest): Promise<ResponseModel> {\n return this.api.executePOST(`${this.BASE_PATH}/admin`, request);\n }\n\n /**\n * Crea la autenticación para un usuario.\n * @param request - Datos de autenticación del usuario\n */\n async createUserAuthentication(request: UserAuthAdminRequest): Promise<ResponseModel> {\n return this.api.executePOST(`${this.BASE_PATH}/admin/authentication`, request);\n }\n\n /**\n * Cambia la contraseña de un administrador.\n * @param id - ID del usuario\n * @param request - Nueva contraseña\n */\n async changePasswordAdmin(id: number, request: ChangePasswordAdminRequest): Promise<ResponseModel> {\n return this.api.executePOST(`${this.BASE_PATH}/me/${id}/password`, request);\n }\n\n /**\n * Obtiene todos los administradores con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getAllAdmins(filter?: UserAdminFilter): Promise<ResponseModel> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/admin`, filter);\n return this.api.executeGET(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para administradores.\n */\n async getAdminFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/admin/filters`, true);\n }\n\n /**\n * Obtiene un administrador por su ID.\n * @param id - ID del administrador\n */\n async getAdminById(id: number): Promise<ResponseModel> {\n return this.api.executeGET(`${this.BASE_PATH}/admin/${id}`, true);\n }\n\n /**\n * Obtiene la autenticación de un administrador.\n * @param id - ID del usuario\n */\n async getAdminAuthentication(id: number): Promise<ResponseModel> {\n return this.api.executeGET(`${this.BASE_PATH}/admin/authentication/${id}`, true);\n }\n\n /**\n * Actualiza un administrador existente.\n * @param id - ID del administrador\n * @param request - Nuevos datos del administrador\n */\n async updateAdmin(id: number, request: UserAdminUpdateRequest): Promise<ResponseModel> {\n return this.api.executePUT(`${this.BASE_PATH}/admin/${id}`, request);\n }\n\n /**\n * Activa o desactiva un administrador.\n * @param id - ID del administrador\n */\n async toggleAdminStatus(id: number): Promise<ResponseModel> {\n return this.api.executePUT(`${this.BASE_PATH}/admin/${id}/toggle-status`);\n }\n\n /**\n * Actualiza la autenticación de un administrador.\n * @param id - ID del usuario\n * @param request - Nuevos datos de autenticación\n */\n async updateAdminAuthentication(id: number, request: UserAuthUpdateRequest): Promise<ResponseModel> {\n return this.api.executePUT(`${this.BASE_PATH}/admin/authentication/${id}`, request);\n }\n\n // #endregion\n}\n","import { API } from \"@/core/API\";\nimport { ResponseModel } from \"@/types/ResponseModel\";\nimport { FilterBuilder, type FilterGroupsModel } from \"@/utils/FilterBuilder\";\nimport {\n Module,\n ModuleRequest,\n ModulesFilter,\n Endpoint,\n EndpointRequest,\n EndpointsFilter,\n UIRoute,\n UIRouteRequest,\n UIRoutesFilter\n} from \"@/interfaces/System\";\n\n/**\n * Servicio para gestionar las configuraciones del sistema.\n */\nexport class SystemService {\n private api: API;\n private readonly BASE_PATH = 'system';\n\n constructor(api: API) {\n this.api = api;\n }\n\n // #region MODULES\n\n /**\n * Obtiene todos los módulos con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getModules(filter?: ModulesFilter): Promise<ResponseModel<Module[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/modules`, filter);\n return this.api.executeGET<Module[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para módulos.\n */\n async getModulesFilters(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/modules/filters`, true);\n }\n\n /**\n * Obtiene un módulo por su ID.\n * @param id - ID del módulo\n */\n async getModuleById(id: number): Promise<ResponseModel<Module>> {\n return this.api.executeGET<Module>(`${this.BASE_PATH}/modules/${id}`, true);\n }\n\n /**\n * Crea un nuevo módulo.\n * @param request - Datos del módulo a crear\n */\n async createModule(request: ModuleRequest): Promise<ResponseModel<Module>> {\n return this.api.executePOST<Module>(`${this.BASE_PATH}/modules`, request);\n }\n\n /**\n * Actualiza un módulo existente.\n * @param id - ID del módulo a actualizar\n * @param request - Nuevos datos del módulo\n */\n async updateModule(id: number, request: ModuleRequest): Promise<ResponseModel<Module>> {\n return this.api.executePUT<Module>(`${this.BASE_PATH}/modules/${id}`, request);\n }\n\n /**\n * Activa o desactiva un módulo.\n * @param id - ID del módulo\n */\n async toggleModuleStatus(id: number): Promise<ResponseModel<Module>> {\n return this.api.executePUT<Module>(`${this.BASE_PATH}/modules/${id}/toggle-status`);\n }\n\n /**\n * Elimina un módulo.\n * @param id - ID del módulo a eliminar\n */\n async deleteModule(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/modules/${id}`);\n }\n\n // #endregion\n\n // #region ENDPOINTS\n\n /**\n * Obtiene todos los endpoints con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getEndpoints(filter?: EndpointsFilter): Promise<ResponseModel<Endpoint[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/endpoints`, filter);\n return this.api.executeGET<Endpoint[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para endpoints.\n */\n async getEndpointsFilters(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/endpoints/filters`, true);\n }\n\n /**\n * Obtiene un endpoint por su ID.\n * @param id - ID del endpoint\n */\n async getEndpointById(id: number): Promise<ResponseModel<Endpoint>> {\n return this.api.executeGET<Endpoint>(`${this.BASE_PATH}/endpoints/${id}`, true);\n }\n\n /**\n * Crea un nuevo endpoint.\n * @param request - Datos del endpoint a crear\n */\n async createEndpoint(request: EndpointRequest): Promise<ResponseModel<Endpoint>> {\n return this.api.executePOST<Endpoint>(`${this.BASE_PATH}/endpoints`, request);\n }\n\n /**\n * Actualiza un endpoint existente.\n * @param id - ID del endpoint a actualizar\n * @param request - Nuevos datos del endpoint\n */\n async updateEndpoint(id: number, request: EndpointRequest): Promise<ResponseModel<Endpoint>> {\n return this.api.executePUT<Endpoint>(`${this.BASE_PATH}/endpoints/${id}`, request);\n }\n\n /**\n * Activa o desactiva un endpoint.\n * @param id - ID del endpoint\n */\n async toggleEndpointStatus(id: number): Promise<ResponseModel<Endpoint>> {\n return this.api.executePUT<Endpoint>(`${this.BASE_PATH}/endpoints/${id}/toggle-status`);\n }\n\n /**\n * Elimina un endpoint.\n * @param id - ID del endpoint a eliminar\n */\n async deleteEndpoint(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/endpoints/${id}`);\n }\n\n // #endregion\n\n // #region UI ROUTES\n\n /**\n * Obtiene todas las rutas de UI con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getUIRoutes(filter?: UIRoutesFilter): Promise<ResponseModel<UIRoute[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/ui-routes`, filter);\n return this.api.executeGET<UIRoute[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para rutas de UI.\n */\n async getUIRoutesFilters(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/ui-routes/filters`, true);\n }\n\n /**\n * Obtiene una ruta de UI por su ID.\n * @param id - ID de la ruta\n */\n async getUIRouteById(id: number): Promise<ResponseModel<UIRoute>> {\n return this.api.executeGET<UIRoute>(`${this.BASE_PATH}/ui-routes/${id}`, true);\n }\n\n /**\n * Crea una nueva ruta de UI.\n * @param request - Datos de la ruta a crear\n */\n async createUIRoute(request: UIRouteRequest): Promise<ResponseModel<UIRoute>> {\n return this.api.executePOST<UIRoute>(`${this.BASE_PATH}/ui-routes`, request);\n }\n\n /**\n * Actualiza una ruta de UI existente.\n * @param id - ID de la ruta a actualizar\n * @param request - Nuevos datos de la ruta\n */\n async updateUIRoute(id: number, request: UIRouteRequest): Promise<ResponseModel<UIRoute>> {\n return this.api.executePUT<UIRoute>(`${this.BASE_PATH}/ui-routes/${id}`, request);\n }\n\n /**\n * Activa o desactiva una ruta de UI.\n * @param id - ID de la ruta\n */\n async toggleUIRouteStatus(id: number): Promise<ResponseModel<UIRoute>> {\n return this.api.executePUT<UIRoute>(`${this.BASE_PATH}/ui-routes/${id}/toggle-status`);\n }\n\n /**\n * Elimina una ruta de UI.\n * @param id - ID de la ruta a eliminar\n */\n async deleteUIRoute(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/ui-routes/${id}`);\n }\n\n // #endregion\n}\n","import { API } from \"@/core/API\";\nimport { ResponseModel } from \"@/types/ResponseModel\";\nimport { FilterBuilder, type FilterGroupsModel } from \"@/utils/FilterBuilder\";\nimport {\n LocationsRequest,\n LocationsFilter,\n InventoryStatusRequest,\n InventoryStatusesFilter\n} from \"@/interfaces/Inventory\";\n\n/**\n * Servicio para gestionar inventario: ubicaciones y estatus.\n */\nexport class InventoryService {\n private api: API;\n private readonly BASE_PATH = 'inventory';\n\n constructor(api: API) {\n this.api = api;\n }\n\n // #region LOCATIONS\n\n /**\n * Obtiene todas las ubicaciones con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getLocations(filter?: LocationsFilter): Promise<ResponseModel> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/locations`, filter);\n return this.api.executeGET(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para ubicaciones.\n */\n async getLocationFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/locations/filters`, true);\n }\n\n /**\n * Obtiene una ubicación por su ID.\n * @param id - ID de la ubicación\n */\n async getLocationById(id: number): Promise<ResponseModel> {\n return this.api.executeGET(`${this.BASE_PATH}/locations/${id}`, true);\n }\n\n /**\n * Crea una nueva ubicación.\n * @param request - Datos de la ubicación a crear\n */\n async createLocation(request: LocationsRequest): Promise<ResponseModel> {\n return this.api.executePOST(`${this.BASE_PATH}/locations`, request);\n }\n\n /**\n * Actualiza una ubicación existente.\n * @param id - ID de la ubicación a actualizar\n * @param request - Nuevos datos de la ubicación\n */\n async updateLocation(id: number, request: LocationsRequest): Promise<ResponseModel> {\n return this.api.executePUT(`${this.BASE_PATH}/locations/${id}`, request);\n }\n\n /**\n * Activa o desactiva una ubicación.\n * @param id - ID de la ubicación\n */\n async toggleLocationStatus(id: number): Promise<ResponseModel> {\n return this.api.executePUT(`${this.BASE_PATH}/locations/${id}/toggle-status`);\n }\n\n /**\n * Elimina una ubicación.\n * @param id - ID de la ubicación a eliminar\n */\n async deleteLocation(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/locations/${id}`);\n }\n\n // #endregion\n\n // #region STATUSES\n\n /**\n * Obtiene todos los estatus de inventario con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getStatuses(filter?: InventoryStatusesFilter): Promise<ResponseModel> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/statuses`, filter);\n return this.api.executeGET(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para estatus de inventario.\n */\n async getStatusFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/statuses/filters`, true);\n }\n\n /**\n * Obtiene un estatus de inventario por su ID.\n * @param id - ID del estatus\n */\n async getStatusById(id: number): Promise<ResponseModel> {\n return this.api.executeGET(`${this.BASE_PATH}/statuses/${id}`, true);\n }\n\n /**\n * Crea un nuevo estatus de inventario.\n * @param request - Datos del estatus a crear\n */\n async createStatus(request: InventoryStatusRequest): Promise<ResponseModel> {\n return this.api.executePOST(`${this.BASE_PATH}/statuses`, request);\n }\n\n /**\n * Actualiza un estatus de inventario existente.\n * @param id - ID del estatus a actualizar\n * @param request - Nuevos datos del estatus\n */\n async updateStatus(id: number, request: InventoryStatusRequest): Promise<ResponseModel> {\n return this.api.executePUT(`${this.BASE_PATH}/statuses/${id}`, request);\n }\n\n /**\n * Activa o desactiva un estatus de inventario.\n * @param id - ID del estatus\n */\n async toggleStatusActive(id: number): Promise<ResponseModel> {\n return this.api.executePUT(`${this.BASE_PATH}/statuses/${id}/toggle-status`);\n }\n\n /**\n * Elimina un estatus de inventario.\n * @param id - ID del estatus a eliminar\n */\n async deleteStatus(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/statuses/${id}`);\n }\n\n // #endregion\n}\n","import { API } from \"./core/API\";\nimport { CryptoService } from \"./core/CryptoService\";\nimport { TokenManager } from \"./core/TokenManager\";\nimport { AuthInterceptor } from \"./core/interceptors/AuthInterceptor\";\nimport { ServiceProperties } from \"./types/ServiceProperties\";\nimport { TokenData } from \"./types/TokenData\";\nimport { AuthService } from \"./services/AuthService\";\nimport { UserService } from \"./services/UserService\";\nimport { SystemService } from \"./services/SystemService\";\nimport { InventoryService } from \"./services/InventoryService\";\n\n/**\n * SDK principal de FalconHUB\n */\nexport class FalconHUBSDK {\n public auth: AuthService;\n public user: UserService;\n public system: SystemService;\n public inventory: InventoryService;\n\n private serviceProperties: ServiceProperties;\n private cryptoService: CryptoService;\n private tokenManager: TokenManager;\n private authInterceptor: AuthInterceptor | null;\n private api: API;\n\n constructor(serviceProperties: ServiceProperties) {\n this.serviceProperties = serviceProperties;\n\n this.cryptoService = new CryptoService();\n\n const autoRefreshConfig = this.normalizeAutoRefreshConfig(this.serviceProperties.autoRefresh);\n\n this.tokenManager = new TokenManager(\n this.serviceProperties.onTokensUpdated,\n this.serviceProperties.onSessionExpiring,\n async () => {\n await this.auth.logout();\n },\n async () => {\n const currentTokens = this.tokenManager.getTokens();\n if (!currentTokens?.refreshToken) return false;\n\n try {\n const response = await this.auth.refreshTokens({\n refreshToken: currentTokens.refreshToken,\n rememberMe: currentTokens.rememberMe\n });\n return response.success === true;\n } catch {\n return false;\n }\n },\n autoRefreshConfig.enabled ? autoRefreshConfig.thresholdMinutes : undefined\n );\n\n if (autoRefreshConfig.enabled) {\n this.authInterceptor = new AuthInterceptor({\n enabled: true,\n thresholdMinutes: autoRefreshConfig.thresholdMinutes,\n isTokenExpiringSoon: () => this.tokenManager.isTokenExpiringSoon(autoRefreshConfig.thresholdMinutes),\n hasValidTokens: () => this.tokenManager.hasValidTokens(),\n shouldAutoRefresh: () => this.tokenManager.shouldAutoRefresh(),\n refreshSession: async () => {\n await this.auth.validateSession();\n }\n });\n } else {\n this.authInterceptor = null;\n }\n\n this.api = new API(\n this.serviceProperties,\n this.cryptoService,\n this.authInterceptor,\n () => this.tokenManager.getAccessToken(),\n () => this.tokenManager.getRefreshToken()\n );\n\n this.auth = new AuthService(\n this.serviceProperties,\n this.tokenManager,\n this.cryptoService,\n this.api\n );\n\n this.user = new UserService(\n this.api\n );\n\n this.system = new SystemService(\n this.api\n );\n\n this.inventory = new InventoryService(\n this.api\n );\n }\n\n private normalizeAutoRefreshConfig(\n config: ServiceProperties[\"autoRefresh\"]\n ): { enabled: boolean; thresholdMinutes: number } {\n if (typeof config === \"boolean\") {\n return { enabled: config, thresholdMinutes: 5 };\n }\n if (typeof config === \"object\" && config !== null) {\n return {\n enabled: config.enabled,\n thresholdMinutes: config.thresholdMinutes ?? 5\n };\n }\n return { enabled: true, thresholdMinutes: 5 };\n }\n\n /**\n * Inyecta tokens desde storage externo (cookies/localStorage/etc)\n * @param expiresAt - Timestamp en milisegundos\n */\n setTokensFromExternal(\n accessToken: string,\n refreshToken: string,\n expiresAt: number,\n rememberMe: boolean = false\n ): void {\n const tokens: TokenData = {\n accessToken,\n refreshToken,\n expiresAt,\n rememberMe\n };\n\n this.tokenManager.setTokensSilent(tokens);\n }\n\n /**\n * Obtiene los tokens actuales\n */\n getTokens(): TokenData | null {\n return this.tokenManager.getTokens();\n }\n\n /**\n * Verifica si el usuario está autenticado\n */\n isAuthenticated(): boolean {\n return this.tokenManager.hasValidTokens();\n }\n\n /**\n * Verifica si la sesión está por expirar\n */\n isSessionExpiringSoon(thresholdMinutes: number = 5): boolean {\n return this.tokenManager.isTokenExpiringSoon(thresholdMinutes);\n }\n\n /**\n * Obtiene el tiempo restante hasta la expiración en milisegundos\n */\n getTimeUntilExpiry(): number | null {\n return this.tokenManager.getTimeUntilExpiry();\n }\n}\n","import CryptoJS from 'crypto-js';\n\nexport function decrypt(encryptedBase64: string, secret: string, timestamp: string): string {\n const fullKey = `${secret}:${timestamp}`;\n // Generate key using SHA256\n const key = CryptoJS.SHA256(fullKey);\n\n // Parse total encrypted data from Base64\n const allData = CryptoJS.enc.Base64.parse(encryptedBase64);\n\n // Extract IV (first 16 bytes = 4 words)\n const iv = CryptoJS.lib.WordArray.create(allData.words.slice(0, 4), 16);\n\n // Extract ciphertext (remaining bytes)\n const ciphertext = CryptoJS.lib.WordArray.create(allData.words.slice(4), allData.sigBytes - 16);\n\n // Decrypt using AES-256-CBC\n // We use PKCS7 padding as it's the default in Node.js createDecipheriv for aes-256-cbc\n const decrypted = CryptoJS.AES.decrypt(\n { ciphertext: ciphertext } as any,\n key,\n {\n iv: iv,\n mode: CryptoJS.mode.CBC,\n padding: CryptoJS.pad.Pkcs7\n }\n );\n\n return decrypted.toString(CryptoJS.enc.Utf8);\n}\n"],"mappings":"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","names":["CryptoJS"]}
1
+ {"version":3,"sources":["../src/core/API.ts","../src/core/CryptoService.ts","../src/core/TokenManager.ts","../src/core/interceptors/AuthInterceptor.ts","../src/types/ErrorResponse.ts","../src/services/AuthService.ts","../src/utils/FilterBuilder.ts","../src/services/UserService.ts","../src/services/SystemService.ts","../src/services/InventoryService.ts","../src/FalconHUBSDK.ts","../src/core/Encryption.ts"],"sourcesContent":["import { ServiceProperties } from \"@/types/ServiceProperties\";\nimport { CryptoService } from \"./CryptoService\";\nimport { MethodTypes, RequestOptions } from \"@/types/RequestOptions\";\nimport { ErrorResponse } from \"@/types/ErrorResponse\";\nimport { RequestConfig } from \"@/types/RequestConfig\";\nimport { AuthInterceptor } from \"./interceptors/AuthInterceptor\";\nimport { InterceptorContext } from \"@/core/interceptors/types/InterceptorContext\";\nimport { ResponseModel } from \"@/types/ResponseModel\";\n\n\n/**\n * Clase base para la ejecución de request HTTP al API\n */\nexport class API {\n private properties: ServiceProperties;\n private cryptoService: CryptoService;\n private authInterceptor: AuthInterceptor | null;\n\n private getAccessToken: () => string | null;\n private getRefreshToken: () => string | null;\n\n constructor(\n properties: ServiceProperties,\n cryptoService: CryptoService,\n authInterceptor: AuthInterceptor | null,\n getAccessToken: () => string | null,\n getRefreshToken: () => string | null\n ) {\n this.properties = properties;\n this.cryptoService = cryptoService;\n this.getAccessToken = getAccessToken;\n this.getRefreshToken = getRefreshToken;\n this.authInterceptor = authInterceptor;\n };\n\n /**\n * Ejecuta una request HTTP al API\n *\n * @param options - Opciones de la request\n * @returns Respuesta del tipo ResponseModel\n */\n private async apiExecute<T>(options: RequestOptions): Promise<ResponseModel<T>> {\n const {\n endpoint,\n method,\n body,\n requiresAuth,\n timeStamp\n } = options;\n\n const context: InterceptorContext = {\n requestId: this.cryptoService.generateUniqueId(),\n startTime: Date.now(),\n retryCount: 0,\n metadata: {}\n };\n\n try {\n const url = `${this.properties.url}/${endpoint}`;\n\n const headers: Record<string, string> = {};\n\n if (body && method !== 'GET') {\n headers['Content-Type'] = 'application/json';\n };\n\n const accessToken = this.getAccessToken();\n\n if (accessToken) {\n headers['Authorization'] = `Bearer ${accessToken}`;\n };\n\n const newTimeStamp = timeStamp || new Date().toString();\n\n headers[\"X-Origin-Request\"] = this.properties.originRequest;\n headers['X-Timestamp'] = newTimeStamp;\n headers[\"X-Domain\"] = this.properties.domain;\n headers[\"X-Device\"] = this.properties.device;\n headers[\"X-Source\"] = this.properties.source;\n\n let bodyString: string | undefined;\n\n if (body && method !== 'GET') {\n bodyString = JSON.stringify(body);\n };\n\n const requestConfig: RequestConfig = {\n url,\n method,\n headers,\n body: bodyString,\n requiresAuth\n };\n\n const modifiedConfig = this.authInterceptor\n ? await this.authInterceptor.onRequest(requestConfig, context)\n : requestConfig;\n\n const requestInit: RequestInit = {\n method: modifiedConfig.method,\n headers: modifiedConfig.headers,\n mode: 'cors',\n credentials: 'omit'\n };\n\n if (bodyString) {\n requestInit.body = bodyString;\n };\n\n const response = await fetch(\n modifiedConfig.url,\n requestInit\n );\n\n const newAccessToken = response.headers.get('X-New-Access-Token');\n const newRefreshToken = response.headers.get('X-New-Refresh-Token');\n\n if (newAccessToken || newRefreshToken) {\n this.properties.onTokensRefreshed?.({\n accessToken: newAccessToken,\n refreshToken: newRefreshToken\n });\n };\n\n const contentType = response.headers.get('Content-Type');\n\n if (contentType && contentType.includes('application/json')) {\n const responseText = await response.text();\n return JSON.parse(responseText) as ResponseModel<T>;\n };\n\n return {\n success: false,\n message: 'Response is not JSON',\n data: null,\n responseTime: null\n };\n } catch (error) {\n return {\n success: false,\n message: error instanceof Error ? error.message : 'Unexpected error occurred during API request.',\n data: null,\n responseTime: null\n };\n };\n };\n\n\n //#region REQUEST METHODS\n\n async executeGET<T>(\n endpoint: string,\n requiresAuth: boolean = false\n ): Promise<ResponseModel<T>> {\n return this.apiExecute<T>({\n endpoint,\n method: 'GET',\n requiresAuth: requiresAuth\n });\n };\n\n async executePOST<T>(\n endpoint: string,\n body?: any,\n requiresAuth: boolean = true,\n ): Promise<ResponseModel<T>> {\n return this.apiExecute<T>({\n endpoint,\n method: 'POST',\n body,\n requiresAuth: requiresAuth\n });\n };\n\n async executePATCH<T>(\n endpoint: string,\n body?: any,\n requiresAuth: boolean = true,\n ): Promise<ResponseModel<T>> {\n return this.apiExecute<T>({\n endpoint,\n method: 'PATCH',\n body,\n requiresAuth: requiresAuth\n });\n };\n\n async executeDELETE<T>(\n endpoint: string,\n body?: any,\n requiresAuth: boolean = true,\n ): Promise<ResponseModel<T>> {\n return this.apiExecute<T>({\n endpoint,\n method: 'DELETE',\n body,\n requiresAuth: requiresAuth\n });\n };\n\n async executePUT<T>(\n endpoint: string,\n body?: any,\n requiresAuth: boolean = true\n ): Promise<ResponseModel<T>> {\n return this.apiExecute<T>({\n endpoint,\n method: 'PUT',\n body,\n requiresAuth: requiresAuth,\n });\n };\n\n async executePublicRequest<T>(\n endpoint: string,\n method: MethodTypes,\n body?: any,\n timestamp?: string\n ): Promise<ResponseModel<T>> {\n return this.apiExecute<T>({\n endpoint,\n method,\n body,\n requiresAuth: false,\n timeStamp: timestamp\n });\n };\n\n //#endregion\n}\n","import * as CryptoJS from \"crypto-js\";\n\nexport class CryptoService {\n /**\n * Genera un hash SHA256 de un texto (útil para fingerprints)\n *\n * @param text - Texto a hashear\n * @returns Hash en formato hexadecimal\n */\n sha256(text: string): string {\n return CryptoJS.SHA256(text).toString(CryptoJS.enc.Hex);\n }\n\n /**\n * Genera un identificador único basado en timestamp y random\n * (útil para request IDs)\n *\n * @returns ID único\n */\n generateUniqueId(): string {\n const timestamp = Date.now().toString(36);\n const randomPart = Math.random().toString(36).substring(2, 15);\n return `${timestamp}-${randomPart}`;\n }\n}\n","import { TokenData } from \"@/types/TokenData\";\n\n/**\n * Manages authentication tokens.\n */\nexport class TokenManager {\n private tokens: TokenData | null = null;\n private onTokensChanged?: (tokens: TokenData | null) => void;\n private sessionCheckInterval: NodeJS.Timeout | null = null;\n private autoRefreshTimeout: NodeJS.Timeout | null = null;\n private onSessionExpiring?: (remainingMinutes: number) => void;\n private onSessionExpired?: () => Promise<void>;\n private onSessionRecovery?: () => Promise<boolean>;\n private hasNotifiedExpiring: boolean = false;\n private autoRefreshThresholdMinutes: number = 5;\n\n constructor(\n onTokensChanged?: (tokens: TokenData | null) => void,\n onSessionExpiring?: (remainingMinutes: number) => void,\n onSessionExpired?: () => Promise<void>,\n onSessionRecovery?: () => Promise<boolean>,\n autoRefreshThresholdMinutes?: number\n ) {\n this.onTokensChanged = onTokensChanged;\n this.onSessionExpiring = onSessionExpiring;\n this.onSessionExpired = onSessionExpired;\n this.onSessionRecovery = onSessionRecovery;\n this.autoRefreshThresholdMinutes = autoRefreshThresholdMinutes ?? 5;\n };\n\n /**\n * Guarda los tokens de autenticación y dispara el callback onTokensChanged.\n */\n setTokens(tokens: TokenData) {\n this.tokens = tokens;\n this.hasNotifiedExpiring = false;\n\n this.onTokensChanged?.(this.tokens);\n\n if (!tokens.rememberMe) {\n this.startExpirationCheck();\n this.stopAutoRefreshTimer();\n } else {\n this.stopExpirationCheck();\n this.scheduleAutoRefresh();\n };\n };\n\n /**\n * Guarda los tokens sin disparar el callback onTokensChanged.\n * Usar para inyectar tokens desde storage externo (cookies/localStorage).\n */\n setTokensSilent(tokens: TokenData) {\n this.tokens = tokens;\n this.hasNotifiedExpiring = false;\n\n if (!tokens.rememberMe) {\n this.startExpirationCheck();\n this.stopAutoRefreshTimer();\n } else {\n this.stopExpirationCheck();\n this.scheduleAutoRefresh();\n };\n };\n\n /**\n * Obtiene los tokens de autenticación almacenados.\n */\n getTokens(): TokenData | null {\n return this.tokens;\n };\n\n /**\n * Limpia los tokens de autenticación almacenados y dispara el callback onTokensChanged.\n */\n clearTokens() {\n this.stopExpirationCheck();\n this.stopAutoRefreshTimer();\n this.tokens = null;\n this.onTokensChanged?.(this.tokens);\n };\n\n /**\n * Valida si existen tokens y si el access token no ha expirado.\n */\n hasValidTokens(): boolean {\n if (!this.tokens) return false;\n\n return Date.now() < this.tokens.expiresAt;\n };\n\n /**\n * Valida si el access token expirará dentro del umbral especificado (en minutos).\n */\n isTokenExpiringSoon(thresholdMinutes: number): boolean {\n if (!this.tokens) return false;\n\n const thresholdMs = thresholdMinutes * 60 * 1000;\n const timeLeft = this.tokens.expiresAt - Date.now();\n\n return timeLeft > 0 && timeLeft <= thresholdMs;\n };\n\n /**\n * Obtiene el tiempo restante hasta la expiración del access token en milisegundos.\n */\n getTimeUntilExpiry(): number | null {\n if (!this.tokens) return null;\n\n return Math.max(0, this.tokens.expiresAt - Date.now());\n };\n\n /**\n * Obtiene el access token almacenado.\n */\n getAccessToken(): string | null {\n return this.tokens ? this.tokens.accessToken : null;\n };\n\n /**\n * Obtiene el refresh token almacenado.\n */\n getRefreshToken(): string | null {\n return this.tokens ? this.tokens.refreshToken : null;\n };\n\n /**\n * Verifica si el auto-refresh debe ejecutarse\n * Solo si el usuario activó \"rememberMe\" durante el login\n */\n shouldAutoRefresh(): boolean {\n if (!this.tokens) return false;\n\n return this.tokens.rememberMe === true;\n }\n\n /**\n * Inicia el monitoreo de expiración para sesiones sin rememberMe\n * - Notifica cuando quedan 5 minutos (onSessionExpiring)\n */\n private startExpirationCheck(): void {\n this.stopExpirationCheck();\n\n this.sessionCheckInterval = setInterval(async () => {\n if (!this.tokens) {\n this.stopExpirationCheck();\n return;\n };\n\n const timeLeft = this.getTimeUntilExpiry();\n if (timeLeft === null) return;\n\n const minutesLeft = Math.floor(timeLeft / (60 * 1000));\n\n if (minutesLeft <= 5 && minutesLeft > 1 && !this.hasNotifiedExpiring) {\n this.hasNotifiedExpiring = true;\n this.onSessionExpiring?.(minutesLeft);\n };\n\n if (minutesLeft <= 1) {\n this.stopExpirationCheck();\n\n if (this.onSessionRecovery) {\n try {\n const recovered = await this.onSessionRecovery();\n if (recovered) return;\n } catch (error) {\n }\n }\n\n if (this.onSessionExpired) {\n await this.onSessionExpired();\n };\n };\n }, 60000);\n }\n\n /**\n * Programa un auto-refresh proactivo para sesiones con rememberMe.\n * Se ejecuta X minutos antes de que expire el token\n */\n private scheduleAutoRefresh(): void {\n this.stopAutoRefreshTimer();\n\n if (!this.tokens || !this.tokens.rememberMe) return;\n\n const timeLeft = this.getTimeUntilExpiry();\n if (timeLeft === null || timeLeft <= 0) return;\n\n const thresholdMs = this.autoRefreshThresholdMinutes * 60 * 1000;\n const delay = Math.max(0, timeLeft - thresholdMs);\n\n this.autoRefreshTimeout = setTimeout(async () => {\n if (!this.tokens || !this.tokens.rememberMe) return;\n\n if (this.onSessionRecovery) {\n try {\n const recovered = await this.onSessionRecovery();\n if (recovered) return;\n } catch (error) {\n }\n }\n\n if (this.onSessionExpired) {\n await this.onSessionExpired();\n }\n }, delay);\n }\n\n /**\n * Detiene el monitoreo de expiración\n */\n private stopExpirationCheck(): void {\n if (this.sessionCheckInterval) {\n clearInterval(this.sessionCheckInterval);\n this.sessionCheckInterval = null;\n };\n }\n\n /**\n * Detiene el timer de auto-refresh proactivo\n */\n private stopAutoRefreshTimer(): void {\n if (this.autoRefreshTimeout) {\n clearTimeout(this.autoRefreshTimeout);\n this.autoRefreshTimeout = null;\n };\n }\n};\n","import { AuthInterceptorConfig } from \"./types/AuthInterceptorConfig\";\nimport { InterceptorContext } from \"@/core/interceptors/types/InterceptorContext\";\nimport { RequestConfig } from \"@/types/RequestConfig\";\nimport { RequestInterceptor } from \"./types/RequestInterceptor\";\n\nexport class AuthInterceptor implements RequestInterceptor {\n readonly name = \"AuthInterceptor\";\n\n private config: Required<AuthInterceptorConfig>;\n private refreshPromise: Promise<void> | null = null;\n private isRefreshing = false;\n\n constructor(config: AuthInterceptorConfig) {\n this.config = {\n enabled: config.enabled ?? true,\n thresholdMinutes: config.thresholdMinutes ?? 5,\n isTokenExpiringSoon: config.isTokenExpiringSoon,\n hasValidTokens: config.hasValidTokens,\n shouldAutoRefresh: config.shouldAutoRefresh,\n refreshSession: config.refreshSession\n };\n };\n\n async onRequest(\n config: RequestConfig,\n context: InterceptorContext\n ): Promise<RequestConfig> {\n\n //Actua en solicitudes que requieren autenticación\n if (!config.requiresAuth || !this.config.enabled) {\n return config;\n };\n\n //Actúa SOLO si los tokens son válidos\n if (!this.config.hasValidTokens()) {\n return config;\n };\n\n if (!this.config.shouldAutoRefresh()) {\n return config;\n };\n\n if (this.config.isTokenExpiringSoon()) {\n try {\n //Evita múltiples llamadas de actualización simultáneas\n if (this.isRefreshing && this.refreshPromise) {\n await this.refreshPromise;\n } else {\n this.isRefreshing = true;\n this.refreshPromise = this.config.refreshSession();\n await this.refreshPromise;\n this.isRefreshing = false;\n this.refreshPromise = null;\n };\n } catch (error) {\n this.isRefreshing = false;\n this.refreshPromise = null;\n };\n };\n\n return config;\n };\n\n updateConfig(config: Partial<AuthInterceptorConfig>): void {\n this.config = {\n ...this.config,\n ...config\n } as Required<AuthInterceptorConfig>;\n };\n\n reset(): void {\n this.isRefreshing = false;\n this.refreshPromise = null;\n };\n};\n","export class ErrorResponse extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n public responseData?: any\n ){\n super(message);\n this.name = \"FalconHUB API Error\";\n };\n};\n","import { API } from \"@/core/API\";\nimport { CryptoService } from \"@/core/CryptoService\";\nimport { TokenManager } from \"@/core/TokenManager\";\nimport { LoginRequest } from \"@/interfaces/Auth/Login/LoginRequest\";\nimport { LoginResponse } from \"@/interfaces/Auth/Login/LoginResponse\";\nimport { RefreshTokenRequest } from \"@/interfaces/Auth/RefreshTokens/RefreshTokenRequest\";\nimport { RefreshTokenResponse } from \"@/interfaces/Auth/RefreshTokens/RefreshTokenResponse\";\nimport { ValidateSessionRenewedResponse, ValidateSessionResponse } from \"@/interfaces/Auth/ValidateSession/ValidateSessionResponse\";\nimport { ConfirmEmailRequest } from \"@/interfaces/Auth/ConfirmEmail/ConfirmEmailRequest\";\nimport { SendOtpRequest } from \"@/interfaces/Auth/SendOtp/SendOtpRequest\";\nimport { ValidateOtpRequest } from \"@/interfaces/Auth/ValidateOtp/ValidateOtpRequest\";\nimport { ChangePasswordRequest } from \"@/interfaces/Auth/ChangePassword/ChangePasswordRequest\";\nimport { ErrorResponse } from \"@/types/ErrorResponse\";\nimport { ResponseModel } from \"@/types/ResponseModel\";\nimport { ServiceProperties } from \"@/types/ServiceProperties\";\nimport { TokenData } from \"@/types/TokenData\";\n\nexport class AuthService {\n private api: API;\n private crytpoService: CryptoService;\n private tokenManager: TokenManager;\n private serviceProperties: ServiceProperties;\n\n constructor(\n serviceProperties: ServiceProperties,\n tokenManager: TokenManager,\n cryptoService: CryptoService,\n api: API\n ) {\n this.api = api;\n this.crytpoService = cryptoService;\n this.tokenManager = tokenManager;\n this.serviceProperties = serviceProperties;\n };\n\n /**\n * Login con las credenciales proporcionadas\n * @param credentials - Objeto con email, password y rememberMe\n * @returns Retorna el cuerpo de respuesta del login.\n */\n async login(credentials: LoginRequest): Promise<ResponseModel<LoginResponse>> {\n const timestamp = Date.now().toString();\n\n const loginData: LoginRequest = {\n email: credentials.email,\n password: credentials.password,\n rememberMe: credentials.rememberMe\n };\n\n const response = await this.api.executePublicRequest<LoginResponse>(\n 'oauth/login',\n 'POST',\n loginData,\n timestamp\n );\n\n if (!response) {\n throw new ErrorResponse('No response from server');\n };\n\n if (response.success && response.data) {\n const data: LoginResponse = response.data;\n\n const expiresIn = parseInt(data.expiresIn.replace('s', ''));\n const expiresAt = Date.now() + expiresIn * 1000;\n\n const tokens: TokenData = {\n accessToken: data.accessToken,\n refreshToken: data.refreshToken,\n expiresAt,\n rememberMe: credentials.rememberMe\n };\n\n await this.tokenManager.setTokens(tokens);\n\n this.serviceProperties.onTokensUpdated?.(tokens);\n }\n\n return response;\n };\n\n /**\n * Valida la sesión actual y retorna información de expiración\n *\n * El servidor puede responder de 2 formas:\n * 1. Sesión renovada (sliding window): retorna nuevos tokens\n * 2. Sesión válida: retorna info de expiración sin renovar\n */\n async validateSession(): Promise<ResponseModel<ValidateSessionRenewedResponse | ValidateSessionResponse>> {\n const response = await this.api.executePOST<ValidateSessionRenewedResponse | ValidateSessionResponse>(\n 'oauth/validateSession'\n );\n\n if (!response) {\n throw new ErrorResponse('No response from server');\n };\n\n if (response.success && response.data) {\n const respData = response.data;\n\n if ('expiresIn' in respData && respData.expiresIn) {\n const sessionData = respData as ValidateSessionRenewedResponse;\n const expiresIn = parseInt(sessionData.expiresIn.replace('s', ''));\n const expiresAt = Date.now() + expiresIn * 1000;\n\n const currentTokens = this.tokenManager.getTokens();\n const rememberMe = currentTokens?.rememberMe ?? sessionData.isRemembered;\n\n const tokens: TokenData = {\n accessToken: sessionData.accessToken,\n refreshToken: sessionData.refreshToken,\n expiresAt,\n rememberMe\n };\n\n this.tokenManager.setTokens(tokens);\n this.serviceProperties.onTokensUpdated?.(tokens);\n }\n else if ('expiresAt' in respData && respData.expiresAt) {\n const sessionData = respData as ValidateSessionResponse;\n\n if (sessionData.remainingMinutes <= 5 && sessionData.remainingMinutes > 1) {\n this.serviceProperties.onSessionExpiring?.(sessionData.remainingMinutes);\n } else if (sessionData.remainingMinutes <= 1) {\n if (this.serviceProperties.onSessionExpired) {\n await this.serviceProperties.onSessionExpired();\n }\n }\n }\n };\n\n return response;\n };\n\n /**\n * Refresca los tokens usando el refresh token\n */\n async refreshTokens(refreshRequest: RefreshTokenRequest): Promise<ResponseModel<RefreshTokenResponse>> {\n const currentTokens = this.tokenManager.getTokens();\n const refreshToken = this.tokenManager.getRefreshToken() ?? refreshRequest.refreshToken;\n\n if (!refreshToken) {\n throw new ErrorResponse('No refresh token available');\n };\n\n const refreshRequestData: RefreshTokenRequest = {\n refreshToken: refreshToken,\n rememberMe: refreshRequest.rememberMe ?? currentTokens?.rememberMe\n }\n\n const response = await this.api.executePublicRequest<RefreshTokenResponse>(\n 'oauth/refresh',\n 'POST',\n refreshRequestData\n );\n\n if (!response) {\n throw new ErrorResponse('No response from server');\n };\n\n if (response.success && response.data) {\n const sessionData: RefreshTokenResponse = response.data;\n\n\n const shouldRemember = refreshRequest.rememberMe ?? currentTokens?.rememberMe ?? false;\n const expiresIn = parseInt(sessionData.expiresIn.replace('s', ''));\n const expiresAt = Date.now() + expiresIn * 1000;\n\n const tokens: TokenData = {\n accessToken: sessionData.accessToken,\n refreshToken: sessionData.refreshToken,\n expiresAt,\n rememberMe: shouldRemember\n };\n\n this.tokenManager.setTokens(tokens);\n this.serviceProperties.onTokensUpdated?.(tokens);\n };\n\n return response;\n };\n\n /**\n * Cierra sesión: notifica al servidor y limpia tokens\n */\n async logout(): Promise<ResponseModel> {\n const res = await this.api.executePOST('oauth/logout');\n\n if (res.success) {\n this.tokenManager.clearTokens();\n this.serviceProperties.onTokensUpdated?.(null);\n }\n\n return res;\n }\n\n // #region Email & OTP & Password (public - no auth)\n\n /**\n * Confirma el correo electrónico de un usuario.\n * @param request - Email y expiresAt\n */\n async confirmEmail(request: ConfirmEmailRequest): Promise<ResponseModel> {\n return this.api.executePublicRequest('oauth/email/confirm', 'PUT', request);\n }\n\n /**\n * Envía un código OTP al correo electrónico.\n * @param request - Email del usuario\n */\n async sendOtp(request: SendOtpRequest): Promise<ResponseModel> {\n return this.api.executePublicRequest('oauth/otp', 'POST', request);\n }\n\n /**\n * Valida un código OTP.\n * @param request - Email y código OTP\n */\n async validateOtp(request: ValidateOtpRequest): Promise<ResponseModel> {\n return this.api.executePublicRequest('oauth/otp/verify', 'POST', request);\n }\n\n /**\n * Cambia la contraseña del usuario (flujo público, sin sesión).\n * @param request - Email, contraseña actual y nueva contraseña\n */\n async changePassword(request: ChangePasswordRequest): Promise<ResponseModel> {\n return this.api.executePublicRequest('oauth/password', 'PUT', request);\n }\n\n // #endregion\n\n /**\n * Verifica si el usuario está autenticado\n */\n isAuthenticated(): boolean {\n return this.tokenManager.hasValidTokens();\n };\n\n /**\n * Obtiene los tokens actuales\n */\n getTokens(): TokenData | null {\n return this.tokenManager.getTokens();\n };\n\n}\n","/**\n * Utilidad para construir query params a partir de objetos de filtro.\n *\n * @example\n * ```typescript\n * const filter: EndpointsFilter = { HttpMethod: 'GET', IsActive: true };\n * const queryString = FilterBuilder.toQueryString(filter);\n * // Result: \"HttpMethod=GET&IsActive=true\"\n * ```\n */\nexport class FilterBuilder {\n /**\n * Convierte un objeto de filtro a query string.\n * Ignora valores null, undefined y strings vacíos.\n *\n * @param filter - Objeto con los filtros a aplicar\n * @returns Query string sin el \"?\" inicial\n */\n static toQueryString<T extends Record<string, any>>(filter: T): string {\n const params = new URLSearchParams();\n\n for (const [key, value] of Object.entries(filter)) {\n if (value !== null && value !== undefined && value !== '') {\n params.append(key, String(value));\n }\n }\n\n return params.toString();\n }\n\n /**\n * Construye la URL completa con filtros aplicados.\n *\n * @param baseEndpoint - Endpoint base sin query params\n * @param filter - Objeto con los filtros a aplicar\n * @returns Endpoint con query params si hay filtros, o el endpoint base si no hay\n */\n static buildEndpoint<T extends Record<string, any>>(baseEndpoint: string, filter?: T): string {\n if (!filter) return baseEndpoint;\n\n const queryString = this.toQueryString(filter);\n\n if (!queryString) return baseEndpoint;\n\n return `${baseEndpoint}?${queryString}`;\n }\n\n /**\n * Verifica si un objeto de filtro tiene al menos un valor válido.\n *\n * @param filter - Objeto con los filtros a verificar\n * @returns true si hay al menos un filtro con valor válido\n */\n static hasFilters<T extends Record<string, any>>(filter?: T): boolean {\n if (!filter) return false;\n\n return Object.values(filter).some(\n value => value !== null && value !== undefined && value !== ''\n );\n }\n\n /**\n * Limpia un objeto de filtro removiendo valores vacíos.\n * Útil para normalizar filtros antes de enviarlos.\n *\n * @param filter - Objeto con los filtros\n * @returns Nuevo objeto solo con valores válidos\n */\n static clean<T extends Record<string, any>>(filter: T): Partial<T> {\n const cleaned: Partial<T> = {};\n\n for (const [key, value] of Object.entries(filter)) {\n if (value !== null && value !== undefined && value !== '') {\n (cleaned as any)[key] = value;\n }\n }\n\n return cleaned;\n }\n}\n\n/**\n * Tipo base para modelos de filtro.\n * Todos los campos son opcionales y pueden ser string, number, boolean o null.\n */\nexport type FilterModel = Record<string, string | number | boolean | null | undefined>;\n\n/**\n * Tipo para definir metadatos de un campo de filtro.\n */\nexport interface FilterFieldMetadata {\n /** Tipo de filtro */\n type: 'search' | 'string' | 'boolean' | 'number' | 'select' | 'multiselect' | 'date' | 'daterange';\n /** Descripción / label del filtro */\n description: string;\n /** Orden de renderizado (menor = primero, default 99) */\n order?: number;\n /** Opciones para select / multiselect */\n options?: string[];\n /** Labels personalizados para boolean (default: Activo/Inactivo) */\n labels?: { true: string; false: string };\n /** Campos en los que busca el backend (solo para type: 'search') */\n searchIn?: string[];\n /** Valor mínimo (para number) */\n min?: number;\n /** Valor máximo (para number) */\n max?: number;\n /** Fecha mínima (para date / daterange) */\n minDate?: string;\n /** Fecha máxima (para date / daterange) */\n maxDate?: string;\n}\n\n/**\n * Tipo para el modelo de filtros retornado por el endpoint /filters.\n */\nexport type FilterMetadataModel = Record<string, FilterFieldMetadata>;\n\n// ── Filter Groups (array-based format) ──\n\n/**\n * Opción dentro de un grupo de filtros.\n */\nexport interface FilterGroupOption {\n /** Campo del backend (e.g. \"Module\", \"IsActive\") */\n key: string;\n /** Label visible en el frontend */\n label: string;\n /** Placeholder del input (solo para string) */\n placeholder?: string;\n /** Opciones disponibles (solo para select) */\n values?: string[];\n /** Label cuando el valor es true (solo para boolean) */\n trueLabel?: string;\n /** Label cuando el valor es false (solo para boolean) */\n falseLabel?: string;\n}\n\n/**\n * Grupo de filtros agrupados por tipo.\n * El frontend renderiza cada grupo de forma diferente.\n */\nexport interface FilterGroup {\n /** Tipo de filtro: \"string\" | \"boolean\" | \"select\" | \"date\" */\n type: 'string' | 'boolean' | 'select' | 'date';\n /** Label del grupo */\n label: string;\n /** Opciones del grupo */\n options: FilterGroupOption[];\n}\n\n/**\n * Modelo retornado por el endpoint /filters (formato array-based).\n */\nexport type FilterGroupsModel = FilterGroup[];\n","import { API } from \"@/core/API\";\nimport { UserProfileResponse } from \"@/interfaces/User/UserProfileResponse\";\nimport { UserBasicResponse } from \"@/interfaces/User/UserBasicResponse\";\nimport {\n AdminUser,\n AdminAuthentication,\n UserAdminRequest,\n UserAuthAdminRequest,\n ChangePasswordAdminRequest,\n UserAdminFilter,\n UserAdminUpdateRequest,\n UserAuthUpdateRequest\n} from \"@/interfaces/User/Admin\";\nimport { ResponseModel } from \"@/types/ResponseModel\";\nimport { FilterBuilder, type FilterGroupsModel } from \"@/utils/FilterBuilder\";\n\nexport class UserService {\n private api: API;\n private readonly BASE_PATH = 'users';\n\n constructor(\n api: API,\n ){\n this.api = api;\n };\n\n async me(): Promise<ResponseModel<UserBasicResponse>> {\n const response: ResponseModel<UserBasicResponse> = await this.api.executeGET(\n `${this.BASE_PATH}/me`,\n true,\n );\n\n return response;\n };\n\n async profile(): Promise<ResponseModel<UserProfileResponse>>{\n const response: ResponseModel<UserProfileResponse> = await this.api.executeGET(\n `${this.BASE_PATH}/profile`,\n true\n );\n\n return response;\n }\n\n // #region Admin CRUD\n\n /**\n * Crea un nuevo usuario administrador.\n * @param request - Datos del nuevo administrador\n */\n async newAdminUser(request: UserAdminRequest): Promise<ResponseModel<AdminUser>> {\n return this.api.executePOST<AdminUser>(`${this.BASE_PATH}/admin`, request);\n }\n\n /**\n * Crea la autenticación para un usuario.\n * @param request - Datos de autenticación del usuario\n */\n async createUserAuthentication(request: UserAuthAdminRequest): Promise<ResponseModel<AdminAuthentication>> {\n return this.api.executePOST<AdminAuthentication>(`${this.BASE_PATH}/admin/authentication`, request);\n }\n\n /**\n * Cambia la contraseña de un administrador.\n * @param id - ID del usuario\n * @param request - Nueva contraseña\n */\n async changePasswordAdmin(id: number, request: ChangePasswordAdminRequest): Promise<ResponseModel> {\n return this.api.executePOST(`${this.BASE_PATH}/me/${id}/password`, request);\n }\n\n /**\n * Obtiene todos los administradores con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getAllAdmins(filter?: UserAdminFilter): Promise<ResponseModel<AdminUser[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/admin`, filter);\n return this.api.executeGET<AdminUser[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para administradores.\n */\n async getAdminFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/admin/filters`, true);\n }\n\n /**\n * Obtiene un administrador por su ID.\n * @param id - ID del administrador\n */\n async getAdminById(id: number): Promise<ResponseModel<AdminUser>> {\n return this.api.executeGET<AdminUser>(`${this.BASE_PATH}/admin/${id}`, true);\n }\n\n /**\n * Obtiene la autenticación de un administrador.\n * @param id - ID del usuario\n */\n async getAdminAuthentication(id: number): Promise<ResponseModel<AdminAuthentication>> {\n return this.api.executeGET<AdminAuthentication>(`${this.BASE_PATH}/admin/authentication/${id}`, true);\n }\n\n /**\n * Actualiza un administrador existente.\n * @param id - ID del administrador\n * @param request - Nuevos datos del administrador\n */\n async updateAdmin(id: number, request: UserAdminUpdateRequest): Promise<ResponseModel<AdminUser>> {\n return this.api.executePUT<AdminUser>(`${this.BASE_PATH}/admin/${id}`, request);\n }\n\n /**\n * Activa o desactiva un administrador.\n * @param id - ID del administrador\n */\n async toggleAdminStatus(id: number): Promise<ResponseModel<AdminUser>> {\n return this.api.executePUT<AdminUser>(`${this.BASE_PATH}/admin/${id}/toggle-status`);\n }\n\n /**\n * Actualiza la autenticación de un administrador.\n * @param id - ID del usuario\n * @param request - Nuevos datos de autenticación\n */\n async updateAdminAuthentication(id: number, request: UserAuthUpdateRequest): Promise<ResponseModel<AdminAuthentication>> {\n return this.api.executePUT<AdminAuthentication>(`${this.BASE_PATH}/admin/authentication/${id}`, request);\n }\n\n // #endregion\n}\n","import { API } from \"@/core/API\";\nimport { ResponseModel } from \"@/types/ResponseModel\";\nimport { FilterBuilder, type FilterGroupsModel } from \"@/utils/FilterBuilder\";\nimport {\n Module,\n ModuleRequest,\n ModulesFilter,\n Endpoint,\n EndpointRequest,\n EndpointsFilter,\n UIRoute,\n UIRouteRequest,\n UIRoutesFilter\n} from \"@/interfaces/System\";\n\n/**\n * Servicio para gestionar las configuraciones del sistema.\n */\nexport class SystemService {\n private api: API;\n private readonly BASE_PATH = 'system';\n\n constructor(api: API) {\n this.api = api;\n }\n\n // #region MODULES\n\n /**\n * Obtiene todos los módulos con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getModules(filter?: ModulesFilter): Promise<ResponseModel<Module[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/modules`, filter);\n return this.api.executeGET<Module[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para módulos.\n */\n async getModulesFilters(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/modules/filters`, true);\n }\n\n /**\n * Obtiene un módulo por su ID.\n * @param id - ID del módulo\n */\n async getModuleById(id: number): Promise<ResponseModel<Module>> {\n return this.api.executeGET<Module>(`${this.BASE_PATH}/modules/${id}`, true);\n }\n\n /**\n * Crea un nuevo módulo.\n * @param request - Datos del módulo a crear\n */\n async createModule(request: ModuleRequest): Promise<ResponseModel<Module>> {\n return this.api.executePOST<Module>(`${this.BASE_PATH}/modules`, request);\n }\n\n /**\n * Actualiza un módulo existente.\n * @param id - ID del módulo a actualizar\n * @param request - Nuevos datos del módulo\n */\n async updateModule(id: number, request: ModuleRequest): Promise<ResponseModel<Module>> {\n return this.api.executePUT<Module>(`${this.BASE_PATH}/modules/${id}`, request);\n }\n\n /**\n * Activa o desactiva un módulo.\n * @param id - ID del módulo\n */\n async toggleModuleStatus(id: number): Promise<ResponseModel<Module>> {\n return this.api.executePUT<Module>(`${this.BASE_PATH}/modules/${id}/toggle-status`);\n }\n\n /**\n * Elimina un módulo.\n * @param id - ID del módulo a eliminar\n */\n async deleteModule(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/modules/${id}`);\n }\n\n // #endregion\n\n // #region ENDPOINTS\n\n /**\n * Obtiene todos los endpoints con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getEndpoints(filter?: EndpointsFilter): Promise<ResponseModel<Endpoint[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/endpoints`, filter);\n return this.api.executeGET<Endpoint[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para endpoints.\n */\n async getEndpointsFilters(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/endpoints/filters`, true);\n }\n\n /**\n * Obtiene un endpoint por su ID.\n * @param id - ID del endpoint\n */\n async getEndpointById(id: number): Promise<ResponseModel<Endpoint>> {\n return this.api.executeGET<Endpoint>(`${this.BASE_PATH}/endpoints/${id}`, true);\n }\n\n /**\n * Crea un nuevo endpoint.\n * @param request - Datos del endpoint a crear\n */\n async createEndpoint(request: EndpointRequest): Promise<ResponseModel<Endpoint>> {\n return this.api.executePOST<Endpoint>(`${this.BASE_PATH}/endpoints`, request);\n }\n\n /**\n * Actualiza un endpoint existente.\n * @param id - ID del endpoint a actualizar\n * @param request - Nuevos datos del endpoint\n */\n async updateEndpoint(id: number, request: EndpointRequest): Promise<ResponseModel<Endpoint>> {\n return this.api.executePUT<Endpoint>(`${this.BASE_PATH}/endpoints/${id}`, request);\n }\n\n /**\n * Activa o desactiva un endpoint.\n * @param id - ID del endpoint\n */\n async toggleEndpointStatus(id: number): Promise<ResponseModel<Endpoint>> {\n return this.api.executePUT<Endpoint>(`${this.BASE_PATH}/endpoints/${id}/toggle-status`);\n }\n\n /**\n * Elimina un endpoint.\n * @param id - ID del endpoint a eliminar\n */\n async deleteEndpoint(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/endpoints/${id}`);\n }\n\n // #endregion\n\n // #region UI ROUTES\n\n /**\n * Obtiene todas las rutas de UI con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getUIRoutes(filter?: UIRoutesFilter): Promise<ResponseModel<UIRoute[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/ui-routes`, filter);\n return this.api.executeGET<UIRoute[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para rutas de UI.\n */\n async getUIRoutesFilters(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/ui-routes/filters`, true);\n }\n\n /**\n * Obtiene una ruta de UI por su ID.\n * @param id - ID de la ruta\n */\n async getUIRouteById(id: number): Promise<ResponseModel<UIRoute>> {\n return this.api.executeGET<UIRoute>(`${this.BASE_PATH}/ui-routes/${id}`, true);\n }\n\n /**\n * Crea una nueva ruta de UI.\n * @param request - Datos de la ruta a crear\n */\n async createUIRoute(request: UIRouteRequest): Promise<ResponseModel<UIRoute>> {\n return this.api.executePOST<UIRoute>(`${this.BASE_PATH}/ui-routes`, request);\n }\n\n /**\n * Actualiza una ruta de UI existente.\n * @param id - ID de la ruta a actualizar\n * @param request - Nuevos datos de la ruta\n */\n async updateUIRoute(id: number, request: UIRouteRequest): Promise<ResponseModel<UIRoute>> {\n return this.api.executePUT<UIRoute>(`${this.BASE_PATH}/ui-routes/${id}`, request);\n }\n\n /**\n * Activa o desactiva una ruta de UI.\n * @param id - ID de la ruta\n */\n async toggleUIRouteStatus(id: number): Promise<ResponseModel<UIRoute>> {\n return this.api.executePUT<UIRoute>(`${this.BASE_PATH}/ui-routes/${id}/toggle-status`);\n }\n\n /**\n * Elimina una ruta de UI.\n * @param id - ID de la ruta a eliminar\n */\n async deleteUIRoute(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/ui-routes/${id}`);\n }\n\n // #endregion\n}\n","import { API } from \"@/core/API\";\nimport { ResponseModel } from \"@/types/ResponseModel\";\nimport { FilterBuilder, type FilterGroupsModel } from \"@/utils/FilterBuilder\";\nimport {\n Location,\n LocationsRequest,\n LocationsFilter,\n InventoryStatus,\n InventoryStatusRequest,\n InventoryStatusesFilter\n} from \"@/interfaces/Inventory\";\n\n/**\n * Servicio para gestionar inventario: ubicaciones y estatus.\n */\nexport class InventoryService {\n private api: API;\n private readonly BASE_PATH = 'inventory';\n\n constructor(api: API) {\n this.api = api;\n }\n\n // #region LOCATIONS\n\n /**\n * Obtiene todas las ubicaciones con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getLocations(filter?: LocationsFilter): Promise<ResponseModel<Location[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/locations`, filter);\n return this.api.executeGET<Location[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para ubicaciones.\n */\n async getLocationFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/locations/filters`, true);\n }\n\n /**\n * Obtiene una ubicación por su ID.\n * @param id - ID de la ubicación\n */\n async getLocationById(id: number): Promise<ResponseModel<Location>> {\n return this.api.executeGET<Location>(`${this.BASE_PATH}/locations/${id}`, true);\n }\n\n /**\n * Crea una nueva ubicación.\n * @param request - Datos de la ubicación a crear\n */\n async createLocation(request: LocationsRequest): Promise<ResponseModel<Location>> {\n return this.api.executePOST<Location>(`${this.BASE_PATH}/locations`, request);\n }\n\n /**\n * Actualiza una ubicación existente.\n * @param id - ID de la ubicación a actualizar\n * @param request - Nuevos datos de la ubicación\n */\n async updateLocation(id: number, request: LocationsRequest): Promise<ResponseModel<Location>> {\n return this.api.executePUT<Location>(`${this.BASE_PATH}/locations/${id}`, request);\n }\n\n /**\n * Activa o desactiva una ubicación.\n * @param id - ID de la ubicación\n */\n async toggleLocationStatus(id: number): Promise<ResponseModel<Location>> {\n return this.api.executePUT<Location>(`${this.BASE_PATH}/locations/${id}/toggle-status`);\n }\n\n /**\n * Elimina una ubicación.\n * @param id - ID de la ubicación a eliminar\n */\n async deleteLocation(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/locations/${id}`);\n }\n\n // #endregion\n\n // #region STATUSES\n\n /**\n * Obtiene todos los estatus de inventario con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getStatuses(filter?: InventoryStatusesFilter): Promise<ResponseModel<InventoryStatus[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/statuses`, filter);\n return this.api.executeGET<InventoryStatus[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para estatus de inventario.\n */\n async getStatusFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/statuses/filters`, true);\n }\n\n /**\n * Obtiene un estatus de inventario por su ID.\n * @param id - ID del estatus\n */\n async getStatusById(id: number): Promise<ResponseModel<InventoryStatus>> {\n return this.api.executeGET<InventoryStatus>(`${this.BASE_PATH}/statuses/${id}`, true);\n }\n\n /**\n * Crea un nuevo estatus de inventario.\n * @param request - Datos del estatus a crear\n */\n async createStatus(request: InventoryStatusRequest): Promise<ResponseModel<InventoryStatus>> {\n return this.api.executePOST<InventoryStatus>(`${this.BASE_PATH}/statuses`, request);\n }\n\n /**\n * Actualiza un estatus de inventario existente.\n * @param id - ID del estatus a actualizar\n * @param request - Nuevos datos del estatus\n */\n async updateStatus(id: number, request: InventoryStatusRequest): Promise<ResponseModel<InventoryStatus>> {\n return this.api.executePUT<InventoryStatus>(`${this.BASE_PATH}/statuses/${id}`, request);\n }\n\n /**\n * Activa o desactiva un estatus de inventario.\n * @param id - ID del estatus\n */\n async toggleStatusActive(id: number): Promise<ResponseModel<InventoryStatus>> {\n return this.api.executePUT<InventoryStatus>(`${this.BASE_PATH}/statuses/${id}/toggle-status`);\n }\n\n /**\n * Elimina un estatus de inventario.\n * @param id - ID del estatus a eliminar\n */\n async deleteStatus(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/statuses/${id}`);\n }\n\n // #endregion\n}\n","import { API } from \"./core/API\";\nimport { CryptoService } from \"./core/CryptoService\";\nimport { TokenManager } from \"./core/TokenManager\";\nimport { AuthInterceptor } from \"./core/interceptors/AuthInterceptor\";\nimport { ServiceProperties } from \"./types/ServiceProperties\";\nimport { TokenData } from \"./types/TokenData\";\nimport { AuthService } from \"./services/AuthService\";\nimport { UserService } from \"./services/UserService\";\nimport { SystemService } from \"./services/SystemService\";\nimport { InventoryService } from \"./services/InventoryService\";\n\n/**\n * SDK principal de FalconHUB\n */\nexport class FalconHUBSDK {\n public auth: AuthService;\n public user: UserService;\n public system: SystemService;\n public inventory: InventoryService;\n\n private serviceProperties: ServiceProperties;\n private cryptoService: CryptoService;\n private tokenManager: TokenManager;\n private authInterceptor: AuthInterceptor | null;\n private api: API;\n\n constructor(serviceProperties: ServiceProperties) {\n this.serviceProperties = serviceProperties;\n\n this.cryptoService = new CryptoService();\n\n const autoRefreshConfig = this.normalizeAutoRefreshConfig(this.serviceProperties.autoRefresh);\n\n this.tokenManager = new TokenManager(\n this.serviceProperties.onTokensUpdated,\n this.serviceProperties.onSessionExpiring,\n async () => {\n await this.auth.logout();\n },\n async () => {\n const currentTokens = this.tokenManager.getTokens();\n if (!currentTokens?.refreshToken) return false;\n\n try {\n const response = await this.auth.refreshTokens({\n refreshToken: currentTokens.refreshToken,\n rememberMe: currentTokens.rememberMe\n });\n return response.success === true;\n } catch {\n return false;\n }\n },\n autoRefreshConfig.enabled ? autoRefreshConfig.thresholdMinutes : undefined\n );\n\n if (autoRefreshConfig.enabled) {\n this.authInterceptor = new AuthInterceptor({\n enabled: true,\n thresholdMinutes: autoRefreshConfig.thresholdMinutes,\n isTokenExpiringSoon: () => this.tokenManager.isTokenExpiringSoon(autoRefreshConfig.thresholdMinutes),\n hasValidTokens: () => this.tokenManager.hasValidTokens(),\n shouldAutoRefresh: () => this.tokenManager.shouldAutoRefresh(),\n refreshSession: async () => {\n await this.auth.validateSession();\n }\n });\n } else {\n this.authInterceptor = null;\n }\n\n this.api = new API(\n this.serviceProperties,\n this.cryptoService,\n this.authInterceptor,\n () => this.tokenManager.getAccessToken(),\n () => this.tokenManager.getRefreshToken()\n );\n\n this.auth = new AuthService(\n this.serviceProperties,\n this.tokenManager,\n this.cryptoService,\n this.api\n );\n\n this.user = new UserService(\n this.api\n );\n\n this.system = new SystemService(\n this.api\n );\n\n this.inventory = new InventoryService(\n this.api\n );\n }\n\n private normalizeAutoRefreshConfig(\n config: ServiceProperties[\"autoRefresh\"]\n ): { enabled: boolean; thresholdMinutes: number } {\n if (typeof config === \"boolean\") {\n return { enabled: config, thresholdMinutes: 5 };\n }\n if (typeof config === \"object\" && config !== null) {\n return {\n enabled: config.enabled,\n thresholdMinutes: config.thresholdMinutes ?? 5\n };\n }\n return { enabled: true, thresholdMinutes: 5 };\n }\n\n /**\n * Inyecta tokens desde storage externo (cookies/localStorage/etc)\n * @param expiresAt - Timestamp en milisegundos\n */\n setTokensFromExternal(\n accessToken: string,\n refreshToken: string,\n expiresAt: number,\n rememberMe: boolean = false\n ): void {\n const tokens: TokenData = {\n accessToken,\n refreshToken,\n expiresAt,\n rememberMe\n };\n\n this.tokenManager.setTokensSilent(tokens);\n }\n\n /**\n * Obtiene los tokens actuales\n */\n getTokens(): TokenData | null {\n return this.tokenManager.getTokens();\n }\n\n /**\n * Verifica si el usuario está autenticado\n */\n isAuthenticated(): boolean {\n return this.tokenManager.hasValidTokens();\n }\n\n /**\n * Verifica si la sesión está por expirar\n */\n isSessionExpiringSoon(thresholdMinutes: number = 5): boolean {\n return this.tokenManager.isTokenExpiringSoon(thresholdMinutes);\n }\n\n /**\n * Obtiene el tiempo restante hasta la expiración en milisegundos\n */\n getTimeUntilExpiry(): number | null {\n return this.tokenManager.getTimeUntilExpiry();\n }\n}\n","import CryptoJS from 'crypto-js';\n\nexport function decrypt(encryptedBase64: string, secret: string, timestamp: string): string {\n const fullKey = `${secret}:${timestamp}`;\n // Generate key using SHA256\n const key = CryptoJS.SHA256(fullKey);\n\n // Parse total encrypted data from Base64\n const allData = CryptoJS.enc.Base64.parse(encryptedBase64);\n\n // Extract IV (first 16 bytes = 4 words)\n const iv = CryptoJS.lib.WordArray.create(allData.words.slice(0, 4), 16);\n\n // Extract ciphertext (remaining bytes)\n const ciphertext = CryptoJS.lib.WordArray.create(allData.words.slice(4), allData.sigBytes - 16);\n\n // Decrypt using AES-256-CBC\n // We use PKCS7 padding as it's the default in Node.js createDecipheriv for aes-256-cbc\n const decrypted = CryptoJS.AES.decrypt(\n { ciphertext: ciphertext } as any,\n key,\n {\n iv: iv,\n mode: CryptoJS.mode.CBC,\n padding: CryptoJS.pad.Pkcs7\n }\n );\n\n return decrypted.toString(CryptoJS.enc.Utf8);\n}\n"],"mappings":"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","names":["CryptoJS"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "falconhub-apilibrary",
3
- "version": "1.2.3-dev.70",
3
+ "version": "1.2.4-dev.71",
4
4
  "description": "FalconHUB SKD",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",