@utilia-os/sdk-js 1.5.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,14 +1,137 @@
1
1
  /**
2
- * Tipos de configuracion del SDK
2
+ * Tipos para autenticación OAuth 2.1 con PKCE
3
3
  */
4
+ /**
5
+ * Configuración de OAuth para el SDK
6
+ */
7
+ interface OAuthConfig {
8
+ /** Identificador de la aplicación OAuth */
9
+ clientId: string;
10
+ /** Secreto de la aplicación (opcional, para apps confidenciales) */
11
+ clientSecret?: string;
12
+ /** URI de redirección registrada */
13
+ redirectUri: string;
14
+ /** Scopes solicitados (default: ['openid', 'profile', 'email']) */
15
+ scopes?: string[];
16
+ /** Almacenamiento personalizado de tokens */
17
+ tokenStorage?: TokenStorage;
18
+ }
19
+ /**
20
+ * Tokens OAuth devueltos por el servidor de autorización
21
+ */
22
+ interface OAuthTokens {
23
+ /** Token de acceso */
24
+ accessToken: string;
25
+ /** Token de refresco (si fue concedido) */
26
+ refreshToken?: string;
27
+ /** Duración en segundos del access token */
28
+ expiresIn: number;
29
+ /** Timestamp absoluto de expiración (Date.now() + expiresIn * 1000) */
30
+ expiresAt: number;
31
+ /** Tipo de token (normalmente 'Bearer') */
32
+ tokenType: string;
33
+ /** Scopes concedidos */
34
+ scope?: string;
35
+ /** Token de identidad OpenID Connect */
36
+ idToken?: string;
37
+ }
38
+ /**
39
+ * Información del usuario autenticado (endpoint /oauth/userinfo)
40
+ */
41
+ interface OAuthUserInfo {
42
+ /** Identificador único del usuario */
43
+ sub: string;
44
+ /** Nombre completo */
45
+ name?: string;
46
+ /** Correo electrónico */
47
+ email?: string;
48
+ /** Si el correo ha sido verificado */
49
+ email_verified?: boolean;
50
+ /** URL de la foto de perfil */
51
+ picture?: string;
52
+ /** Nombre de pila */
53
+ given_name?: string;
54
+ /** Apellido(s) */
55
+ family_name?: string;
56
+ /** Campos adicionales */
57
+ [key: string]: unknown;
58
+ }
59
+ /**
60
+ * Interfaz para almacenamiento personalizado de tokens
61
+ */
62
+ interface TokenStorage {
63
+ /** Obtiene los tokens almacenados */
64
+ getTokens(): Promise<OAuthTokens | null>;
65
+ /** Almacena los tokens */
66
+ setTokens(tokens: OAuthTokens): Promise<void>;
67
+ /** Elimina los tokens almacenados */
68
+ clearTokens(): Promise<void>;
69
+ /** Obtiene el estado PKCE pendiente (opcional, para flujo automático) */
70
+ getPendingState?(): Promise<PendingOAuthState | null>;
71
+ /** Almacena el estado PKCE pendiente (opcional, para flujo automático) */
72
+ setPendingState?(state: PendingOAuthState): Promise<void>;
73
+ /** Elimina el estado PKCE pendiente (opcional, para flujo automático) */
74
+ clearPendingState?(): Promise<void>;
75
+ }
76
+ /**
77
+ * Par de desafío PKCE (code_verifier + code_challenge)
78
+ */
79
+ interface PKCEChallenge {
80
+ /** Cadena aleatoria usada como verificador */
81
+ codeVerifier: string;
82
+ /** Hash SHA-256 base64url del verificador */
83
+ codeChallenge: string;
84
+ }
85
+ /**
86
+ * Estado PKCE pendiente almacenado entre getAuthorizationUrl() y handleCallback()
87
+ */
88
+ interface PendingOAuthState {
89
+ /** Verificador PKCE generado */
90
+ codeVerifier: string;
91
+ /** Valor de state para protección CSRF */
92
+ state: string;
93
+ }
94
+ /**
95
+ * Resultado de generar la URL de inicio de sesión
96
+ */
97
+ interface LoginUrlResult {
98
+ /** URL completa de autorización */
99
+ url: string;
100
+ /** Verificador PKCE (debe guardarse para el callback) */
101
+ codeVerifier: string;
102
+ /** Valor de state para protección CSRF */
103
+ state: string;
104
+ }
105
+ /**
106
+ * Opciones para inicio de sesión OAuth mediante ventana emergente
107
+ */
108
+ interface PopupLoginOptions {
109
+ /** Parámetro state personalizado para protección CSRF */
110
+ state?: string;
111
+ /** Scopes a solicitar */
112
+ scopes?: string[];
113
+ /** Ancho de la ventana emergente en píxeles (por defecto: 500) */
114
+ width?: number;
115
+ /** Alto de la ventana emergente en píxeles (por defecto: 700) */
116
+ height?: number;
117
+ /** Tiempo límite en milisegundos antes de rechazar (por defecto: 300000 = 5 min) */
118
+ timeout?: number;
119
+ }
120
+
121
+ /**
122
+ * Tipos de configuración del SDK
123
+ */
124
+
4
125
  interface UtiliaSDKConfig {
5
126
  /** URL base de la API (ej: https://os.utilia.ai/api) */
6
127
  baseURL: string;
7
- /** API Key para autenticacion */
8
- apiKey: string;
128
+ /** API Key para autenticación (requerida si no se usa OAuth) */
129
+ apiKey?: string;
130
+ /** Configuración OAuth 2.1 con PKCE (alternativa a apiKey) */
131
+ oauth?: OAuthConfig;
9
132
  /** Timeout en milisegundos (default: 30000) */
10
133
  timeout?: number;
11
- /** Numero de reintentos en caso de error (default: 3) */
134
+ /** Número de reintentos en caso de error (default: 3) */
12
135
  retryAttempts?: number;
13
136
  /** Habilitar logs de debug (default: false) */
14
137
  debug?: boolean;
@@ -18,6 +141,109 @@ interface RequestConfig {
18
141
  params?: Record<string, unknown>;
19
142
  }
20
143
 
144
+ /**
145
+ * Servicio OAuth 2.1 con PKCE para el SDK de UTILIA OS
146
+ */
147
+
148
+ /**
149
+ * Servicio que gestiona el flujo OAuth 2.1 con PKCE
150
+ */
151
+ declare class OAuthService {
152
+ private readonly baseURL;
153
+ private readonly config;
154
+ private readonly storage;
155
+ private readonly http;
156
+ /** Estado PKCE en memoria como fallback cuando el storage no soporta pendingState */
157
+ private _pendingState;
158
+ constructor(baseURL: string, config: OAuthConfig);
159
+ /**
160
+ * Genera la URL de autorización OAuth con PKCE y almacena el estado
161
+ * pendiente automáticamente. Usar con handleCallback(code) sin codeVerifier.
162
+ *
163
+ * Este es el método recomendado para la mayoría de los casos.
164
+ *
165
+ * @param options - Opciones adicionales (state personalizado, scopes)
166
+ * @returns URL de autorización lista para redirigir al usuario
167
+ */
168
+ getAuthorizationUrl(options?: {
169
+ state?: string;
170
+ scopes?: string[];
171
+ }): Promise<string>;
172
+ /**
173
+ * Genera la URL de inicio de sesión OAuth con PKCE.
174
+ *
175
+ * Método de control manual: devuelve codeVerifier y state que el desarrollador
176
+ * debe gestionar. Para un flujo automático, usar getAuthorizationUrl() en su lugar.
177
+ *
178
+ * @param options - Opciones adicionales (state personalizado, scopes)
179
+ * @returns URL de autorización, code_verifier y state
180
+ */
181
+ getLoginUrl(options?: {
182
+ state?: string;
183
+ scopes?: string[];
184
+ }): Promise<LoginUrlResult>;
185
+ /**
186
+ * Abre una ventana emergente para inicio de sesión OAuth y devuelve tokens al completarse.
187
+ *
188
+ * @param options - Opciones de configuración de la ventana emergente
189
+ * @returns Tokens OAuth
190
+ * @throws Error si la ventana es bloqueada, cerrada o excede el tiempo límite
191
+ */
192
+ loginWithPopup(options?: PopupLoginOptions): Promise<OAuthTokens>;
193
+ /**
194
+ * Intercambia el código de autorización por tokens.
195
+ *
196
+ * Si se llama sin codeVerifier, recupera automáticamente el estado PKCE
197
+ * almacenado por getAuthorizationUrl() y valida el state CSRF.
198
+ *
199
+ * @param code - Código de autorización recibido en el callback
200
+ * @param codeVerifier - Verificador PKCE (opcional si se usó getAuthorizationUrl)
201
+ * @param callbackState - Valor de state recibido en el callback (para validación CSRF automática)
202
+ * @returns Tokens OAuth
203
+ */
204
+ handleCallback(code: string, codeVerifier?: string, callbackState?: string): Promise<OAuthTokens>;
205
+ /**
206
+ * Refresca el token de acceso usando el refresh_token
207
+ *
208
+ * @returns Nuevos tokens OAuth
209
+ * @throws Error si no hay refresh_token disponible
210
+ */
211
+ refreshToken(): Promise<OAuthTokens>;
212
+ /**
213
+ * Obtiene información del usuario autenticado
214
+ *
215
+ * @returns Datos del usuario desde /oauth/userinfo
216
+ */
217
+ getUserInfo(): Promise<OAuthUserInfo>;
218
+ /**
219
+ * Revoca el token actual
220
+ *
221
+ * @param tokenType - Tipo de token a revocar ('access_token' | 'refresh_token').
222
+ * Por defecto revoca el access_token.
223
+ */
224
+ revokeToken(tokenType?: 'access_token' | 'refresh_token'): Promise<void>;
225
+ /**
226
+ * Obtiene un access token válido, refrescándolo automáticamente si ha expirado
227
+ *
228
+ * @returns Access token válido
229
+ * @throws Error si no hay tokens disponibles
230
+ */
231
+ getAccessToken(): Promise<string>;
232
+ /**
233
+ * Verifica si hay una sesión OAuth activa con tokens válidos.
234
+ *
235
+ * @returns true si hay tokens almacenados y el access token no ha expirado
236
+ * (o si hay un refresh token disponible para renovarlo)
237
+ */
238
+ isAuthenticated(): Promise<boolean>;
239
+ /**
240
+ * Cierra la sesión OAuth: revoca los tokens y limpia el almacenamiento.
241
+ */
242
+ logout(): Promise<void>;
243
+ private getPendingState;
244
+ private clearPendingState;
245
+ }
246
+
21
247
  /**
22
248
  * Cliente HTTP base para el SDK
23
249
  * Maneja la comunicacion con la API de UTILIA OS
@@ -26,7 +252,18 @@ interface RequestConfig {
26
252
  declare class UtiliaClient {
27
253
  private readonly axios;
28
254
  private readonly config;
255
+ private readonly _oauthService?;
256
+ /** Promesa compartida para evitar refreshes concurrentes */
257
+ private _refreshPromise;
29
258
  constructor(config: UtiliaSDKConfig);
259
+ /**
260
+ * Acceso al servicio OAuth (solo disponible en modo OAuth)
261
+ */
262
+ get oauth(): OAuthService;
263
+ /**
264
+ * Configura interceptores para autenticación OAuth
265
+ */
266
+ private setupOAuthInterceptors;
30
267
  /**
31
268
  * Configura los interceptores de request y response
32
269
  */
@@ -36,15 +273,15 @@ declare class UtiliaClient {
36
273
  */
37
274
  private toSDKError;
38
275
  /**
39
- * Determina si un error es recuperable y se debe reintentar
276
+ * Determina si un error es recuperable y se debe reintentar.
40
277
  */
41
278
  private isRetryableError;
42
279
  /**
43
- * Ejecuta una funcion con reintentos y backoff exponencial
280
+ * Ejecuta una función con reintentos y backoff exponencial
44
281
  */
45
282
  private executeWithRetry;
46
283
  /**
47
- * Genera un ID simple como fallback cuando crypto.randomUUID no esta disponible
284
+ * Genera un ID simple como fallback cuando crypto.randomUUID no está disponible
48
285
  */
49
286
  private generateSimpleId;
50
287
  /**
@@ -52,15 +289,23 @@ declare class UtiliaClient {
52
289
  */
53
290
  private sleep;
54
291
  /**
55
- * Construye una URL completa para conexiones SSE con la API key como query param.
56
- * Util para EventSource que no soporta headers personalizados.
292
+ * Construye una URL completa para conexiones SSE con credenciales como query param.
293
+ * Necesario porque EventSource no soporta headers personalizados.
57
294
  *
58
295
  * @param path - Ruta relativa de la API (ej: /external/v1/tickets/ai-suggest/123/stream)
59
- * @returns URL completa con apiKey como parametro de consulta
296
+ * @returns URL completa con credenciales como parametro de consulta
60
297
  */
61
298
  buildSseUrl(path: string): string;
62
299
  /**
63
- * Realiza una peticion GET
300
+ * Construye una URL completa para conexiones SSE, incluyendo token OAuth si está disponible.
301
+ * Versión asíncrona que obtiene el access token actual.
302
+ *
303
+ * @param path - Ruta relativa de la API
304
+ * @returns URL completa con credenciales como parametro de consulta
305
+ */
306
+ buildSseUrlAsync(path: string): Promise<string>;
307
+ /**
308
+ * Realiza una petición GET
64
309
  */
65
310
  get<T>(url: string, config?: RequestConfig): Promise<T>;
66
311
  /**
@@ -1222,6 +1467,8 @@ declare enum ErrorCode {
1222
1467
  VALIDATION_ERROR = "VALIDATION_ERROR",
1223
1468
  /** Error de conexion de red */
1224
1469
  NETWORK_ERROR = "NETWORK_ERROR",
1470
+ /** Sesión OAuth expirada (access token y refresh token inválidos) */
1471
+ AUTH_EXPIRED = "AUTH_EXPIRED",
1225
1472
  /** Error desconocido */
1226
1473
  UNKNOWN = "UNKNOWN"
1227
1474
  }
@@ -1271,6 +1518,67 @@ declare class UtiliaSDKError extends Error {
1271
1518
  isRetryable(): boolean;
1272
1519
  }
1273
1520
 
1521
+ /**
1522
+ * Implementaciones de almacenamiento de tokens OAuth
1523
+ */
1524
+
1525
+ /**
1526
+ * Almacenamiento de tokens en memoria.
1527
+ * Los tokens se pierden al cerrar el proceso.
1528
+ */
1529
+ declare class MemoryTokenStorage implements TokenStorage {
1530
+ private tokens;
1531
+ private pendingState;
1532
+ getTokens(): Promise<OAuthTokens | null>;
1533
+ setTokens(tokens: OAuthTokens): Promise<void>;
1534
+ clearTokens(): Promise<void>;
1535
+ getPendingState(): Promise<PendingOAuthState | null>;
1536
+ setPendingState(state: PendingOAuthState): Promise<void>;
1537
+ clearPendingState(): Promise<void>;
1538
+ }
1539
+ /**
1540
+ * Almacenamiento de tokens en archivo JSON (solo Node.js).
1541
+ * Persiste los tokens entre ejecuciones.
1542
+ */
1543
+ declare class FileTokenStorage implements TokenStorage {
1544
+ private readonly filePath;
1545
+ /**
1546
+ * @param filePath - Ruta absoluta al archivo donde se guardarán los tokens
1547
+ */
1548
+ constructor(filePath: string);
1549
+ getTokens(): Promise<OAuthTokens | null>;
1550
+ setTokens(tokens: OAuthTokens): Promise<void>;
1551
+ clearTokens(): Promise<void>;
1552
+ private get pendingStatePath();
1553
+ getPendingState(): Promise<PendingOAuthState | null>;
1554
+ setPendingState(state: PendingOAuthState): Promise<void>;
1555
+ clearPendingState(): Promise<void>;
1556
+ }
1557
+
1558
+ /**
1559
+ * Utilidades PKCE (Proof Key for Code Exchange) para OAuth 2.1
1560
+ *
1561
+ * Usa crypto.getRandomValues y crypto.subtle, disponibles tanto en
1562
+ * navegador como en Node.js >= 18.
1563
+ */
1564
+ /**
1565
+ * Codifica un ArrayBuffer/Uint8Array en base64url (sin padding)
1566
+ */
1567
+ declare function base64UrlEncode(buffer: ArrayBuffer | Uint8Array): string;
1568
+ /**
1569
+ * Genera un code_verifier aleatorio compatible con RFC 7636
1570
+ *
1571
+ * @param length - Longitud del verificador (entre 43 y 128, default: 64)
1572
+ */
1573
+ declare function generateCodeVerifier(length?: number): string;
1574
+ /**
1575
+ * Genera el code_challenge a partir de un code_verifier usando SHA-256
1576
+ *
1577
+ * @param verifier - El code_verifier generado previamente
1578
+ * @returns code_challenge en base64url
1579
+ */
1580
+ declare function generateCodeChallenge(verifier: string): Promise<string>;
1581
+
1274
1582
  /**
1275
1583
  * Constantes y limites del SDK
1276
1584
  */
@@ -1325,9 +1633,10 @@ declare const SDK_LIMITS: {
1325
1633
  * - `files`: Operaciones con archivos adjuntos
1326
1634
  * - `tickets`: Operaciones con tickets de soporte
1327
1635
  * - `users`: Operaciones con usuarios externos
1328
- * - `ai`: Funcionalidades de IA (transcripcion, sugerencias)
1636
+ * - `ai`: Funcionalidades de IA (transcripción, sugerencias)
1329
1637
  */
1330
1638
  declare class UtiliaSDK {
1639
+ private readonly _client;
1331
1640
  /** Servicio de errores del sistema */
1332
1641
  readonly errors: ErrorsService;
1333
1642
  /** Servicio de archivos adjuntos */
@@ -1336,33 +1645,43 @@ declare class UtiliaSDK {
1336
1645
  readonly tickets: TicketsService;
1337
1646
  /** Servicio de usuarios externos */
1338
1647
  readonly users: UsersService;
1339
- /** Servicio de IA para transcripcion y sugerencias */
1648
+ /** Servicio de IA para transcripción y sugerencias */
1340
1649
  readonly ai: AiService;
1341
1650
  /**
1342
1651
  * Crea una nueva instancia del SDK
1343
1652
  *
1344
- * @param config - Configuracion del SDK
1653
+ * @param config - Configuración del SDK
1345
1654
  *
1346
- * @example
1655
+ * @example Autenticación con API Key
1347
1656
  * ```typescript
1348
1657
  * const sdk = new UtiliaSDK({
1349
1658
  * baseURL: 'https://os.utilia.ai/api',
1350
1659
  * apiKey: 'tu-api-key',
1351
- * timeout: 30000, // opcional
1352
- * debug: true, // opcional, habilita logs
1353
1660
  * });
1661
+ * ```
1354
1662
  *
1355
- * // Subir archivo y crear ticket con adjunto
1356
- * const file = await sdk.files.upload(inputFile);
1357
- * const ticket = await sdk.tickets.create({
1358
- * user: { externalId: 'user-123' },
1359
- * title: 'Problema con facturacion',
1360
- * description: 'No puedo ver mis facturas...',
1361
- * attachmentIds: [file.id],
1663
+ * @example Autenticación con OAuth 2.1 + PKCE
1664
+ * ```typescript
1665
+ * const sdk = new UtiliaSDK({
1666
+ * baseURL: 'https://os.utilia.ai/api',
1667
+ * oauth: {
1668
+ * clientId: 'tu-client-id',
1669
+ * redirectUri: 'https://tu-app.com/callback',
1670
+ * },
1362
1671
  * });
1672
+ *
1673
+ * // Obtener URL de autorización (gestiona PKCE automáticamente)
1674
+ * const authUrl = await sdk.oauth.getAuthorizationUrl();
1675
+ *
1676
+ * // Tras el callback (recupera PKCE automáticamente)
1677
+ * const tokens = await sdk.oauth.handleCallback(code);
1363
1678
  * ```
1364
1679
  */
1365
1680
  constructor(config: UtiliaSDKConfig);
1681
+ /**
1682
+ * Servicio OAuth (solo disponible si se configuro oauth en el constructor)
1683
+ */
1684
+ get oauth(): OAuthService;
1366
1685
  }
1367
1686
 
1368
- export { type AddMessageInput, type AiJobStatus, type AiSuggestInput, type AiSuggestions, type AiUserAction, type CreateTicketInput, type CreateTicketUser, type CreatedMessage, type CreatedTicket, ErrorCode, type ErrorFilters, type ErrorHttpMethod, type ErrorSeverity, type ErrorStats, type ExternalUser, type FileQuota, type GetSuggestionsOptions, type IdentifyUserInput, type MessageAuthor, type PaginatedResponse, type PaginationMeta, type ReportErrorInput, type ReportedError, type RequestConfig, SDK_LIMITS, type SseEvent, type StreamSuggestionsHandle, type StreamSuggestionsOptions, type StreamTranscriptionOptions, type SystemError, type TicketAttachment, type TicketCategory, type TicketContext, type TicketDetail, type TicketFilters, type TicketListItem, type TicketMessage, type TicketPriority, type TicketReporter, type TicketStatus, type TrackAiActionInput, type TranscriptionJobStatus, type UnreadCount, type UploadFileOptions, type UploadedFile, UtiliaSDK, type UtiliaSDKConfig, UtiliaSDKError };
1687
+ export { type AddMessageInput, type AiJobStatus, type AiSuggestInput, type AiSuggestions, type AiUserAction, type CreateTicketInput, type CreateTicketUser, type CreatedMessage, type CreatedTicket, ErrorCode, type ErrorFilters, type ErrorHttpMethod, type ErrorSeverity, type ErrorStats, type ExternalUser, type FileQuota, FileTokenStorage, type GetSuggestionsOptions, type IdentifyUserInput, type LoginUrlResult, MemoryTokenStorage, type MessageAuthor, type OAuthConfig, OAuthService, type OAuthTokens, type OAuthUserInfo, type PKCEChallenge, type PaginatedResponse, type PaginationMeta, type PendingOAuthState, type PopupLoginOptions, type ReportErrorInput, type ReportedError, type RequestConfig, SDK_LIMITS, type SseEvent, type StreamSuggestionsHandle, type StreamSuggestionsOptions, type StreamTranscriptionOptions, type SystemError, type TicketAttachment, type TicketCategory, type TicketContext, type TicketDetail, type TicketFilters, type TicketListItem, type TicketMessage, type TicketPriority, type TicketReporter, type TicketStatus, type TokenStorage, type TrackAiActionInput, type TranscriptionJobStatus, type UnreadCount, type UploadFileOptions, type UploadedFile, UtiliaSDK, type UtiliaSDKConfig, UtiliaSDKError, base64UrlEncode, generateCodeChallenge, generateCodeVerifier };