erp-platform/ui/src/routes/dynamicRouteLoader.tsx
2025-10-30 22:23:59 +03:00

132 lines
5.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { RouteDto } from '@/proxy/routes/models'
import { lazy } from 'react'
import { useComponents } from '@/contexts/ComponentContext'
// 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'])
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) {
const cleanedPath = componentPath.replace(/^@\//, '')
const fullPath = `../${cleanedPath}.tsx`
if (lazyComponentCache.has(fullPath)) {
// console.log(`Physical component loaded from cache: ${fullPath}`)
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}`)
}
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)
}
}
// React Router için uygun bir route tipi
export interface DynamicReactRoute {
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>>
routeType: string
authority?: string[]
componentPath: string
isPhysical: boolean
isDynamic: boolean
}
// 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),
routeType: route.routeType,
authority: route.authority,
componentPath: route.componentPath,
isPhysical: isPhysicalComponent(route.componentPath),
isDynamic: isDynamicComponent(route.componentPath),
}))
}