{"version":3,"file":"ngx-network-monitor.mjs","sources":["../../../projects/ngx-network-monitor/src/lib/tokens/network-monitor-config.token.ts","../../../projects/ngx-network-monitor/src/lib/network-monitor.service.ts","../../../projects/ngx-network-monitor/src/public-api.ts","../../../projects/ngx-network-monitor/src/ngx-network-monitor.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\nimport { NetworkMonitorConfig } from '../models/network-monitor-config.model';\n\nexport const NETWORK_MONITOR_CONFIG = new InjectionToken<NetworkMonitorConfig>('NETWORK_MONITOR_CONFIG', {\n  providedIn: 'root',\n  factory: (): NetworkMonitorConfig => ({\n    pingUrl: '/assets/ping.txt',\n    latencyThreshold: 1800,\n    slowConnectionTypes: ['2g', 'slow-2g', '3g'],\n    pingIntervalMs: 60000,\n    fallbackPingIntervalMs: 10000\n  }),\n});\n","import { Inject, Injectable, NgZone, PLATFORM_ID } from '@angular/core';\nimport { BehaviorSubject, interval, merge, fromEvent, of } from 'rxjs';\nimport { catchError, map, startWith, switchMap } from 'rxjs/operators';\nimport { HttpClient, HttpHeaders } from '@angular/common/http';\nimport { isPlatformBrowser } from '@angular/common';\nimport { NETWORK_MONITOR_CONFIG } from './tokens/network-monitor-config.token';\nimport { NetworkMonitorConfig, SlowConnectionTypes } from './models/network-monitor-config.model';\n\nexport interface NetworkStatus {\n  online: boolean;\n  latency: number | null;\n  effectiveType?: string; // 4g, 3g, 2g, slow-2g (if supported)\n  poorConnection: boolean;\n}\n\n@Injectable({\n  providedIn: 'root'\n})\nexport class NetworkMonitorService {\n  private status$ = new BehaviorSubject<NetworkStatus>({\n    online: true,\n    latency: null,\n    effectiveType: undefined,\n    poorConnection: false,\n  });\n  \n  private isBrowser: boolean;\n\n  private config:NetworkMonitorConfig;\n\n  constructor(\n    private http: HttpClient,\n    private ngZone: NgZone,\n    @Inject(PLATFORM_ID) platformId: Object,\n    @Inject(NETWORK_MONITOR_CONFIG) private networkMonitorconfig: NetworkMonitorConfig\n  ) {\n\n    this.config = { \n      // Ensuring default config merging.\n      // To prevent overwrites of defaults of missing configurations to `undefined`\n      pingUrl: this.networkMonitorconfig?.pingUrl || '/assets/ping.txt',\n      latencyThreshold: this.networkMonitorconfig?.latencyThreshold || 1800,\n      slowConnectionTypes: this.networkMonitorconfig?.slowConnectionTypes || ['2g', 'slow-2g', '3g'],\n      pingIntervalMs: this.networkMonitorconfig?.pingIntervalMs || 60000,\n      fallbackPingIntervalMs: this.networkMonitorconfig?.fallbackPingIntervalMs || 10000\n    };\n\n    this.isBrowser = isPlatformBrowser(platformId);\n    \n    if (this.isBrowser) {\n      this.initMonitoring();\n    }\n\n  }\n\n\n\n  /**\n   * Observe network status changes / updates\n   */\n  get networkStatus$() {\n    return this.status$.asObservable();\n  }\n\n  /**\n   * Get the network current status. This returns a snapshot of the current value\n   */\n  get currentStatus(): NetworkStatus { // Exposing current status snapshot\n    return this.status$.value;\n  }\n\n  private initMonitoring() {\n    // ⬇ Take logic out of Angular with runOutsideAngular for performance\n    this.ngZone.runOutsideAngular(() => {\n      // Online/offline events\n      merge(\n        fromEvent(window, 'online'),\n        fromEvent(window, 'offline')\n      ).subscribe(() => {\n        const status = this.status$.value;\n        this.updateStatus({\n          ...status,\n          online: navigator.onLine,\n        })\n      });\n\n      // Listen for connection type change\n      const connection = this.getNavigatorConnection();\n      const hasConnection = (!!connection && !!connection?.addEventListener)\n      if (hasConnection) {\n        connection.addEventListener('change', (e:any) => {\n          const current = this.status$.value;\n          this.updateStatus({\n            ...current,\n            effectiveType: e.currentTarget.effectiveType,\n            poorConnection: this.isPoorConnection(e.currentTarget.effectiveType, current.latency),\n          })\n        });\n      }\n\n      // Fallback Periodic connection checks\n      // every one min if navigator connection is available\n      // 10 seconds otherwise\n      const pollingInterval = hasConnection ? this.config.pingIntervalMs : this.config.fallbackPingIntervalMs;\n      \n      interval(pollingInterval || 10000)\n        .pipe(startWith(0), switchMap(() => this.checkConnection()))\n        .subscribe((status) => this.updateStatus(status));\n\n    });\n  }\n\n  private updateStatus(value:NetworkStatus){\n    const prev = this.status$.value;\n    if (JSON.stringify(prev) !== JSON.stringify(value)){ //Emit only if status changed\n\n      // ⬇ Bring it back into Angular so UI can update\n      this.ngZone.run(() => {\n        this.status$.next(value);\n      });\n    }\n  }\n\n  private checkConnection() {\n    const connection = this.getNavigatorConnection();\n    const effectiveType = connection?.effectiveType;\n    const startTime = performance.now();\n\n    return this.http.get(this.config.pingUrl!, \n      { responseType: 'text', headers: new HttpHeaders({ 'X-Heartbeat': 'true' }) }\n    ).pipe(\n      map(() => {\n        const latency = performance.now() - startTime;\n        const online = true;\n        const poorConnection = this.isPoorConnection(effectiveType, latency);\n        return { online, latency, effectiveType, poorConnection };\n      }),\n      catchError(() =>\n        of({\n          online: false,\n          latency: null,\n          effectiveType,\n          poorConnection: true,\n        })\n      )\n    );\n  }\n\n  private getNavigatorConnection(): any {\n    return this.isBrowser\n      ? (navigator as any)?.connection ||\n          (navigator as any)?.mozConnection ||\n          (navigator as any)?.webkitConnection\n      : null;\n  }\n\n  private isPoorConnection(effectiveType: SlowConnectionTypes | undefined, latency: number | null): boolean {\n    return !navigator.onLine ||\n      (effectiveType && this.config.slowConnectionTypes?.includes(effectiveType)) ||\n      (latency !== null && latency > (this.config?.latencyThreshold || 1800));\n  }\n\n  /**\n   * Manually trigger a network status check. This accepts an optional callback which returns the new status\n   */\n  runManualCheck(callback?:(status:NetworkStatus) => void) {\n    this.checkConnection().subscribe((status) => {\n      this.updateStatus(status);\n      \n      !!callback && callback(status)\n    });\n  }\n}\n","/*\n * Public API Surface of ngx-network-monitor\n */\n\nexport * from './lib/network-monitor.service';\nexport * from './lib/models/network-monitor-config.model';\nexport * from './lib/tokens/network-monitor-config.token';","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;;;;MAGa,sBAAsB,GAAG,IAAI,cAAc,CAAuB,wBAAwB,EAAE;AACvG,IAAA,UAAU,EAAE,MAAM;AAClB,IAAA,OAAO,EAAE,OAA6B;AACpC,QAAA,OAAO,EAAE,kBAAkB;AAC3B,QAAA,gBAAgB,EAAE,IAAI;AACtB,QAAA,mBAAmB,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC;AAC5C,QAAA,cAAc,EAAE,KAAK;AACrB,QAAA,sBAAsB,EAAE,KAAK;KAC9B,CAAC;AACH,CAAA;;MCMY,qBAAqB,CAAA;AAYhC,IAAA,WAAA,CACU,IAAgB,EAChB,MAAc,EACD,UAAkB,EACC,oBAA0C,EAAA;QAH1E,IAAI,CAAA,IAAA,GAAJ,IAAI,CAAY;QAChB,IAAM,CAAA,MAAA,GAAN,MAAM,CAAQ;QAEkB,IAAoB,CAAA,oBAAA,GAApB,oBAAoB,CAAsB;QAf5E,IAAO,CAAA,OAAA,GAAG,IAAI,eAAe,CAAgB;AACnD,YAAA,MAAM,EAAE,IAAI;AACZ,YAAA,OAAO,EAAE,IAAI;AACb,YAAA,aAAa,EAAE,SAAS;AACxB,YAAA,cAAc,EAAE,KAAK;AACtB,SAAA,CAAC,CAAC;QAaD,IAAI,CAAC,MAAM,GAAG;;;AAGZ,YAAA,OAAO,EAAE,IAAI,CAAC,oBAAoB,EAAE,OAAO,IAAI,kBAAkB;AACjE,YAAA,gBAAgB,EAAE,IAAI,CAAC,oBAAoB,EAAE,gBAAgB,IAAI,IAAI;AACrE,YAAA,mBAAmB,EAAE,IAAI,CAAC,oBAAoB,EAAE,mBAAmB,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC;AAC9F,YAAA,cAAc,EAAE,IAAI,CAAC,oBAAoB,EAAE,cAAc,IAAI,KAAK;AAClE,YAAA,sBAAsB,EAAE,IAAI,CAAC,oBAAoB,EAAE,sBAAsB,IAAI,KAAK;SACnF,CAAC;AAEF,QAAA,IAAI,CAAC,SAAS,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAC;QAE/C,IAAI,IAAI,CAAC,SAAS,EAAE;YAClB,IAAI,CAAC,cAAc,EAAE,CAAC;AACvB,SAAA;KAEF;AAID;;AAEG;AACH,IAAA,IAAI,cAAc,GAAA;AAChB,QAAA,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;KACpC;AAED;;AAEG;AACH,IAAA,IAAI,aAAa,GAAA;AACf,QAAA,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;KAC3B;IAEO,cAAc,GAAA;;AAEpB,QAAA,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,MAAK;;AAEjC,YAAA,KAAK,CACH,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,EAC3B,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,CAC7B,CAAC,SAAS,CAAC,MAAK;AACf,gBAAA,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;gBAClC,IAAI,CAAC,YAAY,CAAC;AAChB,oBAAA,GAAG,MAAM;oBACT,MAAM,EAAE,SAAS,CAAC,MAAM;AACzB,iBAAA,CAAC,CAAA;AACJ,aAAC,CAAC,CAAC;;AAGH,YAAA,MAAM,UAAU,GAAG,IAAI,CAAC,sBAAsB,EAAE,CAAC;AACjD,YAAA,MAAM,aAAa,IAAI,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAA;AACtE,YAAA,IAAI,aAAa,EAAE;gBACjB,UAAU,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,CAAK,KAAI;AAC9C,oBAAA,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;oBACnC,IAAI,CAAC,YAAY,CAAC;AAChB,wBAAA,GAAG,OAAO;AACV,wBAAA,aAAa,EAAE,CAAC,CAAC,aAAa,CAAC,aAAa;AAC5C,wBAAA,cAAc,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,aAAa,CAAC,aAAa,EAAE,OAAO,CAAC,OAAO,CAAC;AACtF,qBAAA,CAAC,CAAA;AACJ,iBAAC,CAAC,CAAC;AACJ,aAAA;;;;AAKD,YAAA,MAAM,eAAe,GAAG,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC;AAExG,YAAA,QAAQ,CAAC,eAAe,IAAI,KAAK,CAAC;AAC/B,iBAAA,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC;AAC3D,iBAAA,SAAS,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;AAEtD,SAAC,CAAC,CAAC;KACJ;AAEO,IAAA,YAAY,CAAC,KAAmB,EAAA;AACtC,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;AAChC,QAAA,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAC;;AAGjD,YAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAK;AACnB,gBAAA,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3B,aAAC,CAAC,CAAC;AACJ,SAAA;KACF;IAEO,eAAe,GAAA;AACrB,QAAA,MAAM,UAAU,GAAG,IAAI,CAAC,sBAAsB,EAAE,CAAC;AACjD,QAAA,MAAM,aAAa,GAAG,UAAU,EAAE,aAAa,CAAC;AAChD,QAAA,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;AAEpC,QAAA,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,OAAQ,EACvC,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,WAAW,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,EAAE,CAC9E,CAAC,IAAI,CACJ,GAAG,CAAC,MAAK;YACP,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YAC9C,MAAM,MAAM,GAAG,IAAI,CAAC;YACpB,MAAM,cAAc,GAAG,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;YACrE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,CAAC;SAC3D,CAAC,EACF,UAAU,CAAC,MACT,EAAE,CAAC;AACD,YAAA,MAAM,EAAE,KAAK;AACb,YAAA,OAAO,EAAE,IAAI;YACb,aAAa;AACb,YAAA,cAAc,EAAE,IAAI;SACrB,CAAC,CACH,CACF,CAAC;KACH;IAEO,sBAAsB,GAAA;QAC5B,OAAO,IAAI,CAAC,SAAS;cAChB,SAAiB,EAAE,UAAU;AAC3B,gBAAA,SAAiB,EAAE,aAAa;AAChC,gBAAA,SAAiB,EAAE,gBAAgB;cACtC,IAAI,CAAC;KACV;IAEO,gBAAgB,CAAC,aAA8C,EAAE,OAAsB,EAAA;QAC7F,OAAO,CAAC,SAAS,CAAC,MAAM;AACtB,aAAC,aAAa,IAAI,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC;AAC3E,aAAC,OAAO,KAAK,IAAI,IAAI,OAAO,IAAI,IAAI,CAAC,MAAM,EAAE,gBAAgB,IAAI,IAAI,CAAC,CAAC,CAAC;KAC3E;AAED;;AAEG;AACH,IAAA,cAAc,CAAC,QAAwC,EAAA;QACrD,IAAI,CAAC,eAAe,EAAE,CAAC,SAAS,CAAC,CAAC,MAAM,KAAI;AAC1C,YAAA,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;AAE1B,YAAA,CAAC,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAA;AAChC,SAAC,CAAC,CAAC;KACJ;;mHAzJU,qBAAqB,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,UAAA,EAAA,EAAA,EAAA,KAAA,EAAA,EAAA,CAAA,MAAA,EAAA,EAAA,EAAA,KAAA,EAetB,WAAW,EAAA,EAAA,EAAA,KAAA,EACX,sBAAsB,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;AAhBrB,qBAAA,CAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,qBAAqB,cAFpB,MAAM,EAAA,CAAA,CAAA;4FAEP,qBAAqB,EAAA,UAAA,EAAA,CAAA;kBAHjC,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE,MAAM;AACnB,iBAAA,CAAA;wGAgBoC,MAAM,EAAA,UAAA,EAAA,CAAA;0BAAtC,MAAM;2BAAC,WAAW,CAAA;;0BAClB,MAAM;2BAAC,sBAAsB,CAAA;;;AClClC;;AAEG;;ACFH;;AAEG;;;;"}