import { boot } from 'quasar/wrappers'; import { RouteConfig } from 'vue-router'; import { Module } from 'vuex'; interface PluginRouteConfig extends RouteConfig { example?: unknown; } interface EssentialLink { title: string; link: string; icon?: string; } interface Plugin { name: string; routes: PluginRouteConfig[] | RouteConfig[]; store?: Module[]; mainLink: PluginMainLink; requiredModules: string[]; } interface PluginMainLink extends PluginChildLink { children: PluginChildLink[]; } interface PluginChildLink { name: string; title: string; link: string; icon: string; } const config = { // Do not change required Modules !! requiredModules: ['user'], // here you can import plugins. loadModules: ['plugin1', 'user-plugin'] }; export { PluginRouteConfig, Plugin, PluginChildLink, PluginMainLink }; 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) { sourceRouteConfig.children?.forEach( (sourcePluginChildRouteConfig: RouteConfig) => { const targetPluginRouteConfig: | RouteConfig | undefined = targetRouteConfig.children?.find( (routeConfig: RouteConfig) => { return sourcePluginChildRouteConfig.path == routeConfig.path; } ); if (targetPluginRouteConfig) { if (targetPluginRouteConfig.children) { targetPluginRouteConfig.children = Object.assign( targetPluginRouteConfig.children, sourcePluginChildRouteConfig.children ); } else { targetPluginRouteConfig.children = sourcePluginChildRouteConfig.children; } } else { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore targetRouteConfig.children.push(sourcePluginChildRouteConfig); } } ); } else { target.push(sourceRouteConfig); } }); return target; } function combineMainLinks( target: PluginMainLink[], source: PluginMainLink ): PluginMainLink[] { console.log('target', target); console.log('source', source); const targetPluginMainLink: PluginMainLink | undefined = target.find( (targetPluginMainLink: PluginMainLink) => { console.log(targetPluginMainLink.title, source.title); return targetPluginMainLink.title == source.title; } ); console.log('targetPluginMainLink', targetPluginMainLink); if (targetPluginMainLink) { source.children.forEach((sourcePluginChildLink: PluginChildLink) => { targetPluginMainLink.children.push(sourcePluginChildLink); }); } else { console.log('push source', source); target.push(source); } console.log('merged', target); return target; } // "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 pluginsContext = require.context('src/plugins', true, /.+\/plugin.ts$/); let pluginMainLinks: PluginMainLink[] = []; const plugins: Plugin[] = []; pluginsContext.keys().forEach((fileName: string) => { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access plugins.push(pluginsContext(fileName).default); }); let routes: RouteConfig[] = []; config.requiredModules.forEach(requiredModule => { const plugin = plugins.find(plugin => { return plugin.name == requiredModule; }); if (plugin) { routes = combineRoutes(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); }); } pluginMainLinks = combineMainLinks(pluginMainLinks, plugin.mainLink); } else { console.exception(`Don't find required Plugin ${requiredModule}`); } }); config.loadModules.forEach(loadModule => { const plugin = plugins.find(plugin => { return plugin.name == loadModule; }); if (plugin) { routes = combineRoutes(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); }); } pluginMainLinks = combineMainLinks(pluginMainLinks, plugin.mainLink); } else { console.exception(`Don't find Plugin ${loadModule}`); } }); console.log(routes); router.addRoutes(routes); // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access Vue.prototype.$flaschengeist_plugins = pluginMainLinks; console.log(pluginMainLinks); });