Skip to content

Commit

Permalink
Reverting Tirth's changes
Browse files Browse the repository at this point in the history
  • Loading branch information
amit-s19 committed Sep 12, 2024
1 parent 35b33cb commit 39d1344
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 172 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "0.1.90",
"version": "0.1.92",
"license": "MIT",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion src/data-sync-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ import { createContext } from "react";

type DataSyncContextType = any;

export const DataSyncContext = createContext<DataSyncContextType | null>(null);
export const DataSyncContext = createContext<DataSyncContextType | null>(null);
2 changes: 1 addition & 1 deletion src/hooks/useNetworkStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ const useNetworkStatus = () => {
return isConnected;
};

export default useNetworkStatus;
export default useNetworkStatus;
199 changes: 30 additions & 169 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,17 @@ import React, {
useContext,
useEffect,
useState,
useRef,
useRef
} from 'react';
import { DataSyncContext } from './data-sync-context';
import axios from 'axios';
import localForage from 'localforage';
import { omit } from 'underscore';

//@ts-ignore
const api = axios?.create();
import { omit } from 'underscore';
const api = axios.create();
const RETRY_LIMIT = 0;
const RETRY_DELAY_MS = 1000;
const API_REQUESTS_STORAGE_KEY = 'apiRequests';
const OFFLINE_RESPONSES_STORAGE_KEY = 'offlineResponses';

import {
generateUuid,
Expand All @@ -34,35 +32,21 @@ import useNetworkStatus from './hooks/useNetworkStatus';
// const hasWindow = () => {
// return window && typeof window !== 'undefined';
// };
interface ApiRequest {
id: string;
type?: string;
url: string;
method: string;
data?: any | ((previousResponses: any[]) => Promise<any>);
isFormdata?: boolean;
retryCount?: number;
dependsOn?: string;
}

type ConfigType = {
isFormdata?: boolean;
maxRetry?: number;
executionOrder?: string[];
sequentialProcessing?: boolean;
};

export const OfflineSyncProvider: FC<{
children: ReactElement;
render?: (status: { isOffline?: boolean; isOnline: boolean }) => ReactNode;
onStatusChange?: (status: { isOnline: boolean }) => void;
onCallback?: (data: any) => void;
toastConfig?: any;
config?: ConfigType;
}> = ({ children, render, onStatusChange, onCallback, config }) => {
}> = ({ children, render, onStatusChange, onCallback }) => {
// Manage state for data, offline status, and online status
const [data, setData] = useState<Record<string, any>>({});
const isSyncing = useRef<boolean>(false);
const isSyncing = useRef<boolean>();
const [isOnline, setIsOnline] = useState<boolean>(
window?.navigator?.onLine ?? true
);
Expand All @@ -77,6 +61,7 @@ export const OfflineSyncProvider: FC<{
handleOnline();
} else {
handleOffline();

}
}
}, [isConnected]);
Expand Down Expand Up @@ -116,7 +101,7 @@ export const OfflineSyncProvider: FC<{

const saveRequestToOfflineStorage = async (apiConfig: any) => {
try {
const storedRequests: any =
const storedRequests: Array<any> =
(await localForage.getItem(API_REQUESTS_STORAGE_KEY)) || [];
console.log('perform stored', {
req: storedRequests,
Expand All @@ -125,17 +110,10 @@ export const OfflineSyncProvider: FC<{
if (apiConfig?.isFormdata && apiConfig?.data instanceof FormData) {
// console.log({ apiConfig })
const newData = await _formDataToObject(apiConfig.data);
storedRequests.push(
omit(
{ ...apiConfig, data: newData, type: apiConfig.type },
'onSuccess'
)
);
storedRequests.push(omit({ ...apiConfig, data: newData }, 'onSuccess'));
} else {
console.log('Saving request normally');
storedRequests.push(
omit({ ...apiConfig, type: apiConfig.type }, 'onSuccess')
);
storedRequests.push(omit({ ...apiConfig }, 'onSuccess'));
}
console.log('perform forage after:', { storedRequests });
const result = await localForage.setItem(
Expand All @@ -148,74 +126,30 @@ export const OfflineSyncProvider: FC<{
}
};

const saveResponseToOfflineStorage = async (type: string, response: any) => {
try {
const storedResponses: Record<string, any> =
(await localForage.getItem(OFFLINE_RESPONSES_STORAGE_KEY)) || {};
if (!storedResponses[type]) {
storedResponses[type] = [];
}
storedResponses[type].push(response);
await localForage.setItem(OFFLINE_RESPONSES_STORAGE_KEY, storedResponses);
} catch (error) {
console.error('Error saving response to offline storage:', error);
}
};

const getOfflineResponses = async (type: string) => {
try {
const storedResponses: Record<string, any> =
(await localForage.getItem(OFFLINE_RESPONSES_STORAGE_KEY)) || {};
return storedResponses[type] || [];
} catch (error) {
console.error('Error getting offline responses:', error);
return [];
}
};

// Function to perform the actual API request and handle retries
const performRequest = async (config: any): Promise<any> => {
console.log('Inside performRequest');
console.log("Inside performRequest")
try {
let requestData = config.data;
if (typeof requestData === 'function') {
const dependencyResponses = config.dependsOn
? await getOfflineResponses(config.dependsOn)
: [];
requestData = await requestData(dependencyResponses);
}

let response;
if (config?.isFormdata && !(requestData instanceof FormData)) {
const updateConfig = { ...config, data: objectToFormData(requestData) };
if (config?.isFormdata && !(config?.data instanceof FormData)) {
const updateConfig = { ...config, data: objectToFormData(config.data) };
response = await api.request(updateConfig);
} else {
response = await api.request({ ...config, data: requestData });
}

if (config.type) {
await saveResponseToOfflineStorage(config.type, response.data);
response = await api.request(config);
}

onCallback && onCallback({ config, data: response, sendRequest });
return response.data;
} catch (error) {
console.log('packageError', { error });
console.log('Inside performRequest error: ', {
rc: config.retryCount,
RETRY_LIMIT,
});
if ((config.retryCount ?? 0) < RETRY_LIMIT) {
console.log("Inside performRequest error: ", { rc: config.retryCount, RETRY_LIMIT })
if (config.retryCount < RETRY_LIMIT) {
await new Promise(resolve => setTimeout(resolve, RETRY_DELAY_MS));
if (config.retryCount === undefined) {
config.retryCount = 1;
} else {
config.retryCount++;
}
config.retryCount++;
return performRequest(config);
} else {
// Retry limit reached, save the request to offline storage
console.log('Saving request to offline storage');
console.log("Saving request to offline storage");
await saveRequestToOfflineStorage(config);
return error;
// throw new Error('Exceeded retry limit, request saved for offline sync.');
Expand All @@ -234,109 +168,36 @@ export const OfflineSyncProvider: FC<{
}
};

const processRequestsSequentially = async (
requests: ApiRequest[],
executionOrder?: string[]
) => {
const results = [];

if (executionOrder && executionOrder.length > 0) {
const requestsByType: Record<string, ApiRequest[]> = {};

for (const request of requests) {
const type = request.type || 'default';
if (!requestsByType[type]) {
requestsByType[type] = [];
}
requestsByType[type].push(request);
}

for (const type of executionOrder) {
const typeRequests = requestsByType[type] || [];
for (const request of typeRequests) {
try {
const result = await performRequest(request);
results.push({ request, result });
} catch (error) {
console.error(`Error processing ${type} request:`, error);
results.push({ request, error });
}
}
}

for (const type in requestsByType) {
if (!executionOrder.includes(type)) {
for (const request of requestsByType[type]) {
try {
const result = await performRequest(request);
results.push({ request, result });
} catch (error) {
console.error(`Error processing ${type} request:`, error);
results.push({ request, error });
}
}
}
}
} else {
for (const request of requests) {
try {
const result = await performRequest(request);
results.push({ request, result });
} catch (error) {
console.error(`Error processing request:`, error);
results.push({ request, error });
}
}
}

return results;
};

const syncOfflineRequests = async () => {
if (isSyncing.current) {
return;
}
isSyncing.current = true;
const storedRequests: any = await getStoredRequests();
if (!storedRequests || storedRequests.length === 0) {
isSyncing.current = false;
return;
}

console.log('Inside syncOfflineRequests', storedRequests);
console.log("Inside syncOfflineRequests", storedRequests)
const requestClone = [...storedRequests];

try {
let results;
if (config?.executionOrder) {
results = await processRequestsSequentially(
requestClone,
config.executionOrder
);
} else if (config?.sequentialProcessing) {
results = await processRequestsSequentially(requestClone);
} else {
results = await Promise.all(requestClone.map(performRequest));
}

for (const result of results) {
const request = result.request || result;
const error = result.error;
if (!error) {
for (const request of storedRequests) {
console.log("Inside syncOfflineRequests loop, ", storedRequests)
if (request) {
try {
await performRequest(request);
// Remove the request with a matching id from requestClone
const updatedRequests = requestClone.filter(
sr => sr.id !== request.id
);
requestClone.splice(0, requestClone.length, ...updatedRequests);
} else {
console.error('Failed to process request:', request, error);
} catch (error) {
console.log({ error });
} finally {
await localForage.setItem(API_REQUESTS_STORAGE_KEY, requestClone);
}
}
} catch (error) {
console.error('Error in syncOfflineRequests:', error);
} finally {
await localForage.setItem(API_REQUESTS_STORAGE_KEY, requestClone);
isSyncing.current = false;
}
isSyncing.current = false;
};

return (
Expand All @@ -361,4 +222,4 @@ export const OfflineSyncProvider: FC<{
// Custom hook to access offline sync context
export const useOfflineSyncContext = () => {
return useContext(DataSyncContext);
};
};

0 comments on commit 39d1344

Please sign in to comment.