132 lines
5.2 KiB
TypeScript
132 lines
5.2 KiB
TypeScript
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),
|
||
}))
|
||
}
|