valtech-components 2.0.839 → 2.0.841
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/esm2022/lib/components/organisms/change-password-modal/change-password-modal.component.mjs +19 -22
- package/esm2022/lib/components/organisms/mfa-modal/mfa-modal.component.mjs +5 -5
- package/esm2022/lib/services/auth/auth.service.mjs +8 -3
- package/esm2022/lib/services/errors/error-logging.interceptor.mjs +75 -0
- package/esm2022/lib/services/errors/index.mjs +15 -0
- package/esm2022/lib/services/errors/interpret-error.mjs +130 -0
- package/esm2022/lib/services/errors/provide-error-handling.mjs +39 -0
- package/esm2022/lib/services/errors/valtech-error.service.mjs +157 -0
- package/esm2022/lib/services/i18n/default-content.mjs +5 -1
- package/esm2022/lib/services/icons.service.mjs +4 -2
- package/esm2022/lib/version.mjs +2 -2
- package/esm2022/public-api.mjs +6 -1
- package/fesm2022/valtech-components.mjs +483 -76
- package/fesm2022/valtech-components.mjs.map +1 -1
- package/lib/components/organisms/change-password-modal/change-password-modal.component.d.ts +0 -1
- package/lib/services/errors/error-logging.interceptor.d.ts +26 -0
- package/lib/services/errors/index.d.ts +16 -0
- package/lib/services/errors/interpret-error.d.ts +63 -0
- package/lib/services/errors/provide-error-handling.d.ts +34 -0
- package/lib/services/errors/valtech-error.service.d.ts +102 -0
- package/lib/version.d.ts +1 -1
- package/package.json +1 -1
- package/public-api.d.ts +1 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { inject } from '@angular/core';
|
|
2
|
+
import { throwError } from 'rxjs';
|
|
3
|
+
import { catchError } from 'rxjs/operators';
|
|
4
|
+
import { AnalyticsService } from '../firebase/analytics.service';
|
|
5
|
+
import { interpretError } from './interpret-error';
|
|
6
|
+
/**
|
|
7
|
+
* Interceptor HTTP de observabilidad (Capa 1 del estándar de manejo de errores).
|
|
8
|
+
*
|
|
9
|
+
* Para CADA respuesta HTTP con error:
|
|
10
|
+
* 1. Normaliza el error con `interpretError`.
|
|
11
|
+
* 2. Loguea un evento estructurado a consola con el prefijo `[HTTP]`.
|
|
12
|
+
* 3. Reporta el error a Firebase Analytics (`source: 'http'`), si hay analytics.
|
|
13
|
+
*
|
|
14
|
+
* **NO traga el error** — lo re-lanza tal cual. Las páginas y servicios siguen
|
|
15
|
+
* recibiendo el error en su `catch` / `catchError` y deciden la UX (eso es
|
|
16
|
+
* Capa 3: `ValtechErrorService`).
|
|
17
|
+
*
|
|
18
|
+
* `AnalyticsService` se inyecta `@Optional()` — apps sin Firebase Analytics
|
|
19
|
+
* igual obtienen el log estructurado a consola.
|
|
20
|
+
*
|
|
21
|
+
* Decisión sobre 401: **se saltea** del tracking de Analytics. Un 401 es el
|
|
22
|
+
* disparador normal del flujo de refresh de token del `authInterceptor`; el
|
|
23
|
+
* token se renueva y la request se reintenta de forma transparente. Trackear
|
|
24
|
+
* cada 401 inundaría Analytics de ruido (cada sesión genera varios al expirar
|
|
25
|
+
* el access token). El 401 SÍ se loguea a consola (nivel `info`, no `error`)
|
|
26
|
+
* para no perder la traza en debugging local, pero no se reporta como error.
|
|
27
|
+
*
|
|
28
|
+
* Se registra vía {@link provideValtechErrorHandling}.
|
|
29
|
+
*/
|
|
30
|
+
export const errorLoggingInterceptor = (request, next) => {
|
|
31
|
+
// `AnalyticsService` puede no estar provisto (apps sin Firebase). El inject
|
|
32
|
+
// funcional con `optional: true` devuelve `null` en ese caso.
|
|
33
|
+
const analytics = inject(AnalyticsService, { optional: true });
|
|
34
|
+
return next(request).pipe(catchError((error) => {
|
|
35
|
+
const interpreted = interpretError(error);
|
|
36
|
+
const status = interpreted.status ?? error?.status;
|
|
37
|
+
// 401 → ruido del refresh de auth. Log informativo, sin Analytics.
|
|
38
|
+
if (status === 401) {
|
|
39
|
+
console.info(`[HTTP] 401 ${request.method} ${request.url}` +
|
|
40
|
+
(interpreted.operationId ? ` (op=${interpreted.operationId})` : ''));
|
|
41
|
+
return throwError(() => error);
|
|
42
|
+
}
|
|
43
|
+
// Log estructurado a consola — siempre, haya o no Analytics.
|
|
44
|
+
console.error('[HTTP] request failed', {
|
|
45
|
+
method: request.method,
|
|
46
|
+
url: request.url,
|
|
47
|
+
status: status ?? 'n/a',
|
|
48
|
+
code: interpreted.code,
|
|
49
|
+
operationId: interpreted.operationId ?? 'n/a',
|
|
50
|
+
isNetwork: interpreted.isNetwork,
|
|
51
|
+
message: interpreted.message,
|
|
52
|
+
});
|
|
53
|
+
// Reporte a Analytics (best-effort) — solo si hay servicio.
|
|
54
|
+
if (analytics) {
|
|
55
|
+
try {
|
|
56
|
+
analytics.logError(interpreted.message, {
|
|
57
|
+
source: 'http',
|
|
58
|
+
code: interpreted.code,
|
|
59
|
+
url: request.url,
|
|
60
|
+
method: request.method,
|
|
61
|
+
status: String(status ?? 0),
|
|
62
|
+
...(interpreted.operationId ? { operationId: interpreted.operationId } : {}),
|
|
63
|
+
...(interpreted.isNetwork ? { error_category: 'network' } : {}),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
catch (trackingError) {
|
|
67
|
+
// El tracking nunca debe romper el flujo HTTP.
|
|
68
|
+
console.warn('[HTTP] analytics tracking failed:', trackingError);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Re-lanzar: NO tragamos el error. La Capa 3 / las páginas lo manejan.
|
|
72
|
+
return throwError(() => error);
|
|
73
|
+
}));
|
|
74
|
+
};
|
|
75
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3ItbG9nZ2luZy5pbnRlcmNlcHRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvc2VydmljZXMvZXJyb3JzL2Vycm9yLWxvZ2dpbmcuaW50ZXJjZXB0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQVF2QyxPQUFPLEVBQWMsVUFBVSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzlDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM1QyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUNqRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFbkQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBdUJHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sdUJBQXVCLEdBQXNCLENBQ3hELE9BQTZCLEVBQzdCLElBQW1CLEVBQ2EsRUFBRTtJQUNsQyw0RUFBNEU7SUFDNUUsOERBQThEO0lBQzlELE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxnQkFBZ0IsRUFBRSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBRS9ELE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FDdkIsVUFBVSxDQUFDLENBQUMsS0FBYyxFQUFFLEVBQUU7UUFDNUIsTUFBTSxXQUFXLEdBQUcsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzFDLE1BQU0sTUFBTSxHQUFHLFdBQVcsQ0FBQyxNQUFNLElBQUssS0FBMkIsRUFBRSxNQUFNLENBQUM7UUFFMUUsbUVBQW1FO1FBQ25FLElBQUksTUFBTSxLQUFLLEdBQUcsRUFBRSxDQUFDO1lBQ25CLE9BQU8sQ0FBQyxJQUFJLENBQ1YsY0FBYyxPQUFPLENBQUMsTUFBTSxJQUFJLE9BQU8sQ0FBQyxHQUFHLEVBQUU7Z0JBQzNDLENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsUUFBUSxXQUFXLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUN0RSxDQUFDO1lBQ0YsT0FBTyxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDakMsQ0FBQztRQUVELDZEQUE2RDtRQUM3RCxPQUFPLENBQUMsS0FBSyxDQUFDLHVCQUF1QixFQUFFO1lBQ3JDLE1BQU0sRUFBRSxPQUFPLENBQUMsTUFBTTtZQUN0QixHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUc7WUFDaEIsTUFBTSxFQUFFLE1BQU0sSUFBSSxLQUFLO1lBQ3ZCLElBQUksRUFBRSxXQUFXLENBQUMsSUFBSTtZQUN0QixXQUFXLEVBQUUsV0FBVyxDQUFDLFdBQVcsSUFBSSxLQUFLO1lBQzdDLFNBQVMsRUFBRSxXQUFXLENBQUMsU0FBUztZQUNoQyxPQUFPLEVBQUUsV0FBVyxDQUFDLE9BQU87U0FDN0IsQ0FBQyxDQUFDO1FBRUgsNERBQTREO1FBQzVELElBQUksU0FBUyxFQUFFLENBQUM7WUFDZCxJQUFJLENBQUM7Z0JBQ0gsU0FBUyxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFO29CQUN0QyxNQUFNLEVBQUUsTUFBTTtvQkFDZCxJQUFJLEVBQUUsV0FBVyxDQUFDLElBQUk7b0JBQ3RCLEdBQUcsRUFBRSxPQUFPLENBQUMsR0FBRztvQkFDaEIsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNO29CQUN0QixNQUFNLEVBQUUsTUFBTSxDQUFDLE1BQU0sSUFBSSxDQUFDLENBQUM7b0JBQzNCLEdBQUcsQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxFQUFFLFdBQVcsRUFBRSxXQUFXLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztvQkFDNUUsR0FBRyxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsY0FBYyxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7aUJBQ2hFLENBQUMsQ0FBQztZQUNMLENBQUM7WUFBQyxPQUFPLGFBQWEsRUFBRSxDQUFDO2dCQUN2QiwrQ0FBK0M7Z0JBQy9DLE9BQU8sQ0FBQyxJQUFJLENBQUMsbUNBQW1DLEVBQUUsYUFBYSxDQUFDLENBQUM7WUFDbkUsQ0FBQztRQUNILENBQUM7UUFFRCx1RUFBdUU7UUFDdkUsT0FBTyxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDakMsQ0FBQyxDQUFDLENBQ0gsQ0FBQztBQUNKLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgSHR0cEVycm9yUmVzcG9uc2UsXG4gIEh0dHBFdmVudCxcbiAgSHR0cEhhbmRsZXJGbixcbiAgSHR0cEludGVyY2VwdG9yRm4sXG4gIEh0dHBSZXF1ZXN0LFxufSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCB0aHJvd0Vycm9yIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBjYXRjaEVycm9yIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgQW5hbHl0aWNzU2VydmljZSB9IGZyb20gJy4uL2ZpcmViYXNlL2FuYWx5dGljcy5zZXJ2aWNlJztcbmltcG9ydCB7IGludGVycHJldEVycm9yIH0gZnJvbSAnLi9pbnRlcnByZXQtZXJyb3InO1xuXG4vKipcbiAqIEludGVyY2VwdG9yIEhUVFAgZGUgb2JzZXJ2YWJpbGlkYWQgKENhcGEgMSBkZWwgZXN0w6FuZGFyIGRlIG1hbmVqbyBkZSBlcnJvcmVzKS5cbiAqXG4gKiBQYXJhIENBREEgcmVzcHVlc3RhIEhUVFAgY29uIGVycm9yOlxuICogMS4gTm9ybWFsaXphIGVsIGVycm9yIGNvbiBgaW50ZXJwcmV0RXJyb3JgLlxuICogMi4gTG9ndWVhIHVuIGV2ZW50byBlc3RydWN0dXJhZG8gYSBjb25zb2xhIGNvbiBlbCBwcmVmaWpvIGBbSFRUUF1gLlxuICogMy4gUmVwb3J0YSBlbCBlcnJvciBhIEZpcmViYXNlIEFuYWx5dGljcyAoYHNvdXJjZTogJ2h0dHAnYCksIHNpIGhheSBhbmFseXRpY3MuXG4gKlxuICogKipOTyB0cmFnYSBlbCBlcnJvcioqIOKAlCBsbyByZS1sYW56YSB0YWwgY3VhbC4gTGFzIHDDoWdpbmFzIHkgc2VydmljaW9zIHNpZ3VlblxuICogcmVjaWJpZW5kbyBlbCBlcnJvciBlbiBzdSBgY2F0Y2hgIC8gYGNhdGNoRXJyb3JgIHkgZGVjaWRlbiBsYSBVWCAoZXNvIGVzXG4gKiBDYXBhIDM6IGBWYWx0ZWNoRXJyb3JTZXJ2aWNlYCkuXG4gKlxuICogYEFuYWx5dGljc1NlcnZpY2VgIHNlIGlueWVjdGEgYEBPcHRpb25hbCgpYCDigJQgYXBwcyBzaW4gRmlyZWJhc2UgQW5hbHl0aWNzXG4gKiBpZ3VhbCBvYnRpZW5lbiBlbCBsb2cgZXN0cnVjdHVyYWRvIGEgY29uc29sYS5cbiAqXG4gKiBEZWNpc2nDs24gc29icmUgNDAxOiAqKnNlIHNhbHRlYSoqIGRlbCB0cmFja2luZyBkZSBBbmFseXRpY3MuIFVuIDQwMSBlcyBlbFxuICogZGlzcGFyYWRvciBub3JtYWwgZGVsIGZsdWpvIGRlIHJlZnJlc2ggZGUgdG9rZW4gZGVsIGBhdXRoSW50ZXJjZXB0b3JgOyBlbFxuICogdG9rZW4gc2UgcmVudWV2YSB5IGxhIHJlcXVlc3Qgc2UgcmVpbnRlbnRhIGRlIGZvcm1hIHRyYW5zcGFyZW50ZS4gVHJhY2tlYXJcbiAqIGNhZGEgNDAxIGludW5kYXLDrWEgQW5hbHl0aWNzIGRlIHJ1aWRvIChjYWRhIHNlc2nDs24gZ2VuZXJhIHZhcmlvcyBhbCBleHBpcmFyXG4gKiBlbCBhY2Nlc3MgdG9rZW4pLiBFbCA0MDEgU8ONIHNlIGxvZ3VlYSBhIGNvbnNvbGEgKG5pdmVsIGBpbmZvYCwgbm8gYGVycm9yYClcbiAqIHBhcmEgbm8gcGVyZGVyIGxhIHRyYXphIGVuIGRlYnVnZ2luZyBsb2NhbCwgcGVybyBubyBzZSByZXBvcnRhIGNvbW8gZXJyb3IuXG4gKlxuICogU2UgcmVnaXN0cmEgdsOtYSB7QGxpbmsgcHJvdmlkZVZhbHRlY2hFcnJvckhhbmRsaW5nfS5cbiAqL1xuZXhwb3J0IGNvbnN0IGVycm9yTG9nZ2luZ0ludGVyY2VwdG9yOiBIdHRwSW50ZXJjZXB0b3JGbiA9IChcbiAgcmVxdWVzdDogSHR0cFJlcXVlc3Q8dW5rbm93bj4sXG4gIG5leHQ6IEh0dHBIYW5kbGVyRm5cbik6IE9ic2VydmFibGU8SHR0cEV2ZW50PHVua25vd24+PiA9PiB7XG4gIC8vIGBBbmFseXRpY3NTZXJ2aWNlYCBwdWVkZSBubyBlc3RhciBwcm92aXN0byAoYXBwcyBzaW4gRmlyZWJhc2UpLiBFbCBpbmplY3RcbiAgLy8gZnVuY2lvbmFsIGNvbiBgb3B0aW9uYWw6IHRydWVgIGRldnVlbHZlIGBudWxsYCBlbiBlc2UgY2Fzby5cbiAgY29uc3QgYW5hbHl0aWNzID0gaW5qZWN0KEFuYWx5dGljc1NlcnZpY2UsIHsgb3B0aW9uYWw6IHRydWUgfSk7XG5cbiAgcmV0dXJuIG5leHQocmVxdWVzdCkucGlwZShcbiAgICBjYXRjaEVycm9yKChlcnJvcjogdW5rbm93bikgPT4ge1xuICAgICAgY29uc3QgaW50ZXJwcmV0ZWQgPSBpbnRlcnByZXRFcnJvcihlcnJvcik7XG4gICAgICBjb25zdCBzdGF0dXMgPSBpbnRlcnByZXRlZC5zdGF0dXMgPz8gKGVycm9yIGFzIEh0dHBFcnJvclJlc3BvbnNlKT8uc3RhdHVzO1xuXG4gICAgICAvLyA0MDEg4oaSIHJ1aWRvIGRlbCByZWZyZXNoIGRlIGF1dGguIExvZyBpbmZvcm1hdGl2bywgc2luIEFuYWx5dGljcy5cbiAgICAgIGlmIChzdGF0dXMgPT09IDQwMSkge1xuICAgICAgICBjb25zb2xlLmluZm8oXG4gICAgICAgICAgYFtIVFRQXSA0MDEgJHtyZXF1ZXN0Lm1ldGhvZH0gJHtyZXF1ZXN0LnVybH1gICtcbiAgICAgICAgICAgIChpbnRlcnByZXRlZC5vcGVyYXRpb25JZCA/IGAgKG9wPSR7aW50ZXJwcmV0ZWQub3BlcmF0aW9uSWR9KWAgOiAnJylcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gZXJyb3IpO1xuICAgICAgfVxuXG4gICAgICAvLyBMb2cgZXN0cnVjdHVyYWRvIGEgY29uc29sYSDigJQgc2llbXByZSwgaGF5YSBvIG5vIEFuYWx5dGljcy5cbiAgICAgIGNvbnNvbGUuZXJyb3IoJ1tIVFRQXSByZXF1ZXN0IGZhaWxlZCcsIHtcbiAgICAgICAgbWV0aG9kOiByZXF1ZXN0Lm1ldGhvZCxcbiAgICAgICAgdXJsOiByZXF1ZXN0LnVybCxcbiAgICAgICAgc3RhdHVzOiBzdGF0dXMgPz8gJ24vYScsXG4gICAgICAgIGNvZGU6IGludGVycHJldGVkLmNvZGUsXG4gICAgICAgIG9wZXJhdGlvbklkOiBpbnRlcnByZXRlZC5vcGVyYXRpb25JZCA/PyAnbi9hJyxcbiAgICAgICAgaXNOZXR3b3JrOiBpbnRlcnByZXRlZC5pc05ldHdvcmssXG4gICAgICAgIG1lc3NhZ2U6IGludGVycHJldGVkLm1lc3NhZ2UsXG4gICAgICB9KTtcblxuICAgICAgLy8gUmVwb3J0ZSBhIEFuYWx5dGljcyAoYmVzdC1lZmZvcnQpIOKAlCBzb2xvIHNpIGhheSBzZXJ2aWNpby5cbiAgICAgIGlmIChhbmFseXRpY3MpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhbmFseXRpY3MubG9nRXJyb3IoaW50ZXJwcmV0ZWQubWVzc2FnZSwge1xuICAgICAgICAgICAgc291cmNlOiAnaHR0cCcsXG4gICAgICAgICAgICBjb2RlOiBpbnRlcnByZXRlZC5jb2RlLFxuICAgICAgICAgICAgdXJsOiByZXF1ZXN0LnVybCxcbiAgICAgICAgICAgIG1ldGhvZDogcmVxdWVzdC5tZXRob2QsXG4gICAgICAgICAgICBzdGF0dXM6IFN0cmluZyhzdGF0dXMgPz8gMCksXG4gICAgICAgICAgICAuLi4oaW50ZXJwcmV0ZWQub3BlcmF0aW9uSWQgPyB7IG9wZXJhdGlvbklkOiBpbnRlcnByZXRlZC5vcGVyYXRpb25JZCB9IDoge30pLFxuICAgICAgICAgICAgLi4uKGludGVycHJldGVkLmlzTmV0d29yayA/IHsgZXJyb3JfY2F0ZWdvcnk6ICduZXR3b3JrJyB9IDoge30pLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGNhdGNoICh0cmFja2luZ0Vycm9yKSB7XG4gICAgICAgICAgLy8gRWwgdHJhY2tpbmcgbnVuY2EgZGViZSByb21wZXIgZWwgZmx1am8gSFRUUC5cbiAgICAgICAgICBjb25zb2xlLndhcm4oJ1tIVFRQXSBhbmFseXRpY3MgdHJhY2tpbmcgZmFpbGVkOicsIHRyYWNraW5nRXJyb3IpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIFJlLWxhbnphcjogTk8gdHJhZ2Ftb3MgZWwgZXJyb3IuIExhIENhcGEgMyAvIGxhcyBww6FnaW5hcyBsbyBtYW5lamFuLlxuICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gZXJyb3IpO1xuICAgIH0pXG4gICk7XG59O1xuIl19
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Estándar de manejo de errores del factory Valtech.
|
|
3
|
+
*
|
|
4
|
+
* - `interpretError` (Capa 0) — normaliza cualquier error a `InterpretedError`.
|
|
5
|
+
* Función pura, sin Angular DI.
|
|
6
|
+
* - `provideValtechErrorHandling` (Capa 1) — registra el interceptor HTTP de
|
|
7
|
+
* observabilidad: log estructurado + reporte a Analytics, re-lanza el error.
|
|
8
|
+
* - `ValtechErrorService` (Capa 3) — punto único para el `catch` de una página:
|
|
9
|
+
* normaliza, observa, resuelve un mensaje i18n y muestra un toast.
|
|
10
|
+
*/
|
|
11
|
+
export { interpretError } from './interpret-error';
|
|
12
|
+
export { errorLoggingInterceptor } from './error-logging.interceptor';
|
|
13
|
+
export { provideValtechErrorHandling } from './provide-error-handling';
|
|
14
|
+
export { ValtechErrorService, VALTECH_NETWORK_ERROR_KEY } from './valtech-error.service';
|
|
15
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL3NlcnZpY2VzL2Vycm9ycy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7O0dBU0c7QUFDSCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFHbkQsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDdEUsT0FBTyxFQUFFLDJCQUEyQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFFdkUsT0FBTyxFQUFFLG1CQUFtQixFQUFFLHlCQUF5QixFQUFFLE1BQU0seUJBQXlCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEVzdMOhbmRhciBkZSBtYW5lam8gZGUgZXJyb3JlcyBkZWwgZmFjdG9yeSBWYWx0ZWNoLlxuICpcbiAqIC0gYGludGVycHJldEVycm9yYCAoQ2FwYSAwKSDigJQgbm9ybWFsaXphIGN1YWxxdWllciBlcnJvciBhIGBJbnRlcnByZXRlZEVycm9yYC5cbiAqICAgRnVuY2nDs24gcHVyYSwgc2luIEFuZ3VsYXIgREkuXG4gKiAtIGBwcm92aWRlVmFsdGVjaEVycm9ySGFuZGxpbmdgIChDYXBhIDEpIOKAlCByZWdpc3RyYSBlbCBpbnRlcmNlcHRvciBIVFRQIGRlXG4gKiAgIG9ic2VydmFiaWxpZGFkOiBsb2cgZXN0cnVjdHVyYWRvICsgcmVwb3J0ZSBhIEFuYWx5dGljcywgcmUtbGFuemEgZWwgZXJyb3IuXG4gKiAtIGBWYWx0ZWNoRXJyb3JTZXJ2aWNlYCAoQ2FwYSAzKSDigJQgcHVudG8gw7puaWNvIHBhcmEgZWwgYGNhdGNoYCBkZSB1bmEgcMOhZ2luYTpcbiAqICAgbm9ybWFsaXphLCBvYnNlcnZhLCByZXN1ZWx2ZSB1biBtZW5zYWplIGkxOG4geSBtdWVzdHJhIHVuIHRvYXN0LlxuICovXG5leHBvcnQgeyBpbnRlcnByZXRFcnJvciB9IGZyb20gJy4vaW50ZXJwcmV0LWVycm9yJztcbmV4cG9ydCB0eXBlIHsgSW50ZXJwcmV0ZWRFcnJvciB9IGZyb20gJy4vaW50ZXJwcmV0LWVycm9yJztcblxuZXhwb3J0IHsgZXJyb3JMb2dnaW5nSW50ZXJjZXB0b3IgfSBmcm9tICcuL2Vycm9yLWxvZ2dpbmcuaW50ZXJjZXB0b3InO1xuZXhwb3J0IHsgcHJvdmlkZVZhbHRlY2hFcnJvckhhbmRsaW5nIH0gZnJvbSAnLi9wcm92aWRlLWVycm9yLWhhbmRsaW5nJztcblxuZXhwb3J0IHsgVmFsdGVjaEVycm9yU2VydmljZSwgVkFMVEVDSF9ORVRXT1JLX0VSUk9SX0tFWSB9IGZyb20gJy4vdmFsdGVjaC1lcnJvci5zZXJ2aWNlJztcbmV4cG9ydCB0eXBlIHsgVmFsdGVjaEVycm9ySGFuZGxlT3B0aW9ucyB9IGZyb20gJy4vdmFsdGVjaC1lcnJvci5zZXJ2aWNlJztcbiJdfQ==
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error interpretation helper for the Valtech factory.
|
|
3
|
+
*
|
|
4
|
+
* Todos los frontends del factory consumen la misma API (backend Go) y la misma
|
|
5
|
+
* librería. La lógica de interpretar errores debe vivir una sola vez, acá.
|
|
6
|
+
*
|
|
7
|
+
* El backend Go (`apperrors`) SIEMPRE devuelve errores como JSON:
|
|
8
|
+
* { "code": string, "message": string, "operationId": string }
|
|
9
|
+
* donde `message` ya viene en español y es user-friendly.
|
|
10
|
+
*
|
|
11
|
+
* En Angular un error HTTP llega como `HttpErrorResponse` (body en `.error`).
|
|
12
|
+
* Un fallo de red es un `HttpErrorResponse` con `status === 0`.
|
|
13
|
+
*
|
|
14
|
+
* Además `AuthService.handleAuthError` aplana el `HttpErrorResponse` a un
|
|
15
|
+
* `AuthError { code, message }` (code/message al nivel superior). Por eso este
|
|
16
|
+
* helper acepta AMBAS formas — el crudo y el aplanado.
|
|
17
|
+
*/
|
|
18
|
+
/** Mensaje genérico para fallos de red (sin conexión / backend inalcanzable). */
|
|
19
|
+
const NETWORK_MESSAGE = 'Sin conexión. Verifica tu conexión a internet e inténtalo de nuevo.';
|
|
20
|
+
/** Mensaje genérico para errores no identificables. */
|
|
21
|
+
const UNKNOWN_MESSAGE = 'Ocurrió un error inesperado. Inténtalo de nuevo.';
|
|
22
|
+
/** Sentinel para fallos de red. */
|
|
23
|
+
const NETWORK_CODE = 'NETWORK';
|
|
24
|
+
/** Sentinel para errores no identificables. */
|
|
25
|
+
const UNKNOWN_CODE = 'UNKNOWN';
|
|
26
|
+
/** Type guard laxo: ¿el valor parece un `HttpErrorResponse`? */
|
|
27
|
+
function isHttpErrorResponse(err) {
|
|
28
|
+
return (typeof err === 'object' &&
|
|
29
|
+
err !== null &&
|
|
30
|
+
// No importamos HttpErrorResponse para mantener la fn libre de Angular;
|
|
31
|
+
// detectamos por shape: tiene `status` numérico y `name` reconocible o `error`.
|
|
32
|
+
('status' in err || err.name === 'HttpErrorResponse'));
|
|
33
|
+
}
|
|
34
|
+
/** Devuelve un string si el valor lo es y no está vacío; si no, `undefined`. */
|
|
35
|
+
function asNonEmptyString(value) {
|
|
36
|
+
return typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Normaliza CUALQUIER error a un `InterpretedError`.
|
|
40
|
+
*
|
|
41
|
+
* Función pura — sin dependencias de Angular DI, testeable y usable desde
|
|
42
|
+
* cualquier lado (componentes, servicios, interceptores, scripts).
|
|
43
|
+
*
|
|
44
|
+
* Nunca lanza: siempre devuelve un `InterpretedError` válido.
|
|
45
|
+
*
|
|
46
|
+
* Casos cubiertos:
|
|
47
|
+
* - `HttpErrorResponse` con `status === 0` (o sin respuesta) → fallo de red.
|
|
48
|
+
* - `HttpErrorResponse` con body `{ code, message, operationId }` del backend.
|
|
49
|
+
* - `AuthError` aplanado `{ code, message }` (code/message top-level).
|
|
50
|
+
* - `Error` plano de JS → `code: 'UNKNOWN'`, `message: err.message`.
|
|
51
|
+
* - Cualquier otra cosa (string, null, undefined, objeto raro) → genérico.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* try {
|
|
56
|
+
* await firstValueFrom(this.http.get(url));
|
|
57
|
+
* } catch (err) {
|
|
58
|
+
* const e = interpretError(err);
|
|
59
|
+
* if (e.isNetwork) {
|
|
60
|
+
* this.toast.show({ message: e.message, color: 'dark' });
|
|
61
|
+
* } else {
|
|
62
|
+
* this.errorCode.set(e.code);
|
|
63
|
+
* }
|
|
64
|
+
* }
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export function interpretError(err) {
|
|
68
|
+
// 1. HttpErrorResponse — el caso más común al hablar con el backend.
|
|
69
|
+
if (isHttpErrorResponse(err)) {
|
|
70
|
+
const status = typeof err.status === 'number' ? err.status : undefined;
|
|
71
|
+
// 1a. Fallo de red: status 0 o sin body de respuesta del servidor.
|
|
72
|
+
if (status === 0) {
|
|
73
|
+
return {
|
|
74
|
+
code: NETWORK_CODE,
|
|
75
|
+
message: NETWORK_MESSAGE,
|
|
76
|
+
status: 0,
|
|
77
|
+
isNetwork: true,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
// 1b. Body del backend `{ code, message, operationId }`.
|
|
81
|
+
const body = err.error;
|
|
82
|
+
if (typeof body === 'object' && body !== null) {
|
|
83
|
+
const b = body;
|
|
84
|
+
return {
|
|
85
|
+
code: asNonEmptyString(b.code) ?? UNKNOWN_CODE,
|
|
86
|
+
message: asNonEmptyString(b.message) ?? UNKNOWN_MESSAGE,
|
|
87
|
+
operationId: asNonEmptyString(b.operationId),
|
|
88
|
+
status,
|
|
89
|
+
isNetwork: false,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// 1c. HttpErrorResponse sin body estructurado (ej. body string / null).
|
|
93
|
+
return {
|
|
94
|
+
code: UNKNOWN_CODE,
|
|
95
|
+
message: asNonEmptyString(err.message) ?? UNKNOWN_MESSAGE,
|
|
96
|
+
status,
|
|
97
|
+
isNetwork: false,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
// 2. AuthError aplanado u objeto con `code`/`message` top-level.
|
|
101
|
+
if (typeof err === 'object' && err !== null) {
|
|
102
|
+
const o = err;
|
|
103
|
+
const code = asNonEmptyString(o.code);
|
|
104
|
+
const message = asNonEmptyString(o.message);
|
|
105
|
+
if (code || message) {
|
|
106
|
+
return {
|
|
107
|
+
code: code ?? UNKNOWN_CODE,
|
|
108
|
+
message: message ?? UNKNOWN_MESSAGE,
|
|
109
|
+
operationId: asNonEmptyString(o.operationId),
|
|
110
|
+
isNetwork: false,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
// 2b. Error plano de JS (instancia de Error sin code) — `message` ya
|
|
114
|
+
// cubierto arriba; este branch atrapa Error con message vacío.
|
|
115
|
+
if (err instanceof Error) {
|
|
116
|
+
return {
|
|
117
|
+
code: UNKNOWN_CODE,
|
|
118
|
+
message: asNonEmptyString(err.message) ?? UNKNOWN_MESSAGE,
|
|
119
|
+
isNetwork: false,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// 3. Cualquier otra cosa: string, null, undefined, objeto raro.
|
|
124
|
+
return {
|
|
125
|
+
code: UNKNOWN_CODE,
|
|
126
|
+
message: UNKNOWN_MESSAGE,
|
|
127
|
+
isNetwork: false,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJwcmV0LWVycm9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9zZXJ2aWNlcy9lcnJvcnMvaW50ZXJwcmV0LWVycm9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7O0dBZ0JHO0FBbUJILGlGQUFpRjtBQUNqRixNQUFNLGVBQWUsR0FBRyxxRUFBcUUsQ0FBQztBQUU5Rix1REFBdUQ7QUFDdkQsTUFBTSxlQUFlLEdBQUcsa0RBQWtELENBQUM7QUFFM0UsbUNBQW1DO0FBQ25DLE1BQU0sWUFBWSxHQUFHLFNBQVMsQ0FBQztBQUUvQiwrQ0FBK0M7QUFDL0MsTUFBTSxZQUFZLEdBQUcsU0FBUyxDQUFDO0FBRS9CLGdFQUFnRTtBQUNoRSxTQUFTLG1CQUFtQixDQUFDLEdBQVk7SUFNdkMsT0FBTyxDQUNMLE9BQU8sR0FBRyxLQUFLLFFBQVE7UUFDdkIsR0FBRyxLQUFLLElBQUk7UUFDWix3RUFBd0U7UUFDeEUsZ0ZBQWdGO1FBQ2hGLENBQUMsUUFBUSxJQUFJLEdBQUcsSUFBSyxHQUF5QixDQUFDLElBQUksS0FBSyxtQkFBbUIsQ0FBQyxDQUM3RSxDQUFDO0FBQ0osQ0FBQztBQUVELGdGQUFnRjtBQUNoRixTQUFTLGdCQUFnQixDQUFDLEtBQWM7SUFDdEMsT0FBTyxPQUFPLEtBQUssS0FBSyxRQUFRLElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQzNFLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTRCRztBQUNILE1BQU0sVUFBVSxjQUFjLENBQUMsR0FBWTtJQUN6QyxxRUFBcUU7SUFDckUsSUFBSSxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQzdCLE1BQU0sTUFBTSxHQUFHLE9BQU8sR0FBRyxDQUFDLE1BQU0sS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztRQUV2RSxtRUFBbUU7UUFDbkUsSUFBSSxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDakIsT0FBTztnQkFDTCxJQUFJLEVBQUUsWUFBWTtnQkFDbEIsT0FBTyxFQUFFLGVBQWU7Z0JBQ3hCLE1BQU0sRUFBRSxDQUFDO2dCQUNULFNBQVMsRUFBRSxJQUFJO2FBQ2hCLENBQUM7UUFDSixDQUFDO1FBRUQseURBQXlEO1FBQ3pELE1BQU0sSUFBSSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUM7UUFDdkIsSUFBSSxPQUFPLElBQUksS0FBSyxRQUFRLElBQUksSUFBSSxLQUFLLElBQUksRUFBRSxDQUFDO1lBQzlDLE1BQU0sQ0FBQyxHQUFHLElBSVQsQ0FBQztZQUNGLE9BQU87Z0JBQ0wsSUFBSSxFQUFFLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxZQUFZO2dCQUM5QyxPQUFPLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLGVBQWU7Z0JBQ3ZELFdBQVcsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDO2dCQUM1QyxNQUFNO2dCQUNOLFNBQVMsRUFBRSxLQUFLO2FBQ2pCLENBQUM7UUFDSixDQUFDO1FBRUQsd0VBQXdFO1FBQ3hFLE9BQU87WUFDTCxJQUFJLEVBQUUsWUFBWTtZQUNsQixPQUFPLEVBQUUsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLGVBQWU7WUFDekQsTUFBTTtZQUNOLFNBQVMsRUFBRSxLQUFLO1NBQ2pCLENBQUM7SUFDSixDQUFDO0lBRUQsaUVBQWlFO0lBQ2pFLElBQUksT0FBTyxHQUFHLEtBQUssUUFBUSxJQUFJLEdBQUcsS0FBSyxJQUFJLEVBQUUsQ0FBQztRQUM1QyxNQUFNLENBQUMsR0FBRyxHQUlULENBQUM7UUFDRixNQUFNLElBQUksR0FBRyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDdEMsTUFBTSxPQUFPLEdBQUcsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRTVDLElBQUksSUFBSSxJQUFJLE9BQU8sRUFBRSxDQUFDO1lBQ3BCLE9BQU87Z0JBQ0wsSUFBSSxFQUFFLElBQUksSUFBSSxZQUFZO2dCQUMxQixPQUFPLEVBQUUsT0FBTyxJQUFJLGVBQWU7Z0JBQ25DLFdBQVcsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDO2dCQUM1QyxTQUFTLEVBQUUsS0FBSzthQUNqQixDQUFDO1FBQ0osQ0FBQztRQUVELHFFQUFxRTtRQUNyRSxtRUFBbUU7UUFDbkUsSUFBSSxHQUFHLFlBQVksS0FBSyxFQUFFLENBQUM7WUFDekIsT0FBTztnQkFDTCxJQUFJLEVBQUUsWUFBWTtnQkFDbEIsT0FBTyxFQUFFLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxlQUFlO2dCQUN6RCxTQUFTLEVBQUUsS0FBSzthQUNqQixDQUFDO1FBQ0osQ0FBQztJQUNILENBQUM7SUFFRCxnRUFBZ0U7SUFDaEUsT0FBTztRQUNMLElBQUksRUFBRSxZQUFZO1FBQ2xCLE9BQU8sRUFBRSxlQUFlO1FBQ3hCLFNBQVMsRUFBRSxLQUFLO0tBQ2pCLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBFcnJvciBpbnRlcnByZXRhdGlvbiBoZWxwZXIgZm9yIHRoZSBWYWx0ZWNoIGZhY3RvcnkuXG4gKlxuICogVG9kb3MgbG9zIGZyb250ZW5kcyBkZWwgZmFjdG9yeSBjb25zdW1lbiBsYSBtaXNtYSBBUEkgKGJhY2tlbmQgR28pIHkgbGEgbWlzbWFcbiAqIGxpYnJlcsOtYS4gTGEgbMOzZ2ljYSBkZSBpbnRlcnByZXRhciBlcnJvcmVzIGRlYmUgdml2aXIgdW5hIHNvbGEgdmV6LCBhY8OhLlxuICpcbiAqIEVsIGJhY2tlbmQgR28gKGBhcHBlcnJvcnNgKSBTSUVNUFJFIGRldnVlbHZlIGVycm9yZXMgY29tbyBKU09OOlxuICogICB7IFwiY29kZVwiOiBzdHJpbmcsIFwibWVzc2FnZVwiOiBzdHJpbmcsIFwib3BlcmF0aW9uSWRcIjogc3RyaW5nIH1cbiAqIGRvbmRlIGBtZXNzYWdlYCB5YSB2aWVuZSBlbiBlc3Bhw7FvbCB5IGVzIHVzZXItZnJpZW5kbHkuXG4gKlxuICogRW4gQW5ndWxhciB1biBlcnJvciBIVFRQIGxsZWdhIGNvbW8gYEh0dHBFcnJvclJlc3BvbnNlYCAoYm9keSBlbiBgLmVycm9yYCkuXG4gKiBVbiBmYWxsbyBkZSByZWQgZXMgdW4gYEh0dHBFcnJvclJlc3BvbnNlYCBjb24gYHN0YXR1cyA9PT0gMGAuXG4gKlxuICogQWRlbcOhcyBgQXV0aFNlcnZpY2UuaGFuZGxlQXV0aEVycm9yYCBhcGxhbmEgZWwgYEh0dHBFcnJvclJlc3BvbnNlYCBhIHVuXG4gKiBgQXV0aEVycm9yIHsgY29kZSwgbWVzc2FnZSB9YCAoY29kZS9tZXNzYWdlIGFsIG5pdmVsIHN1cGVyaW9yKS4gUG9yIGVzbyBlc3RlXG4gKiBoZWxwZXIgYWNlcHRhIEFNQkFTIGZvcm1hcyDigJQgZWwgY3J1ZG8geSBlbCBhcGxhbmFkby5cbiAqL1xuXG4vKipcbiAqIFJlc3VsdGFkbyBub3JtYWxpemFkbyBkZSBjdWFscXVpZXIgZXJyb3IuIEdhcmFudGl6YSB1bmEgZm9ybWEgZXN0YWJsZSB5XG4gKiBwcmVkZWNpYmxlIHBhcmEgcXVlIGxhcyB3ZWJhcHBzIG5vIHRlbmdhbiBxdWUgaGFjZXIgbmFycm93aW5nIG1hbnVhbC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJbnRlcnByZXRlZEVycm9yIHtcbiAgLyoqIEPDs2RpZ28gZGVsIGJhY2tlbmQsIG8gZWwgc2VudGluZWwgYCdORVRXT1JLJ2AgLyBgJ1VOS05PV04nYC4gKi9cbiAgY29kZTogc3RyaW5nO1xuICAvKiogTWVuc2FqZSBkZWwgYmFja2VuZCAoZXNwYcOxb2wsIHVzZXItZnJpZW5kbHkpIG8gdW4gZ2Vuw6lyaWNvIGVuIGVzcGHDsW9sLiAqL1xuICBtZXNzYWdlOiBzdHJpbmc7XG4gIC8qKiBgb3BlcmF0aW9uSWRgIGRlbCBiYWNrZW5kLCBzaSB2aW5vLiDDmnRpbCBwYXJhIHNvcG9ydGUgLyB0cmFjaW5nLiAqL1xuICBvcGVyYXRpb25JZD86IHN0cmluZztcbiAgLyoqIEhUVFAgc3RhdHVzLCBzaSBhcGxpY2EgKGAwYCBwYXJhIGZhbGxvcyBkZSByZWQpLiAqL1xuICBzdGF0dXM/OiBudW1iZXI7XG4gIC8qKiBgdHJ1ZWAgc2kgZnVlIHVuIGZhbGxvIGRlIHJlZCAoc3RhdHVzIDAgLyBzaW4gcmVzcHVlc3RhKS4gKi9cbiAgaXNOZXR3b3JrOiBib29sZWFuO1xufVxuXG4vKiogTWVuc2FqZSBnZW7DqXJpY28gcGFyYSBmYWxsb3MgZGUgcmVkIChzaW4gY29uZXhpw7NuIC8gYmFja2VuZCBpbmFsY2FuemFibGUpLiAqL1xuY29uc3QgTkVUV09SS19NRVNTQUdFID0gJ1NpbiBjb25leGnDs24uIFZlcmlmaWNhIHR1IGNvbmV4acOzbiBhIGludGVybmV0IGUgaW50w6ludGFsbyBkZSBudWV2by4nO1xuXG4vKiogTWVuc2FqZSBnZW7DqXJpY28gcGFyYSBlcnJvcmVzIG5vIGlkZW50aWZpY2FibGVzLiAqL1xuY29uc3QgVU5LTk9XTl9NRVNTQUdFID0gJ09jdXJyacOzIHVuIGVycm9yIGluZXNwZXJhZG8uIEludMOpbnRhbG8gZGUgbnVldm8uJztcblxuLyoqIFNlbnRpbmVsIHBhcmEgZmFsbG9zIGRlIHJlZC4gKi9cbmNvbnN0IE5FVFdPUktfQ09ERSA9ICdORVRXT1JLJztcblxuLyoqIFNlbnRpbmVsIHBhcmEgZXJyb3JlcyBubyBpZGVudGlmaWNhYmxlcy4gKi9cbmNvbnN0IFVOS05PV05fQ09ERSA9ICdVTktOT1dOJztcblxuLyoqIFR5cGUgZ3VhcmQgbGF4bzogwr9lbCB2YWxvciBwYXJlY2UgdW4gYEh0dHBFcnJvclJlc3BvbnNlYD8gKi9cbmZ1bmN0aW9uIGlzSHR0cEVycm9yUmVzcG9uc2UoZXJyOiB1bmtub3duKTogZXJyIGlzIHtcbiAgc3RhdHVzPzogbnVtYmVyO1xuICBlcnJvcj86IHVua25vd247XG4gIG1lc3NhZ2U/OiBzdHJpbmc7XG4gIG5hbWU/OiBzdHJpbmc7XG59IHtcbiAgcmV0dXJuIChcbiAgICB0eXBlb2YgZXJyID09PSAnb2JqZWN0JyAmJlxuICAgIGVyciAhPT0gbnVsbCAmJlxuICAgIC8vIE5vIGltcG9ydGFtb3MgSHR0cEVycm9yUmVzcG9uc2UgcGFyYSBtYW50ZW5lciBsYSBmbiBsaWJyZSBkZSBBbmd1bGFyO1xuICAgIC8vIGRldGVjdGFtb3MgcG9yIHNoYXBlOiB0aWVuZSBgc3RhdHVzYCBudW3DqXJpY28geSBgbmFtZWAgcmVjb25vY2libGUgbyBgZXJyb3JgLlxuICAgICgnc3RhdHVzJyBpbiBlcnIgfHwgKGVyciBhcyB7IG5hbWU/OiBzdHJpbmcgfSkubmFtZSA9PT0gJ0h0dHBFcnJvclJlc3BvbnNlJylcbiAgKTtcbn1cblxuLyoqIERldnVlbHZlIHVuIHN0cmluZyBzaSBlbCB2YWxvciBsbyBlcyB5IG5vIGVzdMOhIHZhY8Otbzsgc2kgbm8sIGB1bmRlZmluZWRgLiAqL1xuZnVuY3Rpb24gYXNOb25FbXB0eVN0cmluZyh2YWx1ZTogdW5rbm93bik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnICYmIHZhbHVlLmxlbmd0aCA+IDAgPyB2YWx1ZSA6IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBOb3JtYWxpemEgQ1VBTFFVSUVSIGVycm9yIGEgdW4gYEludGVycHJldGVkRXJyb3JgLlxuICpcbiAqIEZ1bmNpw7NuIHB1cmEg4oCUIHNpbiBkZXBlbmRlbmNpYXMgZGUgQW5ndWxhciBESSwgdGVzdGVhYmxlIHkgdXNhYmxlIGRlc2RlXG4gKiBjdWFscXVpZXIgbGFkbyAoY29tcG9uZW50ZXMsIHNlcnZpY2lvcywgaW50ZXJjZXB0b3Jlcywgc2NyaXB0cykuXG4gKlxuICogTnVuY2EgbGFuemE6IHNpZW1wcmUgZGV2dWVsdmUgdW4gYEludGVycHJldGVkRXJyb3JgIHbDoWxpZG8uXG4gKlxuICogQ2Fzb3MgY3ViaWVydG9zOlxuICogLSBgSHR0cEVycm9yUmVzcG9uc2VgIGNvbiBgc3RhdHVzID09PSAwYCAobyBzaW4gcmVzcHVlc3RhKSDihpIgZmFsbG8gZGUgcmVkLlxuICogLSBgSHR0cEVycm9yUmVzcG9uc2VgIGNvbiBib2R5IGB7IGNvZGUsIG1lc3NhZ2UsIG9wZXJhdGlvbklkIH1gIGRlbCBiYWNrZW5kLlxuICogLSBgQXV0aEVycm9yYCBhcGxhbmFkbyBgeyBjb2RlLCBtZXNzYWdlIH1gIChjb2RlL21lc3NhZ2UgdG9wLWxldmVsKS5cbiAqIC0gYEVycm9yYCBwbGFubyBkZSBKUyDihpIgYGNvZGU6ICdVTktOT1dOJ2AsIGBtZXNzYWdlOiBlcnIubWVzc2FnZWAuXG4gKiAtIEN1YWxxdWllciBvdHJhIGNvc2EgKHN0cmluZywgbnVsbCwgdW5kZWZpbmVkLCBvYmpldG8gcmFybykg4oaSIGdlbsOpcmljby5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHRyeSB7XG4gKiAgIGF3YWl0IGZpcnN0VmFsdWVGcm9tKHRoaXMuaHR0cC5nZXQodXJsKSk7XG4gKiB9IGNhdGNoIChlcnIpIHtcbiAqICAgY29uc3QgZSA9IGludGVycHJldEVycm9yKGVycik7XG4gKiAgIGlmIChlLmlzTmV0d29yaykge1xuICogICAgIHRoaXMudG9hc3Quc2hvdyh7IG1lc3NhZ2U6IGUubWVzc2FnZSwgY29sb3I6ICdkYXJrJyB9KTtcbiAqICAgfSBlbHNlIHtcbiAqICAgICB0aGlzLmVycm9yQ29kZS5zZXQoZS5jb2RlKTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbnRlcnByZXRFcnJvcihlcnI6IHVua25vd24pOiBJbnRlcnByZXRlZEVycm9yIHtcbiAgLy8gMS4gSHR0cEVycm9yUmVzcG9uc2Ug4oCUIGVsIGNhc28gbcOhcyBjb23Dum4gYWwgaGFibGFyIGNvbiBlbCBiYWNrZW5kLlxuICBpZiAoaXNIdHRwRXJyb3JSZXNwb25zZShlcnIpKSB7XG4gICAgY29uc3Qgc3RhdHVzID0gdHlwZW9mIGVyci5zdGF0dXMgPT09ICdudW1iZXInID8gZXJyLnN0YXR1cyA6IHVuZGVmaW5lZDtcblxuICAgIC8vIDFhLiBGYWxsbyBkZSByZWQ6IHN0YXR1cyAwIG8gc2luIGJvZHkgZGUgcmVzcHVlc3RhIGRlbCBzZXJ2aWRvci5cbiAgICBpZiAoc3RhdHVzID09PSAwKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb2RlOiBORVRXT1JLX0NPREUsXG4gICAgICAgIG1lc3NhZ2U6IE5FVFdPUktfTUVTU0FHRSxcbiAgICAgICAgc3RhdHVzOiAwLFxuICAgICAgICBpc05ldHdvcms6IHRydWUsXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIDFiLiBCb2R5IGRlbCBiYWNrZW5kIGB7IGNvZGUsIG1lc3NhZ2UsIG9wZXJhdGlvbklkIH1gLlxuICAgIGNvbnN0IGJvZHkgPSBlcnIuZXJyb3I7XG4gICAgaWYgKHR5cGVvZiBib2R5ID09PSAnb2JqZWN0JyAmJiBib2R5ICE9PSBudWxsKSB7XG4gICAgICBjb25zdCBiID0gYm9keSBhcyB7XG4gICAgICAgIGNvZGU/OiB1bmtub3duO1xuICAgICAgICBtZXNzYWdlPzogdW5rbm93bjtcbiAgICAgICAgb3BlcmF0aW9uSWQ/OiB1bmtub3duO1xuICAgICAgfTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvZGU6IGFzTm9uRW1wdHlTdHJpbmcoYi5jb2RlKSA/PyBVTktOT1dOX0NPREUsXG4gICAgICAgIG1lc3NhZ2U6IGFzTm9uRW1wdHlTdHJpbmcoYi5tZXNzYWdlKSA/PyBVTktOT1dOX01FU1NBR0UsXG4gICAgICAgIG9wZXJhdGlvbklkOiBhc05vbkVtcHR5U3RyaW5nKGIub3BlcmF0aW9uSWQpLFxuICAgICAgICBzdGF0dXMsXG4gICAgICAgIGlzTmV0d29yazogZmFsc2UsXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIDFjLiBIdHRwRXJyb3JSZXNwb25zZSBzaW4gYm9keSBlc3RydWN0dXJhZG8gKGVqLiBib2R5IHN0cmluZyAvIG51bGwpLlxuICAgIHJldHVybiB7XG4gICAgICBjb2RlOiBVTktOT1dOX0NPREUsXG4gICAgICBtZXNzYWdlOiBhc05vbkVtcHR5U3RyaW5nKGVyci5tZXNzYWdlKSA/PyBVTktOT1dOX01FU1NBR0UsXG4gICAgICBzdGF0dXMsXG4gICAgICBpc05ldHdvcms6IGZhbHNlLFxuICAgIH07XG4gIH1cblxuICAvLyAyLiBBdXRoRXJyb3IgYXBsYW5hZG8gdSBvYmpldG8gY29uIGBjb2RlYC9gbWVzc2FnZWAgdG9wLWxldmVsLlxuICBpZiAodHlwZW9mIGVyciA9PT0gJ29iamVjdCcgJiYgZXJyICE9PSBudWxsKSB7XG4gICAgY29uc3QgbyA9IGVyciBhcyB7XG4gICAgICBjb2RlPzogdW5rbm93bjtcbiAgICAgIG1lc3NhZ2U/OiB1bmtub3duO1xuICAgICAgb3BlcmF0aW9uSWQ/OiB1bmtub3duO1xuICAgIH07XG4gICAgY29uc3QgY29kZSA9IGFzTm9uRW1wdHlTdHJpbmcoby5jb2RlKTtcbiAgICBjb25zdCBtZXNzYWdlID0gYXNOb25FbXB0eVN0cmluZyhvLm1lc3NhZ2UpO1xuXG4gICAgaWYgKGNvZGUgfHwgbWVzc2FnZSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29kZTogY29kZSA/PyBVTktOT1dOX0NPREUsXG4gICAgICAgIG1lc3NhZ2U6IG1lc3NhZ2UgPz8gVU5LTk9XTl9NRVNTQUdFLFxuICAgICAgICBvcGVyYXRpb25JZDogYXNOb25FbXB0eVN0cmluZyhvLm9wZXJhdGlvbklkKSxcbiAgICAgICAgaXNOZXR3b3JrOiBmYWxzZSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gMmIuIEVycm9yIHBsYW5vIGRlIEpTIChpbnN0YW5jaWEgZGUgRXJyb3Igc2luIGNvZGUpIOKAlCBgbWVzc2FnZWAgeWFcbiAgICAvLyAgICAgY3ViaWVydG8gYXJyaWJhOyBlc3RlIGJyYW5jaCBhdHJhcGEgRXJyb3IgY29uIG1lc3NhZ2UgdmFjw61vLlxuICAgIGlmIChlcnIgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29kZTogVU5LTk9XTl9DT0RFLFxuICAgICAgICBtZXNzYWdlOiBhc05vbkVtcHR5U3RyaW5nKGVyci5tZXNzYWdlKSA/PyBVTktOT1dOX01FU1NBR0UsXG4gICAgICAgIGlzTmV0d29yazogZmFsc2UsXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIC8vIDMuIEN1YWxxdWllciBvdHJhIGNvc2E6IHN0cmluZywgbnVsbCwgdW5kZWZpbmVkLCBvYmpldG8gcmFyby5cbiAgcmV0dXJuIHtcbiAgICBjb2RlOiBVTktOT1dOX0NPREUsXG4gICAgbWVzc2FnZTogVU5LTk9XTl9NRVNTQUdFLFxuICAgIGlzTmV0d29yazogZmFsc2UsXG4gIH07XG59XG4iXX0=
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { makeEnvironmentProviders } from '@angular/core';
|
|
2
|
+
import { provideHttpClient, withInterceptors } from '@angular/common/http';
|
|
3
|
+
import { errorLoggingInterceptor } from './error-logging.interceptor';
|
|
4
|
+
/**
|
|
5
|
+
* Provee el manejo de errores estándar del factory Valtech.
|
|
6
|
+
*
|
|
7
|
+
* Registra el {@link errorLoggingInterceptor} (Capa 1 — observabilidad): toda
|
|
8
|
+
* respuesta HTTP con error se normaliza, se loguea de forma estructurada a
|
|
9
|
+
* consola y se reporta a Firebase Analytics. El interceptor **re-lanza** el
|
|
10
|
+
* error, así que las páginas siguen haciendo su `catch`.
|
|
11
|
+
*
|
|
12
|
+
* Se registra vía `withInterceptors`, igual que el `authInterceptor`. Angular
|
|
13
|
+
* fusiona los interceptores de múltiples llamadas a `provideHttpClient` dentro
|
|
14
|
+
* del mismo injector, así que esto compone con `provideValtechAuth()` sin
|
|
15
|
+
* pisarlo. El orden relativo lo determina Angular por orden de provisión;
|
|
16
|
+
* para una traza limpia, declarar `provideValtechErrorHandling()` **después**
|
|
17
|
+
* de `provideValtechAuth(...)` en `main.ts`.
|
|
18
|
+
*
|
|
19
|
+
* La Capa 3 ({@link ValtechErrorService}) es `providedIn: 'root'` — no
|
|
20
|
+
* requiere registro. La Capa 2 (`AnalyticsErrorHandler`, errores no
|
|
21
|
+
* capturados) la activa `provideValtechFirebase` con `enableErrorTracking`.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* // main.ts
|
|
26
|
+
* import { provideValtechAuth, provideValtechErrorHandling } from 'valtech-components';
|
|
27
|
+
*
|
|
28
|
+
* bootstrapApplication(AppComponent, {
|
|
29
|
+
* providers: [
|
|
30
|
+
* provideValtechAuth({ apiUrl: environment.apiUrl }),
|
|
31
|
+
* provideValtechErrorHandling(),
|
|
32
|
+
* ],
|
|
33
|
+
* });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export function provideValtechErrorHandling() {
|
|
37
|
+
return makeEnvironmentProviders([provideHttpClient(withInterceptors([errorLoggingInterceptor]))]);
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmlkZS1lcnJvci1oYW5kbGluZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvc2VydmljZXMvZXJyb3JzL3Byb3ZpZGUtZXJyb3ItaGFuZGxpbmcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUF3Qix3QkFBd0IsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMvRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUMzRSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUV0RTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQStCRztBQUNILE1BQU0sVUFBVSwyQkFBMkI7SUFDekMsT0FBTyx3QkFBd0IsQ0FBQyxDQUFDLGlCQUFpQixDQUFDLGdCQUFnQixDQUFDLENBQUMsdUJBQXVCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3BHLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBFbnZpcm9ubWVudFByb3ZpZGVycywgbWFrZUVudmlyb25tZW50UHJvdmlkZXJzIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBwcm92aWRlSHR0cENsaWVudCwgd2l0aEludGVyY2VwdG9ycyB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7IGVycm9yTG9nZ2luZ0ludGVyY2VwdG9yIH0gZnJvbSAnLi9lcnJvci1sb2dnaW5nLmludGVyY2VwdG9yJztcblxuLyoqXG4gKiBQcm92ZWUgZWwgbWFuZWpvIGRlIGVycm9yZXMgZXN0w6FuZGFyIGRlbCBmYWN0b3J5IFZhbHRlY2guXG4gKlxuICogUmVnaXN0cmEgZWwge0BsaW5rIGVycm9yTG9nZ2luZ0ludGVyY2VwdG9yfSAoQ2FwYSAxIOKAlCBvYnNlcnZhYmlsaWRhZCk6IHRvZGFcbiAqIHJlc3B1ZXN0YSBIVFRQIGNvbiBlcnJvciBzZSBub3JtYWxpemEsIHNlIGxvZ3VlYSBkZSBmb3JtYSBlc3RydWN0dXJhZGEgYVxuICogY29uc29sYSB5IHNlIHJlcG9ydGEgYSBGaXJlYmFzZSBBbmFseXRpY3MuIEVsIGludGVyY2VwdG9yICoqcmUtbGFuemEqKiBlbFxuICogZXJyb3IsIGFzw60gcXVlIGxhcyBww6FnaW5hcyBzaWd1ZW4gaGFjaWVuZG8gc3UgYGNhdGNoYC5cbiAqXG4gKiBTZSByZWdpc3RyYSB2w61hIGB3aXRoSW50ZXJjZXB0b3JzYCwgaWd1YWwgcXVlIGVsIGBhdXRoSW50ZXJjZXB0b3JgLiBBbmd1bGFyXG4gKiBmdXNpb25hIGxvcyBpbnRlcmNlcHRvcmVzIGRlIG3Dumx0aXBsZXMgbGxhbWFkYXMgYSBgcHJvdmlkZUh0dHBDbGllbnRgIGRlbnRyb1xuICogZGVsIG1pc21vIGluamVjdG9yLCBhc8OtIHF1ZSBlc3RvIGNvbXBvbmUgY29uIGBwcm92aWRlVmFsdGVjaEF1dGgoKWAgc2luXG4gKiBwaXNhcmxvLiBFbCBvcmRlbiByZWxhdGl2byBsbyBkZXRlcm1pbmEgQW5ndWxhciBwb3Igb3JkZW4gZGUgcHJvdmlzacOzbjtcbiAqIHBhcmEgdW5hIHRyYXphIGxpbXBpYSwgZGVjbGFyYXIgYHByb3ZpZGVWYWx0ZWNoRXJyb3JIYW5kbGluZygpYCAqKmRlc3B1w6lzKipcbiAqIGRlIGBwcm92aWRlVmFsdGVjaEF1dGgoLi4uKWAgZW4gYG1haW4udHNgLlxuICpcbiAqIExhIENhcGEgMyAoe0BsaW5rIFZhbHRlY2hFcnJvclNlcnZpY2V9KSBlcyBgcHJvdmlkZWRJbjogJ3Jvb3QnYCDigJQgbm9cbiAqIHJlcXVpZXJlIHJlZ2lzdHJvLiBMYSBDYXBhIDIgKGBBbmFseXRpY3NFcnJvckhhbmRsZXJgLCBlcnJvcmVzIG5vXG4gKiBjYXB0dXJhZG9zKSBsYSBhY3RpdmEgYHByb3ZpZGVWYWx0ZWNoRmlyZWJhc2VgIGNvbiBgZW5hYmxlRXJyb3JUcmFja2luZ2AuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIG1haW4udHNcbiAqIGltcG9ydCB7IHByb3ZpZGVWYWx0ZWNoQXV0aCwgcHJvdmlkZVZhbHRlY2hFcnJvckhhbmRsaW5nIH0gZnJvbSAndmFsdGVjaC1jb21wb25lbnRzJztcbiAqXG4gKiBib290c3RyYXBBcHBsaWNhdGlvbihBcHBDb21wb25lbnQsIHtcbiAqICAgcHJvdmlkZXJzOiBbXG4gKiAgICAgcHJvdmlkZVZhbHRlY2hBdXRoKHsgYXBpVXJsOiBlbnZpcm9ubWVudC5hcGlVcmwgfSksXG4gKiAgICAgcHJvdmlkZVZhbHRlY2hFcnJvckhhbmRsaW5nKCksXG4gKiAgIF0sXG4gKiB9KTtcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJvdmlkZVZhbHRlY2hFcnJvckhhbmRsaW5nKCk6IEVudmlyb25tZW50UHJvdmlkZXJzIHtcbiAgcmV0dXJuIG1ha2VFbnZpcm9ubWVudFByb3ZpZGVycyhbcHJvdmlkZUh0dHBDbGllbnQod2l0aEludGVyY2VwdG9ycyhbZXJyb3JMb2dnaW5nSW50ZXJjZXB0b3JdKSldKTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { Injectable, inject } from '@angular/core';
|
|
2
|
+
import { AnalyticsService } from '../firebase/analytics.service';
|
|
3
|
+
import { I18nService } from '../i18n/i18n.service';
|
|
4
|
+
import { ToastService } from '../toast.service';
|
|
5
|
+
import { interpretError } from './interpret-error';
|
|
6
|
+
import * as i0 from "@angular/core";
|
|
7
|
+
/**
|
|
8
|
+
* Key i18n fija de la librería para fallos de red. Las apps pueden definirla en
|
|
9
|
+
* su contenido i18n (namespace `_global`) para personalizar el texto; si no
|
|
10
|
+
* existe, se usa {@link NETWORK_FALLBACK_MESSAGE}.
|
|
11
|
+
*/
|
|
12
|
+
export const VALTECH_NETWORK_ERROR_KEY = 'valtech.error.network';
|
|
13
|
+
/** Texto en español por defecto cuando {@link VALTECH_NETWORK_ERROR_KEY} no está definida. */
|
|
14
|
+
const NETWORK_FALLBACK_MESSAGE = 'Sin conexión. Revisá tu internet.';
|
|
15
|
+
/** Texto genérico en español cuando no hay match ni `fallbackKey`. */
|
|
16
|
+
const GENERIC_FALLBACK_MESSAGE = 'Ocurrió un error. Intentá de nuevo.';
|
|
17
|
+
/**
|
|
18
|
+
* Servicio de UX de errores capturados (Capa 3 del estándar de manejo de errores).
|
|
19
|
+
*
|
|
20
|
+
* Mientras la Capa 1 ({@link errorLoggingInterceptor}) observa TODAS las
|
|
21
|
+
* respuestas HTTP con error, y la Capa 2 (`AnalyticsErrorHandler`) captura los
|
|
22
|
+
* errores NO manejados, la Capa 3 es el punto único que una página usa en su
|
|
23
|
+
* `catch` para convertir un error en feedback al usuario.
|
|
24
|
+
*
|
|
25
|
+
* Responsabilidades de {@link handle}:
|
|
26
|
+
* 1. Normaliza el error (`interpretError`).
|
|
27
|
+
* 2. Loguea a consola + reporta a Analytics (`source: 'handled'`, con `context`).
|
|
28
|
+
* 3. Resuelve un mensaje localizado (ver orden de resolución en {@link handle}).
|
|
29
|
+
* 4. Muestra un toast (`color: 'dark'`, estándar Valtech) salvo `toast: false`.
|
|
30
|
+
* 5. Devuelve el {@link InterpretedError} para que la página decida lógica extra.
|
|
31
|
+
*
|
|
32
|
+
* **Nunca lanza.** `AnalyticsService` se inyecta `@Optional()`.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* private errors = inject(ValtechErrorService);
|
|
37
|
+
*
|
|
38
|
+
* async save() {
|
|
39
|
+
* try {
|
|
40
|
+
* await firstValueFrom(this.api.updateProfile(this.form.value));
|
|
41
|
+
* this.toast.show({ message: 'Perfil actualizado', color: 'dark' });
|
|
42
|
+
* } catch (err) {
|
|
43
|
+
* this.errors.handle(err, {
|
|
44
|
+
* context: 'profile.save',
|
|
45
|
+
* i18nMap: { EMAIL_TAKEN: 'errors.emailTaken' },
|
|
46
|
+
* fallbackKey: 'errors.profileSaveFailed',
|
|
47
|
+
* });
|
|
48
|
+
* }
|
|
49
|
+
* }
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export class ValtechErrorService {
|
|
53
|
+
constructor() {
|
|
54
|
+
this.i18n = inject(I18nService);
|
|
55
|
+
this.toast = inject(ToastService);
|
|
56
|
+
// Apps sin Firebase Analytics: el servicio sigue funcionando (log + toast).
|
|
57
|
+
this.analytics = inject(AnalyticsService, { optional: true });
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Maneja un error capturado: normaliza, observa y produce feedback de usuario.
|
|
61
|
+
*
|
|
62
|
+
* Orden de resolución del mensaje del toast:
|
|
63
|
+
* 1. `i18nMap[code]` definido → `i18n.t(esa key)`.
|
|
64
|
+
* 2. Sin match y `isNetwork` → key de red ({@link VALTECH_NETWORK_ERROR_KEY}),
|
|
65
|
+
* con fallback al texto español si la app no la tradujo.
|
|
66
|
+
* 3. `fallbackKey` definido → `i18n.t(fallbackKey)`.
|
|
67
|
+
* 4. Genérico en español.
|
|
68
|
+
*
|
|
69
|
+
* @param err Cualquier error capturado.
|
|
70
|
+
* @param opts Opciones de contexto, mapeo i18n y toast.
|
|
71
|
+
* @returns El {@link InterpretedError} normalizado. Nunca lanza.
|
|
72
|
+
*/
|
|
73
|
+
handle(err, opts = {}) {
|
|
74
|
+
const interpreted = interpretError(err);
|
|
75
|
+
const { context, i18nMap, fallbackKey, i18nNamespace, toast } = opts;
|
|
76
|
+
// 1. Observabilidad — log estructurado a consola.
|
|
77
|
+
console.error('[ValtechError] handled', {
|
|
78
|
+
context: context ?? 'n/a',
|
|
79
|
+
code: interpreted.code,
|
|
80
|
+
status: interpreted.status ?? 'n/a',
|
|
81
|
+
operationId: interpreted.operationId ?? 'n/a',
|
|
82
|
+
isNetwork: interpreted.isNetwork,
|
|
83
|
+
message: interpreted.message,
|
|
84
|
+
});
|
|
85
|
+
// 2. Reporte a Analytics (best-effort, opcional).
|
|
86
|
+
if (this.analytics) {
|
|
87
|
+
try {
|
|
88
|
+
this.analytics.logError(interpreted.message, {
|
|
89
|
+
source: 'handled',
|
|
90
|
+
code: interpreted.code,
|
|
91
|
+
...(context ? { context } : {}),
|
|
92
|
+
...(interpreted.status !== undefined ? { status: String(interpreted.status) } : {}),
|
|
93
|
+
...(interpreted.operationId ? { operationId: interpreted.operationId } : {}),
|
|
94
|
+
...(interpreted.isNetwork ? { error_category: 'network' } : {}),
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
catch (trackingError) {
|
|
98
|
+
console.warn('[ValtechError] analytics tracking failed:', trackingError);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// 3. Resolver mensaje localizado para el usuario.
|
|
102
|
+
const message = this.resolveMessage(interpreted, {
|
|
103
|
+
i18nMap,
|
|
104
|
+
fallbackKey,
|
|
105
|
+
i18nNamespace,
|
|
106
|
+
});
|
|
107
|
+
// 4. Toast (estándar Valtech: color 'dark', position 'top').
|
|
108
|
+
if (toast !== false) {
|
|
109
|
+
this.toast.show({
|
|
110
|
+
message,
|
|
111
|
+
color: 'dark',
|
|
112
|
+
position: 'top',
|
|
113
|
+
duration: 3000,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
// 5. Devolver el error normalizado para lógica extra del caller.
|
|
117
|
+
return interpreted;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Resuelve el mensaje a mostrar siguiendo el orden documentado en {@link handle}.
|
|
121
|
+
*/
|
|
122
|
+
resolveMessage(interpreted, opts) {
|
|
123
|
+
const ns = opts.i18nNamespace;
|
|
124
|
+
// 1. Match exacto por código de backend.
|
|
125
|
+
const mappedKey = opts.i18nMap?.[interpreted.code];
|
|
126
|
+
if (mappedKey) {
|
|
127
|
+
return this.translate(mappedKey, ns) ?? interpreted.message;
|
|
128
|
+
}
|
|
129
|
+
// 2. Fallo de red → key de red de la lib, con fallback español.
|
|
130
|
+
if (interpreted.isNetwork) {
|
|
131
|
+
return this.translate(VALTECH_NETWORK_ERROR_KEY, ns) ?? NETWORK_FALLBACK_MESSAGE;
|
|
132
|
+
}
|
|
133
|
+
// 3. fallbackKey provisto por la app.
|
|
134
|
+
if (opts.fallbackKey) {
|
|
135
|
+
return this.translate(opts.fallbackKey, ns) ?? interpreted.message;
|
|
136
|
+
}
|
|
137
|
+
// 4. Genérico — preferir el mensaje del backend (ya viene en español) si lo hay.
|
|
138
|
+
return interpreted.message || GENERIC_FALLBACK_MESSAGE;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Traduce una key i18n. Devuelve `null` si la key no está definida — el
|
|
142
|
+
* `I18nService` devuelve un placeholder `[namespace.key]` para keys faltantes;
|
|
143
|
+
* lo detectamos para poder caer a un fallback en lugar de mostrar el placeholder.
|
|
144
|
+
*/
|
|
145
|
+
translate(key, namespace) {
|
|
146
|
+
const text = this.i18n.t(key, namespace);
|
|
147
|
+
const ns = namespace ?? '_global';
|
|
148
|
+
return text === `[${ns}.${key}]` ? null : text;
|
|
149
|
+
}
|
|
150
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ValtechErrorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
151
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ValtechErrorService, providedIn: 'root' }); }
|
|
152
|
+
}
|
|
153
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ValtechErrorService, decorators: [{
|
|
154
|
+
type: Injectable,
|
|
155
|
+
args: [{ providedIn: 'root' }]
|
|
156
|
+
}] });
|
|
157
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsdGVjaC1lcnJvci5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9zZXJ2aWNlcy9lcnJvcnMvdmFsdGVjaC1lcnJvci5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25ELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ2pFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNuRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDaEQsT0FBTyxFQUFvQixjQUFjLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQzs7QUFFckU7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLHlCQUF5QixHQUFHLHVCQUF1QixDQUFDO0FBRWpFLDhGQUE4RjtBQUM5RixNQUFNLHdCQUF3QixHQUFHLG1DQUFtQyxDQUFDO0FBRXJFLHNFQUFzRTtBQUN0RSxNQUFNLHdCQUF3QixHQUFHLHFDQUFxQyxDQUFDO0FBa0N2RTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQWtDRztBQUVILE1BQU0sT0FBTyxtQkFBbUI7SUFEaEM7UUFFbUIsU0FBSSxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUMzQixVQUFLLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQzlDLDRFQUE0RTtRQUMzRCxjQUFTLEdBQUcsTUFBTSxDQUFDLGdCQUFnQixFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7S0EwRzNFO0lBeEdDOzs7Ozs7Ozs7Ozs7O09BYUc7SUFDSCxNQUFNLENBQUMsR0FBWSxFQUFFLE9BQWtDLEVBQUU7UUFDdkQsTUFBTSxXQUFXLEdBQUcsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3hDLE1BQU0sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLFdBQVcsRUFBRSxhQUFhLEVBQUUsS0FBSyxFQUFFLEdBQUcsSUFBSSxDQUFDO1FBRXJFLGtEQUFrRDtRQUNsRCxPQUFPLENBQUMsS0FBSyxDQUFDLHdCQUF3QixFQUFFO1lBQ3RDLE9BQU8sRUFBRSxPQUFPLElBQUksS0FBSztZQUN6QixJQUFJLEVBQUUsV0FBVyxDQUFDLElBQUk7WUFDdEIsTUFBTSxFQUFFLFdBQVcsQ0FBQyxNQUFNLElBQUksS0FBSztZQUNuQyxXQUFXLEVBQUUsV0FBVyxDQUFDLFdBQVcsSUFBSSxLQUFLO1lBQzdDLFNBQVMsRUFBRSxXQUFXLENBQUMsU0FBUztZQUNoQyxPQUFPLEVBQUUsV0FBVyxDQUFDLE9BQU87U0FDN0IsQ0FBQyxDQUFDO1FBRUgsa0RBQWtEO1FBQ2xELElBQUksSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ25CLElBQUksQ0FBQztnQkFDSCxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFO29CQUMzQyxNQUFNLEVBQUUsU0FBUztvQkFDakIsSUFBSSxFQUFFLFdBQVcsQ0FBQyxJQUFJO29CQUN0QixHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7b0JBQy9CLEdBQUcsQ0FBQyxXQUFXLENBQUMsTUFBTSxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7b0JBQ25GLEdBQUcsQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxFQUFFLFdBQVcsRUFBRSxXQUFXLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztvQkFDNUUsR0FBRyxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsY0FBYyxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7aUJBQ2hFLENBQUMsQ0FBQztZQUNMLENBQUM7WUFBQyxPQUFPLGFBQWEsRUFBRSxDQUFDO2dCQUN2QixPQUFPLENBQUMsSUFBSSxDQUFDLDJDQUEyQyxFQUFFLGFBQWEsQ0FBQyxDQUFDO1lBQzNFLENBQUM7UUFDSCxDQUFDO1FBRUQsa0RBQWtEO1FBQ2xELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsV0FBVyxFQUFFO1lBQy9DLE9BQU87WUFDUCxXQUFXO1lBQ1gsYUFBYTtTQUNkLENBQUMsQ0FBQztRQUVILDZEQUE2RDtRQUM3RCxJQUFJLEtBQUssS0FBSyxLQUFLLEVBQUUsQ0FBQztZQUNwQixJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQztnQkFDZCxPQUFPO2dCQUNQLEtBQUssRUFBRSxNQUFNO2dCQUNiLFFBQVEsRUFBRSxLQUFLO2dCQUNmLFFBQVEsRUFBRSxJQUFJO2FBQ2YsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELGlFQUFpRTtRQUNqRSxPQUFPLFdBQVcsQ0FBQztJQUNyQixDQUFDO0lBRUQ7O09BRUc7SUFDSyxjQUFjLENBQ3BCLFdBQTZCLEVBQzdCLElBQWtGO1FBRWxGLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUM7UUFFOUIseUNBQXlDO1FBQ3pDLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDbkQsSUFBSSxTQUFTLEVBQUUsQ0FBQztZQUNkLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLElBQUksV0FBVyxDQUFDLE9BQU8sQ0FBQztRQUM5RCxDQUFDO1FBRUQsZ0VBQWdFO1FBQ2hFLElBQUksV0FBVyxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQzFCLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyx5QkFBeUIsRUFBRSxFQUFFLENBQUMsSUFBSSx3QkFBd0IsQ0FBQztRQUNuRixDQUFDO1FBRUQsc0NBQXNDO1FBQ3RDLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3JCLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQyxJQUFJLFdBQVcsQ0FBQyxPQUFPLENBQUM7UUFDckUsQ0FBQztRQUVELGlGQUFpRjtRQUNqRixPQUFPLFdBQVcsQ0FBQyxPQUFPLElBQUksd0JBQXdCLENBQUM7SUFDekQsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyxTQUFTLENBQUMsR0FBVyxFQUFFLFNBQWtCO1FBQy9DLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUN6QyxNQUFNLEVBQUUsR0FBRyxTQUFTLElBQUksU0FBUyxDQUFDO1FBQ2xDLE9BQU8sSUFBSSxLQUFLLElBQUksRUFBRSxJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUNqRCxDQUFDOytHQTdHVSxtQkFBbUI7bUhBQW5CLG1CQUFtQixjQUROLE1BQU07OzRGQUNuQixtQkFBbUI7a0JBRC9CLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBbmFseXRpY3NTZXJ2aWNlIH0gZnJvbSAnLi4vZmlyZWJhc2UvYW5hbHl0aWNzLnNlcnZpY2UnO1xuaW1wb3J0IHsgSTE4blNlcnZpY2UgfSBmcm9tICcuLi9pMThuL2kxOG4uc2VydmljZSc7XG5pbXBvcnQgeyBUb2FzdFNlcnZpY2UgfSBmcm9tICcuLi90b2FzdC5zZXJ2aWNlJztcbmltcG9ydCB7IEludGVycHJldGVkRXJyb3IsIGludGVycHJldEVycm9yIH0gZnJvbSAnLi9pbnRlcnByZXQtZXJyb3InO1xuXG4vKipcbiAqIEtleSBpMThuIGZpamEgZGUgbGEgbGlicmVyw61hIHBhcmEgZmFsbG9zIGRlIHJlZC4gTGFzIGFwcHMgcHVlZGVuIGRlZmluaXJsYSBlblxuICogc3UgY29udGVuaWRvIGkxOG4gKG5hbWVzcGFjZSBgX2dsb2JhbGApIHBhcmEgcGVyc29uYWxpemFyIGVsIHRleHRvOyBzaSBub1xuICogZXhpc3RlLCBzZSB1c2Ege0BsaW5rIE5FVFdPUktfRkFMTEJBQ0tfTUVTU0FHRX0uXG4gKi9cbmV4cG9ydCBjb25zdCBWQUxURUNIX05FVFdPUktfRVJST1JfS0VZID0gJ3ZhbHRlY2guZXJyb3IubmV0d29yayc7XG5cbi8qKiBUZXh0byBlbiBlc3Bhw7FvbCBwb3IgZGVmZWN0byBjdWFuZG8ge0BsaW5rIFZBTFRFQ0hfTkVUV09SS19FUlJPUl9LRVl9IG5vIGVzdMOhIGRlZmluaWRhLiAqL1xuY29uc3QgTkVUV09SS19GQUxMQkFDS19NRVNTQUdFID0gJ1NpbiBjb25leGnDs24uIFJldmlzw6EgdHUgaW50ZXJuZXQuJztcblxuLyoqIFRleHRvIGdlbsOpcmljbyBlbiBlc3Bhw7FvbCBjdWFuZG8gbm8gaGF5IG1hdGNoIG5pIGBmYWxsYmFja0tleWAuICovXG5jb25zdCBHRU5FUklDX0ZBTExCQUNLX01FU1NBR0UgPSAnT2N1cnJpw7MgdW4gZXJyb3IuIEludGVudMOhIGRlIG51ZXZvLic7XG5cbi8qKlxuICogT3BjaW9uZXMgZGUge0BsaW5rIFZhbHRlY2hFcnJvclNlcnZpY2UuaGFuZGxlfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBWYWx0ZWNoRXJyb3JIYW5kbGVPcHRpb25zIHtcbiAgLyoqXG4gICAqIElkZW50aWZpY2Fkb3IgZGVsIHB1bnRvIGRlIGZhbGxvLCBlai4gYCdwcm9maWxlLnNhdmUnYC4gU2UgaW5jbHV5ZSBlbiBlbFxuICAgKiBsb2cgZGUgY29uc29sYSB5IGVuIGVsIHJlcG9ydGUgYSBBbmFseXRpY3MgcGFyYSBmYWNpbGl0YXIgZWwgdHJhY2luZy5cbiAgICovXG4gIGNvbnRleHQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIE1hcGEgYGPDs2RpZ28gZGUgYmFja2VuZCDihpIga2V5IGkxOG5gLiBMbyBwcm92ZWUgbGEgYXBwLCBxdWUgY29ub2NlIHN1c1xuICAgKiBwcm9waWFzIHRyYWR1Y2Npb25lcy4gRWouIGB7IEVNQUlMX1RBS0VOOiAnZXJyb3JzLmVtYWlsVGFrZW4nIH1gLlxuICAgKi9cbiAgaTE4bk1hcD86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG5cbiAgLyoqXG4gICAqIEtleSBpMThuIGEgdXNhciBjdWFuZG8gbm8gaGF5IG1hdGNoIGVuIGBpMThuTWFwYCAoeSBlbCBlcnJvciBubyBlcyBkZSByZWQpLlxuICAgKiBTaSBzZSBvbWl0ZSwgc2UgdXNhIHVuIG1lbnNhamUgZ2Vuw6lyaWNvIGVuIGVzcGHDsW9sLlxuICAgKi9cbiAgZmFsbGJhY2tLZXk/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIE5hbWVzcGFjZSBpMThuIHBhcmEgcmVzb2x2ZXIgYGkxOG5NYXBgIC8gYGZhbGxiYWNrS2V5YCAvIGxhIGtleSBkZSByZWQuXG4gICAqIERlZmF1bHQ6IGBfZ2xvYmFsYC5cbiAgICovXG4gIGkxOG5OYW1lc3BhY2U/OiBzdHJpbmc7XG5cbiAgLyoqIFNpIG1vc3RyYXIgdW4gdG9hc3QgY29uIGVsIG1lbnNhamUgcmVzdWVsdG8uIERlZmF1bHQ6IGB0cnVlYC4gKi9cbiAgdG9hc3Q/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIFNlcnZpY2lvIGRlIFVYIGRlIGVycm9yZXMgY2FwdHVyYWRvcyAoQ2FwYSAzIGRlbCBlc3TDoW5kYXIgZGUgbWFuZWpvIGRlIGVycm9yZXMpLlxuICpcbiAqIE1pZW50cmFzIGxhIENhcGEgMSAoe0BsaW5rIGVycm9yTG9nZ2luZ0ludGVyY2VwdG9yfSkgb2JzZXJ2YSBUT0RBUyBsYXNcbiAqIHJlc3B1ZXN0YXMgSFRUUCBjb24gZXJyb3IsIHkgbGEgQ2FwYSAyIChgQW5hbHl0aWNzRXJyb3JIYW5kbGVyYCkgY2FwdHVyYSBsb3NcbiAqIGVycm9yZXMgTk8gbWFuZWphZG9zLCBsYSBDYXBhIDMgZXMgZWwgcHVudG8gw7puaWNvIHF1ZSB1bmEgcMOhZ2luYSB1c2EgZW4gc3VcbiAqIGBjYXRjaGAgcGFyYSBjb252ZXJ0aXIgdW4gZXJyb3IgZW4gZmVlZGJhY2sgYWwgdXN1YXJpby5cbiAqXG4gKiBSZXNwb25zYWJpbGlkYWRlcyBkZSB7QGxpbmsgaGFuZGxlfTpcbiAqIDEuIE5vcm1hbGl6YSBlbCBlcnJvciAoYGludGVycHJldEVycm9yYCkuXG4gKiAyLiBMb2d1ZWEgYSBjb25zb2xhICsgcmVwb3J0YSBhIEFuYWx5dGljcyAoYHNvdXJjZTogJ2hhbmRsZWQnYCwgY29uIGBjb250ZXh0YCkuXG4gKiAzLiBSZXN1ZWx2ZSB1biBtZW5zYWplIGxvY2FsaXphZG8gKHZlciBvcmRlbiBkZSByZXNvbHVjacOzbiBlbiB7QGxpbmsgaGFuZGxlfSkuXG4gKiA0LiBNdWVzdHJhIHVuIHRvYXN0IChgY29sb3I6ICdkYXJrJ2AsIGVzdMOhbmRhciBWYWx0ZWNoKSBzYWx2byBgdG9hc3Q6IGZhbHNlYC5cbiAqIDUuIERldnVlbHZlIGVsIHtAbGluayBJbnRlcnByZXRlZEVycm9yfSBwYXJhIHF1ZSBsYSBww6FnaW5hIGRlY2lkYSBsw7NnaWNhIGV4dHJhLlxuICpcbiAqICoqTnVuY2EgbGFuemEuKiogYEFuYWx5dGljc1NlcnZpY2VgIHNlIGlueWVjdGEgYEBPcHRpb25hbCgpYC5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHByaXZhdGUgZXJyb3JzID0gaW5qZWN0KFZhbHRlY2hFcnJvclNlcnZpY2UpO1xuICpcbiAqIGFzeW5jIHNhdmUoKSB7XG4gKiAgIHRyeSB7XG4gKiAgICAgYXdhaXQgZmlyc3RWYWx1ZUZyb20odGhpcy5hcGkudXBkYXRlUHJvZmlsZSh0aGlzLmZvcm0udmFsdWUpKTtcbiAqICAgICB0aGlzLnRvYXN0LnNob3coeyBtZXNzYWdlOiAnUGVyZmlsIGFjdHVhbGl6YWRvJywgY29sb3I6ICdkYXJrJyB9KTtcbiAqICAgfSBjYXRjaCAoZXJyKSB7XG4gKiAgICAgdGhpcy5lcnJvcnMuaGFuZGxlKGVyciwge1xuICogICAgICAgY29udGV4dDogJ3Byb2ZpbGUuc2F2ZScsXG4gKiAgICAgICBpMThuTWFwOiB7IEVNQUlMX1RBS0VOOiAnZXJyb3JzLmVtYWlsVGFrZW4nIH0sXG4gKiAgICAgICBmYWxsYmFja0tleTogJ2Vycm9ycy5wcm9maWxlU2F2ZUZhaWxlZCcsXG4gKiAgICAgfSk7XG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICovXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46ICdyb290JyB9KVxuZXhwb3J0IGNsYXNzIFZhbHRlY2hFcnJvclNlcnZpY2Uge1xuICBwcml2YXRlIHJlYWRvbmx5IGkxOG4gPSBpbmplY3QoSTE4blNlcnZpY2UpO1xuICBwcml2YXRlIHJlYWRvbmx5IHRvYXN0ID0gaW5qZWN0KFRvYXN0U2VydmljZSk7XG4gIC8vIEFwcHMgc2luIEZpcmViYXNlIEFuYWx5dGljczogZWwgc2VydmljaW8gc2lndWUgZnVuY2lvbmFuZG8gKGxvZyArIHRvYXN0KS5cbiAgcHJpdmF0ZSByZWFkb25seSBhbmFseXRpY3MgPSBpbmplY3QoQW5hbHl0aWNzU2VydmljZSwgeyBvcHRpb25hbDogdHJ1ZSB9KTtcblxuICAvKipcbiAgICogTWFuZWphIHVuIGVycm9yIGNhcHR1cmFkbzogbm9ybWFsaXphLCBvYnNlcnZhIHkgcHJvZHVjZSBmZWVkYmFjayBkZSB1c3VhcmlvLlxuICAgKlxuICAgKiBPcmRlbiBkZSByZXNvbHVjacOzbiBkZWwgbWVuc2FqZSBkZWwgdG9hc3Q6XG4gICAqIDEuIGBpMThuTWFwW2NvZGVdYCBkZWZpbmlkbyDihpIgYGkxOG4udChlc2Ega2V5KWAuXG4gICAqIDIuIFNpbiBtYXRjaCB5IGBpc05ldHdvcmtgIOKGkiBrZXkgZGUgcmVkICh7QGxpbmsgVkFMVEVDSF9ORVRXT1JLX0VSUk9SX0tFWX0pLFxuICAgKiAgICBjb24gZmFsbGJhY2sgYWwgdGV4dG8gZXNwYcOxb2wgc2kgbGEgYXBwIG5vIGxhIHRyYWR1am8uXG4gICAqIDMuIGBmYWxsYmFja0tleWAgZGVmaW5pZG8g4oaSIGBpMThuLnQoZmFsbGJhY2tLZXkpYC5cbiAgICogNC4gR2Vuw6lyaWNvIGVuIGVzcGHDsW9sLlxuICAgKlxuICAgKiBAcGFyYW0gZXJyIEN1YWxxdWllciBlcnJvciBjYXB0dXJhZG8uXG4gICAqIEBwYXJhbSBvcHRzIE9wY2lvbmVzIGRlIGNvbnRleHRvLCBtYXBlbyBpMThuIHkgdG9hc3QuXG4gICAqIEByZXR1cm5zIEVsIHtAbGluayBJbnRlcnByZXRlZEVycm9yfSBub3JtYWxpemFkby4gTnVuY2EgbGFuemEuXG4gICAqL1xuICBoYW5kbGUoZXJyOiB1bmtub3duLCBvcHRzOiBWYWx0ZWNoRXJyb3JIYW5kbGVPcHRpb25zID0ge30pOiBJbnRlcnByZXRlZEVycm9yIHtcbiAgICBjb25zdCBpbnRlcnByZXRlZCA9IGludGVycHJldEVycm9yKGVycik7XG4gICAgY29uc3QgeyBjb250ZXh0LCBpMThuTWFwLCBmYWxsYmFja0tleSwgaTE4bk5hbWVzcGFjZSwgdG9hc3QgfSA9IG9wdHM7XG5cbiAgICAvLyAxLiBPYnNlcnZhYmlsaWRhZCDigJQgbG9nIGVzdHJ1Y3R1cmFkbyBhIGNvbnNvbGEuXG4gICAgY29uc29sZS5lcnJvcignW1ZhbHRlY2hFcnJvcl0gaGFuZGxlZCcsIHtcbiAgICAgIGNvbnRleHQ6IGNvbnRleHQgPz8gJ24vYScsXG4gICAgICBjb2RlOiBpbnRlcnByZXRlZC5jb2RlLFxuICAgICAgc3RhdHVzOiBpbnRlcnByZXRlZC5zdGF0dXMgPz8gJ24vYScsXG4gICAgICBvcGVyYXRpb25JZDogaW50ZXJwcmV0ZWQub3BlcmF0aW9uSWQgPz8gJ24vYScsXG4gICAgICBpc05ldHdvcms6IGludGVycHJldGVkLmlzTmV0d29yayxcbiAgICAgIG1lc3NhZ2U6IGludGVycHJldGVkLm1lc3NhZ2UsXG4gICAgfSk7XG5cbiAgICAvLyAyLiBSZXBvcnRlIGEgQW5hbHl0aWNzIChiZXN0LWVmZm9ydCwgb3BjaW9uYWwpLlxuICAgIGlmICh0aGlzLmFuYWx5dGljcykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgdGhpcy5hbmFseXRpY3MubG9nRXJyb3IoaW50ZXJwcmV0ZWQubWVzc2FnZSwge1xuICAgICAgICAgIHNvdXJjZTogJ2hhbmRsZWQnLFxuICAgICAgICAgIGNvZGU6IGludGVycHJldGVkLmNvZGUsXG4gICAgICAgICAgLi4uKGNvbnRleHQgPyB7IGNvbnRleHQgfSA6IHt9KSxcbiAgICAgICAgICAuLi4oaW50ZXJwcmV0ZWQuc3RhdHVzICE9PSB1bmRlZmluZWQgPyB7IHN0YXR1czogU3RyaW5nKGludGVycHJldGVkLnN0YXR1cykgfSA6IHt9KSxcbiAgICAgICAgICAuLi4oaW50ZXJwcmV0ZWQub3BlcmF0aW9uSWQgPyB7IG9wZXJhdGlvbklkOiBpbnRlcnByZXRlZC5vcGVyYXRpb25JZCB9IDoge30pLFxuICAgICAgICAgIC4uLihpbnRlcnByZXRlZC5pc05ldHdvcmsgPyB7IGVycm9yX2NhdGVnb3J5OiAnbmV0d29yaycgfSA6IHt9KSxcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoICh0cmFja2luZ0Vycm9yKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignW1ZhbHRlY2hFcnJvcl0gYW5hbHl0aWNzIHRyYWNraW5nIGZhaWxlZDonLCB0cmFja2luZ0Vycm9yKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyAzLiBSZXNvbHZlciBtZW5zYWplIGxvY2FsaXphZG8gcGFyYSBlbCB1c3VhcmlvLlxuICAgIGNvbnN0IG1lc3NhZ2UgPSB0aGlzLnJlc29sdmVNZXNzYWdlKGludGVycHJldGVkLCB7XG4gICAgICBpMThuTWFwLFxuICAgICAgZmFsbGJhY2tLZXksXG4gICAgICBpMThuTmFtZXNwYWNlLFxuICAgIH0pO1xuXG4gICAgLy8gNC4gVG9hc3QgKGVzdMOhbmRhciBWYWx0ZWNoOiBjb2xvciAnZGFyaycsIHBvc2l0aW9uICd0b3AnKS5cbiAgICBpZiAodG9hc3QgIT09IGZhbHNlKSB7XG4gICAgICB0aGlzLnRvYXN0LnNob3coe1xuICAgICAgICBtZXNzYWdlLFxuICAgICAgICBjb2xvcjogJ2RhcmsnLFxuICAgICAgICBwb3NpdGlvbjogJ3RvcCcsXG4gICAgICAgIGR1cmF0aW9uOiAzMDAwLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gNS4gRGV2b2x2ZXIgZWwgZXJyb3Igbm9ybWFsaXphZG8gcGFyYSBsw7NnaWNhIGV4dHJhIGRlbCBjYWxsZXIuXG4gICAgcmV0dXJuIGludGVycHJldGVkO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc3VlbHZlIGVsIG1lbnNhamUgYSBtb3N0cmFyIHNpZ3VpZW5kbyBlbCBvcmRlbiBkb2N1bWVudGFkbyBlbiB7QGxpbmsgaGFuZGxlfS5cbiAgICovXG4gIHByaXZhdGUgcmVzb2x2ZU1lc3NhZ2UoXG4gICAgaW50ZXJwcmV0ZWQ6IEludGVycHJldGVkRXJyb3IsXG4gICAgb3B0czogUGljazxWYWx0ZWNoRXJyb3JIYW5kbGVPcHRpb25zLCAnaTE4bk1hcCcgfCAnZmFsbGJhY2tLZXknIHwgJ2kxOG5OYW1lc3BhY2UnPlxuICApOiBzdHJpbmcge1xuICAgIGNvbnN0IG5zID0gb3B0cy5pMThuTmFtZXNwYWNlO1xuXG4gICAgLy8gMS4gTWF0Y2ggZXhhY3RvIHBvciBjw7NkaWdvIGRlIGJhY2tlbmQuXG4gICAgY29uc3QgbWFwcGVkS2V5ID0gb3B0cy5pMThuTWFwPy5baW50ZXJwcmV0ZWQuY29kZV07XG4gICAgaWYgKG1hcHBlZEtleSkge1xuICAgICAgcmV0dXJuIHRoaXMudHJhbnNsYXRlKG1hcHBlZEtleSwgbnMpID8/IGludGVycHJldGVkLm1lc3NhZ2U7XG4gICAgfVxuXG4gICAgLy8gMi4gRmFsbG8gZGUgcmVkIOKGkiBrZXkgZGUgcmVkIGRlIGxhIGxpYiwgY29uIGZhbGxiYWNrIGVzcGHDsW9sLlxuICAgIGlmIChpbnRlcnByZXRlZC5pc05ldHdvcmspIHtcbiAgICAgIHJldHVybiB0aGlzLnRyYW5zbGF0ZShWQUxURUNIX05FVFdPUktfRVJST1JfS0VZLCBucykgPz8gTkVUV09SS19GQUxMQkFDS19NRVNTQUdFO1xuICAgIH1cblxuICAgIC8vIDMuIGZhbGxiYWNrS2V5IHByb3Zpc3RvIHBvciBsYSBhcHAuXG4gICAgaWYgKG9wdHMuZmFsbGJhY2tLZXkpIHtcbiAgICAgIHJldHVybiB0aGlzLnRyYW5zbGF0ZShvcHRzLmZhbGxiYWNrS2V5LCBucykgPz8gaW50ZXJwcmV0ZWQubWVzc2FnZTtcbiAgICB9XG5cbiAgICAvLyA0LiBHZW7DqXJpY28g4oCUIHByZWZlcmlyIGVsIG1lbnNhamUgZGVsIGJhY2tlbmQgKHlhIHZpZW5lIGVuIGVzcGHDsW9sKSBzaSBsbyBoYXkuXG4gICAgcmV0dXJuIGludGVycHJldGVkLm1lc3NhZ2UgfHwgR0VORVJJQ19GQUxMQkFDS19NRVNTQUdFO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyYWR1Y2UgdW5hIGtleSBpMThuLiBEZXZ1ZWx2ZSBgbnVsbGAgc2kgbGEga2V5IG5vIGVzdMOhIGRlZmluaWRhIOKAlCBlbFxuICAgKiBgSTE4blNlcnZpY2VgIGRldnVlbHZlIHVuIHBsYWNlaG9sZGVyIGBbbmFtZXNwYWNlLmtleV1gIHBhcmEga2V5cyBmYWx0YW50ZXM7XG4gICAqIGxvIGRldGVjdGFtb3MgcGFyYSBwb2RlciBjYWVyIGEgdW4gZmFsbGJhY2sgZW4gbHVnYXIgZGUgbW9zdHJhciBlbCBwbGFjZWhvbGRlci5cbiAgICovXG4gIHByaXZhdGUgdHJhbnNsYXRlKGtleTogc3RyaW5nLCBuYW1lc3BhY2U/OiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsIHtcbiAgICBjb25zdCB0ZXh0ID0gdGhpcy5pMThuLnQoa2V5LCBuYW1lc3BhY2UpO1xuICAgIGNvbnN0IG5zID0gbmFtZXNwYWNlID8/ICdfZ2xvYmFsJztcbiAgICByZXR1cm4gdGV4dCA9PT0gYFske25zfS4ke2tleX1dYCA/IG51bGwgOiB0ZXh0O1xuICB9XG59XG4iXX0=
|