@dlymon/utils
Advanced tools
| 'use strict'; | ||
| function findMenuByPath(list, path) { | ||
| for (const menu of list) { | ||
| if (menu.path === path) { | ||
| return menu; | ||
| } | ||
| const findMenu = menu.children && findMenuByPath(menu.children, path); | ||
| if (findMenu) { | ||
| return findMenu; | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
| function findRootMenuByPath(menus, path, level = 0) { | ||
| const findMenu = findMenuByPath(menus, path); | ||
| const rootMenuPath = findMenu?.parents?.[level]; | ||
| const rootMenu = rootMenuPath ? menus.find((item) => item.path === rootMenuPath) : void 0; | ||
| return { | ||
| findMenu, | ||
| rootMenu, | ||
| rootMenuPath | ||
| }; | ||
| } | ||
| exports.findMenuByPath = findMenuByPath; | ||
| exports.findRootMenuByPath = findRootMenuByPath; |
| import { MenuRecordRaw } from '@dlymon-core/typings'; | ||
| declare function findMenuByPath(list: MenuRecordRaw[], path?: string): MenuRecordRaw | null; | ||
| declare function findRootMenuByPath(menus: MenuRecordRaw[], path?: string, level?: number): { | ||
| findMenu: MenuRecordRaw | null; | ||
| rootMenu: MenuRecordRaw | undefined; | ||
| rootMenuPath: string | undefined; | ||
| }; | ||
| export { findMenuByPath, findRootMenuByPath }; |
| import { MenuRecordRaw } from '@dlymon-core/typings'; | ||
| declare function findMenuByPath(list: MenuRecordRaw[], path?: string): MenuRecordRaw | null; | ||
| declare function findRootMenuByPath(menus: MenuRecordRaw[], path?: string, level?: number): { | ||
| findMenu: MenuRecordRaw | null; | ||
| rootMenu: MenuRecordRaw | undefined; | ||
| rootMenuPath: string | undefined; | ||
| }; | ||
| export { findMenuByPath, findRootMenuByPath }; |
| import { MenuRecordRaw } from '@dlymon-core/typings'; | ||
| declare function findMenuByPath(list: MenuRecordRaw[], path?: string): MenuRecordRaw | null; | ||
| declare function findRootMenuByPath(menus: MenuRecordRaw[], path?: string, level?: number): { | ||
| findMenu: MenuRecordRaw | null; | ||
| rootMenu: MenuRecordRaw | undefined; | ||
| rootMenuPath: string | undefined; | ||
| }; | ||
| export { findMenuByPath, findRootMenuByPath }; |
| function findMenuByPath(list, path) { | ||
| for (const menu of list) { | ||
| if (menu.path === path) { | ||
| return menu; | ||
| } | ||
| const findMenu = menu.children && findMenuByPath(menu.children, path); | ||
| if (findMenu) { | ||
| return findMenu; | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
| function findRootMenuByPath(menus, path, level = 0) { | ||
| const findMenu = findMenuByPath(menus, path); | ||
| const rootMenuPath = findMenu?.parents?.[level]; | ||
| const rootMenu = rootMenuPath ? menus.find((item) => item.path === rootMenuPath) : void 0; | ||
| return { | ||
| findMenu, | ||
| rootMenu, | ||
| rootMenuPath | ||
| }; | ||
| } | ||
| export { findMenuByPath, findRootMenuByPath }; |
| 'use strict'; | ||
| const utils = require('@dlymon-core/shared/utils'); | ||
| function generateMenus(routes, router) { | ||
| const finalRoutesMap = Object.fromEntries( | ||
| router.getRoutes().map(({ name, path }) => [name, path]) | ||
| ); | ||
| let menus = utils.mapTree(routes, (route) => { | ||
| const path = finalRoutesMap[route.name] ?? route.path ?? ""; | ||
| const { | ||
| meta = {}, | ||
| name: routeName, | ||
| redirect, | ||
| children = [] | ||
| } = route; | ||
| const { | ||
| activeIcon, | ||
| badge, | ||
| badgeType, | ||
| badgeVariants, | ||
| hideChildrenInMenu = false, | ||
| icon, | ||
| link, | ||
| order, | ||
| title = "" | ||
| } = meta; | ||
| const name = title || routeName || ""; | ||
| const resultChildren = hideChildrenInMenu ? [] : children ?? []; | ||
| if (resultChildren.length > 0) { | ||
| resultChildren.forEach((child) => { | ||
| child.parents = [...route.parents ?? [], path]; | ||
| child.parent = path; | ||
| }); | ||
| } | ||
| const resultPath = hideChildrenInMenu ? redirect || path : link || path; | ||
| return { | ||
| activeIcon, | ||
| badge, | ||
| badgeType, | ||
| badgeVariants, | ||
| icon, | ||
| name, | ||
| order, | ||
| parent: route.parent, | ||
| parents: route.parents, | ||
| path: resultPath, | ||
| show: !meta.hideInMenu, | ||
| children: resultChildren | ||
| }; | ||
| }); | ||
| menus = menus.sort((a, b) => (a?.order ?? 999) - (b?.order ?? 999)); | ||
| return utils.filterTree(menus, (menu) => !!menu.show); | ||
| } | ||
| exports.generateMenus = generateMenus; |
| import { RouteRecordRaw, Router } from 'vue-router'; | ||
| import { MenuRecordRaw } from '@dlymon-core/typings'; | ||
| declare function generateMenus(routes: RouteRecordRaw[], router: Router): MenuRecordRaw[]; | ||
| export { generateMenus }; |
| import { RouteRecordRaw, Router } from 'vue-router'; | ||
| import { MenuRecordRaw } from '@dlymon-core/typings'; | ||
| declare function generateMenus(routes: RouteRecordRaw[], router: Router): MenuRecordRaw[]; | ||
| export { generateMenus }; |
| import { RouteRecordRaw, Router } from 'vue-router'; | ||
| import { MenuRecordRaw } from '@dlymon-core/typings'; | ||
| declare function generateMenus(routes: RouteRecordRaw[], router: Router): MenuRecordRaw[]; | ||
| export { generateMenus }; |
| import { mapTree, filterTree } from '@dlymon-core/shared/utils'; | ||
| function generateMenus(routes, router) { | ||
| const finalRoutesMap = Object.fromEntries( | ||
| router.getRoutes().map(({ name, path }) => [name, path]) | ||
| ); | ||
| let menus = mapTree(routes, (route) => { | ||
| const path = finalRoutesMap[route.name] ?? route.path ?? ""; | ||
| const { | ||
| meta = {}, | ||
| name: routeName, | ||
| redirect, | ||
| children = [] | ||
| } = route; | ||
| const { | ||
| activeIcon, | ||
| badge, | ||
| badgeType, | ||
| badgeVariants, | ||
| hideChildrenInMenu = false, | ||
| icon, | ||
| link, | ||
| order, | ||
| title = "" | ||
| } = meta; | ||
| const name = title || routeName || ""; | ||
| const resultChildren = hideChildrenInMenu ? [] : children ?? []; | ||
| if (resultChildren.length > 0) { | ||
| resultChildren.forEach((child) => { | ||
| child.parents = [...route.parents ?? [], path]; | ||
| child.parent = path; | ||
| }); | ||
| } | ||
| const resultPath = hideChildrenInMenu ? redirect || path : link || path; | ||
| return { | ||
| activeIcon, | ||
| badge, | ||
| badgeType, | ||
| badgeVariants, | ||
| icon, | ||
| name, | ||
| order, | ||
| parent: route.parent, | ||
| parents: route.parents, | ||
| path: resultPath, | ||
| show: !meta.hideInMenu, | ||
| children: resultChildren | ||
| }; | ||
| }); | ||
| menus = menus.sort((a, b) => (a?.order ?? 999) - (b?.order ?? 999)); | ||
| return filterTree(menus, (menu) => !!menu.show); | ||
| } | ||
| export { generateMenus }; |
| 'use strict'; | ||
| const utils = require('@dlymon-core/shared/utils'); | ||
| async function generateRoutesByBackend(options) { | ||
| const { fetchMenuListAsync, layoutMap = {}, pageMap = {} } = options; | ||
| try { | ||
| const menuRoutes = await fetchMenuListAsync?.(); | ||
| if (!menuRoutes) { | ||
| return []; | ||
| } | ||
| const normalizePageMap = {}; | ||
| for (const [key, value] of Object.entries(pageMap)) { | ||
| normalizePageMap[normalizeViewPath(key)] = value; | ||
| } | ||
| const routes = convertRoutes(menuRoutes, layoutMap, normalizePageMap); | ||
| return routes; | ||
| } catch (error) { | ||
| console.error(error); | ||
| throw error; | ||
| } | ||
| } | ||
| function convertRoutes(routes, layoutMap, pageMap) { | ||
| return utils.mapTree(routes, (node) => { | ||
| const route = node; | ||
| const { component, name } = node; | ||
| if (!name) { | ||
| console.error("route name is required", route); | ||
| } | ||
| if (component && layoutMap[component]) { | ||
| route.component = layoutMap[component]; | ||
| } else if (component) { | ||
| const normalizePath = normalizeViewPath(component); | ||
| const pageKey = normalizePath.endsWith(".vue") ? normalizePath : `${normalizePath}.vue`; | ||
| if (pageMap[pageKey]) { | ||
| route.component = pageMap[pageKey]; | ||
| } else { | ||
| console.error(`route component is invalid: ${pageKey}`, route); | ||
| route.component = pageMap["/_core/fallback/not-found.vue"]; | ||
| } | ||
| } | ||
| return route; | ||
| }); | ||
| } | ||
| function normalizeViewPath(path) { | ||
| const normalizedPath = path.replace(/^(\.\/|\.\.\/)+/, ""); | ||
| const viewPath = normalizedPath.startsWith("/") ? normalizedPath : `/${normalizedPath}`; | ||
| return viewPath.replace(/^\/views/, ""); | ||
| } | ||
| exports.generateRoutesByBackend = generateRoutesByBackend; |
| import { RouteRecordRaw } from 'vue-router'; | ||
| import { GenerateMenuAndRoutesOptions } from '@dlymon-core/typings'; | ||
| declare function generateRoutesByBackend(options: GenerateMenuAndRoutesOptions): Promise<RouteRecordRaw[]>; | ||
| export { generateRoutesByBackend }; |
| import { RouteRecordRaw } from 'vue-router'; | ||
| import { GenerateMenuAndRoutesOptions } from '@dlymon-core/typings'; | ||
| declare function generateRoutesByBackend(options: GenerateMenuAndRoutesOptions): Promise<RouteRecordRaw[]>; | ||
| export { generateRoutesByBackend }; |
| import { RouteRecordRaw } from 'vue-router'; | ||
| import { GenerateMenuAndRoutesOptions } from '@dlymon-core/typings'; | ||
| declare function generateRoutesByBackend(options: GenerateMenuAndRoutesOptions): Promise<RouteRecordRaw[]>; | ||
| export { generateRoutesByBackend }; |
| import { mapTree } from '@dlymon-core/shared/utils'; | ||
| async function generateRoutesByBackend(options) { | ||
| const { fetchMenuListAsync, layoutMap = {}, pageMap = {} } = options; | ||
| try { | ||
| const menuRoutes = await fetchMenuListAsync?.(); | ||
| if (!menuRoutes) { | ||
| return []; | ||
| } | ||
| const normalizePageMap = {}; | ||
| for (const [key, value] of Object.entries(pageMap)) { | ||
| normalizePageMap[normalizeViewPath(key)] = value; | ||
| } | ||
| const routes = convertRoutes(menuRoutes, layoutMap, normalizePageMap); | ||
| return routes; | ||
| } catch (error) { | ||
| console.error(error); | ||
| throw error; | ||
| } | ||
| } | ||
| function convertRoutes(routes, layoutMap, pageMap) { | ||
| return mapTree(routes, (node) => { | ||
| const route = node; | ||
| const { component, name } = node; | ||
| if (!name) { | ||
| console.error("route name is required", route); | ||
| } | ||
| if (component && layoutMap[component]) { | ||
| route.component = layoutMap[component]; | ||
| } else if (component) { | ||
| const normalizePath = normalizeViewPath(component); | ||
| const pageKey = normalizePath.endsWith(".vue") ? normalizePath : `${normalizePath}.vue`; | ||
| if (pageMap[pageKey]) { | ||
| route.component = pageMap[pageKey]; | ||
| } else { | ||
| console.error(`route component is invalid: ${pageKey}`, route); | ||
| route.component = pageMap["/_core/fallback/not-found.vue"]; | ||
| } | ||
| } | ||
| return route; | ||
| }); | ||
| } | ||
| function normalizeViewPath(path) { | ||
| const normalizedPath = path.replace(/^(\.\/|\.\.\/)+/, ""); | ||
| const viewPath = normalizedPath.startsWith("/") ? normalizedPath : `/${normalizedPath}`; | ||
| return viewPath.replace(/^\/views/, ""); | ||
| } | ||
| export { generateRoutesByBackend }; |
| 'use strict'; | ||
| const utils = require('@dlymon-core/shared/utils'); | ||
| async function generateRoutesByFrontend(routes, roles, forbiddenComponent) { | ||
| const finalRoutes = utils.filterTree(routes, (route) => { | ||
| return hasAuthority(route, roles); | ||
| }); | ||
| if (!forbiddenComponent) { | ||
| return finalRoutes; | ||
| } | ||
| return utils.mapTree(finalRoutes, (route) => { | ||
| if (menuHasVisibleWithForbidden(route)) { | ||
| route.component = forbiddenComponent; | ||
| } | ||
| return route; | ||
| }); | ||
| } | ||
| function hasAuthority(route, access) { | ||
| const authority = route.meta?.authority; | ||
| if (!authority) { | ||
| return true; | ||
| } | ||
| const canAccess = access.some((value) => authority.includes(value)); | ||
| return canAccess || !canAccess && menuHasVisibleWithForbidden(route); | ||
| } | ||
| function menuHasVisibleWithForbidden(route) { | ||
| return !!route.meta?.authority && Reflect.has(route.meta || {}, "menuVisibleWithForbidden") && !!route.meta?.menuVisibleWithForbidden; | ||
| } | ||
| exports.generateRoutesByFrontend = generateRoutesByFrontend; | ||
| exports.hasAuthority = hasAuthority; |
| import { RouteRecordRaw } from 'vue-router'; | ||
| declare function generateRoutesByFrontend(routes: RouteRecordRaw[], roles: string[], forbiddenComponent?: RouteRecordRaw['component']): Promise<RouteRecordRaw[]>; | ||
| declare function hasAuthority(route: RouteRecordRaw, access: string[]): boolean; | ||
| export { generateRoutesByFrontend, hasAuthority }; |
| import { RouteRecordRaw } from 'vue-router'; | ||
| declare function generateRoutesByFrontend(routes: RouteRecordRaw[], roles: string[], forbiddenComponent?: RouteRecordRaw['component']): Promise<RouteRecordRaw[]>; | ||
| declare function hasAuthority(route: RouteRecordRaw, access: string[]): boolean; | ||
| export { generateRoutesByFrontend, hasAuthority }; |
| import { RouteRecordRaw } from 'vue-router'; | ||
| declare function generateRoutesByFrontend(routes: RouteRecordRaw[], roles: string[], forbiddenComponent?: RouteRecordRaw['component']): Promise<RouteRecordRaw[]>; | ||
| declare function hasAuthority(route: RouteRecordRaw, access: string[]): boolean; | ||
| export { generateRoutesByFrontend, hasAuthority }; |
| import { filterTree, mapTree } from '@dlymon-core/shared/utils'; | ||
| async function generateRoutesByFrontend(routes, roles, forbiddenComponent) { | ||
| const finalRoutes = filterTree(routes, (route) => { | ||
| return hasAuthority(route, roles); | ||
| }); | ||
| if (!forbiddenComponent) { | ||
| return finalRoutes; | ||
| } | ||
| return mapTree(finalRoutes, (route) => { | ||
| if (menuHasVisibleWithForbidden(route)) { | ||
| route.component = forbiddenComponent; | ||
| } | ||
| return route; | ||
| }); | ||
| } | ||
| function hasAuthority(route, access) { | ||
| const authority = route.meta?.authority; | ||
| if (!authority) { | ||
| return true; | ||
| } | ||
| const canAccess = access.some((value) => authority.includes(value)); | ||
| return canAccess || !canAccess && menuHasVisibleWithForbidden(route); | ||
| } | ||
| function menuHasVisibleWithForbidden(route) { | ||
| return !!route.meta?.authority && Reflect.has(route.meta || {}, "menuVisibleWithForbidden") && !!route.meta?.menuVisibleWithForbidden; | ||
| } | ||
| export { generateRoutesByFrontend, hasAuthority }; |
| 'use strict'; | ||
| function getPopupContainer(node) { | ||
| return node?.closest("form") ?? node?.parentNode ?? document.body; | ||
| } | ||
| exports.getPopupContainer = getPopupContainer; |
| declare function getPopupContainer(node?: HTMLElement): HTMLElement; | ||
| export { getPopupContainer }; |
| declare function getPopupContainer(node?: HTMLElement): HTMLElement; | ||
| export { getPopupContainer }; |
| declare function getPopupContainer(node?: HTMLElement): HTMLElement; | ||
| export { getPopupContainer }; |
| function getPopupContainer(node) { | ||
| return node?.closest("form") ?? node?.parentNode ?? document.body; | ||
| } | ||
| export { getPopupContainer }; |
| 'use strict'; | ||
| const helpers_findMenuByPath = require('./find-menu-by-path.cjs'); | ||
| const helpers_generateMenus = require('./generate-menus.cjs'); | ||
| const helpers_generateRoutesBackend = require('./generate-routes-backend.cjs'); | ||
| const helpers_generateRoutesFrontend = require('./generate-routes-frontend.cjs'); | ||
| const helpers_getPopupContainer = require('./get-popup-container.cjs'); | ||
| const helpers_mergeRouteModules = require('./merge-route-modules.cjs'); | ||
| const helpers_resetRoutes = require('./reset-routes.cjs'); | ||
| const helpers_unmountGlobalLoading = require('./unmount-global-loading.cjs'); | ||
| require('@dlymon-core/shared/utils'); | ||
| exports.findMenuByPath = helpers_findMenuByPath.findMenuByPath; | ||
| exports.findRootMenuByPath = helpers_findMenuByPath.findRootMenuByPath; | ||
| exports.generateMenus = helpers_generateMenus.generateMenus; | ||
| exports.generateRoutesByBackend = helpers_generateRoutesBackend.generateRoutesByBackend; | ||
| exports.generateRoutesByFrontend = helpers_generateRoutesFrontend.generateRoutesByFrontend; | ||
| exports.hasAuthority = helpers_generateRoutesFrontend.hasAuthority; | ||
| exports.getPopupContainer = helpers_getPopupContainer.getPopupContainer; | ||
| exports.mergeRouteModules = helpers_mergeRouteModules.mergeRouteModules; | ||
| exports.resetStaticRoutes = helpers_resetRoutes.resetStaticRoutes; | ||
| exports.unmountGlobalLoading = helpers_unmountGlobalLoading.unmountGlobalLoading; |
| export { findMenuByPath, findRootMenuByPath } from './find-menu-by-path.cjs'; | ||
| export { generateMenus } from './generate-menus.cjs'; | ||
| export { generateRoutesByBackend } from './generate-routes-backend.cjs'; | ||
| export { generateRoutesByFrontend, hasAuthority } from './generate-routes-frontend.cjs'; | ||
| export { getPopupContainer } from './get-popup-container.cjs'; | ||
| export { RouteModuleType, mergeRouteModules } from './merge-route-modules.cjs'; | ||
| export { resetStaticRoutes } from './reset-routes.cjs'; | ||
| export { unmountGlobalLoading } from './unmount-global-loading.cjs'; | ||
| import '@dlymon-core/shared/cache'; | ||
| import '@dlymon-core/shared/color'; | ||
| import '@dlymon-core/shared/utils'; | ||
| import '@dlymon-core/typings'; | ||
| import 'vue-router'; |
| export { findMenuByPath, findRootMenuByPath } from './find-menu-by-path.mjs'; | ||
| export { generateMenus } from './generate-menus.mjs'; | ||
| export { generateRoutesByBackend } from './generate-routes-backend.mjs'; | ||
| export { generateRoutesByFrontend, hasAuthority } from './generate-routes-frontend.mjs'; | ||
| export { getPopupContainer } from './get-popup-container.mjs'; | ||
| export { RouteModuleType, mergeRouteModules } from './merge-route-modules.mjs'; | ||
| export { resetStaticRoutes } from './reset-routes.mjs'; | ||
| export { unmountGlobalLoading } from './unmount-global-loading.mjs'; | ||
| import '@dlymon-core/shared/cache'; | ||
| import '@dlymon-core/shared/color'; | ||
| import '@dlymon-core/shared/utils'; | ||
| import '@dlymon-core/typings'; | ||
| import 'vue-router'; |
| export { findMenuByPath, findRootMenuByPath } from './find-menu-by-path.js'; | ||
| export { generateMenus } from './generate-menus.js'; | ||
| export { generateRoutesByBackend } from './generate-routes-backend.js'; | ||
| export { generateRoutesByFrontend, hasAuthority } from './generate-routes-frontend.js'; | ||
| export { getPopupContainer } from './get-popup-container.js'; | ||
| export { RouteModuleType, mergeRouteModules } from './merge-route-modules.js'; | ||
| export { resetStaticRoutes } from './reset-routes.js'; | ||
| export { unmountGlobalLoading } from './unmount-global-loading.js'; | ||
| import '@dlymon-core/shared/cache'; | ||
| import '@dlymon-core/shared/color'; | ||
| import '@dlymon-core/shared/utils'; | ||
| import '@dlymon-core/typings'; | ||
| import 'vue-router'; |
| export { findMenuByPath, findRootMenuByPath } from './find-menu-by-path.mjs'; | ||
| export { generateMenus } from './generate-menus.mjs'; | ||
| export { generateRoutesByBackend } from './generate-routes-backend.mjs'; | ||
| export { generateRoutesByFrontend, hasAuthority } from './generate-routes-frontend.mjs'; | ||
| export { getPopupContainer } from './get-popup-container.mjs'; | ||
| export { mergeRouteModules } from './merge-route-modules.mjs'; | ||
| export { resetStaticRoutes } from './reset-routes.mjs'; | ||
| export { unmountGlobalLoading } from './unmount-global-loading.mjs'; | ||
| import '@dlymon-core/shared/utils'; |
| 'use strict'; | ||
| function mergeRouteModules(routeModules) { | ||
| const mergedRoutes = []; | ||
| for (const routeModule of Object.values(routeModules)) { | ||
| const moduleRoutes = routeModule?.default ?? []; | ||
| mergedRoutes.push(...moduleRoutes); | ||
| } | ||
| return mergedRoutes; | ||
| } | ||
| exports.mergeRouteModules = mergeRouteModules; |
| import { RouteRecordRaw } from 'vue-router'; | ||
| interface RouteModuleType { | ||
| default: RouteRecordRaw[]; | ||
| } | ||
| declare function mergeRouteModules(routeModules: Record<string, unknown>): RouteRecordRaw[]; | ||
| export { mergeRouteModules }; | ||
| export type { RouteModuleType }; |
| import { RouteRecordRaw } from 'vue-router'; | ||
| interface RouteModuleType { | ||
| default: RouteRecordRaw[]; | ||
| } | ||
| declare function mergeRouteModules(routeModules: Record<string, unknown>): RouteRecordRaw[]; | ||
| export { mergeRouteModules }; | ||
| export type { RouteModuleType }; |
| import { RouteRecordRaw } from 'vue-router'; | ||
| interface RouteModuleType { | ||
| default: RouteRecordRaw[]; | ||
| } | ||
| declare function mergeRouteModules(routeModules: Record<string, unknown>): RouteRecordRaw[]; | ||
| export { mergeRouteModules }; | ||
| export type { RouteModuleType }; |
| function mergeRouteModules(routeModules) { | ||
| const mergedRoutes = []; | ||
| for (const routeModule of Object.values(routeModules)) { | ||
| const moduleRoutes = routeModule?.default ?? []; | ||
| mergedRoutes.push(...moduleRoutes); | ||
| } | ||
| return mergedRoutes; | ||
| } | ||
| export { mergeRouteModules }; |
| 'use strict'; | ||
| const utils = require('@dlymon-core/shared/utils'); | ||
| function resetStaticRoutes(router, routes) { | ||
| const staticRouteNames = utils.traverseTreeValues(routes, (route) => { | ||
| if (!route.name) { | ||
| console.warn( | ||
| `The route with the path ${route.path} needs to have the field name specified.` | ||
| ); | ||
| } | ||
| return route.name; | ||
| }); | ||
| const { getRoutes, hasRoute, removeRoute } = router; | ||
| const allRoutes = getRoutes(); | ||
| allRoutes.forEach(({ name }) => { | ||
| if (name && !staticRouteNames.includes(name) && hasRoute(name)) { | ||
| removeRoute(name); | ||
| } | ||
| }); | ||
| } | ||
| exports.resetStaticRoutes = resetStaticRoutes; |
| import { Router, RouteRecordRaw } from 'vue-router'; | ||
| declare function resetStaticRoutes(router: Router, routes: RouteRecordRaw[]): void; | ||
| export { resetStaticRoutes }; |
| import { Router, RouteRecordRaw } from 'vue-router'; | ||
| declare function resetStaticRoutes(router: Router, routes: RouteRecordRaw[]): void; | ||
| export { resetStaticRoutes }; |
| import { Router, RouteRecordRaw } from 'vue-router'; | ||
| declare function resetStaticRoutes(router: Router, routes: RouteRecordRaw[]): void; | ||
| export { resetStaticRoutes }; |
| import { traverseTreeValues } from '@dlymon-core/shared/utils'; | ||
| function resetStaticRoutes(router, routes) { | ||
| const staticRouteNames = traverseTreeValues(routes, (route) => { | ||
| if (!route.name) { | ||
| console.warn( | ||
| `The route with the path ${route.path} needs to have the field name specified.` | ||
| ); | ||
| } | ||
| return route.name; | ||
| }); | ||
| const { getRoutes, hasRoute, removeRoute } = router; | ||
| const allRoutes = getRoutes(); | ||
| allRoutes.forEach(({ name }) => { | ||
| if (name && !staticRouteNames.includes(name) && hasRoute(name)) { | ||
| removeRoute(name); | ||
| } | ||
| }); | ||
| } | ||
| export { resetStaticRoutes }; |
| 'use strict'; | ||
| function unmountGlobalLoading() { | ||
| const loadingElement = document.querySelector("#__app-loading__"); | ||
| if (loadingElement) { | ||
| loadingElement.classList.add("hidden"); | ||
| const injectLoadingElements = document.querySelectorAll( | ||
| '[data-app-loading^="inject"]' | ||
| ); | ||
| loadingElement.addEventListener( | ||
| "transitionend", | ||
| () => { | ||
| loadingElement.remove(); | ||
| injectLoadingElements.forEach((el) => el.remove()); | ||
| }, | ||
| { once: true } | ||
| ); | ||
| } | ||
| } | ||
| exports.unmountGlobalLoading = unmountGlobalLoading; |
| declare function unmountGlobalLoading(): void; | ||
| export { unmountGlobalLoading }; |
| declare function unmountGlobalLoading(): void; | ||
| export { unmountGlobalLoading }; |
| declare function unmountGlobalLoading(): void; | ||
| export { unmountGlobalLoading }; |
| function unmountGlobalLoading() { | ||
| const loadingElement = document.querySelector("#__app-loading__"); | ||
| if (loadingElement) { | ||
| loadingElement.classList.add("hidden"); | ||
| const injectLoadingElements = document.querySelectorAll( | ||
| '[data-app-loading^="inject"]' | ||
| ); | ||
| loadingElement.addEventListener( | ||
| "transitionend", | ||
| () => { | ||
| loadingElement.remove(); | ||
| injectLoadingElements.forEach((el) => el.remove()); | ||
| }, | ||
| { once: true } | ||
| ); | ||
| } | ||
| } | ||
| export { unmountGlobalLoading }; |
+36
-221
@@ -6,237 +6,52 @@ 'use strict'; | ||
| const utils = require('@dlymon-core/shared/utils'); | ||
| const helpers_findMenuByPath = require('./helpers/find-menu-by-path.cjs'); | ||
| const helpers_generateMenus = require('./helpers/generate-menus.cjs'); | ||
| const helpers_generateRoutesBackend = require('./helpers/generate-routes-backend.cjs'); | ||
| const helpers_generateRoutesFrontend = require('./helpers/generate-routes-frontend.cjs'); | ||
| const helpers_getPopupContainer = require('./helpers/get-popup-container.cjs'); | ||
| const helpers_mergeRouteModules = require('./helpers/merge-route-modules.cjs'); | ||
| const helpers_resetRoutes = require('./helpers/reset-routes.cjs'); | ||
| const helpers_unmountGlobalLoading = require('./helpers/unmount-global-loading.cjs'); | ||
| function findMenuByPath(list, path) { | ||
| for (const menu of list) { | ||
| if (menu.path === path) { | ||
| return menu; | ||
| } | ||
| const findMenu = menu.children && findMenuByPath(menu.children, path); | ||
| if (findMenu) { | ||
| return findMenu; | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
| function findRootMenuByPath(menus, path, level = 0) { | ||
| const findMenu = findMenuByPath(menus, path); | ||
| const rootMenuPath = findMenu?.parents?.[level]; | ||
| const rootMenu = rootMenuPath ? menus.find((item) => item.path === rootMenuPath) : void 0; | ||
| return { | ||
| findMenu, | ||
| rootMenu, | ||
| rootMenuPath | ||
| }; | ||
| } | ||
| function generateMenus(routes, router) { | ||
| const finalRoutesMap = Object.fromEntries( | ||
| router.getRoutes().map(({ name, path }) => [name, path]) | ||
| ); | ||
| let menus = utils.mapTree(routes, (route) => { | ||
| const path = finalRoutesMap[route.name] ?? route.path ?? ""; | ||
| const { | ||
| meta = {}, | ||
| name: routeName, | ||
| redirect, | ||
| children = [] | ||
| } = route; | ||
| const { | ||
| activeIcon, | ||
| badge, | ||
| badgeType, | ||
| badgeVariants, | ||
| hideChildrenInMenu = false, | ||
| icon, | ||
| link, | ||
| order, | ||
| title = "" | ||
| } = meta; | ||
| const name = title || routeName || ""; | ||
| const resultChildren = hideChildrenInMenu ? [] : children ?? []; | ||
| if (resultChildren.length > 0) { | ||
| resultChildren.forEach((child) => { | ||
| child.parents = [...route.parents ?? [], path]; | ||
| child.parent = path; | ||
| }); | ||
| } | ||
| const resultPath = hideChildrenInMenu ? redirect || path : link || path; | ||
| return { | ||
| activeIcon, | ||
| badge, | ||
| badgeType, | ||
| badgeVariants, | ||
| icon, | ||
| name, | ||
| order, | ||
| parent: route.parent, | ||
| parents: route.parents, | ||
| path: resultPath, | ||
| show: !meta.hideInMenu, | ||
| children: resultChildren | ||
| }; | ||
| }); | ||
| menus = menus.sort((a, b) => (a?.order ?? 999) - (b?.order ?? 999)); | ||
| return utils.filterTree(menus, (menu) => !!menu.show); | ||
| } | ||
| async function generateRoutesByBackend(options) { | ||
| const { fetchMenuListAsync, layoutMap = {}, pageMap = {} } = options; | ||
| try { | ||
| const menuRoutes = await fetchMenuListAsync?.(); | ||
| if (!menuRoutes) { | ||
| return []; | ||
| } | ||
| const normalizePageMap = {}; | ||
| for (const [key, value] of Object.entries(pageMap)) { | ||
| normalizePageMap[normalizeViewPath(key)] = value; | ||
| } | ||
| const routes = convertRoutes(menuRoutes, layoutMap, normalizePageMap); | ||
| return routes; | ||
| } catch (error) { | ||
| console.error(error); | ||
| throw error; | ||
| } | ||
| } | ||
| function convertRoutes(routes, layoutMap, pageMap) { | ||
| return utils.mapTree(routes, (node) => { | ||
| const route = node; | ||
| const { component, name } = node; | ||
| if (!name) { | ||
| console.error("route name is required", route); | ||
| } | ||
| if (component && layoutMap[component]) { | ||
| route.component = layoutMap[component]; | ||
| } else if (component) { | ||
| const normalizePath = normalizeViewPath(component); | ||
| const pageKey = normalizePath.endsWith(".vue") ? normalizePath : `${normalizePath}.vue`; | ||
| if (pageMap[pageKey]) { | ||
| route.component = pageMap[pageKey]; | ||
| } else { | ||
| console.error(`route component is invalid: ${pageKey}`, route); | ||
| route.component = pageMap["/_core/fallback/not-found.vue"]; | ||
| } | ||
| } | ||
| return route; | ||
| }); | ||
| } | ||
| function normalizeViewPath(path) { | ||
| const normalizedPath = path.replace(/^(\.\/|\.\.\/)+/, ""); | ||
| const viewPath = normalizedPath.startsWith("/") ? normalizedPath : `/${normalizedPath}`; | ||
| return viewPath.replace(/^\/views/, ""); | ||
| } | ||
| async function generateRoutesByFrontend(routes, roles, forbiddenComponent) { | ||
| const finalRoutes = utils.filterTree(routes, (route) => { | ||
| return hasAuthority(route, roles); | ||
| }); | ||
| if (!forbiddenComponent) { | ||
| return finalRoutes; | ||
| } | ||
| return utils.mapTree(finalRoutes, (route) => { | ||
| if (menuHasVisibleWithForbidden(route)) { | ||
| route.component = forbiddenComponent; | ||
| } | ||
| return route; | ||
| }); | ||
| } | ||
| function hasAuthority(route, access) { | ||
| const authority = route.meta?.authority; | ||
| if (!authority) { | ||
| return true; | ||
| } | ||
| const canAccess = access.some((value) => authority.includes(value)); | ||
| return canAccess || !canAccess && menuHasVisibleWithForbidden(route); | ||
| } | ||
| function menuHasVisibleWithForbidden(route) { | ||
| return !!route.meta?.authority && Reflect.has(route.meta || {}, "menuVisibleWithForbidden") && !!route.meta?.menuVisibleWithForbidden; | ||
| } | ||
| function getPopupContainer(node) { | ||
| return node?.closest("form") ?? node?.parentNode ?? document.body; | ||
| } | ||
| function mergeRouteModules(routeModules) { | ||
| const mergedRoutes = []; | ||
| for (const routeModule of Object.values(routeModules)) { | ||
| const moduleRoutes = routeModule?.default ?? []; | ||
| mergedRoutes.push(...moduleRoutes); | ||
| } | ||
| return mergedRoutes; | ||
| } | ||
| function resetStaticRoutes(router, routes) { | ||
| const staticRouteNames = utils.traverseTreeValues(routes, (route) => { | ||
| if (!route.name) { | ||
| console.warn( | ||
| `The route with the path ${route.path} needs to have the field name specified.` | ||
| ); | ||
| } | ||
| return route.name; | ||
| }); | ||
| const { getRoutes, hasRoute, removeRoute } = router; | ||
| const allRoutes = getRoutes(); | ||
| allRoutes.forEach(({ name }) => { | ||
| if (name && !staticRouteNames.includes(name) && hasRoute(name)) { | ||
| removeRoute(name); | ||
| } | ||
| }); | ||
| } | ||
| function unmountGlobalLoading() { | ||
| const loadingElement = document.querySelector("#__app-loading__"); | ||
| if (loadingElement) { | ||
| loadingElement.classList.add("hidden"); | ||
| const injectLoadingElements = document.querySelectorAll( | ||
| '[data-app-loading^="inject"]' | ||
| ); | ||
| loadingElement.addEventListener( | ||
| "transitionend", | ||
| () => { | ||
| loadingElement.remove(); | ||
| injectLoadingElements.forEach((el) => el.remove()); | ||
| }, | ||
| { once: true } | ||
| ); | ||
| } | ||
| } | ||
| exports.findMenuByPath = findMenuByPath; | ||
| exports.findRootMenuByPath = findRootMenuByPath; | ||
| exports.generateMenus = generateMenus; | ||
| exports.generateRoutesByBackend = generateRoutesByBackend; | ||
| exports.generateRoutesByFrontend = generateRoutesByFrontend; | ||
| exports.getPopupContainer = getPopupContainer; | ||
| exports.hasAuthority = hasAuthority; | ||
| exports.mergeRouteModules = mergeRouteModules; | ||
| exports.resetStaticRoutes = resetStaticRoutes; | ||
| exports.unmountGlobalLoading = unmountGlobalLoading; | ||
| exports.findMenuByPath = helpers_findMenuByPath.findMenuByPath; | ||
| exports.findRootMenuByPath = helpers_findMenuByPath.findRootMenuByPath; | ||
| exports.generateMenus = helpers_generateMenus.generateMenus; | ||
| exports.generateRoutesByBackend = helpers_generateRoutesBackend.generateRoutesByBackend; | ||
| exports.generateRoutesByFrontend = helpers_generateRoutesFrontend.generateRoutesByFrontend; | ||
| exports.hasAuthority = helpers_generateRoutesFrontend.hasAuthority; | ||
| exports.getPopupContainer = helpers_getPopupContainer.getPopupContainer; | ||
| exports.mergeRouteModules = helpers_mergeRouteModules.mergeRouteModules; | ||
| exports.resetStaticRoutes = helpers_resetRoutes.resetStaticRoutes; | ||
| exports.unmountGlobalLoading = helpers_unmountGlobalLoading.unmountGlobalLoading; | ||
| Object.prototype.hasOwnProperty.call(cache, '__proto__') && | ||
| !Object.prototype.hasOwnProperty.call(exports, '__proto__') && | ||
| Object.defineProperty(exports, '__proto__', { | ||
| enumerable: true, | ||
| value: cache['__proto__'] | ||
| }); | ||
| !Object.prototype.hasOwnProperty.call(exports, '__proto__') && | ||
| Object.defineProperty(exports, '__proto__', { | ||
| enumerable: true, | ||
| value: cache['__proto__'] | ||
| }); | ||
| Object.keys(cache).forEach(function (k) { | ||
| if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) exports[k] = cache[k]; | ||
| if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) exports[k] = cache[k]; | ||
| }); | ||
| Object.prototype.hasOwnProperty.call(color, '__proto__') && | ||
| !Object.prototype.hasOwnProperty.call(exports, '__proto__') && | ||
| Object.defineProperty(exports, '__proto__', { | ||
| enumerable: true, | ||
| value: color['__proto__'] | ||
| }); | ||
| !Object.prototype.hasOwnProperty.call(exports, '__proto__') && | ||
| Object.defineProperty(exports, '__proto__', { | ||
| enumerable: true, | ||
| value: color['__proto__'] | ||
| }); | ||
| Object.keys(color).forEach(function (k) { | ||
| if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) exports[k] = color[k]; | ||
| if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) exports[k] = color[k]; | ||
| }); | ||
| Object.prototype.hasOwnProperty.call(utils, '__proto__') && | ||
| !Object.prototype.hasOwnProperty.call(exports, '__proto__') && | ||
| Object.defineProperty(exports, '__proto__', { | ||
| enumerable: true, | ||
| value: utils['__proto__'] | ||
| }); | ||
| !Object.prototype.hasOwnProperty.call(exports, '__proto__') && | ||
| Object.defineProperty(exports, '__proto__', { | ||
| enumerable: true, | ||
| value: utils['__proto__'] | ||
| }); | ||
| Object.keys(utils).forEach(function (k) { | ||
| if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) exports[k] = utils[k]; | ||
| if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) exports[k] = utils[k]; | ||
| }); |
+10
-30
@@ -1,33 +0,13 @@ | ||
| import { MenuRecordRaw, GenerateMenuAndRoutesOptions } from '@dlymon-core/typings'; | ||
| import { RouteRecordRaw, Router } from 'vue-router'; | ||
| export * from '@dlymon-core/shared/cache'; | ||
| export * from '@dlymon-core/shared/color'; | ||
| export * from '@dlymon-core/shared/utils'; | ||
| declare function findMenuByPath(list: MenuRecordRaw[], path?: string): MenuRecordRaw | null; | ||
| declare function findRootMenuByPath(menus: MenuRecordRaw[], path?: string, level?: number): { | ||
| findMenu: MenuRecordRaw | null; | ||
| rootMenu: MenuRecordRaw | undefined; | ||
| rootMenuPath: string | undefined; | ||
| }; | ||
| declare function generateMenus(routes: RouteRecordRaw[], router: Router): MenuRecordRaw[]; | ||
| declare function generateRoutesByBackend(options: GenerateMenuAndRoutesOptions): Promise<RouteRecordRaw[]>; | ||
| declare function generateRoutesByFrontend(routes: RouteRecordRaw[], roles: string[], forbiddenComponent?: RouteRecordRaw['component']): Promise<RouteRecordRaw[]>; | ||
| declare function hasAuthority(route: RouteRecordRaw, access: string[]): boolean; | ||
| declare function getPopupContainer(node?: HTMLElement): HTMLElement; | ||
| interface RouteModuleType { | ||
| default: RouteRecordRaw[]; | ||
| } | ||
| declare function mergeRouteModules(routeModules: Record<string, unknown>): RouteRecordRaw[]; | ||
| declare function resetStaticRoutes(router: Router, routes: RouteRecordRaw[]): void; | ||
| declare function unmountGlobalLoading(): void; | ||
| export { findMenuByPath, findRootMenuByPath, generateMenus, generateRoutesByBackend, generateRoutesByFrontend, getPopupContainer, hasAuthority, mergeRouteModules, resetStaticRoutes, unmountGlobalLoading }; | ||
| export type { RouteModuleType }; | ||
| export { findMenuByPath, findRootMenuByPath } from './helpers/find-menu-by-path.cjs'; | ||
| export { generateMenus } from './helpers/generate-menus.cjs'; | ||
| export { generateRoutesByBackend } from './helpers/generate-routes-backend.cjs'; | ||
| export { generateRoutesByFrontend, hasAuthority } from './helpers/generate-routes-frontend.cjs'; | ||
| export { getPopupContainer } from './helpers/get-popup-container.cjs'; | ||
| export { RouteModuleType, mergeRouteModules } from './helpers/merge-route-modules.cjs'; | ||
| export { resetStaticRoutes } from './helpers/reset-routes.cjs'; | ||
| export { unmountGlobalLoading } from './helpers/unmount-global-loading.cjs'; | ||
| import '@dlymon-core/typings'; | ||
| import 'vue-router'; |
+10
-30
@@ -1,33 +0,13 @@ | ||
| import { MenuRecordRaw, GenerateMenuAndRoutesOptions } from '@dlymon-core/typings'; | ||
| import { RouteRecordRaw, Router } from 'vue-router'; | ||
| export * from '@dlymon-core/shared/cache'; | ||
| export * from '@dlymon-core/shared/color'; | ||
| export * from '@dlymon-core/shared/utils'; | ||
| declare function findMenuByPath(list: MenuRecordRaw[], path?: string): MenuRecordRaw | null; | ||
| declare function findRootMenuByPath(menus: MenuRecordRaw[], path?: string, level?: number): { | ||
| findMenu: MenuRecordRaw | null; | ||
| rootMenu: MenuRecordRaw | undefined; | ||
| rootMenuPath: string | undefined; | ||
| }; | ||
| declare function generateMenus(routes: RouteRecordRaw[], router: Router): MenuRecordRaw[]; | ||
| declare function generateRoutesByBackend(options: GenerateMenuAndRoutesOptions): Promise<RouteRecordRaw[]>; | ||
| declare function generateRoutesByFrontend(routes: RouteRecordRaw[], roles: string[], forbiddenComponent?: RouteRecordRaw['component']): Promise<RouteRecordRaw[]>; | ||
| declare function hasAuthority(route: RouteRecordRaw, access: string[]): boolean; | ||
| declare function getPopupContainer(node?: HTMLElement): HTMLElement; | ||
| interface RouteModuleType { | ||
| default: RouteRecordRaw[]; | ||
| } | ||
| declare function mergeRouteModules(routeModules: Record<string, unknown>): RouteRecordRaw[]; | ||
| declare function resetStaticRoutes(router: Router, routes: RouteRecordRaw[]): void; | ||
| declare function unmountGlobalLoading(): void; | ||
| export { findMenuByPath, findRootMenuByPath, generateMenus, generateRoutesByBackend, generateRoutesByFrontend, getPopupContainer, hasAuthority, mergeRouteModules, resetStaticRoutes, unmountGlobalLoading }; | ||
| export type { RouteModuleType }; | ||
| export { findMenuByPath, findRootMenuByPath } from './helpers/find-menu-by-path.mjs'; | ||
| export { generateMenus } from './helpers/generate-menus.mjs'; | ||
| export { generateRoutesByBackend } from './helpers/generate-routes-backend.mjs'; | ||
| export { generateRoutesByFrontend, hasAuthority } from './helpers/generate-routes-frontend.mjs'; | ||
| export { getPopupContainer } from './helpers/get-popup-container.mjs'; | ||
| export { RouteModuleType, mergeRouteModules } from './helpers/merge-route-modules.mjs'; | ||
| export { resetStaticRoutes } from './helpers/reset-routes.mjs'; | ||
| export { unmountGlobalLoading } from './helpers/unmount-global-loading.mjs'; | ||
| import '@dlymon-core/typings'; | ||
| import 'vue-router'; |
+10
-30
@@ -1,33 +0,13 @@ | ||
| import { MenuRecordRaw, GenerateMenuAndRoutesOptions } from '@dlymon-core/typings'; | ||
| import { RouteRecordRaw, Router } from 'vue-router'; | ||
| export * from '@dlymon-core/shared/cache'; | ||
| export * from '@dlymon-core/shared/color'; | ||
| export * from '@dlymon-core/shared/utils'; | ||
| declare function findMenuByPath(list: MenuRecordRaw[], path?: string): MenuRecordRaw | null; | ||
| declare function findRootMenuByPath(menus: MenuRecordRaw[], path?: string, level?: number): { | ||
| findMenu: MenuRecordRaw | null; | ||
| rootMenu: MenuRecordRaw | undefined; | ||
| rootMenuPath: string | undefined; | ||
| }; | ||
| declare function generateMenus(routes: RouteRecordRaw[], router: Router): MenuRecordRaw[]; | ||
| declare function generateRoutesByBackend(options: GenerateMenuAndRoutesOptions): Promise<RouteRecordRaw[]>; | ||
| declare function generateRoutesByFrontend(routes: RouteRecordRaw[], roles: string[], forbiddenComponent?: RouteRecordRaw['component']): Promise<RouteRecordRaw[]>; | ||
| declare function hasAuthority(route: RouteRecordRaw, access: string[]): boolean; | ||
| declare function getPopupContainer(node?: HTMLElement): HTMLElement; | ||
| interface RouteModuleType { | ||
| default: RouteRecordRaw[]; | ||
| } | ||
| declare function mergeRouteModules(routeModules: Record<string, unknown>): RouteRecordRaw[]; | ||
| declare function resetStaticRoutes(router: Router, routes: RouteRecordRaw[]): void; | ||
| declare function unmountGlobalLoading(): void; | ||
| export { findMenuByPath, findRootMenuByPath, generateMenus, generateRoutesByBackend, generateRoutesByFrontend, getPopupContainer, hasAuthority, mergeRouteModules, resetStaticRoutes, unmountGlobalLoading }; | ||
| export type { RouteModuleType }; | ||
| export { findMenuByPath, findRootMenuByPath } from './helpers/find-menu-by-path.js'; | ||
| export { generateMenus } from './helpers/generate-menus.js'; | ||
| export { generateRoutesByBackend } from './helpers/generate-routes-backend.js'; | ||
| export { generateRoutesByFrontend, hasAuthority } from './helpers/generate-routes-frontend.js'; | ||
| export { getPopupContainer } from './helpers/get-popup-container.js'; | ||
| export { RouteModuleType, mergeRouteModules } from './helpers/merge-route-modules.js'; | ||
| export { resetStaticRoutes } from './helpers/reset-routes.js'; | ||
| export { unmountGlobalLoading } from './helpers/unmount-global-loading.js'; | ||
| import '@dlymon-core/typings'; | ||
| import 'vue-router'; |
+8
-198
| export * from '@dlymon-core/shared/cache'; | ||
| export * from '@dlymon-core/shared/color'; | ||
| import { mapTree, filterTree, traverseTreeValues } from '@dlymon-core/shared/utils'; | ||
| export * from '@dlymon-core/shared/utils'; | ||
| function findMenuByPath(list, path) { | ||
| for (const menu of list) { | ||
| if (menu.path === path) { | ||
| return menu; | ||
| } | ||
| const findMenu = menu.children && findMenuByPath(menu.children, path); | ||
| if (findMenu) { | ||
| return findMenu; | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
| function findRootMenuByPath(menus, path, level = 0) { | ||
| const findMenu = findMenuByPath(menus, path); | ||
| const rootMenuPath = findMenu?.parents?.[level]; | ||
| const rootMenu = rootMenuPath ? menus.find((item) => item.path === rootMenuPath) : void 0; | ||
| return { | ||
| findMenu, | ||
| rootMenu, | ||
| rootMenuPath | ||
| }; | ||
| } | ||
| function generateMenus(routes, router) { | ||
| const finalRoutesMap = Object.fromEntries( | ||
| router.getRoutes().map(({ name, path }) => [name, path]) | ||
| ); | ||
| let menus = mapTree(routes, (route) => { | ||
| const path = finalRoutesMap[route.name] ?? route.path ?? ""; | ||
| const { | ||
| meta = {}, | ||
| name: routeName, | ||
| redirect, | ||
| children = [] | ||
| } = route; | ||
| const { | ||
| activeIcon, | ||
| badge, | ||
| badgeType, | ||
| badgeVariants, | ||
| hideChildrenInMenu = false, | ||
| icon, | ||
| link, | ||
| order, | ||
| title = "" | ||
| } = meta; | ||
| const name = title || routeName || ""; | ||
| const resultChildren = hideChildrenInMenu ? [] : children ?? []; | ||
| if (resultChildren.length > 0) { | ||
| resultChildren.forEach((child) => { | ||
| child.parents = [...route.parents ?? [], path]; | ||
| child.parent = path; | ||
| }); | ||
| } | ||
| const resultPath = hideChildrenInMenu ? redirect || path : link || path; | ||
| return { | ||
| activeIcon, | ||
| badge, | ||
| badgeType, | ||
| badgeVariants, | ||
| icon, | ||
| name, | ||
| order, | ||
| parent: route.parent, | ||
| parents: route.parents, | ||
| path: resultPath, | ||
| show: !meta.hideInMenu, | ||
| children: resultChildren | ||
| }; | ||
| }); | ||
| menus = menus.sort((a, b) => (a?.order ?? 999) - (b?.order ?? 999)); | ||
| return filterTree(menus, (menu) => !!menu.show); | ||
| } | ||
| async function generateRoutesByBackend(options) { | ||
| const { fetchMenuListAsync, layoutMap = {}, pageMap = {} } = options; | ||
| try { | ||
| const menuRoutes = await fetchMenuListAsync?.(); | ||
| if (!menuRoutes) { | ||
| return []; | ||
| } | ||
| const normalizePageMap = {}; | ||
| for (const [key, value] of Object.entries(pageMap)) { | ||
| normalizePageMap[normalizeViewPath(key)] = value; | ||
| } | ||
| const routes = convertRoutes(menuRoutes, layoutMap, normalizePageMap); | ||
| return routes; | ||
| } catch (error) { | ||
| console.error(error); | ||
| throw error; | ||
| } | ||
| } | ||
| function convertRoutes(routes, layoutMap, pageMap) { | ||
| return mapTree(routes, (node) => { | ||
| const route = node; | ||
| const { component, name } = node; | ||
| if (!name) { | ||
| console.error("route name is required", route); | ||
| } | ||
| if (component && layoutMap[component]) { | ||
| route.component = layoutMap[component]; | ||
| } else if (component) { | ||
| const normalizePath = normalizeViewPath(component); | ||
| const pageKey = normalizePath.endsWith(".vue") ? normalizePath : `${normalizePath}.vue`; | ||
| if (pageMap[pageKey]) { | ||
| route.component = pageMap[pageKey]; | ||
| } else { | ||
| console.error(`route component is invalid: ${pageKey}`, route); | ||
| route.component = pageMap["/_core/fallback/not-found.vue"]; | ||
| } | ||
| } | ||
| return route; | ||
| }); | ||
| } | ||
| function normalizeViewPath(path) { | ||
| const normalizedPath = path.replace(/^(\.\/|\.\.\/)+/, ""); | ||
| const viewPath = normalizedPath.startsWith("/") ? normalizedPath : `/${normalizedPath}`; | ||
| return viewPath.replace(/^\/views/, ""); | ||
| } | ||
| async function generateRoutesByFrontend(routes, roles, forbiddenComponent) { | ||
| const finalRoutes = filterTree(routes, (route) => { | ||
| return hasAuthority(route, roles); | ||
| }); | ||
| if (!forbiddenComponent) { | ||
| return finalRoutes; | ||
| } | ||
| return mapTree(finalRoutes, (route) => { | ||
| if (menuHasVisibleWithForbidden(route)) { | ||
| route.component = forbiddenComponent; | ||
| } | ||
| return route; | ||
| }); | ||
| } | ||
| function hasAuthority(route, access) { | ||
| const authority = route.meta?.authority; | ||
| if (!authority) { | ||
| return true; | ||
| } | ||
| const canAccess = access.some((value) => authority.includes(value)); | ||
| return canAccess || !canAccess && menuHasVisibleWithForbidden(route); | ||
| } | ||
| function menuHasVisibleWithForbidden(route) { | ||
| return !!route.meta?.authority && Reflect.has(route.meta || {}, "menuVisibleWithForbidden") && !!route.meta?.menuVisibleWithForbidden; | ||
| } | ||
| function getPopupContainer(node) { | ||
| return node?.closest("form") ?? node?.parentNode ?? document.body; | ||
| } | ||
| function mergeRouteModules(routeModules) { | ||
| const mergedRoutes = []; | ||
| for (const routeModule of Object.values(routeModules)) { | ||
| const moduleRoutes = routeModule?.default ?? []; | ||
| mergedRoutes.push(...moduleRoutes); | ||
| } | ||
| return mergedRoutes; | ||
| } | ||
| function resetStaticRoutes(router, routes) { | ||
| const staticRouteNames = traverseTreeValues(routes, (route) => { | ||
| if (!route.name) { | ||
| console.warn( | ||
| `The route with the path ${route.path} needs to have the field name specified.` | ||
| ); | ||
| } | ||
| return route.name; | ||
| }); | ||
| const { getRoutes, hasRoute, removeRoute } = router; | ||
| const allRoutes = getRoutes(); | ||
| allRoutes.forEach(({ name }) => { | ||
| if (name && !staticRouteNames.includes(name) && hasRoute(name)) { | ||
| removeRoute(name); | ||
| } | ||
| }); | ||
| } | ||
| function unmountGlobalLoading() { | ||
| const loadingElement = document.querySelector("#__app-loading__"); | ||
| if (loadingElement) { | ||
| loadingElement.classList.add("hidden"); | ||
| const injectLoadingElements = document.querySelectorAll( | ||
| '[data-app-loading^="inject"]' | ||
| ); | ||
| loadingElement.addEventListener( | ||
| "transitionend", | ||
| () => { | ||
| loadingElement.remove(); | ||
| injectLoadingElements.forEach((el) => el.remove()); | ||
| }, | ||
| { once: true } | ||
| ); | ||
| } | ||
| } | ||
| export { findMenuByPath, findRootMenuByPath, generateMenus, generateRoutesByBackend, generateRoutesByFrontend, getPopupContainer, hasAuthority, mergeRouteModules, resetStaticRoutes, unmountGlobalLoading }; | ||
| export { findMenuByPath, findRootMenuByPath } from './helpers/find-menu-by-path.mjs'; | ||
| export { generateMenus } from './helpers/generate-menus.mjs'; | ||
| export { generateRoutesByBackend } from './helpers/generate-routes-backend.mjs'; | ||
| export { generateRoutesByFrontend, hasAuthority } from './helpers/generate-routes-frontend.mjs'; | ||
| export { getPopupContainer } from './helpers/get-popup-container.mjs'; | ||
| export { mergeRouteModules } from './helpers/merge-route-modules.mjs'; | ||
| export { resetStaticRoutes } from './helpers/reset-routes.mjs'; | ||
| export { unmountGlobalLoading } from './helpers/unmount-global-loading.mjs'; |
+9
-4
| { | ||
| "name": "@dlymon/utils", | ||
| "version": "8.0.0", | ||
| "version": "9.0.0", | ||
| "license": "MIT", | ||
@@ -18,6 +18,11 @@ "type": "module", | ||
| }, | ||
| "dependencies": { | ||
| "peerDependencies": { | ||
| "@dlymon-core/shared": "*", | ||
| "@dlymon-core/typings": "*", | ||
| "vue-router": "*" | ||
| }, | ||
| "devDependencies": { | ||
| "vue-router": "^4.6.3", | ||
| "@dlymon-core/shared": "5.0.0", | ||
| "@dlymon-core/typings": "4.0.0" | ||
| "@dlymon-core/shared": "1.0.0-beta.2", | ||
| "@dlymon-core/typings": "1.0.0-beta.2" | ||
| }, | ||
@@ -24,0 +29,0 @@ "scripts": { |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
29112
51.5%52
642.86%557
25.45%0
-100%3
Infinity%1
Infinity%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed