{"version":3,"file":"sdcorejs-angular-interceptors.mjs","sources":["../../../projects/sdcorejs-angular/interceptors/no-internet/no-internet.interceptor.ts","../../../projects/sdcorejs-angular/interceptors/unauthorized/unauthorized.interceptor.ts","../../../projects/sdcorejs-angular/interceptors/sdcorejs-angular-interceptors.ts"],"sourcesContent":["import { HttpClient, HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';\nimport { inject, Injectable, Injector } from '@angular/core';\nimport { MatSnackBar, MatSnackBarRef } from '@angular/material/snack-bar';\nimport { I18nService } from '@sdcorejs/angular/i18n';\nimport { Observable, throwError } from 'rxjs';\nimport { catchError, switchMap } from 'rxjs/operators';\n\n@Injectable()\nexport class SdNoInternetInterceptor implements HttpInterceptor {\n  private snackBar = inject(MatSnackBar);\n  private injector = inject(Injector);\n\n  readonly #i18n = inject(I18nService);\n\n  // Trạng thái offline để tránh spam request check hoặc hiển thị nhiều snackbar\n  #isOffline = false;\n\n  // Giữ tham chiếu để có thể đóng/thao tác snackbar\n  #snackBarRef: MatSnackBarRef<any> | null = null;\n\n  // Giữ tham chiếu interval để clear khi có mạng lại\n  #pollInterval: ReturnType<typeof setInterval> | null = null;\n\n  // Lazy load HttpClient\n  #http: HttpClient | null = null;\n\n  // Endpoint kiểm tra mạng (Nên dùng 1 file tĩnh nhẹ hoặc API ping public uy tín)\n  readonly #healthCheckUrl = 'https://jsonplaceholder.typicode.com/todos/1';\n\n  // Thời gian lặp lại việc kiểm tra mạng (ms)\n  readonly #checkIntervalDuration = 3000;\n\n  /** Inserted by Angular inject() migration for backwards compatibility */\n  constructor(...args: unknown[]);\n\n  constructor() {}\n\n  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {\n    return next.handle(request).pipe(\n      catchError((error: HttpErrorResponse) => {\n        // --- TRƯỜNG HỢP 1: Lỗi mất kết nối (Status 0) ---\n        if (error.status === 0 && !this.#isOffline) {\n          this.#isOffline = true;\n\n          // Lazy load HttpClient để tránh lỗi Circular Dependency\n          if (!this.#http) {\n            this.#http = this.injector.get(HttpClient);\n          }\n\n          // Gọi thử một API public để xác minh xem là Mất mạng thật hay do CORS/Server chặn\n          return this.#http.get(this.#healthCheckUrl).pipe(\n            // 1. Ưu tiên bắt lỗi kết nối trước (Đây là logic MẤT MẠNG THẬT)\n            catchError(_checkError => {\n              // Hiển thị thông báo và bắt đầu polling chờ mạng\n              this.#showReloadSnackbar(this.#i18n.t('core.interceptor.no-internet.offline'), { isSticky: true });\n              this.#startPolling();\n\n              // Ném lại lỗi gốc để Component biết request thất bại\n              return throwError(() => error);\n            }),\n\n            // 2. Nếu không vào catchError ở trên -> Check thành công -> CÓ MẠNG\n            // Lỗi status 0 ban đầu là do CORS, SSL, hoặc Server chặn connection\n            switchMap(() => {\n              this.#isOffline = false; // Reset cờ\n\n              this.snackBar.open(this.#i18n.t('core.interceptor.no-internet.cors-error'), this.#i18n.t('core.common.close'), {\n                duration: 5000,\n                horizontalPosition: 'center',\n                verticalPosition: 'top',\n              });\n\n              // Ném lại lỗi gốc\n              return throwError(() => error);\n            })\n          );\n        }\n\n        // --- TRƯỜNG HỢP 2: Server bảo trì (503) ---\n        else if (error.status === 503) {\n          this.snackBar.open(this.#i18n.t('core.interceptor.no-internet.maintenance'), this.#i18n.t('core.common.close'), {\n            horizontalPosition: 'center',\n            verticalPosition: 'top',\n            duration: 5000,\n          });\n        }\n\n        // --- TRƯỜNG HỢP KHÁC: 401, 404, 500... ---\n        // Ném lỗi ra để component xử lý bình thường\n        return throwError(() => error);\n      })\n    );\n  }\n\n  /**\n   * Hiển thị Snackbar thông báo trạng thái mạng\n   */\n  #showReloadSnackbar = (message: string, options?: { duration?: number; isSticky?: boolean }): void => {\n    // Đóng snackbar cũ nếu đang hiện\n    if (this.#snackBarRef) {\n      this.#snackBarRef.dismiss();\n    }\n\n    this.#snackBarRef = this.snackBar.open(message, this.#i18n.t('core.common.reload'), {\n      horizontalPosition: 'center',\n      verticalPosition: 'top',\n      // Nếu isSticky = true (mất mạng) -> Không tự tắt. Nếu có duration -> tự tắt.\n      duration: options?.duration,\n      panelClass: options?.isSticky ? ['offline-snackbar'] : undefined, // Class CSS tùy chọn\n    });\n\n    // Xử lý sự kiện bấm nút \"Tải lại trang\"\n    this.#snackBarRef.onAction().subscribe(() => {\n      window.location.reload();\n    });\n  };\n\n  /**\n   * Bắt đầu vòng lặp kiểm tra kết nối mạng\n   */\n  #startPolling = (): void => {\n    this.#stopPolling(); // Clear cũ nếu có\n\n    // @i18n-ignore — dev console log\n\n    this.#pollInterval = setInterval(() => {\n      if (!this.#http) {\n        this.#http = this.injector.get(HttpClient);\n      }\n\n      // Check nhẹ\n      this.#http.get(this.#healthCheckUrl).subscribe({\n        next: () => {\n          // --> ĐÃ CÓ MẠNG LẠI\n          // @i18n-ignore — dev console log\n\n          this.#stopPolling();\n          this.#isOffline = false;\n\n          // Thông báo thành công (tự tắt sau 5s)\n          this.#showReloadSnackbar(this.#i18n.t('core.interceptor.no-internet.restored'), { duration: 5000, isSticky: false });\n        },\n        error: () => {\n          // --> VẪN MẤT MẠNG: Không làm gì cả, chờ lần check tiếp theo\n        },\n      });\n    }, this.#checkIntervalDuration);\n  };\n\n  /**\n   * Dừng vòng lặp kiểm tra\n   */\n  #stopPolling = (): void => {\n    if (this.#pollInterval) {\n      clearInterval(this.#pollInterval);\n      this.#pollInterval = null;\n    }\n  };\n}\n","import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';\nimport { Injectable, inject } from '@angular/core';\nimport { SdAuthService } from '@sdcorejs/angular/modules';\nimport { Observable, throwError } from 'rxjs';\nimport { catchError } from 'rxjs/operators';\n\n@Injectable()\nexport class SdUnauthorizedInterceptor implements HttpInterceptor {\n  private authService = inject(SdAuthService);\n\n  #unauthorizedHandled = false;\n\n  /** Inserted by Angular inject() migration for backwards compatibility */\n  constructor(...args: unknown[]);\n\n  constructor() {}\n\n  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {\n    return next.handle(request).pipe(\n      catchError((error: HttpErrorResponse) => {\n        if (error.status === 401 && !this.#unauthorizedHandled) {\n          this.#unauthorizedHandled = true;\n          this.authService.signout();\n        }\n\n        return throwError(() => error);\n      })\n    );\n  }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;;MAQa,uBAAuB,CAAA;AAC1B,IAAA,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC;AAC9B,IAAA,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;AAE1B,IAAA,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC;;IAGpC,UAAU,GAAG,KAAK;;IAGlB,YAAY,GAA+B,IAAI;;IAG/C,aAAa,GAA0C,IAAI;;IAG3D,KAAK,GAAsB,IAAI;;IAGtB,eAAe,GAAG,8CAA8C;;IAGhE,sBAAsB,GAAG,IAAI;AAKtC,IAAA,WAAA,GAAA,EAAe;IAEf,SAAS,CAAC,OAA6B,EAAE,IAAiB,EAAA;AACxD,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAC9B,UAAU,CAAC,CAAC,KAAwB,KAAI;;YAEtC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;AAC1C,gBAAA,IAAI,CAAC,UAAU,GAAG,IAAI;;AAGtB,gBAAA,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE;oBACf,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC;gBAC5C;;gBAGA,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI;;gBAE9C,UAAU,CAAC,WAAW,IAAG;;AAEvB,oBAAA,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,sCAAsC,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;oBAClG,IAAI,CAAC,aAAa,EAAE;;AAGpB,oBAAA,OAAO,UAAU,CAAC,MAAM,KAAK,CAAC;AAChC,gBAAA,CAAC,CAAC;;;gBAIF,SAAS,CAAC,MAAK;AACb,oBAAA,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;oBAExB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,yCAAyC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,mBAAmB,CAAC,EAAE;AAC7G,wBAAA,QAAQ,EAAE,IAAI;AACd,wBAAA,kBAAkB,EAAE,QAAQ;AAC5B,wBAAA,gBAAgB,EAAE,KAAK;AACxB,qBAAA,CAAC;;AAGF,oBAAA,OAAO,UAAU,CAAC,MAAM,KAAK,CAAC;gBAChC,CAAC,CAAC,CACH;YACH;;AAGK,iBAAA,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE;gBAC7B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,0CAA0C,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,mBAAmB,CAAC,EAAE;AAC9G,oBAAA,kBAAkB,EAAE,QAAQ;AAC5B,oBAAA,gBAAgB,EAAE,KAAK;AACvB,oBAAA,QAAQ,EAAE,IAAI;AACf,iBAAA,CAAC;YACJ;;;AAIA,YAAA,OAAO,UAAU,CAAC,MAAM,KAAK,CAAC;QAChC,CAAC,CAAC,CACH;IACH;AAEA;;AAEG;AACH,IAAA,mBAAmB,GAAG,CAAC,OAAe,EAAE,OAAmD,KAAU;;AAEnG,QAAA,IAAI,IAAI,CAAC,YAAY,EAAE;AACrB,YAAA,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;QAC7B;AAEA,QAAA,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,oBAAoB,CAAC,EAAE;AAClF,YAAA,kBAAkB,EAAE,QAAQ;AAC5B,YAAA,gBAAgB,EAAE,KAAK;;YAEvB,QAAQ,EAAE,OAAO,EAAE,QAAQ;AAC3B,YAAA,UAAU,EAAE,OAAO,EAAE,QAAQ,GAAG,CAAC,kBAAkB,CAAC,GAAG,SAAS;AACjE,SAAA,CAAC;;QAGF,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC,MAAK;AAC1C,YAAA,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE;AAC1B,QAAA,CAAC,CAAC;AACJ,IAAA,CAAC;AAED;;AAEG;IACH,aAAa,GAAG,MAAW;AACzB,QAAA,IAAI,CAAC,YAAY,EAAE,CAAC;;AAIpB,QAAA,IAAI,CAAC,aAAa,GAAG,WAAW,CAAC,MAAK;AACpC,YAAA,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE;gBACf,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC;YAC5C;;YAGA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,SAAS,CAAC;gBAC7C,IAAI,EAAE,MAAK;;;oBAIT,IAAI,CAAC,YAAY,EAAE;AACnB,oBAAA,IAAI,CAAC,UAAU,GAAG,KAAK;;oBAGvB,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,uCAAuC,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;gBACtH,CAAC;gBACD,KAAK,EAAE,MAAK;;gBAEZ,CAAC;AACF,aAAA,CAAC;AACJ,QAAA,CAAC,EAAE,IAAI,CAAC,sBAAsB,CAAC;AACjC,IAAA,CAAC;AAED;;AAEG;IACH,YAAY,GAAG,MAAW;AACxB,QAAA,IAAI,IAAI,CAAC,aAAa,EAAE;AACtB,YAAA,aAAa,CAAC,IAAI,CAAC,aAAa,CAAC;AACjC,YAAA,IAAI,CAAC,aAAa,GAAG,IAAI;QAC3B;AACF,IAAA,CAAC;wGArJU,uBAAuB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;4GAAvB,uBAAuB,EAAA,CAAA;;4FAAvB,uBAAuB,EAAA,UAAA,EAAA,CAAA;kBADnC;;;MCAY,yBAAyB,CAAA;AAC5B,IAAA,WAAW,GAAG,MAAM,CAAC,aAAa,CAAC;IAE3C,oBAAoB,GAAG,KAAK;AAK5B,IAAA,WAAA,GAAA,EAAe;IAEf,SAAS,CAAC,OAA6B,EAAE,IAAiB,EAAA;AACxD,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAC9B,UAAU,CAAC,CAAC,KAAwB,KAAI;YACtC,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE;AACtD,gBAAA,IAAI,CAAC,oBAAoB,GAAG,IAAI;AAChC,gBAAA,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE;YAC5B;AAEA,YAAA,OAAO,UAAU,CAAC,MAAM,KAAK,CAAC;QAChC,CAAC,CAAC,CACH;IACH;wGArBW,yBAAyB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;4GAAzB,yBAAyB,EAAA,CAAA;;4FAAzB,yBAAyB,EAAA,UAAA,EAAA,CAAA;kBADrC;;;ACND;;AAEG;;;;"}