erp-platform/ui/src/routes/dynamicRouteLoader.tsx

133 lines
5.2 KiB
TypeScript
Raw Normal View History

2025-08-12 09:39:09 +00:00
import { RouteDto } from '@/proxy/routes/models'
2025-06-28 21:34:28 +00:00
import { lazy } from 'react'
import { useComponents } from '@/contexts/ComponentContext'
2025-06-28 21:34:28 +00:00
// Tüm view bileşenlerini import et (vite özel)
// shared klasörü hariç, çünkü bu bileşenler genellikle başka yerlerde statik import ediliyor
const modules = import.meta.glob(['../views/**/*.tsx', '!../views/shared/**/*.tsx'])
2025-06-28 21:34:28 +00:00
const lazyComponentCache = new Map<string, React.LazyExoticComponent<React.ComponentType<any>>>()
// ComponentPath'in fiziksel mi yoksa dinamik mi olduğunu belirle
function isPhysicalComponent(componentPath: string): boolean {
// @ ile başlayan path'ler fiziksel dosya yolu
// Başka bir kural: dynamic: ile başlayan path'ler dinamik
return componentPath.startsWith('@/') || componentPath.startsWith('../')
}
function isDynamicComponent(componentPath: string): boolean {
// dynamic: ile başlayan path'ler dinamik komponent
return componentPath.startsWith('dynamic:')
}
// Fiziksel komponent yükleme (mevcut mantık)
function loadPhysicalComponent(componentPath: string) {
2025-06-28 21:34:28 +00:00
const cleanedPath = componentPath.replace(/^@\//, '')
const fullPath = `../${cleanedPath}.tsx`
if (lazyComponentCache.has(fullPath)) {
// console.log(`Physical component loaded from cache: ${fullPath}`)
2025-06-28 21:34:28 +00:00
return lazyComponentCache.get(fullPath)!
}
const loader = modules[fullPath]
if (!loader) {
console.error(`Physical component not found for path: ${fullPath}`)
throw new Error(`Physical component not found for path: ${fullPath}`)
2025-06-28 21:34:28 +00:00
}
const LazyComponent = lazy(loader as () => Promise<{ default: React.ComponentType<any> }>)
lazyComponentCache.set(fullPath, LazyComponent)
return LazyComponent
}
// Dinamik komponent yükleme (yeni mantık)
function loadDynamicComponent(
componentPath: string,
registeredComponents: Record<string, React.ComponentType<unknown>>,
renderComponent?: (name: string, props?: any) => React.ReactNode,
isComponentRegistered?: (name: string) => boolean
) {
const componentName = componentPath.replace('dynamic:', '')
if (lazyComponentCache.has(componentPath)) {
// console.log(`Dynamic component loaded from cache: ${componentName}`)
return lazyComponentCache.get(componentPath)!
}
// Önce manuel registered komponentleri kontrol et
let DynamicComponent = registeredComponents[componentName]
// Eğer manuel registered'da yoksa, database compiled komponentleri kontrol et
if (!DynamicComponent && isComponentRegistered && renderComponent && isComponentRegistered(componentName)) {
// console.log(`Database component found: ${componentName}`)
// Database komponentini wrapper ile kullan
DynamicComponent = (props: any) => renderComponent(componentName, props) as React.ReactElement
}
if (!DynamicComponent) {
console.error(`Dynamic component not found: ${componentName}`)
console.log('Available registered components:', Object.keys(registeredComponents))
if (isComponentRegistered) {
console.log('Database component registry available - checking...')
}
throw new Error(`Dynamic component not found: ${componentName}`)
}
// console.log(`Dynamic component loaded: ${componentName}`)
// Dinamik komponent için lazy wrapper oluştur
const LazyComponent = lazy(() => Promise.resolve({ default: DynamicComponent as React.ComponentType<any> }))
lazyComponentCache.set(componentPath, LazyComponent)
return LazyComponent
}
export function loadComponent(
componentPath: string,
registeredComponents?: Record<string, React.ComponentType<unknown>>,
renderComponent?: (name: string, props?: any) => React.ReactNode,
isComponentRegistered?: (name: string) => boolean
) {
if (isPhysicalComponent(componentPath)) {
return loadPhysicalComponent(componentPath)
} else if (isDynamicComponent(componentPath)) {
if (!registeredComponents) {
throw new Error('Registered components required for dynamic component loading')
}
return loadDynamicComponent(componentPath, registeredComponents, renderComponent, isComponentRegistered)
} else {
// Backward compatibility: varsayılan olarak fiziksel komponent kabul et
return loadPhysicalComponent(componentPath)
}
}
2025-06-28 21:34:28 +00:00
// React Router için uygun bir route tipi
export interface DynamicReactRoute {
2025-08-12 09:39:09 +00:00
key: string
path: string
getComponent: (
registeredComponents?: Record<string, React.ComponentType<unknown>>,
renderComponent?: (name: string, props?: any) => React.ReactNode,
isComponentRegistered?: (name: string) => boolean
) => React.LazyExoticComponent<React.ComponentType<any>>
2025-08-12 09:39:09 +00:00
routeType: string
authority?: string[]
componentPath: string
isPhysical: boolean
isDynamic: boolean
2025-06-28 21:34:28 +00:00
}
// API'den gelen route objesini, React Router için uygun hale getirir
export function mapDynamicRoutes(routes: RouteDto[]): DynamicReactRoute[] {
return routes.map((route) => ({
key: route.path,
path: route.path,
getComponent: (registeredComponents, renderComponent, isComponentRegistered) =>
loadComponent(route.componentPath, registeredComponents, renderComponent, isComponentRegistered),
2025-06-28 21:34:28 +00:00
routeType: route.routeType,
authority: route.authority,
componentPath: route.componentPath,
isPhysical: isPhysicalComponent(route.componentPath),
isDynamic: isDynamicComponent(route.componentPath),
2025-08-12 09:39:09 +00:00
}))
2025-06-28 21:34:28 +00:00
}