valtech-components 2.0.828 → 2.0.830

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.
@@ -53,7 +53,7 @@ import 'prismjs/components/prism-json';
53
53
  * Current version of valtech-components.
54
54
  * This is automatically updated during the publish process.
55
55
  */
56
- const VERSION = '2.0.828';
56
+ const VERSION = '2.0.830';
57
57
 
58
58
  /**
59
59
  * Servicio para gestionar presets de componentes.
@@ -19839,6 +19839,15 @@ class AppVersionService {
19839
19839
  this.swUpdate.versionUpdates
19840
19840
  .pipe(filter$1(evt => evt.type === 'VERSION_READY'), takeUntilDestroyed(this.destroyRef))
19841
19841
  .subscribe(() => this.swUpdateReady.set(true));
19842
+ // SW en estado irrecuperable — la caché del service worker se corrompió o
19843
+ // fue parcialmente evictada (común en PWAs standalone de iOS tras deploys
19844
+ // repetidos). La app no puede cargar sus assets → pantalla en blanco.
19845
+ // Recuperación recomendada por Angular: recargar para traer todo fresco
19846
+ // desde la red.
19847
+ this.swUpdate.unrecoverable.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(event => {
19848
+ console.error('[AppVersionService] SW unrecoverable — reloading:', event.reason);
19849
+ this.document.defaultView?.location.reload();
19850
+ });
19842
19851
  // Chequeo periódico.
19843
19852
  const intervalMs = this.serviceConfig?.checkIntervalMs ?? DEFAULT_APP_VERSION_SERVICE_CONFIG.checkIntervalMs;
19844
19853
  interval(intervalMs)
@@ -24636,14 +24645,34 @@ class AuthService {
24636
24645
  void this.ensureFirebaseSessionOnBootstrap();
24637
24646
  }
24638
24647
  else if (storedState.refreshToken) {
24639
- // 4. Token expirado pero hay refresh token - intentar refrescar
24640
- try {
24641
- await firstValueFrom(this.refreshAccessToken());
24648
+ // 4. Token expirado pero hay refresh token.
24649
+ //
24650
+ // NO bloqueamos el bootstrap esperando la red: un /refresh en una
24651
+ // Lambda fría son 2-5s de pantalla en blanco (Angular no renderiza
24652
+ // nada hasta que el APP_INITIALIZER resuelve).
24653
+ //
24654
+ // Restauración optimista: el access token expiró pero sus claims
24655
+ // (uid/email/roles) siguen decodificables — `parseToken` NO valida
24656
+ // `exp`. Restauramos la sesión desde esos claims para que la app
24657
+ // renderice el shell autenticado de inmediato, y disparamos el
24658
+ // /refresh en segundo plano (fire-and-forget).
24659
+ //
24660
+ // Seguridad de la ventana sub-segundo antes de que el refresh llegue:
24661
+ // cualquier API call sale con el token expirado → 401 → el
24662
+ // authInterceptor refresca + reintenta automáticamente. Si el refresh
24663
+ // de fondo falla → signOut + clearState.
24664
+ console.log('[ValtechAuth] bootstrap — access token expired, refreshing in background');
24665
+ this.stateService.restoreFromStorage(storedState);
24666
+ const expiredClaims = this.tokenService.parseToken(storedState.accessToken);
24667
+ if (expiredClaims) {
24668
+ this.stateService.updateUserInfo(expiredClaims.uid, expiredClaims.email);
24642
24669
  }
24643
- catch {
24670
+ // Refresh en segundo plano — NO se hace await: initialize() resuelve ya.
24671
+ firstValueFrom(this.refreshAccessToken()).catch(() => {
24672
+ console.warn('[ValtechAuth] bootstrap — background refresh failed, signing out');
24644
24673
  this.signOutFirebase();
24645
24674
  this.clearState();
24646
- }
24675
+ });
24647
24676
  }
24648
24677
  else {
24649
24678
  this.signOutFirebase();
@@ -25286,8 +25315,15 @@ class AuthService {
25286
25315
  console.log('[ValtechAuth] Calling signInWithFirebase with token length:', response.firebaseToken.length);
25287
25316
  this.signInWithFirebase(response.firebaseToken);
25288
25317
  }
25318
+ else if (this.config.enableFirebaseIntegration) {
25319
+ // El login NO trajo firebaseToken (ej. flujo OAuth que lo perdió). En vez
25320
+ // de quedar sin sesión de Firebase, recurrimos al fallback self-healing:
25321
+ // /refresh sí devuelve un firebaseToken confiable.
25322
+ console.log('[FBAuth] login response sin firebaseToken → recurriendo a fallback /refresh');
25323
+ void this.reestablishFirebaseViaRefresh('login-missing-firebase-token');
25324
+ }
25289
25325
  else {
25290
- console.log('[ValtechAuth] Firebase signin skipped - conditions not met');
25326
+ console.log('[ValtechAuth] Firebase signin skipped - integración Firebase desactivada');
25291
25327
  }
25292
25328
  // Registro automático de dispositivo para push notifications
25293
25329
  if (this.config.enableDeviceRegistration) {
@@ -25438,13 +25474,31 @@ class AuthService {
25438
25474
  console.log('[FBAuth] bootstrap — Firebase session restored on its own');
25439
25475
  return;
25440
25476
  }
25441
- console.log('[FBAuth] bootstrap — session valid but Firebase NOT ready → refreshing to re-establish');
25477
+ console.log('[FBAuth] bootstrap — session valid but Firebase NOT ready → recurriendo a fallback');
25478
+ await this.reestablishFirebaseViaRefresh('bootstrap-session-restore');
25479
+ }
25480
+ /**
25481
+ * Fallback self-healing de Firebase Auth. Pide un firebaseToken fresco vía
25482
+ * `/refresh` (que sí lo devuelve de forma confiable) y, en éxito,
25483
+ * `refreshAccessToken()` ya ejecuta `signInWithFirebase()`.
25484
+ *
25485
+ * Se invoca cuando un path de auth dejó la sesión de Firebase sin establecer:
25486
+ * - login OAuth/password que volvió sin `firebaseToken`,
25487
+ * - cold launch de PWA iOS sin persistencia de Firebase.
25488
+ *
25489
+ * `reason` aparece en los logs `[FBAuth] fallback` para poder atestiguar
25490
+ * desde el debug-console qué disparó el fallback.
25491
+ */
25492
+ async reestablishFirebaseViaRefresh(reason) {
25493
+ if (!this.config.enableFirebaseIntegration || !this.firebaseService)
25494
+ return;
25495
+ console.log(`[FBAuth] fallback — re-estableciendo Firebase vía /refresh (motivo: ${reason})`);
25442
25496
  try {
25443
- // refreshAccessToken() ya llama signInWithFirebase() en éxito.
25444
25497
  await firstValueFrom(this.refreshAccessToken());
25498
+ console.log(`[FBAuth] fallback — /refresh OK, Firebase re-establecido (motivo: ${reason})`);
25445
25499
  }
25446
25500
  catch (e) {
25447
- console.warn('[FBAuth] bootstrap — refresh to re-establish Firebase failed:', e);
25501
+ console.warn(`[FBAuth] fallback/refresh falló (motivo: ${reason}):`, e);
25448
25502
  }
25449
25503
  }
25450
25504
  // =============================================