@@ -49,6 +49,27 @@ import {
4949} from './appsyncUrl' ;
5050import { awsRealTimeHeaderBasedAuth } from './authHeaders' ;
5151
52+ // Platform-safe AsyncStorage import
53+ let AsyncStorage : any ;
54+ try {
55+ // Try to import AsyncStorage for React Native (optional dependency)
56+ // eslint-disable-next-line import/no-extraneous-dependencies
57+ AsyncStorage = require ( '@react-native-async-storage/async-storage' ) . default ;
58+ } catch ( e ) {
59+ // Fallback for web/other platforms - use localStorage if available
60+ AsyncStorage =
61+ typeof localStorage !== 'undefined'
62+ ? {
63+ setItem : ( key : string , value : string ) => {
64+ localStorage . setItem ( key , value ) ;
65+
66+ return Promise . resolve ( ) ;
67+ } ,
68+ getItem : ( key : string ) => Promise . resolve ( localStorage . getItem ( key ) ) ,
69+ }
70+ : null ;
71+ }
72+
5273const dispatchApiEvent = ( payload : HubPayload ) => {
5374 Hub . dispatch ( 'api' , payload , 'PubSub' , AMPLIFY_SYMBOL ) ;
5475} ;
@@ -682,6 +703,18 @@ export abstract class AWSWebSocketProvider {
682703 if ( type === MESSAGE_TYPES . GQL_CONNECTION_KEEP_ALIVE ) {
683704 this . maintainKeepAlive ( ) ;
684705
706+ // Persist keep-alive timestamp for cross-session tracking
707+ if ( AsyncStorage ) {
708+ try {
709+ AsyncStorage . setItem (
710+ 'AWS_AMPLIFY_LAST_KEEP_ALIVE' ,
711+ JSON . stringify ( new Date ( ) ) ,
712+ ) ;
713+ } catch ( error ) {
714+ this . logger . warn ( 'Failed to persist keep-alive timestamp:' , error ) ;
715+ }
716+ }
717+
685718 return ;
686719 }
687720
@@ -1051,6 +1084,59 @@ export abstract class AWSWebSocketProvider {
10511084 } ;
10521085 }
10531086
1087+ /**
1088+ * Get persistent WebSocket health state (survives app restarts)
1089+ */
1090+ async getPersistentConnectionHealth ( ) : Promise <
1091+ import ( '../../types' ) . WebSocketHealthState
1092+ > {
1093+ let persistentKeepAliveTime : number | undefined ;
1094+ let _timeSinceLastPersistentKeepAlive : number | undefined ;
1095+
1096+ // Try to get persistent keep-alive timestamp
1097+ if ( AsyncStorage ) {
1098+ try {
1099+ const persistentKeepAlive = await AsyncStorage . getItem (
1100+ 'AWS_AMPLIFY_LAST_KEEP_ALIVE' ,
1101+ ) ;
1102+ if ( persistentKeepAlive ) {
1103+ const keepAliveDate = new Date ( JSON . parse ( persistentKeepAlive ) ) ;
1104+ persistentKeepAliveTime = keepAliveDate . getTime ( ) ;
1105+ _timeSinceLastPersistentKeepAlive =
1106+ Date . now ( ) - persistentKeepAliveTime ;
1107+ }
1108+ } catch ( error ) {
1109+ this . logger . warn (
1110+ 'Failed to retrieve persistent keep-alive timestamp:' ,
1111+ error ,
1112+ ) ;
1113+ }
1114+ }
1115+
1116+ // Use the more recent timestamp (in-memory vs persistent)
1117+ const lastKeepAliveTime =
1118+ Math . max ( this . keepAliveTimestamp || 0 , persistentKeepAliveTime || 0 ) ||
1119+ undefined ;
1120+
1121+ const timeSinceLastKeepAlive = lastKeepAliveTime
1122+ ? Date . now ( ) - lastKeepAliveTime
1123+ : undefined ;
1124+
1125+ // Health check includes persistent data
1126+ const isHealthy =
1127+ this . connectionState === ConnectionState . Connected &&
1128+ lastKeepAliveTime &&
1129+ timeSinceLastKeepAlive !== undefined &&
1130+ timeSinceLastKeepAlive < 65000 ; // 65 second threshold
1131+
1132+ return {
1133+ isHealthy : Boolean ( isHealthy ) ,
1134+ connectionState : this . connectionState || ConnectionState . Disconnected ,
1135+ lastKeepAliveTime,
1136+ timeSinceLastKeepAlive,
1137+ } ;
1138+ }
1139+
10541140 /**
10551141 * Check if WebSocket is currently connected
10561142 */
0 commit comments