ngx-dsxlibrary 1.21.22 → 1.21.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -16,4 +16,5 @@ Se actualizo el servicio authorize se agrego getTokenValues y se agrego a primeN
16
16
  Se actualizo primeNg se agrego PanelMenuModule y se dio acceso al servicio de error 1.21.9
17
17
  Se actualizo primeNg se agrego DrawerModule 1.21.10
18
18
  Se actualiza url de json loader 1.21.12
19
+ Se actualizo el interceptor http-authorize para manejar correctamente el refresh de token (401), detener peticiones cuando el TokenRefresh es inválido y mostrar mensajes de error más claros al usuario 1.21.24
19
20
  ```
@@ -6,7 +6,7 @@ import { TagModule } from 'primeng/tag';
6
6
  import { CountUpDirective } from 'ngx-countup';
7
7
  import { map, catchError, of, shareReplay, throwError, BehaviorSubject, EMPTY, switchMap, filter, take, finalize } from 'rxjs';
8
8
  import * as i1$1 from '@angular/common/http';
9
- import { HttpClient, HttpHeaders, HttpParams, HttpStatusCode } from '@angular/common/http';
9
+ import { HttpClient, HttpHeaders, HttpParams, HttpStatusCode, HttpErrorResponse } from '@angular/common/http';
10
10
  import * as i2 from '@angular/platform-browser';
11
11
  import { LottieComponent } from 'ngx-lottie';
12
12
  import * as i4 from '@angular/forms';
@@ -1700,7 +1700,8 @@ class ErrorHandlerService {
1700
1700
  'Solicitud incorrecta (400). Verifica los datos ingresados o validaciones existentes.';
1701
1701
  break;
1702
1702
  case HttpStatusCode.Unauthorized:
1703
- userMessage = 'Acceso no autorizado (401). Por favor inicia sesión.';
1703
+ userMessage =
1704
+ '<b>Acceso no autorizado</b> (401). Por favor inicia sesión.';
1704
1705
  break;
1705
1706
  case HttpStatusCode.Forbidden:
1706
1707
  userMessage = 'No tienes permisos para realizar esta acción (403).';
@@ -1725,7 +1726,7 @@ class ErrorHandlerService {
1725
1726
  err.status +
1726
1727
  ' <i>Message:</i> ' +
1727
1728
  userMessage +
1728
- `.<strong class="alertMessageDsx"> (${error.error})</strong>`);
1729
+ `<strong class="alertMessageDsx"> (${error.error})</strong>`);
1729
1730
  // Imprimir el mensaje técnico
1730
1731
  if (isDevMode()) {
1731
1732
  console.error(err);
@@ -1796,16 +1797,32 @@ const httpAuthorizeInterceptor = (req, next) => {
1796
1797
  // Si no se está refrescando el token, inicia el proceso de refresh
1797
1798
  if (!isRefreshing) {
1798
1799
  isRefreshing = true;
1799
- refreshTokenSubject.next(null);
1800
+ // Reiniciar el subject en cada ciclo de refresh para evitar estados cerrados por error
1801
+ refreshTokenSubject = new BehaviorSubject(null);
1800
1802
  // Solicita el refresh del token
1801
1803
  return _securityService.tokenRefresh(refreshToken).pipe(switchMap((response) => {
1804
+ // Si el servicio de refresh indica fallo o no retorna datos, mostrar error y cortar flujo
1805
+ if (!response.isSuccess || !response.data) {
1806
+ //console.log('Refresh token fallido:', response);
1807
+ isRefreshing = false;
1808
+ const refreshError = new HttpErrorResponse({
1809
+ status: HttpStatusCode.Unauthorized,
1810
+ statusText: 'Token de refresco inválido',
1811
+ error: response.message,
1812
+ url: req.url,
1813
+ });
1814
+ // Notificar a las peticiones en espera que el refresh falló
1815
+ refreshTokenSubject.error(refreshError);
1816
+ // Enviamos el error al manejador centralizado para mostrar el mensaje al usuario
1817
+ return _handleErrorService.handleErrorResponse(refreshError);
1818
+ }
1819
+ // Refresh exitoso: actualizar tokens y repetir la petición original
1802
1820
  isRefreshing = false;
1803
1821
  _authorizeService.tokenReload(response.data); // Actualiza el token en el servicio
1804
- refreshTokenSubject.next(response.data?.token); // Emite el nuevo token
1805
- // Repite la petición original con el nuevo token
1822
+ refreshTokenSubject.next(response.data.token); // Emite el nuevo token
1806
1823
  return next(req.clone({
1807
1824
  setHeaders: {
1808
- Authorization: `Bearer ${response.data?.token}`,
1825
+ Authorization: `Bearer ${response.data.token}`,
1809
1826
  },
1810
1827
  }));
1811
1828
  }), catchError((err) => {
@@ -2148,6 +2165,32 @@ function createTypedCacheProvider(tokenName) {
2148
2165
  return { token, provider };
2149
2166
  }
2150
2167
 
2168
+ class DteService {
2169
+ /** Servicio HttpClient para realizar peticiones HTTP */
2170
+ http = inject(HttpClient);
2171
+ /**
2172
+ * Configuración del entorno inyectada mediante el token ENVIRONMENT.
2173
+ * La validación se realiza automáticamente al usar provideEnvironment().
2174
+ */
2175
+ environment = inject(ENVIRONMENT);
2176
+ /** URL base de la API JWT construida desde la configuración del entorno */
2177
+ SeguridadITApi = `${this.environment.SeguridadITApiUrl}api/dte`;
2178
+ pdfDTE(UUID) {
2179
+ // Realiza una solicitud POST al endpoint de refresco de token
2180
+ return this.http.get(`${this.SeguridadITApi}/pdf-dte/${UUID}`, {
2181
+ responseType: 'blob',
2182
+ });
2183
+ }
2184
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DteService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2185
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DteService, providedIn: 'root' });
2186
+ }
2187
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DteService, decorators: [{
2188
+ type: Injectable,
2189
+ args: [{
2190
+ providedIn: 'root',
2191
+ }]
2192
+ }] });
2193
+
2151
2194
  class EndpointService {
2152
2195
  http = inject(HttpClient);
2153
2196
  environment = inject(ENVIRONMENT);
@@ -2404,7 +2447,7 @@ class UtilityAddService {
2404
2447
  * @param actionId 0 para abrir en nueva ventana, 1 para descargar
2405
2448
  * @param fileName Nombre del archivo sin extensión
2406
2449
  */
2407
- handleFileResponse(fileObservable, actionId, fileName) {
2450
+ handleFileResponse(fileObservable, actionId = 0, fileName) {
2408
2451
  fileObservable.subscribe({
2409
2452
  next: (fileBlob) => {
2410
2453
  const fileUrl = URL.createObjectURL(fileBlob);
@@ -2436,6 +2479,67 @@ class UtilityAddService {
2436
2479
  break;
2437
2480
  }
2438
2481
  }
2482
+ /**
2483
+ * Abre un archivo PDF en una nueva pestaña del navegador.
2484
+ *
2485
+ * @param blob - Objeto Blob que contiene los datos del archivo PDF.
2486
+ *
2487
+ * @example
2488
+ * // Uso típico con respuesta de servicio HTTP
2489
+ * this.pdfService.getPdf(id).subscribe(blob => {
2490
+ * this.utilityAddService.PdfView(blob);
2491
+ * });
2492
+ *
2493
+ * @description
2494
+ * Este método crea un URL temporal para el Blob del PDF y lo abre en una nueva
2495
+ * pestaña del navegador. El URL se revoca automáticamente después de 100ms para
2496
+ * liberar memoria.
2497
+ */
2498
+ PdfView(blob) {
2499
+ // Crear un URL temporal para el Blob
2500
+ const pdfUrl = URL.createObjectURL(blob);
2501
+ // Abrir el PDF en una nueva pestaña
2502
+ window.open(pdfUrl, '_blank');
2503
+ // Liberar el URL del Blob una vez que la pestaña ha sido abierta
2504
+ // Esperar un poco para asegurarse de que el archivo se ha abierto
2505
+ setTimeout(() => {
2506
+ window.URL.revokeObjectURL(pdfUrl);
2507
+ }, 100);
2508
+ }
2509
+ /**
2510
+ * Descarga un archivo PDF con un nombre personalizado que incluye el prefijo "DTE_".
2511
+ *
2512
+ * @param blob - Objeto Blob que contiene los datos del archivo PDF a descargar.
2513
+ * @param filename - Nombre base del archivo sin extensión (se agregará automáticamente ".pdf" y el prefijo "DTE_").
2514
+ *
2515
+ * @example
2516
+ * // Uso típico con respuesta de servicio HTTP
2517
+ * this.dteService.getDTE(operacionId).subscribe(blob => {
2518
+ * this.utilityAddService.downloadPdfFile(blob, '12345');
2519
+ * // Descarga el archivo como: DTE_12345.pdf
2520
+ * });
2521
+ *
2522
+ * @description
2523
+ * Este método crea un URL temporal para el Blob y simula un clic en un enlace de
2524
+ * descarga para iniciar la descarga automática del archivo. El nombre del archivo
2525
+ * sigue el formato: DTE_{filename}.pdf. El URL se revoca después de 100ms para
2526
+ * liberar memoria.
2527
+ */
2528
+ downloadPdfFile(blob, filename) {
2529
+ // Crear un URL temporal para el Blob
2530
+ const pdfUrl = URL.createObjectURL(blob);
2531
+ // Crear un enlace de descarga
2532
+ const link = document.createElement('a');
2533
+ link.href = pdfUrl;
2534
+ // Establecer el nombre del archivo utilizando el operacionId
2535
+ link.download = `DTE_${filename}.pdf`;
2536
+ // Simular un clic en el enlace para iniciar la descarga
2537
+ link.click();
2538
+ // Liberar el URL del Blob después de un pequeño retraso
2539
+ setTimeout(() => {
2540
+ window.URL.revokeObjectURL(pdfUrl);
2541
+ }, 100);
2542
+ }
2439
2543
  forceDownload(fileUrl, fullFileName) {
2440
2544
  const downloadLink = document.createElement('a');
2441
2545
  downloadLink.href = fileUrl;
@@ -2672,66 +2776,28 @@ function dateRangeValidator(control) {
2672
2776
  }
2673
2777
  /**
2674
2778
  * Valida que una fecha única esté dentro de un rango mínimo y máximo.
2675
- * Este validador es compatible con fechas en formato string ('YYYY-MM-DD') y objetos Date.
2676
- * Convierte correctamente las fechas string a fechas locales para evitar desfases por zona horaria.
2677
- *
2678
- * @param minDate Fecha mínima permitida (tipo Date, debe ser creada correctamente en local).
2679
- * @param maxDate Fecha máxima permitida (tipo Date, debe ser creada correctamente en local).
2680
- * @returns Una función validadora para Angular Reactive Forms.
2681
- *
2682
- * Ejemplo de uso:
2683
- * myControl = new FormControl('', [dateMinMaxValidator(new Date(2025, 2, 1), new Date(2025, 2, 15))]);
2684
- *
2685
- * Notas de depuración:
2686
- * - Si recibes fechas string, se convierten a local usando parseLocalDate.
2687
- * - Si recibes objetos Date, se usan directamente.
2688
- * - Si la fecha está fuera del rango, se retorna un error con detalles.
2689
- * - Si la fecha es inválida o vacía, no retorna error (null).
2779
+ * Las fechas deben utilizar la función de convertirFechaISOString para asegurar el formato correcto y que funcione con el componente primeNg.
2780
+ * @param minDate Fecha mínima permitida.
2781
+ * @param maxDate Fecha máxima permitida.
2690
2782
  */
2691
2783
  function dateMinMaxValidator(minDate, maxDate) {
2692
- /**
2693
- * Convierte un string 'YYYY-MM-DD' a un objeto Date en la zona horaria local.
2694
- * Esto evita desfases por zona horaria al crear fechas desde strings.
2695
- * @param dateString Fecha en formato 'YYYY-MM-DD'.
2696
- * @returns Date en local.
2697
- */
2698
- function parseLocalDate(dateString) {
2699
- const [year, month, day] = dateString.split('-').map(Number);
2700
- // El mes es 0-indexado en JavaScript
2701
- return new Date(year, month - 1, day);
2702
- }
2703
2784
  return (control) => {
2704
- let date = control.value;
2705
- let currentDate = null;
2706
- // Si el valor existe, intentamos convertirlo a Date
2707
- if (date) {
2708
- // Si es string con formato 'YYYY-MM-DD', convertir a local
2709
- if (typeof date === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(date)) {
2710
- currentDate = parseLocalDate(date);
2711
- }
2712
- else {
2713
- // Si es Date o string con otro formato, intentar convertir directamente
2714
- currentDate = new Date(date);
2715
- }
2716
- // Verificar si la fecha es válida
2717
- if (!isNaN(currentDate.getTime())) {
2718
- // Depuración: descomentar para ver valores en consola
2719
- // console.log('Fecha actual:', currentDate, 'Min:', minDate, 'Max:', maxDate);
2720
- // Validar si la fecha está fuera del rango permitido
2721
- if (currentDate < minDate || currentDate > maxDate) {
2722
- return {
2723
- dateNotRange: {
2724
- message: `La fecha debe estar entre ${minDate.toLocaleDateString()} y ${maxDate.toLocaleDateString()}`,
2725
- minDate: minDate.toISOString(),
2726
- maxDate: maxDate.toISOString(),
2727
- actualDate: currentDate.toISOString(), // Para depuración
2728
- },
2729
- };
2730
- }
2731
- return null; // Fecha válida y dentro del rango
2785
+ const date = control.value;
2786
+ // Verificar si el valor es una fecha válida
2787
+ if (date && !isNaN(new Date(date).getTime())) {
2788
+ const currentDate = new Date(date);
2789
+ // Validar si la fecha está fuera del rango permitido
2790
+ if (currentDate < minDate || currentDate > maxDate) {
2791
+ return {
2792
+ dateNotRange: {
2793
+ message: `La fecha debe estar entre ${minDate.toLocaleDateString()} y ${maxDate.toLocaleDateString()}`,
2794
+ minDate: minDate.toISOString(),
2795
+ maxDate: maxDate.toISOString(),
2796
+ },
2797
+ };
2732
2798
  }
2799
+ return null; // Fecha válida y dentro del rango
2733
2800
  }
2734
- // Si no hay valor o la fecha es inválida, no retorna error
2735
2801
  return null;
2736
2802
  };
2737
2803
  }
@@ -2914,5 +2980,5 @@ function CUICorrecto(cui) {
2914
2980
  * Generated bundle index. Do not edit.
2915
2981
  */
2916
2982
 
2917
- export { AlertaService, AppMessageErrorComponent, AuthorizeService, CACHE_KEYS, CacheService, CssV2Component, DsxAddToolsModule, ENVIRONMENT, EndpointService, ErrorHandlerService, INITIAL_PARAMETERS, IconDsxComponent, JsonHighlightPipe, JsonValuesDebujComponent, KpicardComponent, LoadingComponent, LoadingLottieComponent, NavbarDsxComponent, OnlyRangoPatternDirective, ParameterValuesService, PrimeNgModule, SWEET_ALERT_THEMES, SecurityService, SelectAllOnFocusDirective, TruncatePipe, UtilityAddService, atLeastOneFieldRequiredValidator, createInitialCache, createTypedCacheProvider, cuiValidator, dateMinMaxValidator, dateRangeValidator, httpAuthorizeInterceptor, nitValidator, provideEnvironment, validateEnvironmentConfig };
2983
+ export { AlertaService, AppMessageErrorComponent, AuthorizeService, CACHE_KEYS, CacheService, CssV2Component, DsxAddToolsModule, DteService, ENVIRONMENT, EndpointService, ErrorHandlerService, INITIAL_PARAMETERS, IconDsxComponent, JsonHighlightPipe, JsonValuesDebujComponent, KpicardComponent, LoadingComponent, LoadingLottieComponent, NavbarDsxComponent, OnlyRangoPatternDirective, ParameterValuesService, PrimeNgModule, SWEET_ALERT_THEMES, SecurityService, SelectAllOnFocusDirective, TruncatePipe, UtilityAddService, atLeastOneFieldRequiredValidator, createInitialCache, createTypedCacheProvider, cuiValidator, dateMinMaxValidator, dateRangeValidator, httpAuthorizeInterceptor, nitValidator, provideEnvironment, validateEnvironmentConfig };
2918
2984
  //# sourceMappingURL=ngx-dsxlibrary.mjs.map