MOBILE-3947 core: Fix circular routes

main
Noel De Martin 2023-12-04 17:01:05 +01:00
parent f0586fd93e
commit b1b8b9583b
2 changed files with 58 additions and 8 deletions

View File

@ -27,6 +27,8 @@ import {
import { CoreArray } from '@singletons/array';
const modulesRoutes: WeakMap<InjectionToken<unknown>, ModuleRoutes> = new WeakMap();
/**
* Build app routes.
*
@ -175,6 +177,10 @@ export function conditionalRoutes(routes: Routes, condition: () => boolean): Rou
* @returns Routes.
*/
export function resolveModuleRoutes(injector: Injector, token: InjectionToken<ModuleRoutesConfig[]>): ModuleRoutes {
if (modulesRoutes.has(token)) {
return modulesRoutes.get(token) as ModuleRoutes;
}
const configs = injector.get(token, []);
const routes = configs.map(config => {
if (Array.isArray(config)) {
@ -190,10 +196,14 @@ export function resolveModuleRoutes(injector: Injector, token: InjectionToken<Mo
};
});
return {
const moduleRoutes = {
children: CoreArray.flatten(routes.map(r => r.children)),
siblings: CoreArray.flatten(routes.map(r => r.siblings)),
};
modulesRoutes.set(token, moduleRoutes);
return moduleRoutes;
}
export const APP_ROUTES = new InjectionToken('APP_ROUTES');

View File

@ -18,24 +18,64 @@ import { Route, Routes } from '@angular/router';
import { ModuleRoutesConfig, resolveModuleRoutes } from '@/app/app-routing.module';
const MAIN_MENU_TAB_ROUTES = new InjectionToken('MAIN_MENU_TAB_ROUTES');
const modulesPaths: Record<string, Set<string>> = {};
/**
* Get the name of the module the injector belongs to.
*
* @param injector Injector.
* @returns Injector module name.
*/
function getInjectorModule(injector: Injector): string | null {
if (!('source' in injector) || typeof injector.source !== 'string') {
return null;
}
// Get module name from R3Injector source.
// See https://github.com/angular/angular/blob/16.2.0/packages/core/src/di/r3_injector.ts#L161C8
return injector.source;
}
/**
* Get module paths.
*
* @param injector Injector.
* @returns Module paths.
*/
function getModulePaths(injector: Injector): Set<string> | null {
const module = getInjectorModule(injector);
if (!module) {
return null;
}
return modulesPaths[module] ??= new Set();
}
/**
* Build module routes.
*
* @param injector Injector.
* @param mainRoute Main route.
* @returns Routes.
*/
export function buildTabMainRoutes(injector: Injector, mainRoute: Route): Routes {
const path = mainRoute.path ?? '';
const modulePaths = getModulePaths(injector);
const isRootRoute = modulePaths && !modulePaths.has(path);
const routes = resolveModuleRoutes(injector, MAIN_MENU_TAB_ROUTES);
mainRoute.path = mainRoute.path || '';
mainRoute.children = mainRoute.children || [];
mainRoute.children = mainRoute.children.concat(routes.children);
mainRoute.path = path;
modulePaths?.add(path);
return [
mainRoute,
...routes.siblings,
];
if (isRootRoute && !('redirectTo' in mainRoute)) {
mainRoute.children = mainRoute.children || [];
mainRoute.children = mainRoute.children.concat(routes.children);
}
return isRootRoute
? [mainRoute, ...routes.siblings]
: [mainRoute];
}
@NgModule()