falconhub-apilibrary 1.1.0 → 1.1.2
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/LICENSE +15 -15
- package/README.md +144 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +61 -61
package/LICENSE
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
ISC License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 Blink Solutions SA de CV
|
|
4
|
-
|
|
5
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
-
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
-
copyright notice and this permission notice appear in all copies.
|
|
8
|
-
|
|
9
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
-
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
-
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
-
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
-
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
-
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
15
|
-
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Blink Solutions SA de CV
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
15
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,22 +1,144 @@
|
|
|
1
|
-
# FalconHUB
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
**
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
1
|
+
# FalconHUB API Library
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/falconhub-apilibrary)
|
|
4
|
+
[](https://github.com/fanarmy/falconhub_apilibrary/blob/main/LICENSE)
|
|
5
|
+
|
|
6
|
+
Librería cliente desarrollada en TypeScript dedicada a facilitar el consumo del API de FalconHUB.
|
|
7
|
+
|
|
8
|
+
## Características
|
|
9
|
+
|
|
10
|
+
- **Gestión de tokens**: Al realizar el inicio de sesión mediante el módulo de auth, la librería se encargará de gestionar las sesiones mediante funciones callback
|
|
11
|
+
- **Sliding window**: Cuando se desee mantener la sesión activa, la librería gestionará las renovaciones de tokens mediante Sliding Window
|
|
12
|
+
- **Firmas de seguridad autogestionadas**: Dentro del entorno existen rutas protegidas (de tipo POST) mediante firmas Signature, la librería se encarga de realizar estas firmas y procesarlas
|
|
13
|
+
- **Callbacks**: Funciones que sincronizan información entre la librería y el proyecto que la consuma
|
|
14
|
+
- **TypeScript**: Completamente tipado con soporte para TypeScript
|
|
15
|
+
- **ES Modules y CommonJS**: Compatible con ambos sistemas de módulos
|
|
16
|
+
|
|
17
|
+
## Instalación
|
|
18
|
+
|
|
19
|
+
### Versión de Producción (Estable)
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install falconhub-apilibrary
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
O con yarn:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
yarn add falconhub-apilibrary
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Versión de Desarrollo (Testing)
|
|
32
|
+
|
|
33
|
+
Para probar los últimos cambios antes de que se liberen a producción:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install falconhub-apilibrary@dev
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
O con yarn:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
yarn add falconhub-apilibrary@dev
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
> **Nota**: La versión `@dev` contiene los últimos cambios del branch `development` y se actualiza con cada push. Es ideal para probar nuevas funcionalidades antes de su liberación oficial.
|
|
46
|
+
|
|
47
|
+
## Desarrollo
|
|
48
|
+
|
|
49
|
+
### Requisitos Previos
|
|
50
|
+
|
|
51
|
+
- Node.js 18 o superior
|
|
52
|
+
- npm 8 o superior
|
|
53
|
+
|
|
54
|
+
### Configuración del Entorno de Desarrollo
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Clonar el repositorio
|
|
58
|
+
git clone https://bitbucket.org/fanarmy/falconhub_apilibrary.git
|
|
59
|
+
cd falconhub_apilibrary
|
|
60
|
+
|
|
61
|
+
# Instalar dependencias
|
|
62
|
+
npm install
|
|
63
|
+
|
|
64
|
+
# Compilar el proyecto
|
|
65
|
+
npm run build
|
|
66
|
+
|
|
67
|
+
# Modo desarrollo con watch
|
|
68
|
+
npm run dev
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Scripts Disponibles
|
|
72
|
+
|
|
73
|
+
- `npm run build` - Compila el proyecto a JavaScript
|
|
74
|
+
- `npm run dev` - Modo desarrollo con watch
|
|
75
|
+
- `npm test` - Ejecuta los tests (cuando estén configurados)
|
|
76
|
+
- `npm run prepublishOnly` - Se ejecuta automáticamente antes de publicar
|
|
77
|
+
|
|
78
|
+
### Actualizar Versión y Desplegar
|
|
79
|
+
|
|
80
|
+
La versión se **incrementa automáticamente** al hacer merge a `main`:
|
|
81
|
+
|
|
82
|
+
1. **Trabaja en `development`**:
|
|
83
|
+
```bash
|
|
84
|
+
git checkout development
|
|
85
|
+
git commit -m "Update/Feature/HotFix/Release - [Tu Nombre] - Descripción breve"
|
|
86
|
+
git push origin development
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
2. **Crea Pull Request** de `development` → `main` en Bitbucket:
|
|
90
|
+
- **Título**: `Update - 1.1.1 - Implementación de validaciones`
|
|
91
|
+
- **Descripción**:
|
|
92
|
+
```
|
|
93
|
+
### Notes Update
|
|
94
|
+
- Cambio específico 1
|
|
95
|
+
- Cambio específico 2
|
|
96
|
+
|
|
97
|
+
### Notes Fixes
|
|
98
|
+
- Bug corregido 1
|
|
99
|
+
|
|
100
|
+
### Breaking Changes
|
|
101
|
+
Ninguno
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
3. **Aprueba el merge**: El pipeline automáticamente:
|
|
105
|
+
- Incrementa la versión .
|
|
106
|
+
- Usa el título del PR como mensaje de versión
|
|
107
|
+
- Genera release notes con la descripción completa
|
|
108
|
+
- Publica a npm
|
|
109
|
+
- Despliega a S3
|
|
110
|
+
|
|
111
|
+
## Estructura del Proyecto
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
falconhub_apilibrary/
|
|
115
|
+
├── src/ # Código fuente TypeScript
|
|
116
|
+
├── dist/ # Código compilado (generado)
|
|
117
|
+
│ ├── index.js # CommonJS
|
|
118
|
+
│ ├── index.mjs # ES Modules
|
|
119
|
+
│ └── index.d.ts # TypeScript definitions
|
|
120
|
+
├── node_modules/ # Dependencias
|
|
121
|
+
├── .npmignore # Archivos excluidos del paquete npm
|
|
122
|
+
├── bitbucket-pipelines.yml # Configuración del pipeline
|
|
123
|
+
├── package.json # Configuración del paquete
|
|
124
|
+
├── tsconfig.json # Configuración de TypeScript
|
|
125
|
+
├── tsup.config.ts # Configuración del bundler
|
|
126
|
+
└── README.md # Este archivo
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Soporte
|
|
130
|
+
|
|
131
|
+
Para reportar problemas o solicitar características:
|
|
132
|
+
- Issues: https://bitbucket.org/fanarmy/falconhub_apilibrary/issues
|
|
133
|
+
|
|
134
|
+
## Licencia
|
|
135
|
+
|
|
136
|
+
ISC License - Copyright (c) 2025 Blink Solutions SA de CV
|
|
137
|
+
|
|
138
|
+
## Autor
|
|
139
|
+
|
|
140
|
+
**FanArmy / Blink Solutions**
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
**Versión actual**: Ver [package.json](./package.json) o [npm](https://www.npmjs.com/package/falconhub-apilibrary)
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/types/ErrorResponse.ts","../src/core/API.ts","../src/core/CryptoService.ts","../src/core/TokenManager.ts","../src/core/interceptors/AuthInterceptor.ts","../src/services/AuthService.ts","../src/FalconHUBSDK.ts"],"sourcesContent":["/**\n * FalconHUB API Library\n *\n * SDK cliente para consumir el API de FalconHUB\n *\n * @packageDocumentation\n */\n\nexport { FalconHUBSDK } from './FalconHUBSDK';\n\nexport { AuthService } from './services/AuthService';\n\nexport type { ServiceProperties } from './types/ServiceProperties';\nexport type { TokenData } from './types/TokenData';\nexport type { ErrorResponse } from './types/ErrorResponse';\nexport type { ResponseModel } from './types/ResponseModel';\nexport type { RequestOptions, MethodTypes } from './types/RequestOptions';\nexport type { RequestConfig } from './types/RequestConfig';\n\nexport { API } from './core/API';\nexport { TokenManager } from './core/TokenManager';\nexport { CryptoService } from './core/CryptoService';\n\nexport { AuthInterceptor } from './core/interceptors/AuthInterceptor';\nexport type { AuthInterceptorConfig } from './core/interceptors/types/AuthInterceptorConfig';\nexport type { InterceptorContext } from './core/interceptors/types/InterceptorContext';\nexport type { RequestInterceptor } from './core/interceptors/types/RequestInterceptor';\n\nexport type { LoginRequest } from './interfaces/Auth/Login/LoginRequest';\nexport type { LoginResponse } from './interfaces/Auth/Login/LoginResponse';\nexport type { RefreshTokenRequest } from './interfaces/Auth/RefreshTokens/RefreshTokenRequest';\nexport type { RefreshTokenResponse } from './interfaces/Auth/RefreshTokens/RefreshTokenResponse';\nexport type { ValidateSessionResponse, ValidateSessionRenewedResponse } from './interfaces/Auth/ValidateSession/ValidateSessionResponse';\n","export class ErrorResponse extends Error {\r\n constructor(\r\n message: string,\r\n public statusCode?: number,\r\n public responseData?: any\r\n ){\r\n super(message);\r\n this.name = \"FalconHUB API Error\";\r\n };\r\n};\r\n","import { ServiceProperties } from \"@/types/ServiceProperties\";\r\nimport { CryptoService } from \"./CryptoService\";\r\nimport { MethodTypes, RequestOptions } from \"@/types/RequestOptions\";\r\nimport { ErrorResponse } from \"@/types/ErrorResponse\";\r\nimport { RequestConfig } from \"@/types/RequestConfig\";\r\nimport { AuthInterceptor } from \"./interceptors/AuthInterceptor\";\r\nimport { InterceptorContext } from \"@/core/interceptors/types/InterceptorContext\";\r\n\r\n\r\n/**\r\n * Clase base para la ejecución de request HTTP al API\r\n */\r\nexport class API {\r\n private properties: ServiceProperties;\r\n private cryptoService: CryptoService;\r\n private authInterceptor: AuthInterceptor | null;\r\n\r\n private getAccessToken: () => string | null;\r\n private getRefreshToken: () => string | null;\r\n\r\n constructor(\r\n properties: ServiceProperties,\r\n cryptoService: CryptoService,\r\n authInterceptor: AuthInterceptor | null,\r\n getAccessToken: () => string | null,\r\n getRefreshToken: () => string | null\r\n ) {\r\n this.properties = properties;\r\n this.cryptoService = cryptoService;\r\n this.getAccessToken = getAccessToken;\r\n this.getRefreshToken = getRefreshToken;\r\n this.authInterceptor = authInterceptor;\r\n };\r\n\r\n /**\r\n * Ejecuta una request HTTP al API\r\n *\r\n * @param options - Opciones de la request\r\n * @returns Respuesta parseada del tipo esperado\r\n */\r\n private async apiExecute<T>(options: RequestOptions): Promise<T | undefined> {\r\n const {\r\n endpoint,\r\n method,\r\n body,\r\n requiresSignature,\r\n requiresAuth,\r\n timeStamp\r\n } = options;\r\n\r\n const context: InterceptorContext = {\r\n requestId: this.cryptoService.generateUniqueId(),\r\n startTime: Date.now(),\r\n retryCount: 0,\r\n metadata: {}\r\n };\r\n\r\n try {\r\n const url = `${this.properties.url}/${endpoint}`;\r\n\r\n const headers: Record<string, string> = {};\r\n\r\n if (body && method !== 'GET') {\r\n headers['Content-Type'] = 'application/json';\r\n };\r\n\r\n const accessToken = this.getAccessToken();\r\n\r\n if (accessToken) {\r\n headers['Authorization'] = `Bearer ${accessToken}`;\r\n };\r\n\r\n const newTimeStamp = timeStamp || new Date().toString();\r\n\r\n headers['X-Timestamp'] = newTimeStamp;\r\n\r\n let bodyString: string | undefined;\r\n\r\n if (body && method !== 'GET') {\r\n bodyString = JSON.stringify(body);\r\n };\r\n\r\n if (requiresSignature && bodyString) {\r\n try {\r\n const refreshToken = this.getRefreshToken();\r\n\r\n if (refreshToken) {\r\n const signature = this.cryptoService.genSignature(\r\n bodyString,\r\n newTimeStamp,\r\n refreshToken\r\n );\r\n\r\n if (signature) {\r\n headers['X-Signature'] = signature;\r\n };\r\n };\r\n } catch (error) {\r\n throw new ErrorResponse(\r\n \"Failed to generate request signature.\",\r\n 401\r\n );\r\n };\r\n };\r\n\r\n const requestConfig: RequestConfig = {\r\n url,\r\n method,\r\n headers,\r\n body: bodyString,\r\n requiresAuth,\r\n requiresSignature\r\n };\r\n\r\n const modifiedConfig = this.authInterceptor\r\n ? await this.authInterceptor.onRequest(requestConfig, context)\r\n : requestConfig;\r\n\r\n const requestInit: RequestInit = {\r\n method: modifiedConfig.method,\r\n headers: modifiedConfig.headers,\r\n mode: 'cors',\r\n credentials: 'omit'\r\n };\r\n\r\n if (bodyString) {\r\n requestInit.body = bodyString;\r\n };\r\n\r\n const response = await fetch(\r\n modifiedConfig.url,\r\n requestInit\r\n );\r\n\r\n if (response.ok) {\r\n // Detectar sliding window: nuevos tokens en headers\r\n const newAccessToken = response.headers.get('X-New-Access-Token');\r\n const newRefreshToken = response.headers.get('X-New-Refresh-Token');\r\n\r\n if (newAccessToken || newRefreshToken) {\r\n this.properties.onTokensRefreshed?.({\r\n accessToken: newAccessToken,\r\n refreshToken: newRefreshToken\r\n });\r\n };\r\n\r\n const contentType = response.headers.get('Content-Type');\r\n\r\n if (contentType && contentType.includes('application/json')) {\r\n const responseText = await response.text();\r\n\r\n return JSON.parse(responseText) as T;\r\n };\r\n\r\n return undefined;\r\n } else {\r\n await this.handleErrorResponse(response);\r\n };\r\n } catch (error) {\r\n if (error instanceof ErrorResponse) {\r\n throw error;\r\n };\r\n\r\n throw new ErrorResponse(\r\n 'Unexpected error occurred during API request.',\r\n 500\r\n );\r\n };\r\n };\r\n\r\n /**\r\n * Maneja errores HTTP y lanza excepciones apropiadas\r\n */\r\n private async handleErrorResponse(\r\n response: Response\r\n ): Promise<never> {\r\n\r\n const statusCode = response.status;\r\n let errorMessage = `Error ${statusCode}`;\r\n let responseData: any = null;\r\n\r\n try {\r\n const contentType = response.headers.get('Content-Type');\r\n if (contentType && contentType.includes('application/json')) {\r\n responseData = await response.json();\r\n errorMessage = responseData.message || responseData.error || errorMessage;\r\n } else {\r\n errorMessage = await response.text();\r\n };\r\n } catch (error) {\r\n\r\n };\r\n\r\n switch (statusCode) {\r\n case 401:\r\n const authError = new ErrorResponse(\r\n 'Unauthorized access.',\r\n 401,\r\n responseData\r\n );\r\n\r\n this.properties.onAuthError?.(authError);\r\n throw authError;\r\n case 403:\r\n throw new ErrorResponse(\r\n 'No tienes permisos para realizar esta acción.',\r\n 403,\r\n responseData\r\n );\r\n\r\n case 404:\r\n throw new ErrorResponse(\r\n 'Recurso no encontrado.',\r\n 404,\r\n responseData\r\n );\r\n\r\n case 422:\r\n throw new ErrorResponse(\r\n errorMessage || 'Datos de entrada inválidos.',\r\n 422,\r\n responseData\r\n );\r\n\r\n case 500:\r\n throw new ErrorResponse(\r\n 'Error interno del servidor.',\r\n 500,\r\n responseData\r\n );\r\n\r\n default:\r\n throw new ErrorResponse(\r\n errorMessage,\r\n statusCode,\r\n responseData\r\n );\r\n };\r\n };\r\n\r\n //#region REQUEST METHODS\r\n\r\n async executeGET<T>(\r\n endpoint: string,\r\n requiresAuth: boolean = false\r\n ): Promise<T | undefined> {\r\n return this.apiExecute<T>({\r\n endpoint,\r\n method: 'GET',\r\n requiresAuth: requiresAuth,\r\n requiresSignature: false\r\n });\r\n };\r\n\r\n async executePOST<T>(\r\n endpoint: string,\r\n body?: any,\r\n requiresAuth: boolean = true,\r\n requiresSignature: boolean = true\r\n ): Promise<T | undefined> {\r\n return this.apiExecute<T>({\r\n endpoint,\r\n method: 'POST',\r\n body,\r\n requiresAuth: requiresAuth,\r\n requiresSignature: requiresSignature\r\n });\r\n };\r\n\r\n async executePATCH<T>(\r\n endpoint: string,\r\n body?: any,\r\n requiresAuth: boolean = true,\r\n requiresSignature: boolean = true\r\n ): Promise<T | undefined> {\r\n return this.apiExecute<T>({\r\n endpoint,\r\n method: 'PATCH',\r\n body,\r\n requiresAuth: requiresAuth,\r\n requiresSignature: requiresSignature\r\n });\r\n };\r\n\r\n async executeDELETE<T>(\r\n endpoint: string,\r\n body?: any,\r\n requiresAuth: boolean = true,\r\n requiresSignature: boolean = false\r\n ): Promise<T | undefined> {\r\n return this.apiExecute<T>({\r\n endpoint,\r\n method: 'DELETE',\r\n body,\r\n requiresAuth: requiresAuth,\r\n requiresSignature: requiresSignature\r\n });\r\n };\r\n\r\n async executePUT<T>(\r\n endpoint: string,\r\n body?: any,\r\n requiresAuth: boolean = true,\r\n requiresSignature: boolean = true\r\n ): Promise<T | undefined> {\r\n return this.apiExecute<T>({\r\n endpoint,\r\n method: 'PUT',\r\n body,\r\n requiresAuth: requiresAuth,\r\n requiresSignature: requiresSignature\r\n });\r\n };\r\n\r\n async executePublicRequest<T>(\r\n endpoint: string,\r\n method: MethodTypes,\r\n body?: any,\r\n timestamp?: string\r\n ): Promise<T | undefined> {\r\n return this.apiExecute<T>({\r\n endpoint,\r\n method,\r\n body,\r\n requiresAuth: false,\r\n requiresSignature: false,\r\n timeStamp: timestamp\r\n });\r\n };\r\n\r\n //#endregion\r\n}\r\n","import * as CryptoJS from 'crypto-js';\r\n\r\nexport class CryptoService {\r\n\r\n /**\r\n * Encripta el texto plano utilizando AES con una clave derivada del secretWord y el timestamp\r\n *\r\n * @param plaintText -- Texto plano a encriptar\r\n * @param secretWord - Palabra secreta utilizada para derivar la clave\r\n * @param timestamp - Timestamp actual\r\n * @returns Texto encriptado en formato Base64\r\n */\r\n encrypt(plaintText: string, secretWord: string, timestamp: string): string {\r\n const fullKey = `${secretWord}:${timestamp}`;\r\n const key = CryptoJS.SHA256(fullKey);\r\n\r\n const iv = CryptoJS.lib.WordArray.random(16);\r\n const encrypted = CryptoJS.AES.encrypt(plaintText, key, {\r\n iv: iv,\r\n mode: CryptoJS.mode.CBC,\r\n padding: CryptoJS.pad.Pkcs7\r\n });\r\n\r\n const ivAndCipher = iv.concat(encrypted.ciphertext);\r\n return CryptoJS.enc.Base64.stringify(ivAndCipher);\r\n };\r\n\r\n /**\r\n * Genera la firma Signature para las operaciones de tipo POST\r\n *\r\n * @param body - Cuerpo de la solicitud\r\n * @param timestamp - Timestamp actual\r\n * @param refreshToken - Refresh token del usuario\r\n * @returns Firma signature en formato Base64\r\n */\r\n genSignature(body: string, timestamp: string, refreshToken: string): string {\r\n const message = `${body}:${timestamp}`;\r\n const hmac = CryptoJS.HmacSHA256(message, refreshToken);\r\n\r\n return CryptoJS.enc.Base64.stringify(hmac);\r\n };\r\n\r\n /**\r\n * Desencripta texto usando AES-256-CBC\r\n *\r\n * @param encryptedBase64 - Texto encriptado en base64\r\n * @param secret - Clave secreta\r\n * @param timestamp - Timestamp usado en la encriptación\r\n * @returns Texto desencriptado\r\n */\r\n decrypt(encryptedText: string, secretWord: string, timestamp: string): string {\r\n try {\r\n const fullKey = `${secretWord}:${timestamp}`;\r\n const key = CryptoJS.SHA256(fullKey);\r\n\r\n const ivAndCipher = CryptoJS.enc.Base64.parse(encryptedText);\r\n const iv = CryptoJS.lib.WordArray.create(ivAndCipher.words.slice(0, 4));\r\n\r\n const ciphertext = CryptoJS.lib.WordArray.create(\r\n ivAndCipher.words.slice(4),\r\n ivAndCipher.sigBytes - 16\r\n );\r\n\r\n const decrypted = CryptoJS.AES.decrypt(\r\n { ciphertext } as any,\r\n key,\r\n {\r\n iv: iv,\r\n mode: CryptoJS.mode.CBC,\r\n padding: CryptoJS.pad.Pkcs7\r\n }\r\n );\r\n\r\n return CryptoJS.enc.Utf8.stringify(decrypted);\r\n } catch (error) {\r\n throw new Error('Decryption failed, ex:' + error);\r\n }\r\n };\r\n\r\n /**\r\n * Verifica una firma HMAC-SHA256 (útil para testing o validación)\r\n *\r\n * @param body - Cuerpo original\r\n * @param timestamp - Timestamp original\r\n * @param refreshToken - Token usado como clave\r\n * @param signature - Firma a verificar\r\n * @returns true si la firma es válida\r\n */\r\n verifySignature(body: string, timestamp: string, refreshToken: string, signature: string): boolean {\r\n try {\r\n const expectedSignature = this.genSignature(body, timestamp, refreshToken);\r\n return expectedSignature === signature;\r\n } catch {\r\n return false;\r\n }\r\n };\r\n\r\n /**\r\n * Genera un hash SHA256 de un texto (útil para fingerprints)\r\n *\r\n * @param text - Texto a hashear\r\n * @returns Hash en formato hexadecimal\r\n */\r\n sha256(text: string): string {\r\n return CryptoJS.SHA256(text).toString(CryptoJS.enc.Hex);\r\n }\r\n\r\n /**\r\n * Genera un identificador único basado en timestamp y random\r\n * (útil para request IDs)\r\n *\r\n * @returns ID único\r\n */\r\n generateUniqueId(): string {\r\n const timestamp = Date.now().toString(36);\r\n const randomPart = Math.random().toString(36).substring(2, 15);\r\n return `${timestamp}-${randomPart}`;\r\n };\r\n\r\n}\r\n","import { TokenData } from \"@/types/TokenData\";\r\n\r\n/**\r\n * Manages authentication tokens.\r\n */\r\nexport class TokenManager {\r\n private tokens: TokenData | null = null;\r\n private onTokensChanged?: (tokens: TokenData | null) => void;\r\n private sessionCheckInterval: NodeJS.Timeout | null = null;\r\n private onSessionExpiring?: (remainingMinutes: number) => void;\r\n private onSessionExpired?: () => Promise<void>;\r\n private hasNotifiedExpiring: boolean = false;\r\n\r\n constructor(\r\n onTokensChanged?: (tokens: TokenData | null) => void,\r\n onSessionExpiring?: (remainingMinutes: number) => void,\r\n onSessionExpired?: () => Promise<void>\r\n ) {\r\n this.onTokensChanged = onTokensChanged;\r\n this.onSessionExpiring = onSessionExpiring;\r\n this.onSessionExpired = onSessionExpired;\r\n };\r\n\r\n /**\r\n * Guarda los tokens de autenticación y dispara el callback onTokensChanged.\r\n */\r\n setTokens(tokens: TokenData) {\r\n this.tokens = tokens;\r\n this.hasNotifiedExpiring = false; // Resetear flag\r\n\r\n this.onTokensChanged?.(this.tokens);\r\n\r\n // Si NO tiene rememberMe, iniciar monitoreo de expiración\r\n if (!tokens.rememberMe) {\r\n this.startExpirationCheck();\r\n } else {\r\n this.stopExpirationCheck();\r\n };\r\n };\r\n\r\n /**\r\n * Obtiene los tokens de autenticación almacenados.\r\n */\r\n getTokens(): TokenData | null {\r\n return this.tokens;\r\n };\r\n\r\n /**\r\n * Limpia los tokens de autenticación almacenados y dispara el callback onTokensChanged.\r\n */\r\n clearTokens() {\r\n this.stopExpirationCheck();\r\n this.tokens = null;\r\n this.onTokensChanged?.(this.tokens);\r\n };\r\n\r\n /**\r\n * Valida si existen tokens y si el access token no ha expirado.\r\n */\r\n hasValidTokens(): boolean {\r\n if (!this.tokens) return false;\r\n\r\n const now = Date.now();\r\n const expiresAt = this.tokens.expiresAt.getTime();\r\n\r\n return now < expiresAt;\r\n };\r\n\r\n /**\r\n * Valida si el access token expirará dentro del umbral especificado (en minutos).\r\n */\r\n isTokenExpiringSoon(thresholdMinutes: number): boolean {\r\n if (!this.tokens) return false;\r\n\r\n const now = Date.now();\r\n const expiresAt = this.tokens.expiresAt.getTime();\r\n const thresholdMs = thresholdMinutes * 60 * 1000;\r\n\r\n const timeLeft = expiresAt - now;\r\n return timeLeft > 0 && timeLeft <= thresholdMs;\r\n };\r\n\r\n /**\r\n * Obtiene el tiempo restante hasta la expiración del access token en milisegundos.\r\n */\r\n getTimeUntilExpiry(): number | null {\r\n if (!this.tokens) return null;\r\n\r\n const now = Date.now();\r\n const expiresAt = this.tokens.expiresAt.getTime();\r\n const timeLeft = Math.max(0, expiresAt - now);\r\n\r\n return timeLeft;\r\n };\r\n\r\n /**\r\n * Obtiene el access token almacenado.\r\n */\r\n getAccessToken(): string | null {\r\n return this.tokens ? this.tokens.accessToken : null;\r\n };\r\n\r\n /**\r\n * Obtiene el refresh token almacenado.\r\n */\r\n getRefreshToken(): string | null {\r\n return this.tokens ? this.tokens.refreshToken : null;\r\n };\r\n\r\n /**\r\n * Verifica si el auto-refresh debe ejecutarse\r\n * Solo si el usuario activó \"rememberMe\" durante el login\r\n */\r\n shouldAutoRefresh(): boolean {\r\n if (!this.tokens) return false;\r\n\r\n return this.tokens.rememberMe === true;\r\n }\r\n\r\n /**\r\n * Inicia el monitoreo de expiración para sesiones sin rememberMe\r\n * - Notifica cuando quedan 5 minutos (onSessionExpiring)\r\n * - Ejecuta logout cuando queda 1 minuto (onSessionExpired)\r\n */\r\n private startExpirationCheck(): void {\r\n this.stopExpirationCheck();\r\n\r\n this.sessionCheckInterval = setInterval(async () => {\r\n if (!this.tokens) {\r\n this.stopExpirationCheck();\r\n return;\r\n };\r\n\r\n const timeLeft = this.getTimeUntilExpiry();\r\n if (timeLeft === null) return;\r\n\r\n const minutesLeft = Math.floor(timeLeft / (60 * 1000));\r\n\r\n // Notificar cuando quedan 5 minutos (solo una vez)\r\n if (minutesLeft <= 5 && minutesLeft > 1 && !this.hasNotifiedExpiring) {\r\n this.hasNotifiedExpiring = true;\r\n this.onSessionExpiring?.(minutesLeft);\r\n };\r\n\r\n // Cuando queda 1 minuto o menos: ejecutar logout automático\r\n if (minutesLeft <= 1) {\r\n this.stopExpirationCheck();\r\n\r\n // Ejecutar callback para logout en servidor\r\n if (this.onSessionExpired) {\r\n await this.onSessionExpired();\r\n };\r\n };\r\n }, 60000); // Cada 1 minuto\r\n }\r\n\r\n /**\r\n * Detiene el monitoreo de expiración\r\n */\r\n private stopExpirationCheck(): void {\r\n if (this.sessionCheckInterval) {\r\n clearInterval(this.sessionCheckInterval);\r\n this.sessionCheckInterval = null;\r\n };\r\n }\r\n};\r\n","import { AuthInterceptorConfig } from \"./types/AuthInterceptorConfig\";\r\nimport { InterceptorContext } from \"@/core/interceptors/types/InterceptorContext\";\r\nimport { RequestConfig } from \"@/types/RequestConfig\";\r\nimport { RequestInterceptor } from \"./types/RequestInterceptor\";\r\n\r\nexport class AuthInterceptor implements RequestInterceptor {\r\n readonly name = \"AuthInterceptor\";\r\n\r\n private config: Required<AuthInterceptorConfig>;\r\n private refreshPromise: Promise<void> | null = null;\r\n private isRefreshing = false;\r\n\r\n constructor(config: AuthInterceptorConfig) {\r\n this.config = {\r\n enabled: config.enabled ?? true,\r\n thresholdMinutes: config.thresholdMinutes ?? 5,\r\n isTokenExpiringSoon: config.isTokenExpiringSoon,\r\n hasValidTokens: config.hasValidTokens,\r\n shouldAutoRefresh: config.shouldAutoRefresh,\r\n refreshSession: config.refreshSession\r\n };\r\n };\r\n\r\n async onRequest(\r\n config: RequestConfig,\r\n context: InterceptorContext\r\n ): Promise<RequestConfig> {\r\n\r\n //Actua en solicitudes que requieren autenticación\r\n if (!config.requiresAuth || !this.config.enabled) {\r\n return config;\r\n };\r\n\r\n //Actúa SOLO si los tokens son válidos\r\n if (!this.config.hasValidTokens()) {\r\n return config;\r\n };\r\n\r\n if (!this.config.shouldAutoRefresh()) {\r\n return config;\r\n };\r\n\r\n if (this.config.isTokenExpiringSoon()) {\r\n try {\r\n //Evita múltiples llamadas de actualización simultáneas\r\n if (this.isRefreshing && this.refreshPromise) {\r\n await this.refreshPromise;\r\n } else {\r\n this.isRefreshing = true;\r\n this.refreshPromise = this.config.refreshSession();\r\n await this.refreshPromise;\r\n this.isRefreshing = false;\r\n this.refreshPromise = null;\r\n };\r\n } catch (error) {\r\n this.isRefreshing = false;\r\n this.refreshPromise = null;\r\n };\r\n };\r\n\r\n return config;\r\n };\r\n\r\n updateConfig(config: Partial<AuthInterceptorConfig>): void {\r\n this.config = {\r\n ...this.config,\r\n ...config\r\n } as Required<AuthInterceptorConfig>;\r\n };\r\n\r\n reset(): void {\r\n this.isRefreshing = false;\r\n this.refreshPromise = null;\r\n };\r\n};\r\n","import { API } from \"@/core/API\";\r\nimport { CryptoService } from \"@/core/CryptoService\";\r\nimport { TokenManager } from \"@/core/TokenManager\";\r\nimport { LoginRequest } from \"@/interfaces/Auth/Login/LoginRequest\";\r\nimport { LoginResponse } from \"@/interfaces/Auth/Login/LoginResponse\";\r\nimport { RefreshTokenResponse } from \"@/interfaces/Auth/RefreshTokens/RefreshTokenResponse\";\r\nimport { ValidateSessionRenewedResponse, ValidateSessionResponse } from \"@/interfaces/Auth/ValidateSession/ValidateSessionResponse\";\r\nimport { ErrorResponse } from \"@/types/ErrorResponse\";\r\nimport { ResponseModel } from \"@/types/ResponseModel\";\r\nimport { ServiceProperties } from \"@/types/ServiceProperties\";\r\nimport { TokenData } from \"@/types/TokenData\";\r\n\r\nexport class AuthService {\r\n private api: API;\r\n private crytpoService: CryptoService;\r\n private tokenManager: TokenManager;\r\n private serviceProperties: ServiceProperties;\r\n\r\n constructor(\r\n serviceProperties: ServiceProperties,\r\n tokenManager: TokenManager,\r\n cryptoService: CryptoService,\r\n api: API\r\n ) {\r\n this.api = api;\r\n this.crytpoService = cryptoService;\r\n this.tokenManager = tokenManager;\r\n this.serviceProperties = serviceProperties;\r\n };\r\n\r\n /**\r\n * Login con las credenciales proporcionadas\r\n * @param credentials - Objeto con email, password y rememberMe\r\n * @returns Retorna el cuerpo de respuesta del login.\r\n */\r\n async login(credentials: LoginRequest): Promise<ResponseModel<LoginResponse>> {\r\n const timestamp = Date.now().toString();\r\n\r\n const encryptedEmail = this.crytpoService.encrypt(\r\n credentials.email,\r\n `${this.serviceProperties.originRequest}_${this.serviceProperties.domain}`,\r\n timestamp\r\n );\r\n\r\n const encryptedPassword = this.crytpoService.encrypt(\r\n credentials.password,\r\n `${this.serviceProperties.originRequest}_${this.serviceProperties.domain}`,\r\n timestamp\r\n );\r\n\r\n const loginData: LoginRequest = {\r\n email: encryptedEmail,\r\n password: encryptedPassword,\r\n rememberMe: credentials.rememberMe\r\n };\r\n\r\n const response = await this.api.executePublicRequest<ResponseModel>(\r\n 'oauth/login',\r\n 'POST',\r\n loginData,\r\n timestamp\r\n );\r\n\r\n if (!response) {\r\n throw new ErrorResponse('No response from server');\r\n };\r\n\r\n if (response.success) {\r\n const data: LoginResponse = response.data;\r\n\r\n const expiresIn = parseInt(data.expiresIn.replace('s', ''));\r\n const expiresAt = new Date(Date.now() + expiresIn * 1000);\r\n\r\n const tokens: TokenData = {\r\n accessToken: data.accessToken,\r\n refreshToken: data.refreshToken,\r\n expiresAt: expiresAt,\r\n rememberMe: credentials.rememberMe\r\n };\r\n\r\n await this.tokenManager.setTokens(tokens);\r\n\r\n this.serviceProperties.onTokensUpdated?.(tokens);\r\n\r\n const responseData: ResponseModel<LoginResponse> = {\r\n success: data.accessToken ? true : false,\r\n data: data,\r\n message: response.message,\r\n responseTime: '3s'\r\n };\r\n\r\n return responseData;\r\n }\r\n\r\n return response;\r\n };\r\n\r\n\r\n /**\r\n * Valida la sesión actual y retorna información de expiración\r\n *\r\n * El servidor puede responder de 2 formas:\r\n * 1. Sesión renovada (sliding window): retorna nuevos tokens\r\n * 2. Sesión válida: retorna info de expiración sin renovar\r\n */\r\n async validateSession(): Promise<ResponseModel<ValidateSessionRenewedResponse | ValidateSessionResponse>> {\r\n const response = await this.api.executePOST<ResponseModel<ValidateSessionRenewedResponse | ValidateSessionResponse>>(\r\n 'oauth/validateSession'\r\n );\r\n\r\n if (!response) {\r\n throw new ErrorResponse('No response from server');\r\n };\r\n\r\n if (response.success && response.data) {\r\n const respData = response.data;\r\n\r\n if ('expiresIn' in respData && respData.expiresIn) {\r\n const sessionData = respData as ValidateSessionRenewedResponse;\r\n const expiresIn = parseInt(sessionData.expiresIn.replace('s', ''));\r\n const expiresAt = new Date(Date.now() + expiresIn * 1000);\r\n\r\n const currentTokens = this.tokenManager.getTokens();\r\n const rememberMe = currentTokens?.rememberMe ?? sessionData.isRemembered;\r\n\r\n const tokens: TokenData = {\r\n accessToken: sessionData.accessToken,\r\n refreshToken: sessionData.refreshToken,\r\n expiresAt: expiresAt,\r\n rememberMe: rememberMe\r\n };\r\n\r\n this.tokenManager.setTokens(tokens);\r\n this.serviceProperties.onTokensUpdated?.(tokens);\r\n }\r\n else if ('expiresAt' in respData && respData.expiresAt) {\r\n const sessionData = respData as ValidateSessionResponse;\r\n\r\n if (sessionData.remainingMinutes <= 5 && sessionData.remainingMinutes > 1) {\r\n this.serviceProperties.onSessionExpiring?.(sessionData.remainingMinutes);\r\n } else if (sessionData.remainingMinutes <= 1) {\r\n if (this.serviceProperties.onSessionExpired) {\r\n await this.serviceProperties.onSessionExpired();\r\n }\r\n }\r\n }\r\n };\r\n\r\n return response;\r\n };\r\n\r\n /**\r\n * Refresca los tokens usando el refresh token\r\n */\r\n async refreshTokens(rememberMe?: boolean): Promise<ResponseModel<RefreshTokenResponse>> {\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n\r\n if (!refreshToken) {\r\n throw new ErrorResponse('No refresh token available');\r\n };\r\n\r\n const response = await this.api.executePublicRequest<ResponseModel<any>>(\r\n 'oauth/refresh',\r\n 'POST',\r\n { refreshToken }\r\n );\r\n\r\n if (!response) {\r\n throw new ErrorResponse('No response from server');\r\n };\r\n\r\n if (response.success) {\r\n const sessionData: RefreshTokenResponse = response.data;\r\n\r\n const currentTokens = this.tokenManager.getTokens();\r\n const shouldRemember = rememberMe ?? currentTokens?.rememberMe ?? false;\r\n const expiresIn = parseInt(sessionData.expiresIn.replace('s', ''));\r\n const expiresAt = new Date(Date.now() + expiresIn * 1000);\r\n\r\n const tokens: TokenData = {\r\n accessToken: sessionData.accessToken,\r\n refreshToken: sessionData.refreshToken,\r\n expiresAt: expiresAt,\r\n rememberMe: shouldRemember\r\n };\r\n\r\n this.tokenManager.setTokens(tokens);\r\n this.serviceProperties.onTokensUpdated?.(tokens);\r\n };\r\n\r\n return response;\r\n };\r\n\r\n /**\r\n * Cierra sesión: notifica al servidor y limpia tokens\r\n */\r\n async logout(): Promise<void> {\r\n try {\r\n await this.api.executePOST('oauth/logout');\r\n } catch (error) {\r\n // Continuar con logout local aunque falle el servidor\r\n };\r\n\r\n this.tokenManager.clearTokens();\r\n this.serviceProperties.onTokensUpdated?.(null);\r\n };\r\n\r\n /**\r\n * Verifica si el usuario está autenticado\r\n */\r\n isAuthenticated(): boolean {\r\n return this.tokenManager.hasValidTokens();\r\n };\r\n\r\n /**\r\n * Obtiene los tokens actuales\r\n */\r\n getTokens(): TokenData | null {\r\n return this.tokenManager.getTokens();\r\n };\r\n\r\n}\r\n","import { API } from \"./core/API\";\r\nimport { CryptoService } from \"./core/CryptoService\";\r\nimport { TokenManager } from \"./core/TokenManager\";\r\nimport { AuthInterceptor } from \"./core/interceptors/AuthInterceptor\";\r\nimport { ServiceProperties } from \"./types/ServiceProperties\";\r\nimport { TokenData } from \"./types/TokenData\";\r\nimport { AuthService } from \"./services/AuthService\";\r\n\r\n/**\r\n * SDK principal de FalconHUB\r\n */\r\nexport class FalconHUBSDK {\r\n public auth: AuthService;\r\n\r\n private serviceProperties: ServiceProperties;\r\n private cryptoService: CryptoService;\r\n private tokenManager: TokenManager;\r\n private authInterceptor: AuthInterceptor | null;\r\n private api: API;\r\n\r\n constructor(serviceProperties: ServiceProperties) {\r\n this.serviceProperties = serviceProperties;\r\n\r\n this.cryptoService = new CryptoService();\r\n\r\n this.tokenManager = new TokenManager(\r\n this.serviceProperties.onTokensUpdated,\r\n this.serviceProperties.onSessionExpiring,\r\n async () => {\r\n await this.auth.logout();\r\n }\r\n );\r\n\r\n const autoRefreshConfig = this.normalizeAutoRefreshConfig(this.serviceProperties.autoRefresh);\r\n\r\n if (autoRefreshConfig.enabled) {\r\n this.authInterceptor = new AuthInterceptor({\r\n enabled: true,\r\n thresholdMinutes: autoRefreshConfig.thresholdMinutes,\r\n isTokenExpiringSoon: () => this.tokenManager.isTokenExpiringSoon(autoRefreshConfig.thresholdMinutes),\r\n hasValidTokens: () => this.tokenManager.hasValidTokens(),\r\n shouldAutoRefresh: () => this.tokenManager.shouldAutoRefresh(),\r\n refreshSession: async () => {\r\n await this.auth.validateSession();\r\n }\r\n });\r\n } else {\r\n this.authInterceptor = null;\r\n }\r\n\r\n this.api = new API(\r\n this.serviceProperties,\r\n this.cryptoService,\r\n this.authInterceptor,\r\n () => this.tokenManager.getAccessToken(),\r\n () => this.tokenManager.getRefreshToken()\r\n );\r\n\r\n this.auth = new AuthService(\r\n this.serviceProperties,\r\n this.tokenManager,\r\n this.cryptoService,\r\n this.api\r\n );\r\n }\r\n\r\n private normalizeAutoRefreshConfig(\r\n config: ServiceProperties[\"autoRefresh\"]\r\n ): { enabled: boolean; thresholdMinutes: number } {\r\n if (typeof config === \"boolean\") {\r\n return { enabled: config, thresholdMinutes: 5 };\r\n }\r\n if (typeof config === \"object\" && config !== null) {\r\n return {\r\n enabled: config.enabled,\r\n thresholdMinutes: config.thresholdMinutes ?? 5\r\n };\r\n }\r\n return { enabled: true, thresholdMinutes: 5 };\r\n }\r\n\r\n /**\r\n * Inyecta tokens desde storage externo (cookies/localStorage/etc)\r\n */\r\n setTokensFromExternal(\r\n accessToken: string,\r\n refreshToken: string,\r\n expiresAt: Date,\r\n rememberMe: boolean = false\r\n ): void {\r\n const tokens: TokenData = {\r\n accessToken,\r\n refreshToken,\r\n expiresAt,\r\n rememberMe\r\n };\r\n\r\n this.tokenManager.setTokens(tokens);\r\n }\r\n\r\n /**\r\n * Obtiene los tokens actuales\r\n */\r\n getTokens(): TokenData | null {\r\n return this.tokenManager.getTokens();\r\n }\r\n\r\n /**\r\n * Verifica si el usuario está autenticado\r\n */\r\n isAuthenticated(): boolean {\r\n return this.tokenManager.hasValidTokens();\r\n }\r\n\r\n /**\r\n * Verifica si la sesión está por expirar\r\n */\r\n isSessionExpiringSoon(thresholdMinutes: number = 5): boolean {\r\n return this.tokenManager.isTokenExpiringSoon(thresholdMinutes);\r\n }\r\n\r\n /**\r\n * Obtiene el tiempo restante hasta la expiración en milisegundos\r\n */\r\n getTimeUntilExpiry(): number | null {\r\n return this.tokenManager.getTimeUntilExpiry();\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/types/ErrorResponse.ts","../src/core/API.ts","../src/core/CryptoService.ts","../src/core/TokenManager.ts","../src/core/interceptors/AuthInterceptor.ts","../src/services/AuthService.ts","../src/FalconHUBSDK.ts"],"sourcesContent":["/**\n * FalconHUB API Library\n *\n * SDK cliente para consumir el API de FalconHUB\n *\n * @packageDocumentation\n */\n\nexport { FalconHUBSDK } from './FalconHUBSDK';\n\nexport { AuthService } from './services/AuthService';\n\nexport type { ServiceProperties } from './types/ServiceProperties';\nexport type { TokenData } from './types/TokenData';\nexport type { ErrorResponse } from './types/ErrorResponse';\nexport type { ResponseModel } from './types/ResponseModel';\nexport type { RequestOptions, MethodTypes } from './types/RequestOptions';\nexport type { RequestConfig } from './types/RequestConfig';\n\nexport { API } from './core/API';\nexport { TokenManager } from './core/TokenManager';\nexport { CryptoService } from './core/CryptoService';\n\nexport { AuthInterceptor } from './core/interceptors/AuthInterceptor';\nexport type { AuthInterceptorConfig } from './core/interceptors/types/AuthInterceptorConfig';\nexport type { InterceptorContext } from './core/interceptors/types/InterceptorContext';\nexport type { RequestInterceptor } from './core/interceptors/types/RequestInterceptor';\n\nexport type { LoginRequest } from './interfaces/Auth/Login/LoginRequest';\nexport type { LoginResponse } from './interfaces/Auth/Login/LoginResponse';\nexport type { RefreshTokenRequest } from './interfaces/Auth/RefreshTokens/RefreshTokenRequest';\nexport type { RefreshTokenResponse } from './interfaces/Auth/RefreshTokens/RefreshTokenResponse';\nexport type { ValidateSessionResponse, ValidateSessionRenewedResponse } from './interfaces/Auth/ValidateSession/ValidateSessionResponse';\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 { 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\";\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 parseada del tipo esperado\n */\n private async apiExecute<T>(options: RequestOptions): Promise<T | undefined> {\n const {\n endpoint,\n method,\n body,\n requiresSignature,\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-Timestamp'] = newTimeStamp;\n\n let bodyString: string | undefined;\n\n if (body && method !== 'GET') {\n bodyString = JSON.stringify(body);\n };\n\n if (requiresSignature && bodyString) {\n try {\n const refreshToken = this.getRefreshToken();\n\n if (refreshToken) {\n const signature = this.cryptoService.genSignature(\n bodyString,\n newTimeStamp,\n refreshToken\n );\n\n if (signature) {\n headers['X-Signature'] = signature;\n };\n };\n } catch (error) {\n throw new ErrorResponse(\n \"Failed to generate request signature.\",\n 401\n );\n };\n };\n\n const requestConfig: RequestConfig = {\n url,\n method,\n headers,\n body: bodyString,\n requiresAuth,\n requiresSignature\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 if (response.ok) {\n // Detectar sliding window: nuevos tokens en headers\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\n return JSON.parse(responseText) as T;\n };\n\n return undefined;\n } else {\n await this.handleErrorResponse(response);\n };\n } catch (error) {\n if (error instanceof ErrorResponse) {\n throw error;\n };\n\n throw new ErrorResponse(\n 'Unexpected error occurred during API request.',\n 500\n );\n };\n };\n\n /**\n * Maneja errores HTTP y lanza excepciones apropiadas\n */\n private async handleErrorResponse(\n response: Response\n ): Promise<never> {\n\n const statusCode = response.status;\n let errorMessage = `Error ${statusCode}`;\n let responseData: any = null;\n\n try {\n const contentType = response.headers.get('Content-Type');\n if (contentType && contentType.includes('application/json')) {\n responseData = await response.json();\n errorMessage = responseData.message || responseData.error || errorMessage;\n } else {\n errorMessage = await response.text();\n };\n } catch (error) {\n\n };\n\n switch (statusCode) {\n case 401:\n const authError = new ErrorResponse(\n 'Unauthorized access.',\n 401,\n responseData\n );\n\n this.properties.onAuthError?.(authError);\n throw authError;\n case 403:\n throw new ErrorResponse(\n 'No tienes permisos para realizar esta acción.',\n 403,\n responseData\n );\n\n case 404:\n throw new ErrorResponse(\n 'Recurso no encontrado.',\n 404,\n responseData\n );\n\n case 422:\n throw new ErrorResponse(\n errorMessage || 'Datos de entrada inválidos.',\n 422,\n responseData\n );\n\n case 500:\n throw new ErrorResponse(\n 'Error interno del servidor.',\n 500,\n responseData\n );\n\n default:\n throw new ErrorResponse(\n errorMessage,\n statusCode,\n responseData\n );\n };\n };\n\n //#region REQUEST METHODS\n\n async executeGET<T>(\n endpoint: string,\n requiresAuth: boolean = false\n ): Promise<T | undefined> {\n return this.apiExecute<T>({\n endpoint,\n method: 'GET',\n requiresAuth: requiresAuth,\n requiresSignature: false\n });\n };\n\n async executePOST<T>(\n endpoint: string,\n body?: any,\n requiresAuth: boolean = true,\n requiresSignature: boolean = true\n ): Promise<T | undefined> {\n return this.apiExecute<T>({\n endpoint,\n method: 'POST',\n body,\n requiresAuth: requiresAuth,\n requiresSignature: requiresSignature\n });\n };\n\n async executePATCH<T>(\n endpoint: string,\n body?: any,\n requiresAuth: boolean = true,\n requiresSignature: boolean = true\n ): Promise<T | undefined> {\n return this.apiExecute<T>({\n endpoint,\n method: 'PATCH',\n body,\n requiresAuth: requiresAuth,\n requiresSignature: requiresSignature\n });\n };\n\n async executeDELETE<T>(\n endpoint: string,\n body?: any,\n requiresAuth: boolean = true,\n requiresSignature: boolean = false\n ): Promise<T | undefined> {\n return this.apiExecute<T>({\n endpoint,\n method: 'DELETE',\n body,\n requiresAuth: requiresAuth,\n requiresSignature: requiresSignature\n });\n };\n\n async executePUT<T>(\n endpoint: string,\n body?: any,\n requiresAuth: boolean = true,\n requiresSignature: boolean = true\n ): Promise<T | undefined> {\n return this.apiExecute<T>({\n endpoint,\n method: 'PUT',\n body,\n requiresAuth: requiresAuth,\n requiresSignature: requiresSignature\n });\n };\n\n async executePublicRequest<T>(\n endpoint: string,\n method: MethodTypes,\n body?: any,\n timestamp?: string\n ): Promise<T | undefined> {\n return this.apiExecute<T>({\n endpoint,\n method,\n body,\n requiresAuth: false,\n requiresSignature: false,\n timeStamp: timestamp\n });\n };\n\n //#endregion\n}\n","import * as CryptoJS from 'crypto-js';\n\nexport class CryptoService {\n\n /**\n * Encripta el texto plano utilizando AES con una clave derivada del secretWord y el timestamp\n *\n * @param plaintText -- Texto plano a encriptar\n * @param secretWord - Palabra secreta utilizada para derivar la clave\n * @param timestamp - Timestamp actual\n * @returns Texto encriptado en formato Base64\n */\n encrypt(plaintText: string, secretWord: string, timestamp: string): string {\n const fullKey = `${secretWord}:${timestamp}`;\n const key = CryptoJS.SHA256(fullKey);\n\n const iv = CryptoJS.lib.WordArray.random(16);\n const encrypted = CryptoJS.AES.encrypt(plaintText, key, {\n iv: iv,\n mode: CryptoJS.mode.CBC,\n padding: CryptoJS.pad.Pkcs7\n });\n\n const ivAndCipher = iv.concat(encrypted.ciphertext);\n return CryptoJS.enc.Base64.stringify(ivAndCipher);\n };\n\n /**\n * Genera la firma Signature para las operaciones de tipo POST\n *\n * @param body - Cuerpo de la solicitud\n * @param timestamp - Timestamp actual\n * @param refreshToken - Refresh token del usuario\n * @returns Firma signature en formato Base64\n */\n genSignature(body: string, timestamp: string, refreshToken: string): string {\n const message = `${body}:${timestamp}`;\n const hmac = CryptoJS.HmacSHA256(message, refreshToken);\n\n return CryptoJS.enc.Base64.stringify(hmac);\n };\n\n /**\n * Desencripta texto usando AES-256-CBC\n *\n * @param encryptedBase64 - Texto encriptado en base64\n * @param secret - Clave secreta\n * @param timestamp - Timestamp usado en la encriptación\n * @returns Texto desencriptado\n */\n decrypt(encryptedText: string, secretWord: string, timestamp: string): string {\n try {\n const fullKey = `${secretWord}:${timestamp}`;\n const key = CryptoJS.SHA256(fullKey);\n\n const ivAndCipher = CryptoJS.enc.Base64.parse(encryptedText);\n const iv = CryptoJS.lib.WordArray.create(ivAndCipher.words.slice(0, 4));\n\n const ciphertext = CryptoJS.lib.WordArray.create(\n ivAndCipher.words.slice(4),\n ivAndCipher.sigBytes - 16\n );\n\n const decrypted = CryptoJS.AES.decrypt(\n { ciphertext } as any,\n key,\n {\n iv: iv,\n mode: CryptoJS.mode.CBC,\n padding: CryptoJS.pad.Pkcs7\n }\n );\n\n return CryptoJS.enc.Utf8.stringify(decrypted);\n } catch (error) {\n throw new Error('Decryption failed, ex:' + error);\n }\n };\n\n /**\n * Verifica una firma HMAC-SHA256 (útil para testing o validación)\n *\n * @param body - Cuerpo original\n * @param timestamp - Timestamp original\n * @param refreshToken - Token usado como clave\n * @param signature - Firma a verificar\n * @returns true si la firma es válida\n */\n verifySignature(body: string, timestamp: string, refreshToken: string, signature: string): boolean {\n try {\n const expectedSignature = this.genSignature(body, timestamp, refreshToken);\n return expectedSignature === signature;\n } catch {\n return false;\n }\n };\n\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}\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 onSessionExpiring?: (remainingMinutes: number) => void;\n private onSessionExpired?: () => Promise<void>;\n private hasNotifiedExpiring: boolean = false;\n\n constructor(\n onTokensChanged?: (tokens: TokenData | null) => void,\n onSessionExpiring?: (remainingMinutes: number) => void,\n onSessionExpired?: () => Promise<void>\n ) {\n this.onTokensChanged = onTokensChanged;\n this.onSessionExpiring = onSessionExpiring;\n this.onSessionExpired = onSessionExpired;\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; // Resetear flag\n\n this.onTokensChanged?.(this.tokens);\n\n // Si NO tiene rememberMe, iniciar monitoreo de expiración\n if (!tokens.rememberMe) {\n this.startExpirationCheck();\n } else {\n this.stopExpirationCheck();\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.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 const now = Date.now();\n const expiresAt = this.tokens.expiresAt.getTime();\n\n return now < 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 now = Date.now();\n const expiresAt = this.tokens.expiresAt.getTime();\n const thresholdMs = thresholdMinutes * 60 * 1000;\n\n const timeLeft = expiresAt - now;\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 const now = Date.now();\n const expiresAt = this.tokens.expiresAt.getTime();\n const timeLeft = Math.max(0, expiresAt - now);\n\n return timeLeft;\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 * - Ejecuta logout cuando queda 1 minuto (onSessionExpired)\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 // Notificar cuando quedan 5 minutos (solo una vez)\n if (minutesLeft <= 5 && minutesLeft > 1 && !this.hasNotifiedExpiring) {\n this.hasNotifiedExpiring = true;\n this.onSessionExpiring?.(minutesLeft);\n };\n\n // Cuando queda 1 minuto o menos: ejecutar logout automático\n if (minutesLeft <= 1) {\n this.stopExpirationCheck();\n\n // Ejecutar callback para logout en servidor\n if (this.onSessionExpired) {\n await this.onSessionExpired();\n };\n };\n }, 60000); // Cada 1 minuto\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","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","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 { RefreshTokenResponse } from \"@/interfaces/Auth/RefreshTokens/RefreshTokenResponse\";\nimport { ValidateSessionRenewedResponse, ValidateSessionResponse } from \"@/interfaces/Auth/ValidateSession/ValidateSessionResponse\";\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 encryptedEmail = this.crytpoService.encrypt(\n credentials.email,\n `${this.serviceProperties.originRequest}_${this.serviceProperties.domain}`,\n timestamp\n );\n\n const encryptedPassword = this.crytpoService.encrypt(\n credentials.password,\n `${this.serviceProperties.originRequest}_${this.serviceProperties.domain}`,\n timestamp\n );\n\n const loginData: LoginRequest = {\n email: encryptedEmail,\n password: encryptedPassword,\n rememberMe: credentials.rememberMe\n };\n\n const response = await this.api.executePublicRequest<ResponseModel>(\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) {\n const data: LoginResponse = response.data;\n\n const expiresIn = parseInt(data.expiresIn.replace('s', ''));\n const expiresAt = new Date(Date.now() + expiresIn * 1000);\n\n const tokens: TokenData = {\n accessToken: data.accessToken,\n refreshToken: data.refreshToken,\n expiresAt: expiresAt,\n rememberMe: credentials.rememberMe\n };\n\n await this.tokenManager.setTokens(tokens);\n\n this.serviceProperties.onTokensUpdated?.(tokens);\n\n const responseData: ResponseModel<LoginResponse> = {\n success: data.accessToken ? true : false,\n data: data,\n message: response.message,\n responseTime: '3s'\n };\n\n return responseData;\n }\n\n return response;\n };\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<ResponseModel<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 = new Date(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: expiresAt,\n rememberMe: 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(rememberMe?: boolean): Promise<ResponseModel<RefreshTokenResponse>> {\n const refreshToken = this.tokenManager.getRefreshToken();\n\n if (!refreshToken) {\n throw new ErrorResponse('No refresh token available');\n };\n\n const response = await this.api.executePublicRequest<ResponseModel<any>>(\n 'oauth/refresh',\n 'POST',\n { refreshToken }\n );\n\n if (!response) {\n throw new ErrorResponse('No response from server');\n };\n\n if (response.success) {\n const sessionData: RefreshTokenResponse = response.data;\n\n const currentTokens = this.tokenManager.getTokens();\n const shouldRemember = rememberMe ?? currentTokens?.rememberMe ?? false;\n const expiresIn = parseInt(sessionData.expiresIn.replace('s', ''));\n const expiresAt = new Date(Date.now() + expiresIn * 1000);\n\n const tokens: TokenData = {\n accessToken: sessionData.accessToken,\n refreshToken: sessionData.refreshToken,\n expiresAt: 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<void> {\n try {\n await this.api.executePOST('oauth/logout');\n } catch (error) {\n // Continuar con logout local aunque falle el servidor\n };\n\n this.tokenManager.clearTokens();\n this.serviceProperties.onTokensUpdated?.(null);\n };\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","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\";\n\n/**\n * SDK principal de FalconHUB\n */\nexport class FalconHUBSDK {\n public auth: AuthService;\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 this.tokenManager = new TokenManager(\n this.serviceProperties.onTokensUpdated,\n this.serviceProperties.onSessionExpiring,\n async () => {\n await this.auth.logout();\n }\n );\n\n const autoRefreshConfig = this.normalizeAutoRefreshConfig(this.serviceProperties.autoRefresh);\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\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 */\n setTokensFromExternal(\n accessToken: string,\n refreshToken: string,\n expiresAt: Date,\n rememberMe: boolean = false\n ): void {\n const tokens: TokenData = {\n accessToken,\n refreshToken,\n expiresAt,\n rememberMe\n };\n\n this.tokenManager.setTokens(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"],"mappings":"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","names":[]}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types/ErrorResponse.ts","../src/core/API.ts","../src/core/CryptoService.ts","../src/core/TokenManager.ts","../src/core/interceptors/AuthInterceptor.ts","../src/services/AuthService.ts","../src/FalconHUBSDK.ts"],"sourcesContent":["export class ErrorResponse extends Error {\r\n constructor(\r\n message: string,\r\n public statusCode?: number,\r\n public responseData?: any\r\n ){\r\n super(message);\r\n this.name = \"FalconHUB API Error\";\r\n };\r\n};\r\n","import { ServiceProperties } from \"@/types/ServiceProperties\";\r\nimport { CryptoService } from \"./CryptoService\";\r\nimport { MethodTypes, RequestOptions } from \"@/types/RequestOptions\";\r\nimport { ErrorResponse } from \"@/types/ErrorResponse\";\r\nimport { RequestConfig } from \"@/types/RequestConfig\";\r\nimport { AuthInterceptor } from \"./interceptors/AuthInterceptor\";\r\nimport { InterceptorContext } from \"@/core/interceptors/types/InterceptorContext\";\r\n\r\n\r\n/**\r\n * Clase base para la ejecución de request HTTP al API\r\n */\r\nexport class API {\r\n private properties: ServiceProperties;\r\n private cryptoService: CryptoService;\r\n private authInterceptor: AuthInterceptor | null;\r\n\r\n private getAccessToken: () => string | null;\r\n private getRefreshToken: () => string | null;\r\n\r\n constructor(\r\n properties: ServiceProperties,\r\n cryptoService: CryptoService,\r\n authInterceptor: AuthInterceptor | null,\r\n getAccessToken: () => string | null,\r\n getRefreshToken: () => string | null\r\n ) {\r\n this.properties = properties;\r\n this.cryptoService = cryptoService;\r\n this.getAccessToken = getAccessToken;\r\n this.getRefreshToken = getRefreshToken;\r\n this.authInterceptor = authInterceptor;\r\n };\r\n\r\n /**\r\n * Ejecuta una request HTTP al API\r\n *\r\n * @param options - Opciones de la request\r\n * @returns Respuesta parseada del tipo esperado\r\n */\r\n private async apiExecute<T>(options: RequestOptions): Promise<T | undefined> {\r\n const {\r\n endpoint,\r\n method,\r\n body,\r\n requiresSignature,\r\n requiresAuth,\r\n timeStamp\r\n } = options;\r\n\r\n const context: InterceptorContext = {\r\n requestId: this.cryptoService.generateUniqueId(),\r\n startTime: Date.now(),\r\n retryCount: 0,\r\n metadata: {}\r\n };\r\n\r\n try {\r\n const url = `${this.properties.url}/${endpoint}`;\r\n\r\n const headers: Record<string, string> = {};\r\n\r\n if (body && method !== 'GET') {\r\n headers['Content-Type'] = 'application/json';\r\n };\r\n\r\n const accessToken = this.getAccessToken();\r\n\r\n if (accessToken) {\r\n headers['Authorization'] = `Bearer ${accessToken}`;\r\n };\r\n\r\n const newTimeStamp = timeStamp || new Date().toString();\r\n\r\n headers['X-Timestamp'] = newTimeStamp;\r\n\r\n let bodyString: string | undefined;\r\n\r\n if (body && method !== 'GET') {\r\n bodyString = JSON.stringify(body);\r\n };\r\n\r\n if (requiresSignature && bodyString) {\r\n try {\r\n const refreshToken = this.getRefreshToken();\r\n\r\n if (refreshToken) {\r\n const signature = this.cryptoService.genSignature(\r\n bodyString,\r\n newTimeStamp,\r\n refreshToken\r\n );\r\n\r\n if (signature) {\r\n headers['X-Signature'] = signature;\r\n };\r\n };\r\n } catch (error) {\r\n throw new ErrorResponse(\r\n \"Failed to generate request signature.\",\r\n 401\r\n );\r\n };\r\n };\r\n\r\n const requestConfig: RequestConfig = {\r\n url,\r\n method,\r\n headers,\r\n body: bodyString,\r\n requiresAuth,\r\n requiresSignature\r\n };\r\n\r\n const modifiedConfig = this.authInterceptor\r\n ? await this.authInterceptor.onRequest(requestConfig, context)\r\n : requestConfig;\r\n\r\n const requestInit: RequestInit = {\r\n method: modifiedConfig.method,\r\n headers: modifiedConfig.headers,\r\n mode: 'cors',\r\n credentials: 'omit'\r\n };\r\n\r\n if (bodyString) {\r\n requestInit.body = bodyString;\r\n };\r\n\r\n const response = await fetch(\r\n modifiedConfig.url,\r\n requestInit\r\n );\r\n\r\n if (response.ok) {\r\n // Detectar sliding window: nuevos tokens en headers\r\n const newAccessToken = response.headers.get('X-New-Access-Token');\r\n const newRefreshToken = response.headers.get('X-New-Refresh-Token');\r\n\r\n if (newAccessToken || newRefreshToken) {\r\n this.properties.onTokensRefreshed?.({\r\n accessToken: newAccessToken,\r\n refreshToken: newRefreshToken\r\n });\r\n };\r\n\r\n const contentType = response.headers.get('Content-Type');\r\n\r\n if (contentType && contentType.includes('application/json')) {\r\n const responseText = await response.text();\r\n\r\n return JSON.parse(responseText) as T;\r\n };\r\n\r\n return undefined;\r\n } else {\r\n await this.handleErrorResponse(response);\r\n };\r\n } catch (error) {\r\n if (error instanceof ErrorResponse) {\r\n throw error;\r\n };\r\n\r\n throw new ErrorResponse(\r\n 'Unexpected error occurred during API request.',\r\n 500\r\n );\r\n };\r\n };\r\n\r\n /**\r\n * Maneja errores HTTP y lanza excepciones apropiadas\r\n */\r\n private async handleErrorResponse(\r\n response: Response\r\n ): Promise<never> {\r\n\r\n const statusCode = response.status;\r\n let errorMessage = `Error ${statusCode}`;\r\n let responseData: any = null;\r\n\r\n try {\r\n const contentType = response.headers.get('Content-Type');\r\n if (contentType && contentType.includes('application/json')) {\r\n responseData = await response.json();\r\n errorMessage = responseData.message || responseData.error || errorMessage;\r\n } else {\r\n errorMessage = await response.text();\r\n };\r\n } catch (error) {\r\n\r\n };\r\n\r\n switch (statusCode) {\r\n case 401:\r\n const authError = new ErrorResponse(\r\n 'Unauthorized access.',\r\n 401,\r\n responseData\r\n );\r\n\r\n this.properties.onAuthError?.(authError);\r\n throw authError;\r\n case 403:\r\n throw new ErrorResponse(\r\n 'No tienes permisos para realizar esta acción.',\r\n 403,\r\n responseData\r\n );\r\n\r\n case 404:\r\n throw new ErrorResponse(\r\n 'Recurso no encontrado.',\r\n 404,\r\n responseData\r\n );\r\n\r\n case 422:\r\n throw new ErrorResponse(\r\n errorMessage || 'Datos de entrada inválidos.',\r\n 422,\r\n responseData\r\n );\r\n\r\n case 500:\r\n throw new ErrorResponse(\r\n 'Error interno del servidor.',\r\n 500,\r\n responseData\r\n );\r\n\r\n default:\r\n throw new ErrorResponse(\r\n errorMessage,\r\n statusCode,\r\n responseData\r\n );\r\n };\r\n };\r\n\r\n //#region REQUEST METHODS\r\n\r\n async executeGET<T>(\r\n endpoint: string,\r\n requiresAuth: boolean = false\r\n ): Promise<T | undefined> {\r\n return this.apiExecute<T>({\r\n endpoint,\r\n method: 'GET',\r\n requiresAuth: requiresAuth,\r\n requiresSignature: false\r\n });\r\n };\r\n\r\n async executePOST<T>(\r\n endpoint: string,\r\n body?: any,\r\n requiresAuth: boolean = true,\r\n requiresSignature: boolean = true\r\n ): Promise<T | undefined> {\r\n return this.apiExecute<T>({\r\n endpoint,\r\n method: 'POST',\r\n body,\r\n requiresAuth: requiresAuth,\r\n requiresSignature: requiresSignature\r\n });\r\n };\r\n\r\n async executePATCH<T>(\r\n endpoint: string,\r\n body?: any,\r\n requiresAuth: boolean = true,\r\n requiresSignature: boolean = true\r\n ): Promise<T | undefined> {\r\n return this.apiExecute<T>({\r\n endpoint,\r\n method: 'PATCH',\r\n body,\r\n requiresAuth: requiresAuth,\r\n requiresSignature: requiresSignature\r\n });\r\n };\r\n\r\n async executeDELETE<T>(\r\n endpoint: string,\r\n body?: any,\r\n requiresAuth: boolean = true,\r\n requiresSignature: boolean = false\r\n ): Promise<T | undefined> {\r\n return this.apiExecute<T>({\r\n endpoint,\r\n method: 'DELETE',\r\n body,\r\n requiresAuth: requiresAuth,\r\n requiresSignature: requiresSignature\r\n });\r\n };\r\n\r\n async executePUT<T>(\r\n endpoint: string,\r\n body?: any,\r\n requiresAuth: boolean = true,\r\n requiresSignature: boolean = true\r\n ): Promise<T | undefined> {\r\n return this.apiExecute<T>({\r\n endpoint,\r\n method: 'PUT',\r\n body,\r\n requiresAuth: requiresAuth,\r\n requiresSignature: requiresSignature\r\n });\r\n };\r\n\r\n async executePublicRequest<T>(\r\n endpoint: string,\r\n method: MethodTypes,\r\n body?: any,\r\n timestamp?: string\r\n ): Promise<T | undefined> {\r\n return this.apiExecute<T>({\r\n endpoint,\r\n method,\r\n body,\r\n requiresAuth: false,\r\n requiresSignature: false,\r\n timeStamp: timestamp\r\n });\r\n };\r\n\r\n //#endregion\r\n}\r\n","import * as CryptoJS from 'crypto-js';\r\n\r\nexport class CryptoService {\r\n\r\n /**\r\n * Encripta el texto plano utilizando AES con una clave derivada del secretWord y el timestamp\r\n *\r\n * @param plaintText -- Texto plano a encriptar\r\n * @param secretWord - Palabra secreta utilizada para derivar la clave\r\n * @param timestamp - Timestamp actual\r\n * @returns Texto encriptado en formato Base64\r\n */\r\n encrypt(plaintText: string, secretWord: string, timestamp: string): string {\r\n const fullKey = `${secretWord}:${timestamp}`;\r\n const key = CryptoJS.SHA256(fullKey);\r\n\r\n const iv = CryptoJS.lib.WordArray.random(16);\r\n const encrypted = CryptoJS.AES.encrypt(plaintText, key, {\r\n iv: iv,\r\n mode: CryptoJS.mode.CBC,\r\n padding: CryptoJS.pad.Pkcs7\r\n });\r\n\r\n const ivAndCipher = iv.concat(encrypted.ciphertext);\r\n return CryptoJS.enc.Base64.stringify(ivAndCipher);\r\n };\r\n\r\n /**\r\n * Genera la firma Signature para las operaciones de tipo POST\r\n *\r\n * @param body - Cuerpo de la solicitud\r\n * @param timestamp - Timestamp actual\r\n * @param refreshToken - Refresh token del usuario\r\n * @returns Firma signature en formato Base64\r\n */\r\n genSignature(body: string, timestamp: string, refreshToken: string): string {\r\n const message = `${body}:${timestamp}`;\r\n const hmac = CryptoJS.HmacSHA256(message, refreshToken);\r\n\r\n return CryptoJS.enc.Base64.stringify(hmac);\r\n };\r\n\r\n /**\r\n * Desencripta texto usando AES-256-CBC\r\n *\r\n * @param encryptedBase64 - Texto encriptado en base64\r\n * @param secret - Clave secreta\r\n * @param timestamp - Timestamp usado en la encriptación\r\n * @returns Texto desencriptado\r\n */\r\n decrypt(encryptedText: string, secretWord: string, timestamp: string): string {\r\n try {\r\n const fullKey = `${secretWord}:${timestamp}`;\r\n const key = CryptoJS.SHA256(fullKey);\r\n\r\n const ivAndCipher = CryptoJS.enc.Base64.parse(encryptedText);\r\n const iv = CryptoJS.lib.WordArray.create(ivAndCipher.words.slice(0, 4));\r\n\r\n const ciphertext = CryptoJS.lib.WordArray.create(\r\n ivAndCipher.words.slice(4),\r\n ivAndCipher.sigBytes - 16\r\n );\r\n\r\n const decrypted = CryptoJS.AES.decrypt(\r\n { ciphertext } as any,\r\n key,\r\n {\r\n iv: iv,\r\n mode: CryptoJS.mode.CBC,\r\n padding: CryptoJS.pad.Pkcs7\r\n }\r\n );\r\n\r\n return CryptoJS.enc.Utf8.stringify(decrypted);\r\n } catch (error) {\r\n throw new Error('Decryption failed, ex:' + error);\r\n }\r\n };\r\n\r\n /**\r\n * Verifica una firma HMAC-SHA256 (útil para testing o validación)\r\n *\r\n * @param body - Cuerpo original\r\n * @param timestamp - Timestamp original\r\n * @param refreshToken - Token usado como clave\r\n * @param signature - Firma a verificar\r\n * @returns true si la firma es válida\r\n */\r\n verifySignature(body: string, timestamp: string, refreshToken: string, signature: string): boolean {\r\n try {\r\n const expectedSignature = this.genSignature(body, timestamp, refreshToken);\r\n return expectedSignature === signature;\r\n } catch {\r\n return false;\r\n }\r\n };\r\n\r\n /**\r\n * Genera un hash SHA256 de un texto (útil para fingerprints)\r\n *\r\n * @param text - Texto a hashear\r\n * @returns Hash en formato hexadecimal\r\n */\r\n sha256(text: string): string {\r\n return CryptoJS.SHA256(text).toString(CryptoJS.enc.Hex);\r\n }\r\n\r\n /**\r\n * Genera un identificador único basado en timestamp y random\r\n * (útil para request IDs)\r\n *\r\n * @returns ID único\r\n */\r\n generateUniqueId(): string {\r\n const timestamp = Date.now().toString(36);\r\n const randomPart = Math.random().toString(36).substring(2, 15);\r\n return `${timestamp}-${randomPart}`;\r\n };\r\n\r\n}\r\n","import { TokenData } from \"@/types/TokenData\";\r\n\r\n/**\r\n * Manages authentication tokens.\r\n */\r\nexport class TokenManager {\r\n private tokens: TokenData | null = null;\r\n private onTokensChanged?: (tokens: TokenData | null) => void;\r\n private sessionCheckInterval: NodeJS.Timeout | null = null;\r\n private onSessionExpiring?: (remainingMinutes: number) => void;\r\n private onSessionExpired?: () => Promise<void>;\r\n private hasNotifiedExpiring: boolean = false;\r\n\r\n constructor(\r\n onTokensChanged?: (tokens: TokenData | null) => void,\r\n onSessionExpiring?: (remainingMinutes: number) => void,\r\n onSessionExpired?: () => Promise<void>\r\n ) {\r\n this.onTokensChanged = onTokensChanged;\r\n this.onSessionExpiring = onSessionExpiring;\r\n this.onSessionExpired = onSessionExpired;\r\n };\r\n\r\n /**\r\n * Guarda los tokens de autenticación y dispara el callback onTokensChanged.\r\n */\r\n setTokens(tokens: TokenData) {\r\n this.tokens = tokens;\r\n this.hasNotifiedExpiring = false; // Resetear flag\r\n\r\n this.onTokensChanged?.(this.tokens);\r\n\r\n // Si NO tiene rememberMe, iniciar monitoreo de expiración\r\n if (!tokens.rememberMe) {\r\n this.startExpirationCheck();\r\n } else {\r\n this.stopExpirationCheck();\r\n };\r\n };\r\n\r\n /**\r\n * Obtiene los tokens de autenticación almacenados.\r\n */\r\n getTokens(): TokenData | null {\r\n return this.tokens;\r\n };\r\n\r\n /**\r\n * Limpia los tokens de autenticación almacenados y dispara el callback onTokensChanged.\r\n */\r\n clearTokens() {\r\n this.stopExpirationCheck();\r\n this.tokens = null;\r\n this.onTokensChanged?.(this.tokens);\r\n };\r\n\r\n /**\r\n * Valida si existen tokens y si el access token no ha expirado.\r\n */\r\n hasValidTokens(): boolean {\r\n if (!this.tokens) return false;\r\n\r\n const now = Date.now();\r\n const expiresAt = this.tokens.expiresAt.getTime();\r\n\r\n return now < expiresAt;\r\n };\r\n\r\n /**\r\n * Valida si el access token expirará dentro del umbral especificado (en minutos).\r\n */\r\n isTokenExpiringSoon(thresholdMinutes: number): boolean {\r\n if (!this.tokens) return false;\r\n\r\n const now = Date.now();\r\n const expiresAt = this.tokens.expiresAt.getTime();\r\n const thresholdMs = thresholdMinutes * 60 * 1000;\r\n\r\n const timeLeft = expiresAt - now;\r\n return timeLeft > 0 && timeLeft <= thresholdMs;\r\n };\r\n\r\n /**\r\n * Obtiene el tiempo restante hasta la expiración del access token en milisegundos.\r\n */\r\n getTimeUntilExpiry(): number | null {\r\n if (!this.tokens) return null;\r\n\r\n const now = Date.now();\r\n const expiresAt = this.tokens.expiresAt.getTime();\r\n const timeLeft = Math.max(0, expiresAt - now);\r\n\r\n return timeLeft;\r\n };\r\n\r\n /**\r\n * Obtiene el access token almacenado.\r\n */\r\n getAccessToken(): string | null {\r\n return this.tokens ? this.tokens.accessToken : null;\r\n };\r\n\r\n /**\r\n * Obtiene el refresh token almacenado.\r\n */\r\n getRefreshToken(): string | null {\r\n return this.tokens ? this.tokens.refreshToken : null;\r\n };\r\n\r\n /**\r\n * Verifica si el auto-refresh debe ejecutarse\r\n * Solo si el usuario activó \"rememberMe\" durante el login\r\n */\r\n shouldAutoRefresh(): boolean {\r\n if (!this.tokens) return false;\r\n\r\n return this.tokens.rememberMe === true;\r\n }\r\n\r\n /**\r\n * Inicia el monitoreo de expiración para sesiones sin rememberMe\r\n * - Notifica cuando quedan 5 minutos (onSessionExpiring)\r\n * - Ejecuta logout cuando queda 1 minuto (onSessionExpired)\r\n */\r\n private startExpirationCheck(): void {\r\n this.stopExpirationCheck();\r\n\r\n this.sessionCheckInterval = setInterval(async () => {\r\n if (!this.tokens) {\r\n this.stopExpirationCheck();\r\n return;\r\n };\r\n\r\n const timeLeft = this.getTimeUntilExpiry();\r\n if (timeLeft === null) return;\r\n\r\n const minutesLeft = Math.floor(timeLeft / (60 * 1000));\r\n\r\n // Notificar cuando quedan 5 minutos (solo una vez)\r\n if (minutesLeft <= 5 && minutesLeft > 1 && !this.hasNotifiedExpiring) {\r\n this.hasNotifiedExpiring = true;\r\n this.onSessionExpiring?.(minutesLeft);\r\n };\r\n\r\n // Cuando queda 1 minuto o menos: ejecutar logout automático\r\n if (minutesLeft <= 1) {\r\n this.stopExpirationCheck();\r\n\r\n // Ejecutar callback para logout en servidor\r\n if (this.onSessionExpired) {\r\n await this.onSessionExpired();\r\n };\r\n };\r\n }, 60000); // Cada 1 minuto\r\n }\r\n\r\n /**\r\n * Detiene el monitoreo de expiración\r\n */\r\n private stopExpirationCheck(): void {\r\n if (this.sessionCheckInterval) {\r\n clearInterval(this.sessionCheckInterval);\r\n this.sessionCheckInterval = null;\r\n };\r\n }\r\n};\r\n","import { AuthInterceptorConfig } from \"./types/AuthInterceptorConfig\";\r\nimport { InterceptorContext } from \"@/core/interceptors/types/InterceptorContext\";\r\nimport { RequestConfig } from \"@/types/RequestConfig\";\r\nimport { RequestInterceptor } from \"./types/RequestInterceptor\";\r\n\r\nexport class AuthInterceptor implements RequestInterceptor {\r\n readonly name = \"AuthInterceptor\";\r\n\r\n private config: Required<AuthInterceptorConfig>;\r\n private refreshPromise: Promise<void> | null = null;\r\n private isRefreshing = false;\r\n\r\n constructor(config: AuthInterceptorConfig) {\r\n this.config = {\r\n enabled: config.enabled ?? true,\r\n thresholdMinutes: config.thresholdMinutes ?? 5,\r\n isTokenExpiringSoon: config.isTokenExpiringSoon,\r\n hasValidTokens: config.hasValidTokens,\r\n shouldAutoRefresh: config.shouldAutoRefresh,\r\n refreshSession: config.refreshSession\r\n };\r\n };\r\n\r\n async onRequest(\r\n config: RequestConfig,\r\n context: InterceptorContext\r\n ): Promise<RequestConfig> {\r\n\r\n //Actua en solicitudes que requieren autenticación\r\n if (!config.requiresAuth || !this.config.enabled) {\r\n return config;\r\n };\r\n\r\n //Actúa SOLO si los tokens son válidos\r\n if (!this.config.hasValidTokens()) {\r\n return config;\r\n };\r\n\r\n if (!this.config.shouldAutoRefresh()) {\r\n return config;\r\n };\r\n\r\n if (this.config.isTokenExpiringSoon()) {\r\n try {\r\n //Evita múltiples llamadas de actualización simultáneas\r\n if (this.isRefreshing && this.refreshPromise) {\r\n await this.refreshPromise;\r\n } else {\r\n this.isRefreshing = true;\r\n this.refreshPromise = this.config.refreshSession();\r\n await this.refreshPromise;\r\n this.isRefreshing = false;\r\n this.refreshPromise = null;\r\n };\r\n } catch (error) {\r\n this.isRefreshing = false;\r\n this.refreshPromise = null;\r\n };\r\n };\r\n\r\n return config;\r\n };\r\n\r\n updateConfig(config: Partial<AuthInterceptorConfig>): void {\r\n this.config = {\r\n ...this.config,\r\n ...config\r\n } as Required<AuthInterceptorConfig>;\r\n };\r\n\r\n reset(): void {\r\n this.isRefreshing = false;\r\n this.refreshPromise = null;\r\n };\r\n};\r\n","import { API } from \"@/core/API\";\r\nimport { CryptoService } from \"@/core/CryptoService\";\r\nimport { TokenManager } from \"@/core/TokenManager\";\r\nimport { LoginRequest } from \"@/interfaces/Auth/Login/LoginRequest\";\r\nimport { LoginResponse } from \"@/interfaces/Auth/Login/LoginResponse\";\r\nimport { RefreshTokenResponse } from \"@/interfaces/Auth/RefreshTokens/RefreshTokenResponse\";\r\nimport { ValidateSessionRenewedResponse, ValidateSessionResponse } from \"@/interfaces/Auth/ValidateSession/ValidateSessionResponse\";\r\nimport { ErrorResponse } from \"@/types/ErrorResponse\";\r\nimport { ResponseModel } from \"@/types/ResponseModel\";\r\nimport { ServiceProperties } from \"@/types/ServiceProperties\";\r\nimport { TokenData } from \"@/types/TokenData\";\r\n\r\nexport class AuthService {\r\n private api: API;\r\n private crytpoService: CryptoService;\r\n private tokenManager: TokenManager;\r\n private serviceProperties: ServiceProperties;\r\n\r\n constructor(\r\n serviceProperties: ServiceProperties,\r\n tokenManager: TokenManager,\r\n cryptoService: CryptoService,\r\n api: API\r\n ) {\r\n this.api = api;\r\n this.crytpoService = cryptoService;\r\n this.tokenManager = tokenManager;\r\n this.serviceProperties = serviceProperties;\r\n };\r\n\r\n /**\r\n * Login con las credenciales proporcionadas\r\n * @param credentials - Objeto con email, password y rememberMe\r\n * @returns Retorna el cuerpo de respuesta del login.\r\n */\r\n async login(credentials: LoginRequest): Promise<ResponseModel<LoginResponse>> {\r\n const timestamp = Date.now().toString();\r\n\r\n const encryptedEmail = this.crytpoService.encrypt(\r\n credentials.email,\r\n `${this.serviceProperties.originRequest}_${this.serviceProperties.domain}`,\r\n timestamp\r\n );\r\n\r\n const encryptedPassword = this.crytpoService.encrypt(\r\n credentials.password,\r\n `${this.serviceProperties.originRequest}_${this.serviceProperties.domain}`,\r\n timestamp\r\n );\r\n\r\n const loginData: LoginRequest = {\r\n email: encryptedEmail,\r\n password: encryptedPassword,\r\n rememberMe: credentials.rememberMe\r\n };\r\n\r\n const response = await this.api.executePublicRequest<ResponseModel>(\r\n 'oauth/login',\r\n 'POST',\r\n loginData,\r\n timestamp\r\n );\r\n\r\n if (!response) {\r\n throw new ErrorResponse('No response from server');\r\n };\r\n\r\n if (response.success) {\r\n const data: LoginResponse = response.data;\r\n\r\n const expiresIn = parseInt(data.expiresIn.replace('s', ''));\r\n const expiresAt = new Date(Date.now() + expiresIn * 1000);\r\n\r\n const tokens: TokenData = {\r\n accessToken: data.accessToken,\r\n refreshToken: data.refreshToken,\r\n expiresAt: expiresAt,\r\n rememberMe: credentials.rememberMe\r\n };\r\n\r\n await this.tokenManager.setTokens(tokens);\r\n\r\n this.serviceProperties.onTokensUpdated?.(tokens);\r\n\r\n const responseData: ResponseModel<LoginResponse> = {\r\n success: data.accessToken ? true : false,\r\n data: data,\r\n message: response.message,\r\n responseTime: '3s'\r\n };\r\n\r\n return responseData;\r\n }\r\n\r\n return response;\r\n };\r\n\r\n\r\n /**\r\n * Valida la sesión actual y retorna información de expiración\r\n *\r\n * El servidor puede responder de 2 formas:\r\n * 1. Sesión renovada (sliding window): retorna nuevos tokens\r\n * 2. Sesión válida: retorna info de expiración sin renovar\r\n */\r\n async validateSession(): Promise<ResponseModel<ValidateSessionRenewedResponse | ValidateSessionResponse>> {\r\n const response = await this.api.executePOST<ResponseModel<ValidateSessionRenewedResponse | ValidateSessionResponse>>(\r\n 'oauth/validateSession'\r\n );\r\n\r\n if (!response) {\r\n throw new ErrorResponse('No response from server');\r\n };\r\n\r\n if (response.success && response.data) {\r\n const respData = response.data;\r\n\r\n if ('expiresIn' in respData && respData.expiresIn) {\r\n const sessionData = respData as ValidateSessionRenewedResponse;\r\n const expiresIn = parseInt(sessionData.expiresIn.replace('s', ''));\r\n const expiresAt = new Date(Date.now() + expiresIn * 1000);\r\n\r\n const currentTokens = this.tokenManager.getTokens();\r\n const rememberMe = currentTokens?.rememberMe ?? sessionData.isRemembered;\r\n\r\n const tokens: TokenData = {\r\n accessToken: sessionData.accessToken,\r\n refreshToken: sessionData.refreshToken,\r\n expiresAt: expiresAt,\r\n rememberMe: rememberMe\r\n };\r\n\r\n this.tokenManager.setTokens(tokens);\r\n this.serviceProperties.onTokensUpdated?.(tokens);\r\n }\r\n else if ('expiresAt' in respData && respData.expiresAt) {\r\n const sessionData = respData as ValidateSessionResponse;\r\n\r\n if (sessionData.remainingMinutes <= 5 && sessionData.remainingMinutes > 1) {\r\n this.serviceProperties.onSessionExpiring?.(sessionData.remainingMinutes);\r\n } else if (sessionData.remainingMinutes <= 1) {\r\n if (this.serviceProperties.onSessionExpired) {\r\n await this.serviceProperties.onSessionExpired();\r\n }\r\n }\r\n }\r\n };\r\n\r\n return response;\r\n };\r\n\r\n /**\r\n * Refresca los tokens usando el refresh token\r\n */\r\n async refreshTokens(rememberMe?: boolean): Promise<ResponseModel<RefreshTokenResponse>> {\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n\r\n if (!refreshToken) {\r\n throw new ErrorResponse('No refresh token available');\r\n };\r\n\r\n const response = await this.api.executePublicRequest<ResponseModel<any>>(\r\n 'oauth/refresh',\r\n 'POST',\r\n { refreshToken }\r\n );\r\n\r\n if (!response) {\r\n throw new ErrorResponse('No response from server');\r\n };\r\n\r\n if (response.success) {\r\n const sessionData: RefreshTokenResponse = response.data;\r\n\r\n const currentTokens = this.tokenManager.getTokens();\r\n const shouldRemember = rememberMe ?? currentTokens?.rememberMe ?? false;\r\n const expiresIn = parseInt(sessionData.expiresIn.replace('s', ''));\r\n const expiresAt = new Date(Date.now() + expiresIn * 1000);\r\n\r\n const tokens: TokenData = {\r\n accessToken: sessionData.accessToken,\r\n refreshToken: sessionData.refreshToken,\r\n expiresAt: expiresAt,\r\n rememberMe: shouldRemember\r\n };\r\n\r\n this.tokenManager.setTokens(tokens);\r\n this.serviceProperties.onTokensUpdated?.(tokens);\r\n };\r\n\r\n return response;\r\n };\r\n\r\n /**\r\n * Cierra sesión: notifica al servidor y limpia tokens\r\n */\r\n async logout(): Promise<void> {\r\n try {\r\n await this.api.executePOST('oauth/logout');\r\n } catch (error) {\r\n // Continuar con logout local aunque falle el servidor\r\n };\r\n\r\n this.tokenManager.clearTokens();\r\n this.serviceProperties.onTokensUpdated?.(null);\r\n };\r\n\r\n /**\r\n * Verifica si el usuario está autenticado\r\n */\r\n isAuthenticated(): boolean {\r\n return this.tokenManager.hasValidTokens();\r\n };\r\n\r\n /**\r\n * Obtiene los tokens actuales\r\n */\r\n getTokens(): TokenData | null {\r\n return this.tokenManager.getTokens();\r\n };\r\n\r\n}\r\n","import { API } from \"./core/API\";\r\nimport { CryptoService } from \"./core/CryptoService\";\r\nimport { TokenManager } from \"./core/TokenManager\";\r\nimport { AuthInterceptor } from \"./core/interceptors/AuthInterceptor\";\r\nimport { ServiceProperties } from \"./types/ServiceProperties\";\r\nimport { TokenData } from \"./types/TokenData\";\r\nimport { AuthService } from \"./services/AuthService\";\r\n\r\n/**\r\n * SDK principal de FalconHUB\r\n */\r\nexport class FalconHUBSDK {\r\n public auth: AuthService;\r\n\r\n private serviceProperties: ServiceProperties;\r\n private cryptoService: CryptoService;\r\n private tokenManager: TokenManager;\r\n private authInterceptor: AuthInterceptor | null;\r\n private api: API;\r\n\r\n constructor(serviceProperties: ServiceProperties) {\r\n this.serviceProperties = serviceProperties;\r\n\r\n this.cryptoService = new CryptoService();\r\n\r\n this.tokenManager = new TokenManager(\r\n this.serviceProperties.onTokensUpdated,\r\n this.serviceProperties.onSessionExpiring,\r\n async () => {\r\n await this.auth.logout();\r\n }\r\n );\r\n\r\n const autoRefreshConfig = this.normalizeAutoRefreshConfig(this.serviceProperties.autoRefresh);\r\n\r\n if (autoRefreshConfig.enabled) {\r\n this.authInterceptor = new AuthInterceptor({\r\n enabled: true,\r\n thresholdMinutes: autoRefreshConfig.thresholdMinutes,\r\n isTokenExpiringSoon: () => this.tokenManager.isTokenExpiringSoon(autoRefreshConfig.thresholdMinutes),\r\n hasValidTokens: () => this.tokenManager.hasValidTokens(),\r\n shouldAutoRefresh: () => this.tokenManager.shouldAutoRefresh(),\r\n refreshSession: async () => {\r\n await this.auth.validateSession();\r\n }\r\n });\r\n } else {\r\n this.authInterceptor = null;\r\n }\r\n\r\n this.api = new API(\r\n this.serviceProperties,\r\n this.cryptoService,\r\n this.authInterceptor,\r\n () => this.tokenManager.getAccessToken(),\r\n () => this.tokenManager.getRefreshToken()\r\n );\r\n\r\n this.auth = new AuthService(\r\n this.serviceProperties,\r\n this.tokenManager,\r\n this.cryptoService,\r\n this.api\r\n );\r\n }\r\n\r\n private normalizeAutoRefreshConfig(\r\n config: ServiceProperties[\"autoRefresh\"]\r\n ): { enabled: boolean; thresholdMinutes: number } {\r\n if (typeof config === \"boolean\") {\r\n return { enabled: config, thresholdMinutes: 5 };\r\n }\r\n if (typeof config === \"object\" && config !== null) {\r\n return {\r\n enabled: config.enabled,\r\n thresholdMinutes: config.thresholdMinutes ?? 5\r\n };\r\n }\r\n return { enabled: true, thresholdMinutes: 5 };\r\n }\r\n\r\n /**\r\n * Inyecta tokens desde storage externo (cookies/localStorage/etc)\r\n */\r\n setTokensFromExternal(\r\n accessToken: string,\r\n refreshToken: string,\r\n expiresAt: Date,\r\n rememberMe: boolean = false\r\n ): void {\r\n const tokens: TokenData = {\r\n accessToken,\r\n refreshToken,\r\n expiresAt,\r\n rememberMe\r\n };\r\n\r\n this.tokenManager.setTokens(tokens);\r\n }\r\n\r\n /**\r\n * Obtiene los tokens actuales\r\n */\r\n getTokens(): TokenData | null {\r\n return this.tokenManager.getTokens();\r\n }\r\n\r\n /**\r\n * Verifica si el usuario está autenticado\r\n */\r\n isAuthenticated(): boolean {\r\n return this.tokenManager.hasValidTokens();\r\n }\r\n\r\n /**\r\n * Verifica si la sesión está por expirar\r\n */\r\n isSessionExpiringSoon(thresholdMinutes: number = 5): boolean {\r\n return this.tokenManager.isTokenExpiringSoon(thresholdMinutes);\r\n }\r\n\r\n /**\r\n * Obtiene el tiempo restante hasta la expiración en milisegundos\r\n */\r\n getTimeUntilExpiry(): number | null {\r\n return this.tokenManager.getTimeUntilExpiry();\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/types/ErrorResponse.ts","../src/core/API.ts","../src/core/CryptoService.ts","../src/core/TokenManager.ts","../src/core/interceptors/AuthInterceptor.ts","../src/services/AuthService.ts","../src/FalconHUBSDK.ts"],"sourcesContent":["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 { 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\";\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 parseada del tipo esperado\n */\n private async apiExecute<T>(options: RequestOptions): Promise<T | undefined> {\n const {\n endpoint,\n method,\n body,\n requiresSignature,\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-Timestamp'] = newTimeStamp;\n\n let bodyString: string | undefined;\n\n if (body && method !== 'GET') {\n bodyString = JSON.stringify(body);\n };\n\n if (requiresSignature && bodyString) {\n try {\n const refreshToken = this.getRefreshToken();\n\n if (refreshToken) {\n const signature = this.cryptoService.genSignature(\n bodyString,\n newTimeStamp,\n refreshToken\n );\n\n if (signature) {\n headers['X-Signature'] = signature;\n };\n };\n } catch (error) {\n throw new ErrorResponse(\n \"Failed to generate request signature.\",\n 401\n );\n };\n };\n\n const requestConfig: RequestConfig = {\n url,\n method,\n headers,\n body: bodyString,\n requiresAuth,\n requiresSignature\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 if (response.ok) {\n // Detectar sliding window: nuevos tokens en headers\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\n return JSON.parse(responseText) as T;\n };\n\n return undefined;\n } else {\n await this.handleErrorResponse(response);\n };\n } catch (error) {\n if (error instanceof ErrorResponse) {\n throw error;\n };\n\n throw new ErrorResponse(\n 'Unexpected error occurred during API request.',\n 500\n );\n };\n };\n\n /**\n * Maneja errores HTTP y lanza excepciones apropiadas\n */\n private async handleErrorResponse(\n response: Response\n ): Promise<never> {\n\n const statusCode = response.status;\n let errorMessage = `Error ${statusCode}`;\n let responseData: any = null;\n\n try {\n const contentType = response.headers.get('Content-Type');\n if (contentType && contentType.includes('application/json')) {\n responseData = await response.json();\n errorMessage = responseData.message || responseData.error || errorMessage;\n } else {\n errorMessage = await response.text();\n };\n } catch (error) {\n\n };\n\n switch (statusCode) {\n case 401:\n const authError = new ErrorResponse(\n 'Unauthorized access.',\n 401,\n responseData\n );\n\n this.properties.onAuthError?.(authError);\n throw authError;\n case 403:\n throw new ErrorResponse(\n 'No tienes permisos para realizar esta acción.',\n 403,\n responseData\n );\n\n case 404:\n throw new ErrorResponse(\n 'Recurso no encontrado.',\n 404,\n responseData\n );\n\n case 422:\n throw new ErrorResponse(\n errorMessage || 'Datos de entrada inválidos.',\n 422,\n responseData\n );\n\n case 500:\n throw new ErrorResponse(\n 'Error interno del servidor.',\n 500,\n responseData\n );\n\n default:\n throw new ErrorResponse(\n errorMessage,\n statusCode,\n responseData\n );\n };\n };\n\n //#region REQUEST METHODS\n\n async executeGET<T>(\n endpoint: string,\n requiresAuth: boolean = false\n ): Promise<T | undefined> {\n return this.apiExecute<T>({\n endpoint,\n method: 'GET',\n requiresAuth: requiresAuth,\n requiresSignature: false\n });\n };\n\n async executePOST<T>(\n endpoint: string,\n body?: any,\n requiresAuth: boolean = true,\n requiresSignature: boolean = true\n ): Promise<T | undefined> {\n return this.apiExecute<T>({\n endpoint,\n method: 'POST',\n body,\n requiresAuth: requiresAuth,\n requiresSignature: requiresSignature\n });\n };\n\n async executePATCH<T>(\n endpoint: string,\n body?: any,\n requiresAuth: boolean = true,\n requiresSignature: boolean = true\n ): Promise<T | undefined> {\n return this.apiExecute<T>({\n endpoint,\n method: 'PATCH',\n body,\n requiresAuth: requiresAuth,\n requiresSignature: requiresSignature\n });\n };\n\n async executeDELETE<T>(\n endpoint: string,\n body?: any,\n requiresAuth: boolean = true,\n requiresSignature: boolean = false\n ): Promise<T | undefined> {\n return this.apiExecute<T>({\n endpoint,\n method: 'DELETE',\n body,\n requiresAuth: requiresAuth,\n requiresSignature: requiresSignature\n });\n };\n\n async executePUT<T>(\n endpoint: string,\n body?: any,\n requiresAuth: boolean = true,\n requiresSignature: boolean = true\n ): Promise<T | undefined> {\n return this.apiExecute<T>({\n endpoint,\n method: 'PUT',\n body,\n requiresAuth: requiresAuth,\n requiresSignature: requiresSignature\n });\n };\n\n async executePublicRequest<T>(\n endpoint: string,\n method: MethodTypes,\n body?: any,\n timestamp?: string\n ): Promise<T | undefined> {\n return this.apiExecute<T>({\n endpoint,\n method,\n body,\n requiresAuth: false,\n requiresSignature: false,\n timeStamp: timestamp\n });\n };\n\n //#endregion\n}\n","import * as CryptoJS from 'crypto-js';\n\nexport class CryptoService {\n\n /**\n * Encripta el texto plano utilizando AES con una clave derivada del secretWord y el timestamp\n *\n * @param plaintText -- Texto plano a encriptar\n * @param secretWord - Palabra secreta utilizada para derivar la clave\n * @param timestamp - Timestamp actual\n * @returns Texto encriptado en formato Base64\n */\n encrypt(plaintText: string, secretWord: string, timestamp: string): string {\n const fullKey = `${secretWord}:${timestamp}`;\n const key = CryptoJS.SHA256(fullKey);\n\n const iv = CryptoJS.lib.WordArray.random(16);\n const encrypted = CryptoJS.AES.encrypt(plaintText, key, {\n iv: iv,\n mode: CryptoJS.mode.CBC,\n padding: CryptoJS.pad.Pkcs7\n });\n\n const ivAndCipher = iv.concat(encrypted.ciphertext);\n return CryptoJS.enc.Base64.stringify(ivAndCipher);\n };\n\n /**\n * Genera la firma Signature para las operaciones de tipo POST\n *\n * @param body - Cuerpo de la solicitud\n * @param timestamp - Timestamp actual\n * @param refreshToken - Refresh token del usuario\n * @returns Firma signature en formato Base64\n */\n genSignature(body: string, timestamp: string, refreshToken: string): string {\n const message = `${body}:${timestamp}`;\n const hmac = CryptoJS.HmacSHA256(message, refreshToken);\n\n return CryptoJS.enc.Base64.stringify(hmac);\n };\n\n /**\n * Desencripta texto usando AES-256-CBC\n *\n * @param encryptedBase64 - Texto encriptado en base64\n * @param secret - Clave secreta\n * @param timestamp - Timestamp usado en la encriptación\n * @returns Texto desencriptado\n */\n decrypt(encryptedText: string, secretWord: string, timestamp: string): string {\n try {\n const fullKey = `${secretWord}:${timestamp}`;\n const key = CryptoJS.SHA256(fullKey);\n\n const ivAndCipher = CryptoJS.enc.Base64.parse(encryptedText);\n const iv = CryptoJS.lib.WordArray.create(ivAndCipher.words.slice(0, 4));\n\n const ciphertext = CryptoJS.lib.WordArray.create(\n ivAndCipher.words.slice(4),\n ivAndCipher.sigBytes - 16\n );\n\n const decrypted = CryptoJS.AES.decrypt(\n { ciphertext } as any,\n key,\n {\n iv: iv,\n mode: CryptoJS.mode.CBC,\n padding: CryptoJS.pad.Pkcs7\n }\n );\n\n return CryptoJS.enc.Utf8.stringify(decrypted);\n } catch (error) {\n throw new Error('Decryption failed, ex:' + error);\n }\n };\n\n /**\n * Verifica una firma HMAC-SHA256 (útil para testing o validación)\n *\n * @param body - Cuerpo original\n * @param timestamp - Timestamp original\n * @param refreshToken - Token usado como clave\n * @param signature - Firma a verificar\n * @returns true si la firma es válida\n */\n verifySignature(body: string, timestamp: string, refreshToken: string, signature: string): boolean {\n try {\n const expectedSignature = this.genSignature(body, timestamp, refreshToken);\n return expectedSignature === signature;\n } catch {\n return false;\n }\n };\n\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}\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 onSessionExpiring?: (remainingMinutes: number) => void;\n private onSessionExpired?: () => Promise<void>;\n private hasNotifiedExpiring: boolean = false;\n\n constructor(\n onTokensChanged?: (tokens: TokenData | null) => void,\n onSessionExpiring?: (remainingMinutes: number) => void,\n onSessionExpired?: () => Promise<void>\n ) {\n this.onTokensChanged = onTokensChanged;\n this.onSessionExpiring = onSessionExpiring;\n this.onSessionExpired = onSessionExpired;\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; // Resetear flag\n\n this.onTokensChanged?.(this.tokens);\n\n // Si NO tiene rememberMe, iniciar monitoreo de expiración\n if (!tokens.rememberMe) {\n this.startExpirationCheck();\n } else {\n this.stopExpirationCheck();\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.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 const now = Date.now();\n const expiresAt = this.tokens.expiresAt.getTime();\n\n return now < 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 now = Date.now();\n const expiresAt = this.tokens.expiresAt.getTime();\n const thresholdMs = thresholdMinutes * 60 * 1000;\n\n const timeLeft = expiresAt - now;\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 const now = Date.now();\n const expiresAt = this.tokens.expiresAt.getTime();\n const timeLeft = Math.max(0, expiresAt - now);\n\n return timeLeft;\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 * - Ejecuta logout cuando queda 1 minuto (onSessionExpired)\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 // Notificar cuando quedan 5 minutos (solo una vez)\n if (minutesLeft <= 5 && minutesLeft > 1 && !this.hasNotifiedExpiring) {\n this.hasNotifiedExpiring = true;\n this.onSessionExpiring?.(minutesLeft);\n };\n\n // Cuando queda 1 minuto o menos: ejecutar logout automático\n if (minutesLeft <= 1) {\n this.stopExpirationCheck();\n\n // Ejecutar callback para logout en servidor\n if (this.onSessionExpired) {\n await this.onSessionExpired();\n };\n };\n }, 60000); // Cada 1 minuto\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","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","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 { RefreshTokenResponse } from \"@/interfaces/Auth/RefreshTokens/RefreshTokenResponse\";\nimport { ValidateSessionRenewedResponse, ValidateSessionResponse } from \"@/interfaces/Auth/ValidateSession/ValidateSessionResponse\";\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 encryptedEmail = this.crytpoService.encrypt(\n credentials.email,\n `${this.serviceProperties.originRequest}_${this.serviceProperties.domain}`,\n timestamp\n );\n\n const encryptedPassword = this.crytpoService.encrypt(\n credentials.password,\n `${this.serviceProperties.originRequest}_${this.serviceProperties.domain}`,\n timestamp\n );\n\n const loginData: LoginRequest = {\n email: encryptedEmail,\n password: encryptedPassword,\n rememberMe: credentials.rememberMe\n };\n\n const response = await this.api.executePublicRequest<ResponseModel>(\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) {\n const data: LoginResponse = response.data;\n\n const expiresIn = parseInt(data.expiresIn.replace('s', ''));\n const expiresAt = new Date(Date.now() + expiresIn * 1000);\n\n const tokens: TokenData = {\n accessToken: data.accessToken,\n refreshToken: data.refreshToken,\n expiresAt: expiresAt,\n rememberMe: credentials.rememberMe\n };\n\n await this.tokenManager.setTokens(tokens);\n\n this.serviceProperties.onTokensUpdated?.(tokens);\n\n const responseData: ResponseModel<LoginResponse> = {\n success: data.accessToken ? true : false,\n data: data,\n message: response.message,\n responseTime: '3s'\n };\n\n return responseData;\n }\n\n return response;\n };\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<ResponseModel<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 = new Date(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: expiresAt,\n rememberMe: 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(rememberMe?: boolean): Promise<ResponseModel<RefreshTokenResponse>> {\n const refreshToken = this.tokenManager.getRefreshToken();\n\n if (!refreshToken) {\n throw new ErrorResponse('No refresh token available');\n };\n\n const response = await this.api.executePublicRequest<ResponseModel<any>>(\n 'oauth/refresh',\n 'POST',\n { refreshToken }\n );\n\n if (!response) {\n throw new ErrorResponse('No response from server');\n };\n\n if (response.success) {\n const sessionData: RefreshTokenResponse = response.data;\n\n const currentTokens = this.tokenManager.getTokens();\n const shouldRemember = rememberMe ?? currentTokens?.rememberMe ?? false;\n const expiresIn = parseInt(sessionData.expiresIn.replace('s', ''));\n const expiresAt = new Date(Date.now() + expiresIn * 1000);\n\n const tokens: TokenData = {\n accessToken: sessionData.accessToken,\n refreshToken: sessionData.refreshToken,\n expiresAt: 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<void> {\n try {\n await this.api.executePOST('oauth/logout');\n } catch (error) {\n // Continuar con logout local aunque falle el servidor\n };\n\n this.tokenManager.clearTokens();\n this.serviceProperties.onTokensUpdated?.(null);\n };\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","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\";\n\n/**\n * SDK principal de FalconHUB\n */\nexport class FalconHUBSDK {\n public auth: AuthService;\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 this.tokenManager = new TokenManager(\n this.serviceProperties.onTokensUpdated,\n this.serviceProperties.onSessionExpiring,\n async () => {\n await this.auth.logout();\n }\n );\n\n const autoRefreshConfig = this.normalizeAutoRefreshConfig(this.serviceProperties.autoRefresh);\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\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 */\n setTokensFromExternal(\n accessToken: string,\n refreshToken: string,\n expiresAt: Date,\n rememberMe: boolean = false\n ): void {\n const tokens: TokenData = {\n accessToken,\n refreshToken,\n expiresAt,\n rememberMe\n };\n\n this.tokenManager.setTokens(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"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "falconhub-apilibrary",
|
|
3
|
-
"version": "1.1.
|
|
4
|
-
"description": "FalconHUB SKD",
|
|
5
|
-
"main": "./dist/index.js",
|
|
6
|
-
"module": "./dist/index.mjs",
|
|
7
|
-
"types": "./dist/index.d.ts",
|
|
8
|
-
"sideEffects": false,
|
|
9
|
-
"exports": {
|
|
10
|
-
".": {
|
|
11
|
-
"types": "./dist/index.d.ts",
|
|
12
|
-
"import": "./dist/index.mjs",
|
|
13
|
-
"require": "./dist/index.js"
|
|
14
|
-
},
|
|
15
|
-
"./package.json": "./package.json"
|
|
16
|
-
},
|
|
17
|
-
"files": [
|
|
18
|
-
"dist",
|
|
19
|
-
"README.md",
|
|
20
|
-
"LICENSE"
|
|
21
|
-
],
|
|
22
|
-
"scripts": {
|
|
23
|
-
"build": "tsup",
|
|
24
|
-
"dev": "tsup --watch",
|
|
25
|
-
"test": "echo \"Error: no test specified\" && exit 1",
|
|
26
|
-
"prepublishOnly": "npm run build",
|
|
27
|
-
"package": "npm pack"
|
|
28
|
-
},
|
|
29
|
-
"repository": {
|
|
30
|
-
"type": "git",
|
|
31
|
-
"url": "git+https://fanarmy-admin@bitbucket.org/fanarmy/falconhub_apilibrary.git"
|
|
32
|
-
},
|
|
33
|
-
"keywords": [
|
|
34
|
-
"falconhub",
|
|
35
|
-
"api",
|
|
36
|
-
"client",
|
|
37
|
-
"authentication",
|
|
38
|
-
"token-management"
|
|
39
|
-
],
|
|
40
|
-
"author": "FanArmy",
|
|
41
|
-
"license": "ISC",
|
|
42
|
-
"bugs": {
|
|
43
|
-
"url": "https://bitbucket.org/fanarmy/falconhub_apilibrary/issues"
|
|
44
|
-
},
|
|
45
|
-
"homepage": "https://bitbucket.org/fanarmy/falconhub_apilibrary#readme",
|
|
46
|
-
"devDependencies": {
|
|
47
|
-
"@types/crypto-js": "^4.2.2",
|
|
48
|
-
"@types/node": "^24.7.0",
|
|
49
|
-
"bestzip": "^2.2.1",
|
|
50
|
-
"tsup": "^8.0.1",
|
|
51
|
-
"tsx": "^4.20.6",
|
|
52
|
-
"typescript": "^5.9.3"
|
|
53
|
-
},
|
|
54
|
-
"dependencies": {
|
|
55
|
-
"crypto-js": "^4.2.0",
|
|
56
|
-
"dotenv": "^17.2.3"
|
|
57
|
-
},
|
|
58
|
-
"optionalDependencies": {
|
|
59
|
-
"@rollup/rollup-linux-x64-gnu": "4.50.1"
|
|
60
|
-
}
|
|
61
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "falconhub-apilibrary",
|
|
3
|
+
"version": "1.1.2",
|
|
4
|
+
"description": "FalconHUB SKD",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"sideEffects": false,
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.mjs",
|
|
13
|
+
"require": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"./package.json": "./package.json"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md",
|
|
20
|
+
"LICENSE"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsup",
|
|
24
|
+
"dev": "tsup --watch",
|
|
25
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
26
|
+
"prepublishOnly": "npm run build",
|
|
27
|
+
"package": "npm pack"
|
|
28
|
+
},
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "git+https://fanarmy-admin@bitbucket.org/fanarmy/falconhub_apilibrary.git"
|
|
32
|
+
},
|
|
33
|
+
"keywords": [
|
|
34
|
+
"falconhub",
|
|
35
|
+
"api",
|
|
36
|
+
"client",
|
|
37
|
+
"authentication",
|
|
38
|
+
"token-management"
|
|
39
|
+
],
|
|
40
|
+
"author": "FanArmy",
|
|
41
|
+
"license": "ISC",
|
|
42
|
+
"bugs": {
|
|
43
|
+
"url": "https://bitbucket.org/fanarmy/falconhub_apilibrary/issues"
|
|
44
|
+
},
|
|
45
|
+
"homepage": "https://bitbucket.org/fanarmy/falconhub_apilibrary#readme",
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/crypto-js": "^4.2.2",
|
|
48
|
+
"@types/node": "^24.7.0",
|
|
49
|
+
"bestzip": "^2.2.1",
|
|
50
|
+
"tsup": "^8.0.1",
|
|
51
|
+
"tsx": "^4.20.6",
|
|
52
|
+
"typescript": "^5.9.3"
|
|
53
|
+
},
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"crypto-js": "^4.2.0",
|
|
56
|
+
"dotenv": "^17.2.3"
|
|
57
|
+
},
|
|
58
|
+
"optionalDependencies": {
|
|
59
|
+
"@rollup/rollup-linux-x64-gnu": "4.50.1"
|
|
60
|
+
}
|
|
61
|
+
}
|