/* eslint-disable @typescript-eslint/no-explicit-any */ import { lazy, useEffect, type LazyExoticComponent, type FunctionComponent, type ReactNode, } from 'react'; import { initializeModules, type ModulesConfigurator, type ModulesInstanceType, type AnyModule, } from '@equinor/fusion-framework-module'; import moduleContext from './context.js'; type ModuleProviderCreator = < TModules extends Array = Array, // biome-ignore lint/suspicious/noExplicitAny: Default type parameter for module instance reference TRef extends ModulesInstanceType<[AnyModule]> = any, >( configurator: ModulesConfigurator, modules: TModules, ref?: TRef, ) => Promise>; /** * Function for creating a `ModuleProvider` component. * * __NOTE:__ this function requires component to be wrapped in `Suspense` * * @example * ```ts * import http, { HttpModule } from '@equinor/fusion-framework-module-http'; * import msal, { MsalModule } from '@equinor/fusion-framework-module-msal'; * import { createModuleProvider } from '@equinor/fusion-framework-react-module'; * * export default createModuleProvider( * (config) => { * config.auth.configureDefault({ * tenantId: 'MY_TENANT_ID', * clientId: 'MY_CLIENT_ID', * redirectUri: '/authentication/login-callback', * }); * config.http.configureClient('foo', { * baseUri: 'https://foo.bar', * defaultScopes: ['FOO_CLIENT_ID/.default'], * }); * }, * [http, msal] *); * ``` * @param configurator callback for configuring provided modules * @param modules modules which should be initiated * @param ref optional parent module instance * @returns Suspensive `ModuleProvider` */ export const createModuleProvider: ModuleProviderCreator = async < TModules extends Array, // biome-ignore lint/suspicious/noExplicitAny: Default type parameter for module instance reference TRef extends ModulesInstanceType<[AnyModule]> = any, >( configurator: ModulesConfigurator, ref?: TRef, ): Promise> => { const Component = lazy(async () => { const { dispose, ...instance } = await initializeModules(configurator, ref); return { default: ({ children }: { children?: ReactNode }) => { // biome-ignore lint/correctness/useExhaustiveDependencies: should dispose when new instance is provided useEffect(() => dispose, [instance]); return {children}; }, }; }); return Component; }; export const ModuleProvider = moduleContext.Provider; export default ModuleProvider;