@@ -6,19 +6,17 @@ import React, {
6
6
useContext ,
7
7
useEffect ,
8
8
useState ,
9
- useRef ,
9
+ useRef
10
10
} from 'react' ;
11
11
import { DataSyncContext } from './data-sync-context' ;
12
12
import axios from 'axios' ;
13
13
import localForage from 'localforage' ;
14
- import { omit } from 'underscore' ;
15
14
16
- // @ts -ignore
17
- const api = axios ? .create ( ) ;
15
+ import { omit } from 'underscore' ;
16
+ const api = axios . create ( ) ;
18
17
const RETRY_LIMIT = 0 ;
19
18
const RETRY_DELAY_MS = 1000 ;
20
19
const API_REQUESTS_STORAGE_KEY = 'apiRequests' ;
21
- const OFFLINE_RESPONSES_STORAGE_KEY = 'offlineResponses' ;
22
20
23
21
import {
24
22
generateUuid ,
@@ -34,35 +32,21 @@ import useNetworkStatus from './hooks/useNetworkStatus';
34
32
// const hasWindow = () => {
35
33
// return window && typeof window !== 'undefined';
36
34
// };
37
- interface ApiRequest {
38
- id : string ;
39
- type ?: string ;
40
- url : string ;
41
- method : string ;
42
- data ?: any | ( ( previousResponses : any [ ] ) => Promise < any > ) ;
43
- isFormdata ?: boolean ;
44
- retryCount ?: number ;
45
- dependsOn ?: string ;
46
- }
47
-
48
35
type ConfigType = {
49
36
isFormdata ?: boolean ;
50
37
maxRetry ?: number ;
51
- executionOrder ?: string [ ] ;
52
- sequentialProcessing ?: boolean ;
53
38
} ;
54
-
55
39
export const OfflineSyncProvider : FC < {
56
40
children : ReactElement ;
57
41
render ?: ( status : { isOffline ?: boolean ; isOnline : boolean } ) => ReactNode ;
58
42
onStatusChange ?: ( status : { isOnline : boolean } ) => void ;
59
43
onCallback ?: ( data : any ) => void ;
60
44
toastConfig ?: any ;
61
45
config ?: ConfigType ;
62
- } > = ( { children, render, onStatusChange, onCallback, config } ) => {
46
+ } > = ( { children, render, onStatusChange, onCallback } ) => {
63
47
// Manage state for data, offline status, and online status
64
48
const [ data , setData ] = useState < Record < string , any > > ( { } ) ;
65
- const isSyncing = useRef < boolean > ( false ) ;
49
+ const isSyncing = useRef < boolean > ( ) ;
66
50
const [ isOnline , setIsOnline ] = useState < boolean > (
67
51
window ?. navigator ?. onLine ?? true
68
52
) ;
@@ -77,6 +61,7 @@ export const OfflineSyncProvider: FC<{
77
61
handleOnline ( ) ;
78
62
} else {
79
63
handleOffline ( ) ;
64
+
80
65
}
81
66
}
82
67
} , [ isConnected ] ) ;
@@ -116,7 +101,7 @@ export const OfflineSyncProvider: FC<{
116
101
117
102
const saveRequestToOfflineStorage = async ( apiConfig : any ) => {
118
103
try {
119
- const storedRequests : any =
104
+ const storedRequests : Array < any > =
120
105
( await localForage . getItem ( API_REQUESTS_STORAGE_KEY ) ) || [ ] ;
121
106
console . log ( 'perform stored' , {
122
107
req : storedRequests ,
@@ -125,17 +110,10 @@ export const OfflineSyncProvider: FC<{
125
110
if ( apiConfig ?. isFormdata && apiConfig ?. data instanceof FormData ) {
126
111
// console.log({ apiConfig })
127
112
const newData = await _formDataToObject ( apiConfig . data ) ;
128
- storedRequests . push (
129
- omit (
130
- { ...apiConfig , data : newData , type : apiConfig . type } ,
131
- 'onSuccess'
132
- )
133
- ) ;
113
+ storedRequests . push ( omit ( { ...apiConfig , data : newData } , 'onSuccess' ) ) ;
134
114
} else {
135
115
console . log ( 'Saving request normally' ) ;
136
- storedRequests . push (
137
- omit ( { ...apiConfig , type : apiConfig . type } , 'onSuccess' )
138
- ) ;
116
+ storedRequests . push ( omit ( { ...apiConfig } , 'onSuccess' ) ) ;
139
117
}
140
118
console . log ( 'perform forage after:' , { storedRequests } ) ;
141
119
const result = await localForage . setItem (
@@ -148,74 +126,30 @@ export const OfflineSyncProvider: FC<{
148
126
}
149
127
} ;
150
128
151
- const saveResponseToOfflineStorage = async ( type : string , response : any ) => {
152
- try {
153
- const storedResponses : Record < string , any > =
154
- ( await localForage . getItem ( OFFLINE_RESPONSES_STORAGE_KEY ) ) || { } ;
155
- if ( ! storedResponses [ type ] ) {
156
- storedResponses [ type ] = [ ] ;
157
- }
158
- storedResponses [ type ] . push ( response ) ;
159
- await localForage . setItem ( OFFLINE_RESPONSES_STORAGE_KEY , storedResponses ) ;
160
- } catch ( error ) {
161
- console . error ( 'Error saving response to offline storage:' , error ) ;
162
- }
163
- } ;
164
-
165
- const getOfflineResponses = async ( type : string ) => {
166
- try {
167
- const storedResponses : Record < string , any > =
168
- ( await localForage . getItem ( OFFLINE_RESPONSES_STORAGE_KEY ) ) || { } ;
169
- return storedResponses [ type ] || [ ] ;
170
- } catch ( error ) {
171
- console . error ( 'Error getting offline responses:' , error ) ;
172
- return [ ] ;
173
- }
174
- } ;
175
-
176
129
// Function to perform the actual API request and handle retries
177
130
const performRequest = async ( config : any ) : Promise < any > => {
178
- console . log ( ' Inside performRequest' ) ;
131
+ console . log ( " Inside performRequest" )
179
132
try {
180
- let requestData = config . data ;
181
- if ( typeof requestData === 'function' ) {
182
- const dependencyResponses = config . dependsOn
183
- ? await getOfflineResponses ( config . dependsOn )
184
- : [ ] ;
185
- requestData = await requestData ( dependencyResponses ) ;
186
- }
187
-
188
133
let response ;
189
- if ( config ?. isFormdata && ! ( requestData instanceof FormData ) ) {
190
- const updateConfig = { ...config , data : objectToFormData ( requestData ) } ;
134
+ if ( config ?. isFormdata && ! ( config ?. data instanceof FormData ) ) {
135
+ const updateConfig = { ...config , data : objectToFormData ( config . data ) } ;
191
136
response = await api . request ( updateConfig ) ;
192
137
} else {
193
- response = await api . request ( { ...config , data : requestData } ) ;
194
- }
195
-
196
- if ( config . type ) {
197
- await saveResponseToOfflineStorage ( config . type , response . data ) ;
138
+ response = await api . request ( config ) ;
198
139
}
199
140
200
141
onCallback && onCallback ( { config, data : response , sendRequest } ) ;
201
142
return response . data ;
202
143
} catch ( error ) {
203
144
console . log ( 'packageError' , { error } ) ;
204
- console . log ( 'Inside performRequest error: ' , {
205
- rc : config . retryCount ,
206
- RETRY_LIMIT ,
207
- } ) ;
208
- if ( ( config . retryCount ?? 0 ) < RETRY_LIMIT ) {
145
+ console . log ( "Inside performRequest error: " , { rc : config . retryCount , RETRY_LIMIT } )
146
+ if ( config . retryCount < RETRY_LIMIT ) {
209
147
await new Promise ( resolve => setTimeout ( resolve , RETRY_DELAY_MS ) ) ;
210
- if ( config . retryCount === undefined ) {
211
- config . retryCount = 1 ;
212
- } else {
213
- config . retryCount ++ ;
214
- }
148
+ config . retryCount ++ ;
215
149
return performRequest ( config ) ;
216
150
} else {
217
151
// Retry limit reached, save the request to offline storage
218
- console . log ( ' Saving request to offline storage' ) ;
152
+ console . log ( " Saving request to offline storage" ) ;
219
153
await saveRequestToOfflineStorage ( config ) ;
220
154
return error ;
221
155
// throw new Error('Exceeded retry limit, request saved for offline sync.');
@@ -234,109 +168,36 @@ export const OfflineSyncProvider: FC<{
234
168
}
235
169
} ;
236
170
237
- const processRequestsSequentially = async (
238
- requests : ApiRequest [ ] ,
239
- executionOrder ?: string [ ]
240
- ) => {
241
- const results = [ ] ;
242
-
243
- if ( executionOrder && executionOrder . length > 0 ) {
244
- const requestsByType : Record < string , ApiRequest [ ] > = { } ;
245
-
246
- for ( const request of requests ) {
247
- const type = request . type || 'default' ;
248
- if ( ! requestsByType [ type ] ) {
249
- requestsByType [ type ] = [ ] ;
250
- }
251
- requestsByType [ type ] . push ( request ) ;
252
- }
253
-
254
- for ( const type of executionOrder ) {
255
- const typeRequests = requestsByType [ type ] || [ ] ;
256
- for ( const request of typeRequests ) {
257
- try {
258
- const result = await performRequest ( request ) ;
259
- results . push ( { request, result } ) ;
260
- } catch ( error ) {
261
- console . error ( `Error processing ${ type } request:` , error ) ;
262
- results . push ( { request, error } ) ;
263
- }
264
- }
265
- }
266
-
267
- for ( const type in requestsByType ) {
268
- if ( ! executionOrder . includes ( type ) ) {
269
- for ( const request of requestsByType [ type ] ) {
270
- try {
271
- const result = await performRequest ( request ) ;
272
- results . push ( { request, result } ) ;
273
- } catch ( error ) {
274
- console . error ( `Error processing ${ type } request:` , error ) ;
275
- results . push ( { request, error } ) ;
276
- }
277
- }
278
- }
279
- }
280
- } else {
281
- for ( const request of requests ) {
282
- try {
283
- const result = await performRequest ( request ) ;
284
- results . push ( { request, result } ) ;
285
- } catch ( error ) {
286
- console . error ( `Error processing request:` , error ) ;
287
- results . push ( { request, error } ) ;
288
- }
289
- }
290
- }
291
-
292
- return results ;
293
- } ;
294
-
295
171
const syncOfflineRequests = async ( ) => {
296
172
if ( isSyncing . current ) {
297
173
return ;
298
174
}
299
175
isSyncing . current = true ;
300
176
const storedRequests : any = await getStoredRequests ( ) ;
301
177
if ( ! storedRequests || storedRequests . length === 0 ) {
302
- isSyncing . current = false ;
303
178
return ;
304
179
}
305
180
306
- console . log ( ' Inside syncOfflineRequests' , storedRequests ) ;
181
+ console . log ( " Inside syncOfflineRequests" , storedRequests )
307
182
const requestClone = [ ...storedRequests ] ;
308
-
309
- try {
310
- let results ;
311
- if ( config ?. executionOrder ) {
312
- results = await processRequestsSequentially (
313
- requestClone ,
314
- config . executionOrder
315
- ) ;
316
- } else if ( config ?. sequentialProcessing ) {
317
- results = await processRequestsSequentially ( requestClone ) ;
318
- } else {
319
- results = await Promise . all ( requestClone . map ( performRequest ) ) ;
320
- }
321
-
322
- for ( const result of results ) {
323
- const request = result . request || result ;
324
- const error = result . error ;
325
- if ( ! error ) {
183
+ for ( const request of storedRequests ) {
184
+ console . log ( "Inside syncOfflineRequests loop, " , storedRequests )
185
+ if ( request ) {
186
+ try {
187
+ await performRequest ( request ) ;
188
+ // Remove the request with a matching id from requestClone
326
189
const updatedRequests = requestClone . filter (
327
190
sr => sr . id !== request . id
328
191
) ;
329
192
requestClone . splice ( 0 , requestClone . length , ...updatedRequests ) ;
330
- } else {
331
- console . error ( 'Failed to process request:' , request , error ) ;
193
+ } catch ( error ) {
194
+ console . log ( { error } ) ;
195
+ } finally {
196
+ await localForage . setItem ( API_REQUESTS_STORAGE_KEY , requestClone ) ;
332
197
}
333
198
}
334
- } catch ( error ) {
335
- console . error ( 'Error in syncOfflineRequests:' , error ) ;
336
- } finally {
337
- await localForage . setItem ( API_REQUESTS_STORAGE_KEY , requestClone ) ;
338
- isSyncing . current = false ;
339
199
}
200
+ isSyncing . current = false ;
340
201
} ;
341
202
342
203
return (
@@ -361,4 +222,4 @@ export const OfflineSyncProvider: FC<{
361
222
// Custom hook to access offline sync context
362
223
export const useOfflineSyncContext = ( ) => {
363
224
return useContext ( DataSyncContext ) ;
364
- } ;
225
+ } ;
0 commit comments