sozsoft-platform/ui/src/routes/dynamicRouteLoader.tsx
2026-07-11 23:35:32 +03:00

155 lines
5.3 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 React, { lazy } from 'react'
import { RouteDto } from '@/proxy/routes/models'
import { CustomComponent } from '@/proxy/developerKit/models'
// 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>>>()
// Fiziksel komponent yükleme (mevcut mantık)
function loadPhysicalComponent(componentPath: string) {
const cleanedPath = componentPath.replace(/^@\//, '')
const fullPath = `../${cleanedPath}.tsx`
if (lazyComponentCache.has(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,
) {
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[componentPath]
// Eğer manuel registered'da yoksa, database compiled komponentleri kontrol et
if (
!DynamicComponent &&
isComponentRegistered &&
renderComponent &&
isComponentRegistered(componentPath)
) {
DynamicComponent = (props: any) => renderComponent(componentPath, props) as React.ReactElement
}
if (!DynamicComponent) {
if (isComponentRegistered) {
console.log('Database component registry available - checking...')
}
throw new Error(`Dynamic component not found: ${componentPath}`)
}
// console.log(`Dynamic component loaded: ${componentPath}`)
// 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(
componentType: string,
componentPath: string,
registeredComponents?: Record<string, React.ComponentType<unknown>>,
renderComponent?: (name: string, props?: any) => React.ReactNode,
isComponentRegistered?: (name: string) => boolean,
) {
if (componentType === 'normal') {
return loadPhysicalComponent(componentPath)
} else if (componentType === 'dynamic') {
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[]
componentType: string
componentPath: string
}
// 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.componentType,
route.componentPath,
registeredComponents,
renderComponent,
isComponentRegistered,
),
routeType: route.routeType,
authority: route.authority,
componentType: route.componentType,
componentPath: route.componentPath,
}))
}
// Custom components are the single source of truth for runtime routes.
export function mapCustomComponentRoutes(
components: Pick<CustomComponent, 'id' | 'name' | 'routePath' | 'isActive'>[],
): DynamicReactRoute[] {
return components
.filter((component) => component.isActive && component.routePath?.trim())
.map((component) => ({
key: `custom-component-${component.id}`,
path: component.routePath.startsWith('/') ? component.routePath : `/${component.routePath}`,
getComponent: (registeredComponents, renderComponent, isComponentRegistered) =>
loadComponent(
'dynamic',
component.name,
registeredComponents,
renderComponent,
isComponentRegistered,
),
routeType: component.routePath.startsWith('/admin/') ? 'protected' : 'public',
authority: [],
componentType: 'dynamic',
componentPath: component.name,
}))
}