import { boot } from 'quasar/wrappers'; import { RouteConfig } from 'vue-router'; import { Module } from 'vuex'; const config = { // Do not change required Modules !! requiredModules: ['user'], // here you can import plugins. loadModules: ['plugin1', 'user-plugin'] }; // do not change anything here !! interface ShortCutLink { link: string; icon: string; } interface Plugin { name: string; routes: RouteConfig[]; store?: Module[]; mainLink: PluginMainLink; requiredModules: string[]; shortCuts: ShortCutLink[]; shortCutsOut: ShortCutLink[]; version: string; } interface PluginMainLink extends PluginChildLink { children: PluginChildLink[]; } interface PluginChildLink { name: string; title: string; link: string; icon: string; } interface LoadedPlugin { name: string; version: string; } interface LoadedPlugins { plugins: LoadedPlugin[]; routes: RouteConfig[]; mainLinks: PluginMainLink[]; shortcuts: ShortCutLink[]; shortcutsOut: ShortCutLink[]; } export { Plugin, PluginChildLink, PluginMainLink, ShortCutLink, LoadedPlugins, LoadedPlugin }; // combine routes from source to target function combineRoutes( target: RouteConfig[], source: RouteConfig[] ): RouteConfig[] { // iterate first layer e.g. /main, /login etc. source.forEach((sourceRouteConfig: RouteConfig) => { const targetRouteConfig: RouteConfig | undefined = target.find( (routeConfig: RouteConfig) => { return sourceRouteConfig.path == routeConfig.path; } ); if (targetRouteConfig) { // if exists first layer in target exist iterate through 2nd layer e.g. /main/user, /main/about sourceRouteConfig.children?.forEach( (sourcePluginChildRouteConfig: RouteConfig) => { const targetPluginRouteConfig: | RouteConfig | undefined = targetRouteConfig.children?.find( (routeConfig: RouteConfig) => { return sourcePluginChildRouteConfig.path == routeConfig.path; } ); if (targetPluginRouteConfig) { // if 2nd layer in target exist check if target has children path. if (targetPluginRouteConfig.children) { // if target has children path, add children from source. targetPluginRouteConfig.children = Object.assign( targetPluginRouteConfig.children, sourcePluginChildRouteConfig.children ); } else { // if not set children of targen from children of source targetPluginRouteConfig.children = sourcePluginChildRouteConfig.children; } } else { // if target not exists in 2nd layer, add source to children of first targen // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore targetRouteConfig.children.push(sourcePluginChildRouteConfig); } } ); } else { // if target not exists in first layer, add source target.push(sourceRouteConfig); } }); return target; } // combine Links of Plugins from source to target function combineMainLinks( target: PluginMainLink[], source: PluginMainLink ): PluginMainLink[] { const targetPluginMainLink: PluginMainLink | undefined = target.find( (targetPluginMainLink: PluginMainLink) => { console.log(targetPluginMainLink.title, source.title); return targetPluginMainLink.title == source.title; } ); if (targetPluginMainLink) { source.children.forEach((sourcePluginChildLink: PluginChildLink) => { targetPluginMainLink.children.push(sourcePluginChildLink); }); } else { target.push(source); } return target; } // loade plugins function loadPlugin( loadedPlugins: LoadedPlugins, modules: string[], plugins: Plugin[], store: any ): LoadedPlugins { modules.forEach(requiredModule => { const plugin = plugins.find(plugin => { return plugin.name == requiredModule; }); if (plugin) { loadedPlugins.routes = combineRoutes(loadedPlugins.routes, plugin.routes); if (plugin.store) { plugin.store.forEach(store_module => { // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access store.registerModule(store_module); }); } loadedPlugins.mainLinks = combineMainLinks( loadedPlugins.mainLinks, plugin.mainLink ); loadedPlugins.shortcuts.concat(plugin.shortCuts); loadedPlugins.shortcutsOut.concat(plugin.shortCutsOut); loadedPlugins.plugins.push({ name: plugin.name, version: plugin.version }); } else { console.exception(`Don't find required Plugin ${requiredModule}`); } }); return loadedPlugins; } // "async" is optional; // more info on params: https://quasar.dev/quasar-cli/cli-documentation/boot-files#Anatomy-of-a-boot-file export default boot(({ Vue, router, store }) => { const plugins: Plugin[] = []; let loadedPlugins: LoadedPlugins = { routes: [], plugins: [], mainLinks: [], shortcuts: [], shortcutsOut: [] }; // get all plugins const pluginsContext = require.context('src/plugins', true, /.+\/plugin.ts$/); pluginsContext.keys().forEach((fileName: string) => { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access plugins.push(pluginsContext(fileName).default); }); // load plugins loadedPlugins = loadPlugin( loadedPlugins, config.requiredModules, plugins, store ); loadedPlugins = loadPlugin(loadedPlugins, config.loadModules, plugins, store); console.log(loadedPlugins.routes); // add new routes for plugins router.addRoutes(loadedPlugins.routes); // save plugins in VM-variable // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access Vue.prototype.$flaschengeistPlugins = loadedPlugins; console.log(loadedPlugins); });