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 +1 -0
- package/fesm2022/ngx-dsxlibrary.mjs +130 -64
- package/fesm2022/ngx-dsxlibrary.mjs.map +1 -1
- package/ngx-dsxlibrary-1.21.25.tgz +0 -0
- package/package.json +1 -1
- package/types/ngx-dsxlibrary.d.ts +57 -17
- package/ngx-dsxlibrary-1.21.22.tgz +0 -0
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
*
|
|
2676
|
-
*
|
|
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
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
//
|
|
2709
|
-
if (
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
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
|