diff --git a/admin-ui/app/routes/index.tsx b/admin-ui/app/routes/index.tsx index 65a20a67d7..e5a93491dc 100755 --- a/admin-ui/app/routes/index.tsx +++ b/admin-ui/app/routes/index.tsx @@ -3,7 +3,7 @@ import { Route, Routes, Navigate } from 'react-router-dom' import { useSelector } from 'react-redux' // ----------- Layout Imports --------------- -import { processRoutes, processRoutesSync } from 'Plugins/PluginMenuResolver' +import { processRoutes } from 'Plugins/PluginMenuResolver' import GluuSuspenseLoader from 'Routes/Apps/Gluu/GluuSuspenseLoader' @@ -22,9 +22,8 @@ export const RoutedContent = () => { const routes = await processRoutes() setPluginMenus(routes) } catch (error) { - console.error('Failed to load plugins:', error) - // Fallback to sync loading - setPluginMenus(processRoutesSync()) + console.error('Failed to load plugin routes:', error) + setPluginMenus([]) } } diff --git a/admin-ui/config/webpack.config.client.dev.ts b/admin-ui/config/webpack.config.client.dev.ts index 7a9b96fab1..1d73672c6a 100755 --- a/admin-ui/config/webpack.config.client.dev.ts +++ b/admin-ui/config/webpack.config.client.dev.ts @@ -177,7 +177,7 @@ const webpackConfig: WebpackConfig & { devServer?: DevServerConfig } = { path.resolve(__dirname, '../jans_config_api_orval'), path.resolve(__dirname, '..'), // Include root directory for api-client.ts ], - exclude: /node_modules/, + exclude: /(node_modules|\.test\.(ts|tsx)$)/, use: 'babel-loader', }, { @@ -186,9 +186,14 @@ const webpackConfig: WebpackConfig & { devServer?: DevServerConfig } = { }, { test: /\.js$/, - exclude: /node_modules/, + exclude: /(node_modules|\.test\.js$)/, use: 'babel-loader', }, + { + test: /\.test\.(js|ts|tsx)$/, + include: [config.srcDir, config.pluginsDir], + use: 'ignore-loader', + }, { test: /\.css$/i, use: ['style-loader', 'css-loader', 'postcss-loader'], diff --git a/admin-ui/plugins/PluginMenuResolver.js b/admin-ui/plugins/PluginMenuResolver.js index 15006bc21c..fe5de38019 100644 --- a/admin-ui/plugins/PluginMenuResolver.js +++ b/admin-ui/plugins/PluginMenuResolver.js @@ -11,6 +11,7 @@ export async function processMenus() { const metadata = await import( /* webpackChunkName: "plugin-[request]" */ /* webpackMode: "lazy" */ + /* webpackExclude: /\.test\.(js|jsx|ts|tsx)$/ */ `./${pluginName}/plugin-metadata` ) return metadata.default.menus || [] @@ -45,6 +46,7 @@ export async function processRoutes() { const metadata = await import( /* webpackChunkName: "plugin-[request]" */ /* webpackMode: "lazy" */ + /* webpackExclude: /\.test\.(js|jsx|ts|tsx)$/ */ `./${pluginName}/plugin-metadata` ) return metadata.default.routes || [] @@ -67,36 +69,6 @@ export async function processRoutes() { return pluginRoutes } -// Synchronous fallback for backward compatibility -export function processMenusSync() { - let pluginMenus = [] - plugins - .map((item) => item.metadataFile) - .forEach((path) => { - try { - pluginMenus = pluginMenus.concat(require(`${path}`).default.menus || []) - } catch (error) { - console.warn(`Failed to load plugin menus: ${path}`, error) - } - }) - pluginMenus = sortMenu(pluginMenus) - return pluginMenus -} - -export function processRoutesSync() { - let pluginRoutes = [] - plugins - .map((item) => item.metadataFile) - .forEach((path) => { - try { - pluginRoutes = pluginRoutes.concat(require(`${path}`).default.routes || []) - } catch (error) { - console.warn(`Failed to load plugin routes: ${path}`, error) - } - }) - return pluginRoutes -} - const sortMenu = (menu) => { menu = sortParentMenu(menu) return menu diff --git a/admin-ui/plugins/PluginReducersResolver.js b/admin-ui/plugins/PluginReducersResolver.js index 468290bcbc..0ebc413e08 100644 --- a/admin-ui/plugins/PluginReducersResolver.js +++ b/admin-ui/plugins/PluginReducersResolver.js @@ -1,15 +1,26 @@ import plugins from '../plugins.config.json' import reducerRegistry from 'Redux/reducers/ReducerRegistry' -function process() { +async function process() { const metadataFilePath = plugins.map((item) => item.metadataFile) let pluginReducers = [] - metadataFilePath.forEach(async (path) => { - pluginReducers = await [...pluginReducers, ...require(`${path}`).default.reducers] - pluginReducers.forEach((element) => { - reducerRegistry.register(element.name, element.reducer) - }) - }) + for (const path of metadataFilePath) { + const pluginName = path?.match(/\.\/([^/]+)\/plugin-metadata/)?.[1] + if (pluginName) { + const metadata = await import( + /* webpackChunkName: "plugin-[request]" */ + /* webpackMode: "lazy" */ + /* webpackExclude: /\.test\.(js|jsx|ts|tsx)$/ */ + `./${pluginName}/plugin-metadata` + ) + const reducers = metadata.default.reducers || [] + pluginReducers = [...pluginReducers, ...reducers] + + reducers.forEach((element) => { + reducerRegistry.register(element.name, element.reducer) + }) + } + } } export default process diff --git a/admin-ui/plugins/PluginSagasResolver.js b/admin-ui/plugins/PluginSagasResolver.js index 649c7cccf5..842f451e75 100644 --- a/admin-ui/plugins/PluginSagasResolver.js +++ b/admin-ui/plugins/PluginSagasResolver.js @@ -2,13 +2,31 @@ import plugins from '../plugins.config.json' //get all metadata path -function process() { +async function process() { let pluginSagas = [] - plugins - .map((item) => item.metadataFile) - .forEach((path) => { - pluginSagas = [...pluginSagas, ...require(`${path}`).default.sagas] - }) + + const pluginPromises = plugins.map(async (item) => { + const path = item.metadataFile + const pluginName = path?.match(/\.\/([^/]+)\/plugin-metadata/)?.[1] + if (pluginName) { + const metadata = await import( + /* webpackChunkName: "plugin-[request]" */ + /* webpackMode: "lazy" */ + /* webpackExclude: /\.test\.(js|jsx|ts|tsx)$/ */ + `./${pluginName}/plugin-metadata` + ) + return metadata.default.sagas || [] + } + return [] + }) + + const results = await Promise.allSettled(pluginPromises) + results.forEach((result) => { + if (result.status === 'fulfilled') { + pluginSagas = [...pluginSagas, ...result.value] + } + }) + return pluginSagas } export default process