Fix typescript compilation error on public properties

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
Jonathan
2025-06-11 18:42:10 +02:00
committed by Sacha Al Himdani
parent 155bbbd840
commit fb9bce0282

View File

@@ -1,166 +1,176 @@
import { import {
lazy as reactLazy, lazy as reactLazy,
type LazyExoticComponent, type LazyExoticComponent,
type ComponentType, type ComponentType,
type FC, type FC,
} from "react"; } from "react";
const DEFAULT_STORAGE_KEY = "reactLazyReloadedFunctions"; const DEFAULT_STORAGE_KEY = "reactLazyReloadedFunctions";
class ReloadStorage { class ReloadStorage {
constructor(public readonly storageKey = DEFAULT_STORAGE_KEY) {} public readonly storageKey: string;
getMap(): Map<string, number> { constructor(storageKey = DEFAULT_STORAGE_KEY) {
const stored = sessionStorage.getItem(this.storageKey); this.storageKey = storageKey;
try {
const parsed: unknown = stored ? JSON.parse(stored) : [];
return new Map(
Array.isArray(parsed)
? parsed.filter(
(value) =>
Array.isArray(value) &&
typeof value[0] === "string" &&
typeof value[1] === "number"
)
: []
);
} catch (error) {
console.error("Error parsing react-lazy storage:", error);
return new Map();
} }
}
addFunction(functionName: string): void { getMap(): Map<string, number> {
const stored = this.getMap(); const stored = sessionStorage.getItem(this.storageKey);
stored.set(functionName, (stored.get(functionName) ?? 0) + 1);
this.save(stored);
}
removeFunction(functionName: string): void { try {
const stored = this.getMap(); const parsed: unknown = stored ? JSON.parse(stored) : [];
stored.delete(functionName); return new Map(
this.save(stored); Array.isArray(parsed)
} ? parsed.filter(
(value) =>
Array.isArray(value) &&
typeof value[0] === "string" &&
typeof value[1] === "number",
)
: [],
);
} catch (error) {
console.error("Error parsing react-lazy storage:", error);
return new Map();
}
}
protected save(stored: Map<string, number>): void { addFunction(functionName: string): void {
sessionStorage.setItem( const stored = this.getMap();
this.storageKey, stored.set(functionName, (stored.get(functionName) ?? 0) + 1);
JSON.stringify([...stored.entries()]) this.save(stored);
); }
}
removeFunction(functionName: string): void {
const stored = this.getMap();
stored.delete(functionName);
this.save(stored);
}
protected save(stored: Map<string, number>): void {
sessionStorage.setItem(
this.storageKey,
JSON.stringify([...stored.entries()]),
);
}
} }
type ForceReloadConfig = { type ForceReloadConfig = {
maxRetries: number; maxRetries: number;
storageKey?: string; storageKey?: string;
}; };
type LazyConfigInit = { type LazyConfigInit = {
forceReload?: false | Partial<ForceReloadConfig>; forceReload?: false | Partial<ForceReloadConfig>;
importRetries?: number; importRetries?: number;
retryDelay?: number; retryDelay?: number;
onImportError?: (error: unknown) => void; onImportError?: (error: unknown) => void;
}; };
type LazyConfig = { type LazyConfig = {
forceReload: ForceReloadConfig; forceReload: ForceReloadConfig;
importRetries: number; importRetries: number;
retryDelay: number; retryDelay: number;
onImportError?: (error: unknown) => void; onImportError?: (error: unknown) => void;
}; };
const createConfig = (init: LazyConfigInit = {}): LazyConfig => ({ const createConfig = (init: LazyConfigInit = {}): LazyConfig => ({
forceReload: { forceReload: {
maxRetries: 1, maxRetries: 1,
storageKey: DEFAULT_STORAGE_KEY, storageKey: DEFAULT_STORAGE_KEY,
...(typeof init.forceReload === "object" ...(typeof init.forceReload === "object"
? init.forceReload ? init.forceReload
: init.forceReload === false : init.forceReload === false
? { maxRetries: 0 } ? { maxRetries: 0 }
: {}), : {}),
}, },
importRetries: importRetries:
typeof init.importRetries === "number" typeof init.importRetries === "number"
? Math.max(0, init.importRetries) ? Math.max(0, init.importRetries)
: 0, : 0,
retryDelay: retryDelay:
typeof init.retryDelay === "number" ? Math.max(0, init.retryDelay) : 300, typeof init.retryDelay === "number"
onImportError: init.onImportError, ? Math.max(0, init.retryDelay)
: 300,
onImportError: init.onImportError,
}); });
export function createLazy<P = {}>(config: LazyConfigInit = {}) { export function createLazy<P = {}>(config: LazyConfigInit = {}) {
const { forceReload, importRetries, retryDelay, onImportError } = const { forceReload, importRetries, retryDelay, onImportError } =
createConfig(config); createConfig(config);
const reloadStorage = new ReloadStorage(forceReload.storageKey); const reloadStorage = new ReloadStorage(forceReload.storageKey);
function enhancedLazy<T = P>( function enhancedLazy<T = P>(
importFunction: () => Promise<{ default: ComponentType<T> }> importFunction: () => Promise<{ default: ComponentType<T> }>,
): LazyExoticComponent<ComponentType<T>> { ): LazyExoticComponent<ComponentType<T>> {
const functionString = importFunction.toString(); const functionString = importFunction.toString();
const importWithRetry = async () => { const importWithRetry = async () => {
let retryCount = 0; let retryCount = 0;
const tryImport = async (): Promise<{ default: ComponentType<T> }> => { const tryImport = async (): Promise<{
try { default: ComponentType<T>;
return await importFunction(); }> => {
} catch (error) { try {
if (onImportError) { return await importFunction();
onImportError(error); } catch (error) {
} else { if (onImportError) {
console.error("React-lazy import error:", error); onImportError(error);
} } else {
console.error("React-lazy import error:", error);
}
if (retryCount < importRetries) { if (retryCount < importRetries) {
retryCount++; retryCount++;
if (retryDelay > 0) { if (retryDelay > 0) {
await new Promise((resolve) => setTimeout(resolve, retryDelay)); await new Promise((resolve) =>
} setTimeout(resolve, retryDelay),
);
}
return tryImport();
}
throw error;
}
};
return tryImport(); return tryImport();
} };
throw error; return reactLazy(async () => {
} try {
}; const component = await importWithRetry();
if (forceReload.maxRetries > 0) {
reloadStorage.removeFunction(functionString);
}
return component;
} catch (error) {
if (
forceReload.maxRetries > 0 &&
(reloadStorage.getMap().get(functionString) ?? 0) <
forceReload.maxRetries
) {
reloadStorage.addFunction(functionString);
window.location.reload();
return tryImport(); const EmptyComponent: FC<T> = () => null;
}; return { default: EmptyComponent };
}
throw error;
}
});
}
return reactLazy(async () => { return enhancedLazy;
try {
const component = await importWithRetry();
if (forceReload.maxRetries > 0) {
reloadStorage.removeFunction(functionString);
}
return component;
} catch (error) {
if (
forceReload.maxRetries > 0 &&
(reloadStorage.getMap().get(functionString) ?? 0) <
forceReload.maxRetries
) {
reloadStorage.addFunction(functionString);
window.location.reload();
const EmptyComponent: FC<T> = () => null;
return { default: EmptyComponent };
}
throw error;
}
});
}
return enhancedLazy;
} }
export const lazy = createLazy({ export const lazy = createLazy({
forceReload: { forceReload: {
maxRetries: 3, maxRetries: 3,
storageKey: DEFAULT_STORAGE_KEY, storageKey: DEFAULT_STORAGE_KEY,
}, },
importRetries: 3, importRetries: 3,
retryDelay: 300, retryDelay: 300,
}); });