valtech-components 4.0.990 → 4.0.991

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.
@@ -1,9 +1,17 @@
1
1
  import { inject } from '@angular/core';
2
2
  import { HttpContextToken, } from '@angular/common/http';
3
- import { throwError } from 'rxjs';
4
- import { catchError } from 'rxjs/operators';
3
+ import { throwError, timer } from 'rxjs';
4
+ import { catchError, retry } from 'rxjs/operators';
5
5
  import { AnalyticsService } from '../firebase/analytics.service';
6
6
  import { interpretError } from './interpret-error';
7
+ /**
8
+ * Códigos de status que ameritan reintento — cold-start / infra tibia, no un
9
+ * error de negocio. Nunca 4xx: eso es la app pidiendo algo mal, reintentar no
10
+ * lo arregla.
11
+ */
12
+ const RETRYABLE_STATUSES = new Set([502, 503, 504]);
13
+ /** Backoff corto entre reintentos — no queremos que la UI perciba una espera larga. */
14
+ const RETRY_DELAY_MS = 400;
7
15
  /**
8
16
  * Marca un request cuyo 404 es un ESTADO ESPERADO del dominio, no un error —
9
17
  * ej. `GET /v1/game-profile/me` cuando el usuario todavía no creó su perfil
@@ -21,7 +29,15 @@ export const EXPECTED_NOT_FOUND = new HttpContextToken(() => false);
21
29
  * Interceptor HTTP de observabilidad (Capa 1 del estándar de manejo de errores).
22
30
  *
23
31
  * Para CADA respuesta HTTP con error:
24
- * 1. Normaliza el error con `interpretError`.
32
+ * 0. Si es un GET (idempotente) que falló con 502/503/504, reintenta hasta 2
33
+ * veces con un backoff corto (400ms/800ms) ANTES de pasar al resto del
34
+ * pipeline — el caso típico es un cold-start de Lambda en dev: 3-4
35
+ * requests en paralelo al bootstrap (auth/profile + runs + org/{id})
36
+ * pegan contra lambdas frías al mismo tiempo, todas 504, y ~2s después ya
37
+ * están tibias y funcionan. Detectado en Merotz dev 2026-08-17. Nunca
38
+ * reintenta POST/PUT/DELETE/PATCH (no son idempotentes) ni 4xx (error de
39
+ * negocio, reintentar no lo arregla).
40
+ * 1. Si sigue fallando tras los reintentos: normaliza el error con `interpretError`.
25
41
  * 2. Loguea un evento estructurado a consola con el prefijo `[HTTP]`.
26
42
  * 3. Reporta el error a Firebase Analytics (`source: 'http'`), si hay analytics.
27
43
  *
@@ -45,7 +61,16 @@ export const errorLoggingInterceptor = (request, next) => {
45
61
  // `AnalyticsService` puede no estar provisto (apps sin Firebase). El inject
46
62
  // funcional con `optional: true` devuelve `null` en ese caso.
47
63
  const analytics = inject(AnalyticsService, { optional: true });
48
- return next(request).pipe(catchError((error) => {
64
+ return next(request).pipe(retry({
65
+ count: 2,
66
+ delay: (error, retryCount) => {
67
+ const status = error?.status;
68
+ if (request.method !== 'GET' || !RETRYABLE_STATUSES.has(status)) {
69
+ return throwError(() => error);
70
+ }
71
+ return timer(RETRY_DELAY_MS * retryCount);
72
+ },
73
+ }), catchError((error) => {
49
74
  const interpreted = interpretError(error);
50
75
  const status = interpreted.status ?? error?.status;
51
76
  // 401 → ruido del refresh de auth. Log informativo, sin Analytics.
@@ -94,4 +119,4 @@ export const errorLoggingInterceptor = (request, next) => {
94
119
  return throwError(() => error);
95
120
  }));
96
121
  };
97
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3ItbG9nZ2luZy5pbnRlcmNlcHRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvc2VydmljZXMvZXJyb3JzL2Vycm9yLWxvZ2dpbmcuaW50ZXJjZXB0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN2QyxPQUFPLEVBQ0wsZ0JBQWdCLEdBTWpCLE1BQU0sc0JBQXNCLENBQUM7QUFDOUIsT0FBTyxFQUFjLFVBQVUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUM5QyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDNUMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDakUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRW5EOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxnQkFBZ0IsQ0FBVSxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUU3RTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F1Qkc7QUFDSCxNQUFNLENBQUMsTUFBTSx1QkFBdUIsR0FBc0IsQ0FDeEQsT0FBNkIsRUFDN0IsSUFBbUIsRUFDYSxFQUFFO0lBQ2xDLDRFQUE0RTtJQUM1RSw4REFBOEQ7SUFDOUQsTUFBTSxTQUFTLEdBQUcsTUFBTSxDQUFDLGdCQUFnQixFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7SUFFL0QsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUN2QixVQUFVLENBQUMsQ0FBQyxLQUFjLEVBQUUsRUFBRTtRQUM1QixNQUFNLFdBQVcsR0FBRyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDMUMsTUFBTSxNQUFNLEdBQUcsV0FBVyxDQUFDLE1BQU0sSUFBSyxLQUEyQixFQUFFLE1BQU0sQ0FBQztRQUUxRSxtRUFBbUU7UUFDbkUsSUFBSSxNQUFNLEtBQUssR0FBRyxFQUFFLENBQUM7WUFDbkIsT0FBTyxDQUFDLElBQUksQ0FDVixjQUFjLE9BQU8sQ0FBQyxNQUFNLElBQUksT0FBTyxDQUFDLEdBQUcsRUFBRTtnQkFDM0MsQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxRQUFRLFdBQVcsQ0FBQyxXQUFXLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQ3RFLENBQUM7WUFDRixPQUFPLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNqQyxDQUFDO1FBRUQsd0VBQXdFO1FBQ3hFLHVFQUF1RTtRQUN2RSxpREFBaUQ7UUFDakQsSUFBSSxNQUFNLEtBQUssR0FBRyxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGtCQUFrQixDQUFDLEVBQUUsQ0FBQztZQUM5RCxPQUFPLENBQUMsSUFBSSxDQUNWLHlCQUF5QixPQUFPLENBQUMsTUFBTSxJQUFJLE9BQU8sQ0FBQyxHQUFHLEVBQUU7Z0JBQ3RELENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsUUFBUSxXQUFXLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUN0RSxDQUFDO1lBQ0YsT0FBTyxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDakMsQ0FBQztRQUVELDZEQUE2RDtRQUM3RCxPQUFPLENBQUMsS0FBSyxDQUFDLHVCQUF1QixFQUFFO1lBQ3JDLE1BQU0sRUFBRSxPQUFPLENBQUMsTUFBTTtZQUN0QixHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUc7WUFDaEIsTUFBTSxFQUFFLE1BQU0sSUFBSSxLQUFLO1lBQ3ZCLElBQUksRUFBRSxXQUFXLENBQUMsSUFBSTtZQUN0QixXQUFXLEVBQUUsV0FBVyxDQUFDLFdBQVcsSUFBSSxLQUFLO1lBQzdDLFNBQVMsRUFBRSxXQUFXLENBQUMsU0FBUztZQUNoQyxPQUFPLEVBQUUsV0FBVyxDQUFDLE9BQU87U0FDN0IsQ0FBQyxDQUFDO1FBRUgsNERBQTREO1FBQzVELElBQUksU0FBUyxFQUFFLENBQUM7WUFDZCxJQUFJLENBQUM7Z0JBQ0gsU0FBUyxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFO29CQUN0QyxNQUFNLEVBQUUsTUFBTTtvQkFDZCxJQUFJLEVBQUUsV0FBVyxDQUFDLElBQUk7b0JBQ3RCLEdBQUcsRUFBRSxPQUFPLENBQUMsR0FBRztvQkFDaEIsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNO29CQUN0QixNQUFNLEVBQUUsTUFBTSxDQUFDLE1BQU0sSUFBSSxDQUFDLENBQUM7b0JBQzNCLEdBQUcsQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxFQUFFLFdBQVcsRUFBRSxXQUFXLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztvQkFDNUUsR0FBRyxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsY0FBYyxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7aUJBQ2hFLENBQUMsQ0FBQztZQUNMLENBQUM7WUFBQyxPQUFPLGFBQWEsRUFBRSxDQUFDO2dCQUN2QiwrQ0FBK0M7Z0JBQy9DLE9BQU8sQ0FBQyxJQUFJLENBQUMsbUNBQW1DLEVBQUUsYUFBYSxDQUFDLENBQUM7WUFDbkUsQ0FBQztRQUNILENBQUM7UUFFRCx1RUFBdUU7UUFDdkUsT0FBTyxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDakMsQ0FBQyxDQUFDLENBQ0gsQ0FBQztBQUNKLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgSHR0cENvbnRleHRUb2tlbixcbiAgSHR0cEVycm9yUmVzcG9uc2UsXG4gIEh0dHBFdmVudCxcbiAgSHR0cEhhbmRsZXJGbixcbiAgSHR0cEludGVyY2VwdG9yRm4sXG4gIEh0dHBSZXF1ZXN0LFxufSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCB0aHJvd0Vycm9yIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBjYXRjaEVycm9yIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgQW5hbHl0aWNzU2VydmljZSB9IGZyb20gJy4uL2ZpcmViYXNlL2FuYWx5dGljcy5zZXJ2aWNlJztcbmltcG9ydCB7IGludGVycHJldEVycm9yIH0gZnJvbSAnLi9pbnRlcnByZXQtZXJyb3InO1xuXG4vKipcbiAqIE1hcmNhIHVuIHJlcXVlc3QgY3V5byA0MDQgZXMgdW4gRVNUQURPIEVTUEVSQURPIGRlbCBkb21pbmlvLCBubyB1biBlcnJvciDigJRcbiAqIGVqLiBgR0VUIC92MS9nYW1lLXByb2ZpbGUvbWVgIGN1YW5kbyBlbCB1c3VhcmlvIHRvZGF2w61hIG5vIGNyZcOzIHN1IHBlcmZpbFxuICogZGUganVlZ28uIE1pc21vIGNyaXRlcmlvIHF1ZSBlbCA0MDEgZGUgYWJham8gKHJ1aWRvIG5vcm1hbCBkZWwgZmx1am8sIG5vXG4gKiB1biBidWcpOiBzZSBsb2d1ZWEgYSBjb25zb2xhIGNvbW8gYGluZm9gLCBudW5jYSBhIEFuYWx5dGljcyBjb21vIGVycm9yLlxuICpcbiAqIFVzbyBlbiBlbCBjYWxsZXI6IGB0aGlzLmh0dHAuZ2V0KHVybCwgeyBjb250ZXh0OiBuZXcgSHR0cENvbnRleHQoKS5zZXQoRVhQRUNURURfTk9UX0ZPVU5ELCB0cnVlKSB9KWAuXG4gKlxuICogTm8gYXBsaWNhIGEgVE9ETyA0MDQg4oCUIHNvbG8gYSBsb3MgcXVlIGVsIHByb3BpbyBjYWxsZXIgc2FiZSBxdWUgc29uIHVuXG4gKiBcInRvZGF2w61hIG5vIGV4aXN0ZVwiIGxlZ8OtdGltby4gVW4gNDA0IG5vIG1hcmNhZG8gc2lndWUgc2llbmRvIGVycm9yIHJlYWxcbiAqIChVUkwgcm90YSwgcmVjdXJzbyBxdWUgZGViZXLDrWEgZXhpc3RpcikgeSBzZSBsb2d1ZWEgY29tbyB0YWwuXG4gKi9cbmV4cG9ydCBjb25zdCBFWFBFQ1RFRF9OT1RfRk9VTkQgPSBuZXcgSHR0cENvbnRleHRUb2tlbjxib29sZWFuPigoKSA9PiBmYWxzZSk7XG5cbi8qKlxuICogSW50ZXJjZXB0b3IgSFRUUCBkZSBvYnNlcnZhYmlsaWRhZCAoQ2FwYSAxIGRlbCBlc3TDoW5kYXIgZGUgbWFuZWpvIGRlIGVycm9yZXMpLlxuICpcbiAqIFBhcmEgQ0FEQSByZXNwdWVzdGEgSFRUUCBjb24gZXJyb3I6XG4gKiAxLiBOb3JtYWxpemEgZWwgZXJyb3IgY29uIGBpbnRlcnByZXRFcnJvcmAuXG4gKiAyLiBMb2d1ZWEgdW4gZXZlbnRvIGVzdHJ1Y3R1cmFkbyBhIGNvbnNvbGEgY29uIGVsIHByZWZpam8gYFtIVFRQXWAuXG4gKiAzLiBSZXBvcnRhIGVsIGVycm9yIGEgRmlyZWJhc2UgQW5hbHl0aWNzIChgc291cmNlOiAnaHR0cCdgKSwgc2kgaGF5IGFuYWx5dGljcy5cbiAqXG4gKiAqKk5PIHRyYWdhIGVsIGVycm9yKiog4oCUIGxvIHJlLWxhbnphIHRhbCBjdWFsLiBMYXMgcMOhZ2luYXMgeSBzZXJ2aWNpb3Mgc2lndWVuXG4gKiByZWNpYmllbmRvIGVsIGVycm9yIGVuIHN1IGBjYXRjaGAgLyBgY2F0Y2hFcnJvcmAgeSBkZWNpZGVuIGxhIFVYIChlc28gZXNcbiAqIENhcGEgMzogYFZhbHRlY2hFcnJvclNlcnZpY2VgKS5cbiAqXG4gKiBgQW5hbHl0aWNzU2VydmljZWAgc2UgaW55ZWN0YSBgQE9wdGlvbmFsKClgIOKAlCBhcHBzIHNpbiBGaXJlYmFzZSBBbmFseXRpY3NcbiAqIGlndWFsIG9idGllbmVuIGVsIGxvZyBlc3RydWN0dXJhZG8gYSBjb25zb2xhLlxuICpcbiAqIERlY2lzacOzbiBzb2JyZSA0MDE6ICoqc2Ugc2FsdGVhKiogZGVsIHRyYWNraW5nIGRlIEFuYWx5dGljcy4gVW4gNDAxIGVzIGVsXG4gKiBkaXNwYXJhZG9yIG5vcm1hbCBkZWwgZmx1am8gZGUgcmVmcmVzaCBkZSB0b2tlbiBkZWwgYGF1dGhJbnRlcmNlcHRvcmA7IGVsXG4gKiB0b2tlbiBzZSByZW51ZXZhIHkgbGEgcmVxdWVzdCBzZSByZWludGVudGEgZGUgZm9ybWEgdHJhbnNwYXJlbnRlLiBUcmFja2VhclxuICogY2FkYSA0MDEgaW51bmRhcsOtYSBBbmFseXRpY3MgZGUgcnVpZG8gKGNhZGEgc2VzacOzbiBnZW5lcmEgdmFyaW9zIGFsIGV4cGlyYXJcbiAqIGVsIGFjY2VzcyB0b2tlbikuIEVsIDQwMSBTw40gc2UgbG9ndWVhIGEgY29uc29sYSAobml2ZWwgYGluZm9gLCBubyBgZXJyb3JgKVxuICogcGFyYSBubyBwZXJkZXIgbGEgdHJhemEgZW4gZGVidWdnaW5nIGxvY2FsLCBwZXJvIG5vIHNlIHJlcG9ydGEgY29tbyBlcnJvci5cbiAqXG4gKiBTZSByZWdpc3RyYSB2w61hIHtAbGluayBwcm92aWRlVmFsdGVjaEVycm9ySGFuZGxpbmd9LlxuICovXG5leHBvcnQgY29uc3QgZXJyb3JMb2dnaW5nSW50ZXJjZXB0b3I6IEh0dHBJbnRlcmNlcHRvckZuID0gKFxuICByZXF1ZXN0OiBIdHRwUmVxdWVzdDx1bmtub3duPixcbiAgbmV4dDogSHR0cEhhbmRsZXJGblxuKTogT2JzZXJ2YWJsZTxIdHRwRXZlbnQ8dW5rbm93bj4+ID0+IHtcbiAgLy8gYEFuYWx5dGljc1NlcnZpY2VgIHB1ZWRlIG5vIGVzdGFyIHByb3Zpc3RvIChhcHBzIHNpbiBGaXJlYmFzZSkuIEVsIGluamVjdFxuICAvLyBmdW5jaW9uYWwgY29uIGBvcHRpb25hbDogdHJ1ZWAgZGV2dWVsdmUgYG51bGxgIGVuIGVzZSBjYXNvLlxuICBjb25zdCBhbmFseXRpY3MgPSBpbmplY3QoQW5hbHl0aWNzU2VydmljZSwgeyBvcHRpb25hbDogdHJ1ZSB9KTtcblxuICByZXR1cm4gbmV4dChyZXF1ZXN0KS5waXBlKFxuICAgIGNhdGNoRXJyb3IoKGVycm9yOiB1bmtub3duKSA9PiB7XG4gICAgICBjb25zdCBpbnRlcnByZXRlZCA9IGludGVycHJldEVycm9yKGVycm9yKTtcbiAgICAgIGNvbnN0IHN0YXR1cyA9IGludGVycHJldGVkLnN0YXR1cyA/PyAoZXJyb3IgYXMgSHR0cEVycm9yUmVzcG9uc2UpPy5zdGF0dXM7XG5cbiAgICAgIC8vIDQwMSDihpIgcnVpZG8gZGVsIHJlZnJlc2ggZGUgYXV0aC4gTG9nIGluZm9ybWF0aXZvLCBzaW4gQW5hbHl0aWNzLlxuICAgICAgaWYgKHN0YXR1cyA9PT0gNDAxKSB7XG4gICAgICAgIGNvbnNvbGUuaW5mbyhcbiAgICAgICAgICBgW0hUVFBdIDQwMSAke3JlcXVlc3QubWV0aG9kfSAke3JlcXVlc3QudXJsfWAgK1xuICAgICAgICAgICAgKGludGVycHJldGVkLm9wZXJhdGlvbklkID8gYCAob3A9JHtpbnRlcnByZXRlZC5vcGVyYXRpb25JZH0pYCA6ICcnKVxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBlcnJvcik7XG4gICAgICB9XG5cbiAgICAgIC8vIDQwNCBtYXJjYWRvIHBvciBlbCBjYWxsZXIgY29tbyBlc3RhZG8gZXNwZXJhZG8gKEVYUEVDVEVEX05PVF9GT1VORCkg4oaSXG4gICAgICAvLyBtaXNtbyB0cmF0YW1pZW50byBxdWUgZWwgNDAxOiBpbmZvcm1hdGl2bywgc2luIEFuYWx5dGljcy4gVW4gNDA0IFNJTlxuICAgICAgLy8gbWFyY2FyIHNpZ3VlIGNheWVuZG8gYWwgbG9nIGRlIGVycm9yIGRlIGFiYWpvLlxuICAgICAgaWYgKHN0YXR1cyA9PT0gNDA0ICYmIHJlcXVlc3QuY29udGV4dC5nZXQoRVhQRUNURURfTk9UX0ZPVU5EKSkge1xuICAgICAgICBjb25zb2xlLmluZm8oXG4gICAgICAgICAgYFtIVFRQXSA0MDQgKGVzcGVyYWRvKSAke3JlcXVlc3QubWV0aG9kfSAke3JlcXVlc3QudXJsfWAgK1xuICAgICAgICAgICAgKGludGVycHJldGVkLm9wZXJhdGlvbklkID8gYCAob3A9JHtpbnRlcnByZXRlZC5vcGVyYXRpb25JZH0pYCA6ICcnKVxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBlcnJvcik7XG4gICAgICB9XG5cbiAgICAgIC8vIExvZyBlc3RydWN0dXJhZG8gYSBjb25zb2xhIOKAlCBzaWVtcHJlLCBoYXlhIG8gbm8gQW5hbHl0aWNzLlxuICAgICAgY29uc29sZS5lcnJvcignW0hUVFBdIHJlcXVlc3QgZmFpbGVkJywge1xuICAgICAgICBtZXRob2Q6IHJlcXVlc3QubWV0aG9kLFxuICAgICAgICB1cmw6IHJlcXVlc3QudXJsLFxuICAgICAgICBzdGF0dXM6IHN0YXR1cyA/PyAnbi9hJyxcbiAgICAgICAgY29kZTogaW50ZXJwcmV0ZWQuY29kZSxcbiAgICAgICAgb3BlcmF0aW9uSWQ6IGludGVycHJldGVkLm9wZXJhdGlvbklkID8/ICduL2EnLFxuICAgICAgICBpc05ldHdvcms6IGludGVycHJldGVkLmlzTmV0d29yayxcbiAgICAgICAgbWVzc2FnZTogaW50ZXJwcmV0ZWQubWVzc2FnZSxcbiAgICAgIH0pO1xuXG4gICAgICAvLyBSZXBvcnRlIGEgQW5hbHl0aWNzIChiZXN0LWVmZm9ydCkg4oCUIHNvbG8gc2kgaGF5IHNlcnZpY2lvLlxuICAgICAgaWYgKGFuYWx5dGljcykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGFuYWx5dGljcy5sb2dFcnJvcihpbnRlcnByZXRlZC5tZXNzYWdlLCB7XG4gICAgICAgICAgICBzb3VyY2U6ICdodHRwJyxcbiAgICAgICAgICAgIGNvZGU6IGludGVycHJldGVkLmNvZGUsXG4gICAgICAgICAgICB1cmw6IHJlcXVlc3QudXJsLFxuICAgICAgICAgICAgbWV0aG9kOiByZXF1ZXN0Lm1ldGhvZCxcbiAgICAgICAgICAgIHN0YXR1czogU3RyaW5nKHN0YXR1cyA/PyAwKSxcbiAgICAgICAgICAgIC4uLihpbnRlcnByZXRlZC5vcGVyYXRpb25JZCA/IHsgb3BlcmF0aW9uSWQ6IGludGVycHJldGVkLm9wZXJhdGlvbklkIH0gOiB7fSksXG4gICAgICAgICAgICAuLi4oaW50ZXJwcmV0ZWQuaXNOZXR3b3JrID8geyBlcnJvcl9jYXRlZ29yeTogJ25ldHdvcmsnIH0gOiB7fSksXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gY2F0Y2ggKHRyYWNraW5nRXJyb3IpIHtcbiAgICAgICAgICAvLyBFbCB0cmFja2luZyBudW5jYSBkZWJlIHJvbXBlciBlbCBmbHVqbyBIVFRQLlxuICAgICAgICAgIGNvbnNvbGUud2FybignW0hUVFBdIGFuYWx5dGljcyB0cmFja2luZyBmYWlsZWQ6JywgdHJhY2tpbmdFcnJvcik7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gUmUtbGFuemFyOiBOTyB0cmFnYW1vcyBlbCBlcnJvci4gTGEgQ2FwYSAzIC8gbGFzIHDDoWdpbmFzIGxvIG1hbmVqYW4uXG4gICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBlcnJvcik7XG4gICAgfSlcbiAgKTtcbn07XG4iXX0=
122
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3ItbG9nZ2luZy5pbnRlcmNlcHRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvc2VydmljZXMvZXJyb3JzL2Vycm9yLWxvZ2dpbmcuaW50ZXJjZXB0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN2QyxPQUFPLEVBQ0wsZ0JBQWdCLEdBTWpCLE1BQU0sc0JBQXNCLENBQUM7QUFDOUIsT0FBTyxFQUFjLFVBQVUsRUFBRSxLQUFLLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDckQsT0FBTyxFQUFFLFVBQVUsRUFBRSxLQUFLLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNuRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUNqRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFbkQ7Ozs7R0FJRztBQUNILE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7QUFFcEQsdUZBQXVGO0FBQ3ZGLE1BQU0sY0FBYyxHQUFHLEdBQUcsQ0FBQztBQUUzQjs7Ozs7Ozs7Ozs7R0FXRztBQUNILE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFHLElBQUksZ0JBQWdCLENBQVUsR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUM7QUFFN0U7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0ErQkc7QUFDSCxNQUFNLENBQUMsTUFBTSx1QkFBdUIsR0FBc0IsQ0FDeEQsT0FBNkIsRUFDN0IsSUFBbUIsRUFDYSxFQUFFO0lBQ2xDLDRFQUE0RTtJQUM1RSw4REFBOEQ7SUFDOUQsTUFBTSxTQUFTLEdBQUcsTUFBTSxDQUFDLGdCQUFnQixFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFD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LFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7b0JBQzVFLEdBQUcsQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLGNBQWMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO2lCQUNoRSxDQUFDLENBQUM7WUFDTCxDQUFDO1lBQUMsT0FBTyxhQUFhLEVBQUUsQ0FBQztnQkFDdkIsK0NBQStDO2dCQUMvQyxPQUFPLENBQUMsSUFBSSxDQUFDLG1DQUFtQyxFQUFFLGFBQWEsQ0FBQyxDQUFDO1lBQ25FLENBQUM7UUFDSCxDQUFDO1FBRUQsdUVBQXVFO1FBQ3ZFLE9BQU8sVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2pDLENBQUMsQ0FBQyxDQUNILENBQUM7QUFDSixDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gIEh0dHBDb250ZXh0VG9rZW4sXG4gIEh0dHBFcnJvclJlc3BvbnNlLFxuICBIdHRwRXZlbnQsXG4gIEh0dHBIYW5kbGVyRm4sXG4gIEh0dHBJbnRlcmNlcHRvckZuLFxuICBIdHRwUmVxdWVzdCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgdGhyb3dFcnJvciwgdGltZXIgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGNhdGNoRXJyb3IsIHJldHJ5IH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgQW5hbHl0aWNzU2VydmljZSB9IGZyb20gJy4uL2ZpcmViYXNlL2FuYWx5dGljcy5zZXJ2aWNlJztcbmltcG9ydCB7IGludGVycHJldEVycm9yIH0gZnJvbSAnLi9pbnRlcnByZXQtZXJyb3InO1xuXG4vKipcbiAqIEPDs2RpZ29zIGRlIHN0YXR1cyBxdWUgYW1lcml0YW4gcmVpbnRlbnRvIOKAlCBjb2xkLXN0YXJ0IC8gaW5mcmEgdGliaWEsIG5vIHVuXG4gKiBlcnJvciBkZSBuZWdvY2lvLiBOdW5jYSA0eHg6IGVzbyBlcyBsYSBhcHAgcGlkaWVuZG8gYWxnbyBtYWwsIHJlaW50ZW50YXIgbm9cbiAqIGxvIGFycmVnbGEuXG4gKi9cbmNvbnN0IFJFVFJZQUJMRV9TVEFUVVNFUyA9IG5ldyBTZXQoWzUwMiwgNTAzLCA1MDRdKTtcblxuLyoqIEJhY2tvZmYgY29ydG8gZW50cmUgcmVpbnRlbnRvcyDigJQgbm8gcXVlcmVtb3MgcXVlIGxhIFVJIHBlcmNpYmEgdW5hIGVzcGVyYSBsYXJnYS4gKi9cbmNvbnN0IFJFVFJZX0RFTEFZX01TID0gNDAwO1xuXG4vKipcbiAqIE1hcmNhIHVuIHJlcXVlc3QgY3V5byA0MDQgZXMgdW4gRVNUQURPIEVTUEVSQURPIGRlbCBkb21pbmlvLCBubyB1biBlcnJvciDigJRcbiAqIGVqLiBgR0VUIC92MS9nYW1lLXByb2ZpbGUvbWVgIGN1YW5kbyBlbCB1c3VhcmlvIHRvZGF2w61hIG5vIGNyZcOzIHN1IHBlcmZpbFxuICogZGUganVlZ28uIE1pc21vIGNyaXRlcmlvIHF1ZSBlbCA0MDEgZGUgYWJham8gKHJ1aWRvIG5vcm1hbCBkZWwgZmx1am8sIG5vXG4gKiB1biBidWcpOiBzZSBsb2d1ZWEgYSBjb25zb2xhIGNvbW8gYGluZm9gLCBudW5jYSBhIEFuYWx5dGljcyBjb21vIGVycm9yLlxuICpcbiAqIFVzbyBlbiBlbCBjYWxsZXI6IGB0aGlzLmh0dHAuZ2V0KHVybCwgeyBjb250ZXh0OiBuZXcgSHR0cENvbnRleHQoKS5zZXQoRVhQRUNURURfTk9UX0ZPVU5ELCB0cnVlKSB9KWAuXG4gKlxuICogTm8gYXBsaWNhIGEgVE9ETyA0MDQg4oCUIHNvbG8gYSBsb3MgcXVlIGVsIHByb3BpbyBjYWxsZXIgc2FiZSBxdWUgc29uIHVuXG4gKiBcInRvZGF2w61hIG5vIGV4aXN0ZVwiIGxlZ8OtdGltby4gVW4gNDA0IG5vIG1hcmNhZG8gc2lndWUgc2llbmRvIGVycm9yIHJlYWxcbiAqIChVUkwgcm90YSwgcmVjdXJzbyBxdWUgZGViZXLDrWEgZXhpc3RpcikgeSBzZSBsb2d1ZWEgY29tbyB0YWwuXG4gKi9cbmV4cG9ydCBjb25zdCBFWFBFQ1RFRF9OT1RfRk9VTkQgPSBuZXcgSHR0cENvbnRleHRUb2tlbjxib29sZWFuPigoKSA9PiBmYWxzZSk7XG5cbi8qKlxuICogSW50ZXJjZXB0b3IgSFRUUCBkZSBvYnNlcnZhYmlsaWRhZCAoQ2FwYSAxIGRlbCBlc3TDoW5kYXIgZGUgbWFuZWpvIGRlIGVycm9yZXMpLlxuICpcbiAqIFBhcmEgQ0FEQSByZXNwdWVzdGEgSFRUUCBjb24gZXJyb3I6XG4gKiAwLiBTaSBlcyB1biBHRVQgKGlkZW1wb3RlbnRlKSBxdWUgZmFsbMOzIGNvbiA1MDIvNTAzLzUwNCwgcmVpbnRlbnRhIGhhc3RhIDJcbiAqICAgIHZlY2VzIGNvbiB1biBiYWNrb2ZmIGNvcnRvICg0MDBtcy84MDBtcykgQU5URVMgZGUgcGFzYXIgYWwgcmVzdG8gZGVsXG4gKiAgICBwaXBlbGluZSDigJQgZWwgY2FzbyB0w61waWNvIGVzIHVuIGNvbGQtc3RhcnQgZGUgTGFtYmRhIGVuIGRldjogMy00XG4gKiAgICByZXF1ZXN0cyBlbiBwYXJhbGVsbyBhbCBib290c3RyYXAgKGF1dGgvcHJvZmlsZSArIHJ1bnMgKyBvcmcve2lkfSlcbiAqICAgIHBlZ2FuIGNvbnRyYSBsYW1iZGFzIGZyw61hcyBhbCBtaXNtbyB0aWVtcG8sIHRvZGFzIDUwNCwgeSB+MnMgZGVzcHXDqXMgeWFcbiAqICAgIGVzdMOhbiB0aWJpYXMgeSBmdW5jaW9uYW4uIERldGVjdGFkbyBlbiBNZXJvdHogZGV2IDIwMjYtMDgtMTcuIE51bmNhXG4gKiAgICByZWludGVudGEgUE9TVC9QVVQvREVMRVRFL1BBVENIIChubyBzb24gaWRlbXBvdGVudGVzKSBuaSA0eHggKGVycm9yIGRlXG4gKiAgICBuZWdvY2lvLCByZWludGVudGFyIG5vIGxvIGFycmVnbGEpLlxuICogMS4gU2kgc2lndWUgZmFsbGFuZG8gdHJhcyBsb3MgcmVpbnRlbnRvczogbm9ybWFsaXphIGVsIGVycm9yIGNvbiBgaW50ZXJwcmV0RXJyb3JgLlxuICogMi4gTG9ndWVhIHVuIGV2ZW50byBlc3RydWN0dXJhZG8gYSBjb25zb2xhIGNvbiBlbCBwcmVmaWpvIGBbSFRUUF1gLlxuICogMy4gUmVwb3J0YSBlbCBlcnJvciBhIEZpcmViYXNlIEFuYWx5dGljcyAoYHNvdXJjZTogJ2h0dHAnYCksIHNpIGhheSBhbmFseXRpY3MuXG4gKlxuICogKipOTyB0cmFnYSBlbCBlcnJvcioqIOKAlCBsbyByZS1sYW56YSB0YWwgY3VhbC4gTGFzIHDDoWdpbmFzIHkgc2VydmljaW9zIHNpZ3VlblxuICogcmVjaWJpZW5kbyBlbCBlcnJvciBlbiBzdSBgY2F0Y2hgIC8gYGNhdGNoRXJyb3JgIHkgZGVjaWRlbiBsYSBVWCAoZXNvIGVzXG4gKiBDYXBhIDM6IGBWYWx0ZWNoRXJyb3JTZXJ2aWNlYCkuXG4gKlxuICogYEFuYWx5dGljc1NlcnZpY2VgIHNlIGlueWVjdGEgYEBPcHRpb25hbCgpYCDigJQgYXBwcyBzaW4gRmlyZWJhc2UgQW5hbHl0aWNzXG4gKiBpZ3VhbCBvYnRpZW5lbiBlbCBsb2cgZXN0cnVjdHVyYWRvIGEgY29uc29sYS5cbiAqXG4gKiBEZWNpc2nDs24gc29icmUgNDAxOiAqKnNlIHNhbHRlYSoqIGRlbCB0cmFja2luZyBkZSBBbmFseXRpY3MuIFVuIDQwMSBlcyBlbFxuICogZGlzcGFyYWRvciBub3JtYWwgZGVsIGZsdWpvIGRlIHJlZnJlc2ggZGUgdG9rZW4gZGVsIGBhdXRoSW50ZXJjZXB0b3JgOyBlbFxuICogdG9rZW4gc2UgcmVudWV2YSB5IGxhIHJlcXVlc3Qgc2UgcmVpbnRlbnRhIGRlIGZvcm1hIHRyYW5zcGFyZW50ZS4gVHJhY2tlYXJcbiAqIGNhZGEgNDAxIGludW5kYXLDrWEgQW5hbHl0aWNzIGRlIHJ1aWRvIChjYWRhIHNlc2nDs24gZ2VuZXJhIHZhcmlvcyBhbCBleHBpcmFyXG4gKiBlbCBhY2Nlc3MgdG9rZW4pLiBFbCA0MDEgU8ONIHNlIGxvZ3VlYSBhIGNvbnNvbGEgKG5pdmVsIGBpbmZvYCwgbm8gYGVycm9yYClcbiAqIHBhcmEgbm8gcGVyZGVyIGxhIHRyYXphIGVuIGRlYnVnZ2luZyBsb2NhbCwgcGVybyBubyBzZSByZXBvcnRhIGNvbW8gZXJyb3IuXG4gKlxuICogU2UgcmVnaXN0cmEgdsOtYSB7QGxpbmsgcHJvdmlkZVZhbHRlY2hFcnJvckhhbmRsaW5nfS5cbiAqL1xuZXhwb3J0IGNvbnN0IGVycm9yTG9nZ2luZ0ludGVyY2VwdG9yOiBIdHRwSW50ZXJjZXB0b3JGbiA9IChcbiAgcmVxdWVzdDogSHR0cFJlcXVlc3Q8dW5rbm93bj4sXG4gIG5leHQ6IEh0dHBIYW5kbGVyRm5cbik6IE9ic2VydmFibGU8SHR0cEV2ZW50PHVua25vd24+PiA9PiB7XG4gIC8vIGBBbmFseXRpY3NTZXJ2aWNlYCBwdWVkZSBubyBlc3RhciBwcm92aXN0byAoYXBwcyBzaW4gRmlyZWJhc2UpLiBFbCBpbmplY3RcbiAgLy8gZnVuY2lvbmFsIGNvbiBgb3B0aW9uYWw6IHRydWVgIGRldnVlbHZlIGBudWxsYCBlbiBlc2UgY2Fzby5cbiAgY29uc3QgYW5hbHl0aWNzID0gaW5qZWN0KEFuYWx5dGljc1NlcnZpY2UsIHsgb3B0aW9uYWw6IHRydWUgfSk7XG5cbiAgcmV0dXJuIG5leHQocmVxdWVzdCkucGlwZShcbiAgICByZXRyeSh7XG4gICAgICBjb3VudDogMixcbiAgICAgIGRlbGF5OiAoZXJyb3I6IHVua25vd24sIHJldHJ5Q291bnQ6IG51bWJlcikgPT4ge1xuICAgICAgICBjb25zdCBzdGF0dXMgPSAoZXJyb3IgYXMgSHR0cEVycm9yUmVzcG9uc2UpPy5zdGF0dXM7XG4gICAgICAgIGlmIChyZXF1ZXN0Lm1ldGhvZCAhPT0gJ0dFVCcgfHwgIVJFVFJZQUJMRV9TVEFUVVNFUy5oYXMoc3RhdHVzKSkge1xuICAgICAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IGVycm9yKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGltZXIoUkVUUllfREVMQVlfTVMgKiByZXRyeUNvdW50KTtcbiAgICAgIH0sXG4gICAgfSksXG4gICAgY2F0Y2hFcnJvcigoZXJyb3I6IHVua25vd24pID0+IHtcbiAgICAgIGNvbnN0IGludGVycHJldGVkID0gaW50ZXJwcmV0RXJyb3IoZXJyb3IpO1xuICAgICAgY29uc3Qgc3RhdHVzID0gaW50ZXJwcmV0ZWQuc3RhdHVzID8/IChlcnJvciBhcyBIdHRwRXJyb3JSZXNwb25zZSk/LnN0YXR1cztcblxuICAgICAgLy8gNDAxIOKGkiBydWlkbyBkZWwgcmVmcmVzaCBkZSBhdXRoLiBMb2cgaW5mb3JtYXRpdm8sIHNpbiBBbmFseXRpY3MuXG4gICAgICBpZiAoc3RhdHVzID09PSA0MDEpIHtcbiAgICAgICAgY29uc29sZS5pbmZvKFxuICAgICAgICAgIGBbSFRUUF0gNDAxICR7cmVxdWVzdC5tZXRob2R9ICR7cmVxdWVzdC51cmx9YCArXG4gICAgICAgICAgICAoaW50ZXJwcmV0ZWQub3BlcmF0aW9uSWQgPyBgIChvcD0ke2ludGVycHJldGVkLm9wZXJhdGlvbklkfSlgIDogJycpXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IGVycm9yKTtcbiAgICAgIH1cblxuICAgICAgLy8gNDA0IG1hcmNhZG8gcG9yIGVsIGNhbGxlciBjb21vIGVzdGFkbyBlc3BlcmFkbyAoRVhQRUNURURfTk9UX0ZPVU5EKSDihpJcbiAgICAgIC8vIG1pc21vIHRyYXRhbWllbnRvIHF1ZSBlbCA0MDE6IGluZm9ybWF0aXZvLCBzaW4gQW5hbHl0aWNzLiBVbiA0MDQgU0lOXG4gICAgICAvLyBtYXJjYXIgc2lndWUgY2F5ZW5kbyBhbCBsb2cgZGUgZXJyb3IgZGUgYWJham8uXG4gICAgICBpZiAoc3RhdHVzID09PSA0MDQgJiYgcmVxdWVzdC5jb250ZXh0LmdldChFWFBFQ1RFRF9OT1RfRk9VTkQpKSB7XG4gICAgICAgIGNvbnNvbGUuaW5mbyhcbiAgICAgICAgICBgW0hUVFBdIDQwNCAoZXNwZXJhZG8pICR7cmVxdWVzdC5tZXRob2R9ICR7cmVxdWVzdC51cmx9YCArXG4gICAgICAgICAgICAoaW50ZXJwcmV0ZWQub3BlcmF0aW9uSWQgPyBgIChvcD0ke2ludGVycHJldGVkLm9wZXJhdGlvbklkfSlgIDogJycpXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IGVycm9yKTtcbiAgICAgIH1cblxuICAgICAgLy8gTG9nIGVzdHJ1Y3R1cmFkbyBhIGNvbnNvbGEg4oCUIHNpZW1wcmUsIGhheWEgbyBubyBBbmFseXRpY3MuXG4gICAgICBjb25zb2xlLmVycm9yKCdbSFRUUF0gcmVxdWVzdCBmYWlsZWQnLCB7XG4gICAgICAgIG1ldGhvZDogcmVxdWVzdC5tZXRob2QsXG4gICAgICAgIHVybDogcmVxdWVzdC51cmwsXG4gICAgICAgIHN0YXR1czogc3RhdHVzID8/ICduL2EnLFxuICAgICAgICBjb2RlOiBpbnRlcnByZXRlZC5jb2RlLFxuICAgICAgICBvcGVyYXRpb25JZDogaW50ZXJwcmV0ZWQub3BlcmF0aW9uSWQgPz8gJ24vYScsXG4gICAgICAgIGlzTmV0d29yazogaW50ZXJwcmV0ZWQuaXNOZXR3b3JrLFxuICAgICAgICBtZXNzYWdlOiBpbnRlcnByZXRlZC5tZXNzYWdlLFxuICAgICAgfSk7XG5cbiAgICAgIC8vIFJlcG9ydGUgYSBBbmFseXRpY3MgKGJlc3QtZWZmb3J0KSDigJQgc29sbyBzaSBoYXkgc2VydmljaW8uXG4gICAgICBpZiAoYW5hbHl0aWNzKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYW5hbHl0aWNzLmxvZ0Vycm9yKGludGVycHJldGVkLm1lc3NhZ2UsIHtcbiAgICAgICAgICAgIHNvdXJjZTogJ2h0dHAnLFxuICAgICAgICAgICAgY29kZTogaW50ZXJwcmV0ZWQuY29kZSxcbiAgICAgICAgICAgIHVybDogcmVxdWVzdC51cmwsXG4gICAgICAgICAgICBtZXRob2Q6IHJlcXVlc3QubWV0aG9kLFxuICAgICAgICAgICAgc3RhdHVzOiBTdHJpbmcoc3RhdHVzID8/IDApLFxuICAgICAgICAgICAgLi4uKGludGVycHJldGVkLm9wZXJhdGlvbklkID8geyBvcGVyYXRpb25JZDogaW50ZXJwcmV0ZWQub3BlcmF0aW9uSWQgfSA6IHt9KSxcbiAgICAgICAgICAgIC4uLihpbnRlcnByZXRlZC5pc05ldHdvcmsgPyB7IGVycm9yX2NhdGVnb3J5OiAnbmV0d29yaycgfSA6IHt9KSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBjYXRjaCAodHJhY2tpbmdFcnJvcikge1xuICAgICAgICAgIC8vIEVsIHRyYWNraW5nIG51bmNhIGRlYmUgcm9tcGVyIGVsIGZsdWpvIEhUVFAuXG4gICAgICAgICAgY29uc29sZS53YXJuKCdbSFRUUF0gYW5hbHl0aWNzIHRyYWNraW5nIGZhaWxlZDonLCB0cmFja2luZ0Vycm9yKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBSZS1sYW56YXI6IE5PIHRyYWdhbW9zIGVsIGVycm9yLiBMYSBDYXBhIDMgLyBsYXMgcMOhZ2luYXMgbG8gbWFuZWphbi5cbiAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IGVycm9yKTtcbiAgICB9KVxuICApO1xufTtcbiJdfQ==
@@ -2,5 +2,5 @@
2
2
  * Current version of valtech-components.
3
3
  * This is automatically updated during the publish process.
4
4
  */
5
- export const VERSION = '4.0.990';
6
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVyc2lvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvdmVyc2lvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFDSCxNQUFNLENBQUMsTUFBTSxPQUFPLEdBQUcsU0FBUyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDdXJyZW50IHZlcnNpb24gb2YgdmFsdGVjaC1jb21wb25lbnRzLlxuICogVGhpcyBpcyBhdXRvbWF0aWNhbGx5IHVwZGF0ZWQgZHVyaW5nIHRoZSBwdWJsaXNoIHByb2Nlc3MuXG4gKi9cbmV4cG9ydCBjb25zdCBWRVJTSU9OID0gJzQuMC45OTAnO1xuIl19
5
+ export const VERSION = '4.0.991';
6
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVyc2lvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvdmVyc2lvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFDSCxNQUFNLENBQUMsTUFBTSxPQUFPLEdBQUcsU0FBUyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDdXJyZW50IHZlcnNpb24gb2YgdmFsdGVjaC1jb21wb25lbnRzLlxuICogVGhpcyBpcyBhdXRvbWF0aWNhbGx5IHVwZGF0ZWQgZHVyaW5nIHRoZSBwdWJsaXNoIHByb2Nlc3MuXG4gKi9cbmV4cG9ydCBjb25zdCBWRVJTSU9OID0gJzQuMC45OTEnO1xuIl19
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, makeEnvironmentProviders, inject, APP_INITIALIZER, ErrorHandler, Injectable, DestroyRef, Inject, signal, computed, PLATFORM_ID, isDevMode, Optional, runInInjectionContext, effect, Pipe, Component, Input, ChangeDetectionStrategy, input, output, Injector, TemplateRef, ViewContainerRef, Directive, ElementRef, Renderer2, HostListener, EventEmitter, Output, HostBinding, SecurityContext, NgZone, ViewChild, ChangeDetectorRef, ContentChild, model, ViewEncapsulation, untracked, ViewChildren, viewChild, isSignal } from '@angular/core';
3
- import { BehaviorSubject, throwError, Subject, map, distinctUntilChanged, filter as filter$1, take as take$1, firstValueFrom, timeout as timeout$1, catchError as catchError$1, of, from, EMPTY, Observable, interval, defer, timer, merge, concat, debounceTime, switchMap as switchMap$1, takeUntil, isObservable, forkJoin, race, shareReplay as shareReplay$1, tap as tap$1 } from 'rxjs';
4
- import { catchError, switchMap, finalize, filter, take, timeout, map as map$1, tap, shareReplay, distinctUntilChanged as distinctUntilChanged$1, retry, debounceTime as debounceTime$1, takeUntil as takeUntil$1 } from 'rxjs/operators';
3
+ import { BehaviorSubject, throwError, timer, Subject, map, distinctUntilChanged, filter as filter$1, take as take$1, firstValueFrom, timeout as timeout$1, catchError as catchError$1, of, from, EMPTY, Observable, interval, defer, merge, concat, debounceTime, switchMap as switchMap$1, takeUntil, isObservable, forkJoin, race, shareReplay as shareReplay$1, tap as tap$1 } from 'rxjs';
4
+ import { catchError, switchMap, finalize, filter, take, timeout, retry, map as map$1, tap, shareReplay, distinctUntilChanged as distinctUntilChanged$1, debounceTime as debounceTime$1, takeUntil as takeUntil$1 } from 'rxjs/operators';
5
5
  import * as i1$3 from '@angular/common/http';
6
6
  import { provideHttpClient, withInterceptors, HttpContextToken, HttpClient, HttpErrorResponse, HttpContext, HttpParams } from '@angular/common/http';
7
7
  import * as i1$1 from '@angular/fire/firestore';
@@ -70,7 +70,7 @@ import fixWebmDuration from 'fix-webm-duration';
70
70
  * Current version of valtech-components.
71
71
  * This is automatically updated during the publish process.
72
72
  */
73
- const VERSION = '4.0.990';
73
+ const VERSION = '4.0.991';
74
74
 
75
75
  function evaluateValtechAccess(rule, context, features = {}, visitedFeatures = new Set()) {
76
76
  if (rule == null)
@@ -1500,6 +1500,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
1500
1500
  args: [PLATFORM_ID]
1501
1501
  }] }] });
1502
1502
 
1503
+ /**
1504
+ * Códigos de status que ameritan reintento — cold-start / infra tibia, no un
1505
+ * error de negocio. Nunca 4xx: eso es la app pidiendo algo mal, reintentar no
1506
+ * lo arregla.
1507
+ */
1508
+ const RETRYABLE_STATUSES = new Set([502, 503, 504]);
1509
+ /** Backoff corto entre reintentos — no queremos que la UI perciba una espera larga. */
1510
+ const RETRY_DELAY_MS = 400;
1503
1511
  /**
1504
1512
  * Marca un request cuyo 404 es un ESTADO ESPERADO del dominio, no un error —
1505
1513
  * ej. `GET /v1/game-profile/me` cuando el usuario todavía no creó su perfil
@@ -1517,7 +1525,15 @@ const EXPECTED_NOT_FOUND = new HttpContextToken(() => false);
1517
1525
  * Interceptor HTTP de observabilidad (Capa 1 del estándar de manejo de errores).
1518
1526
  *
1519
1527
  * Para CADA respuesta HTTP con error:
1520
- * 1. Normaliza el error con `interpretError`.
1528
+ * 0. Si es un GET (idempotente) que falló con 502/503/504, reintenta hasta 2
1529
+ * veces con un backoff corto (400ms/800ms) ANTES de pasar al resto del
1530
+ * pipeline — el caso típico es un cold-start de Lambda en dev: 3-4
1531
+ * requests en paralelo al bootstrap (auth/profile + runs + org/{id})
1532
+ * pegan contra lambdas frías al mismo tiempo, todas 504, y ~2s después ya
1533
+ * están tibias y funcionan. Detectado en Merotz dev 2026-08-17. Nunca
1534
+ * reintenta POST/PUT/DELETE/PATCH (no son idempotentes) ni 4xx (error de
1535
+ * negocio, reintentar no lo arregla).
1536
+ * 1. Si sigue fallando tras los reintentos: normaliza el error con `interpretError`.
1521
1537
  * 2. Loguea un evento estructurado a consola con el prefijo `[HTTP]`.
1522
1538
  * 3. Reporta el error a Firebase Analytics (`source: 'http'`), si hay analytics.
1523
1539
  *
@@ -1541,7 +1557,16 @@ const errorLoggingInterceptor = (request, next) => {
1541
1557
  // `AnalyticsService` puede no estar provisto (apps sin Firebase). El inject
1542
1558
  // funcional con `optional: true` devuelve `null` en ese caso.
1543
1559
  const analytics = inject(AnalyticsService, { optional: true });
1544
- return next(request).pipe(catchError((error) => {
1560
+ return next(request).pipe(retry({
1561
+ count: 2,
1562
+ delay: (error, retryCount) => {
1563
+ const status = error?.status;
1564
+ if (request.method !== 'GET' || !RETRYABLE_STATUSES.has(status)) {
1565
+ return throwError(() => error);
1566
+ }
1567
+ return timer(RETRY_DELAY_MS * retryCount);
1568
+ },
1569
+ }), catchError((error) => {
1545
1570
  const interpreted = interpretError(error);
1546
1571
  const status = interpreted.status ?? error?.status;
1547
1572
  // 401 → ruido del refresh de auth. Log informativo, sin Analytics.