mirror of
https://github.com/johndoe6345789/low-code-react-app-b.git
synced 2026-04-24 13:44:54 +00:00
Generated by Spark: I see loading screen, which is fine but we need really good console.log trace logging so i can trace the initialisation flow
This commit is contained in:
102
src/App.tsx
102
src/App.tsx
@@ -1,15 +1,34 @@
|
||||
console.log('[APP] 🚀 App.tsx loading - BEGIN')
|
||||
console.time('[APP] Component initialization')
|
||||
|
||||
import { useState, lazy, Suspense, useMemo, useEffect } from 'react'
|
||||
console.log('[APP] ✅ React hooks imported')
|
||||
|
||||
import { Tabs, TabsContent } from '@/components/ui/tabs'
|
||||
console.log('[APP] ✅ Tabs imported')
|
||||
|
||||
import { AppHeader, PageHeader } from '@/components/organisms'
|
||||
console.log('[APP] ✅ Header components imported')
|
||||
|
||||
import { LoadingFallback } from '@/components/molecules'
|
||||
console.log('[APP] ✅ LoadingFallback imported')
|
||||
|
||||
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from '@/components/ui/resizable'
|
||||
console.log('[APP] ✅ Resizable components imported')
|
||||
|
||||
import { useProjectState } from '@/hooks/use-project-state'
|
||||
import { useFileOperations } from '@/hooks/use-file-operations'
|
||||
import { useKeyboardShortcuts } from '@/hooks/use-keyboard-shortcuts'
|
||||
import { useSeedData } from '@/hooks/data/use-seed-data'
|
||||
import { getPageConfig, getEnabledPages, getPageShortcuts, resolveProps } from '@/config/page-loader'
|
||||
import { toast } from 'sonner'
|
||||
console.log('[APP] ✅ Custom hooks imported')
|
||||
|
||||
import { getPageConfig, getEnabledPages, getPageShortcuts, resolveProps } from '@/config/page-loader'
|
||||
console.log('[APP] ✅ Page config imported')
|
||||
|
||||
import { toast } from 'sonner'
|
||||
console.log('[APP] ✅ Toast imported')
|
||||
|
||||
console.log('[APP] 📦 Setting up lazy-loaded components')
|
||||
const componentMap: Record<string, React.LazyExoticComponent<any>> = {
|
||||
ProjectDashboard: lazy(() => import('@/components/ProjectDashboard').then(m => ({ default: m.ProjectDashboard }))),
|
||||
CodeEditor: lazy(() => import('@/components/CodeEditor').then(m => ({ default: m.CodeEditor }))),
|
||||
@@ -34,6 +53,7 @@ const componentMap: Record<string, React.LazyExoticComponent<any>> = {
|
||||
FeatureIdeaCloud: lazy(() => import('@/components/FeatureIdeaCloud').then(m => ({ default: m.FeatureIdeaCloud }))),
|
||||
TemplateSelector: lazy(() => import('@/components/TemplateSelector').then(m => ({ default: m.TemplateSelector }))),
|
||||
}
|
||||
console.log('[APP] ✅ Component map created with', Object.keys(componentMap).length, 'components')
|
||||
|
||||
const GlobalSearch = lazy(() => import('@/components/GlobalSearch').then(m => ({ default: m.GlobalSearch })))
|
||||
const KeyboardShortcutsDialog = lazy(() => import('@/components/KeyboardShortcutsDialog').then(m => ({ default: m.KeyboardShortcutsDialog })))
|
||||
@@ -41,9 +61,18 @@ const PreviewDialog = lazy(() => import('@/components/PreviewDialog').then(m =>
|
||||
const PWAInstallPrompt = lazy(() => import('@/components/PWAInstallPrompt').then(m => ({ default: m.PWAInstallPrompt })))
|
||||
const PWAUpdatePrompt = lazy(() => import('@/components/PWAUpdatePrompt').then(m => ({ default: m.PWAUpdatePrompt })))
|
||||
const PWAStatusBar = lazy(() => import('@/components/PWAStatusBar').then(m => ({ default: m.PWAStatusBar })))
|
||||
console.log('[APP] ✅ Additional lazy components registered')
|
||||
|
||||
console.log('[APP] 🎯 App component function executing')
|
||||
|
||||
function App() {
|
||||
console.log('[APP] 🔧 Initializing App component')
|
||||
console.time('[APP] App render')
|
||||
|
||||
console.log('[APP] 📊 Initializing project state hook')
|
||||
const projectState = useProjectState()
|
||||
console.log('[APP] ✅ Project state initialized')
|
||||
|
||||
const {
|
||||
files,
|
||||
models,
|
||||
@@ -75,10 +104,17 @@ function App() {
|
||||
setFeatureToggles,
|
||||
} = projectState
|
||||
|
||||
console.log('[APP] 📁 Initializing file operations')
|
||||
const fileOps = useFileOperations(files, setFiles)
|
||||
console.log('[APP] ✅ File operations initialized')
|
||||
|
||||
const { activeFileId, setActiveFileId, handleFileChange, handleFileAdd, handleFileClose } = fileOps
|
||||
|
||||
console.log('[APP] 🌱 Initializing seed data hook')
|
||||
const { loadSeedData } = useSeedData()
|
||||
console.log('[APP] ✅ Seed data hook initialized')
|
||||
|
||||
console.log('[APP] 💾 Initializing state variables')
|
||||
const [activeTab, setActiveTab] = useState('dashboard')
|
||||
const [searchOpen, setSearchOpen] = useState(false)
|
||||
const [shortcutsOpen, setShortcutsOpen] = useState(false)
|
||||
@@ -86,28 +122,63 @@ function App() {
|
||||
const [lastSaved] = useState<number | null>(Date.now())
|
||||
const [errorCount] = useState(0)
|
||||
const [appReady, setAppReady] = useState(false)
|
||||
console.log('[APP] ✅ State variables initialized')
|
||||
|
||||
console.log('[APP] ⏰ Setting up initialization effect')
|
||||
useEffect(() => {
|
||||
console.log('[APP] 🚀 Initialization effect triggered')
|
||||
console.time('[APP] Seed data loading')
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
console.log('[APP] ⏱️ Fallback timer triggered (100ms)')
|
||||
setAppReady(true)
|
||||
}, 100)
|
||||
|
||||
console.log('[APP] 📥 Starting seed data load')
|
||||
loadSeedData()
|
||||
.then(() => {
|
||||
console.log('[APP] ✅ Seed data loaded successfully')
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Seed data loading failed:', err)
|
||||
console.error('[APP] ❌ Seed data loading failed:', err)
|
||||
})
|
||||
.finally(() => {
|
||||
console.log('[APP] 🏁 Seed data loading complete')
|
||||
clearTimeout(timer)
|
||||
setAppReady(true)
|
||||
console.timeEnd('[APP] Seed data loading')
|
||||
console.log('[APP] ✅ App marked as ready')
|
||||
})
|
||||
|
||||
return () => clearTimeout(timer)
|
||||
return () => {
|
||||
console.log('[APP] 🧹 Cleaning up initialization effect')
|
||||
clearTimeout(timer)
|
||||
}
|
||||
}, [loadSeedData])
|
||||
|
||||
const pageConfig = useMemo(() => getPageConfig(), [])
|
||||
const enabledPages = useMemo(() => getEnabledPages(featureToggles), [featureToggles])
|
||||
const shortcuts = useMemo(() => getPageShortcuts(featureToggles), [featureToggles])
|
||||
console.log('[APP] 🧮 Computing page configuration')
|
||||
const pageConfig = useMemo(() => {
|
||||
console.log('[APP] 📄 Getting page config')
|
||||
const config = getPageConfig()
|
||||
console.log('[APP] ✅ Page config retrieved:', Object.keys(config).length, 'pages')
|
||||
return config
|
||||
}, [])
|
||||
|
||||
const enabledPages = useMemo(() => {
|
||||
console.log('[APP] 🔍 Filtering enabled pages')
|
||||
const pages = getEnabledPages(featureToggles)
|
||||
console.log('[APP] ✅ Enabled pages:', pages.map(p => p.id).join(', '))
|
||||
return pages
|
||||
}, [featureToggles])
|
||||
|
||||
const shortcuts = useMemo(() => {
|
||||
console.log('[APP] ⌨️ Getting keyboard shortcuts')
|
||||
const s = getPageShortcuts(featureToggles)
|
||||
console.log('[APP] ✅ Shortcuts configured:', s.length)
|
||||
return s
|
||||
}, [featureToggles])
|
||||
|
||||
console.log('[APP] ⌨️ Configuring keyboard shortcuts')
|
||||
useKeyboardShortcuts([
|
||||
...shortcuts.map(s => ({
|
||||
key: s.key,
|
||||
@@ -120,6 +191,7 @@ function App() {
|
||||
{ key: '/', ctrl: true, description: 'Shortcuts', action: () => setShortcutsOpen(true) },
|
||||
{ key: 'p', ctrl: true, description: 'Preview', action: () => setPreviewOpen(true) },
|
||||
])
|
||||
console.log('[APP] ✅ Keyboard shortcuts configured')
|
||||
|
||||
const getCurrentProject = () => ({
|
||||
name: nextjsConfig.appName,
|
||||
@@ -203,20 +275,26 @@ function App() {
|
||||
}
|
||||
|
||||
const renderPageContent = (page: any) => {
|
||||
console.log('[APP] 🎨 Rendering page:', page.id)
|
||||
try {
|
||||
const Component = componentMap[page.component]
|
||||
if (!Component) {
|
||||
console.error('[APP] ❌ Component not found:', page.component)
|
||||
return <LoadingFallback message={`Component ${page.component} not found`} />
|
||||
}
|
||||
console.log('[APP] ✅ Component found:', page.component)
|
||||
|
||||
if (page.requiresResizable && page.resizableConfig) {
|
||||
console.log('[APP] 🔀 Rendering resizable layout for:', page.id)
|
||||
const config = page.resizableConfig
|
||||
const LeftComponent = componentMap[config.leftComponent]
|
||||
const RightComponent = Component
|
||||
|
||||
if (!LeftComponent) {
|
||||
console.error('[APP] ❌ Left component not found:', config.leftComponent)
|
||||
return <LoadingFallback message={`Component ${config.leftComponent} not found`} />
|
||||
}
|
||||
console.log('[APP] ✅ Resizable layout components ready')
|
||||
|
||||
const stateContext = {
|
||||
files,
|
||||
@@ -280,6 +358,7 @@ function App() {
|
||||
)
|
||||
}
|
||||
|
||||
console.log('[APP] 📦 Rendering standard component:', page.component)
|
||||
const props = getPropsForComponent(page.id)
|
||||
return (
|
||||
<Suspense fallback={<LoadingFallback message={`Loading ${page.title.toLowerCase()}...`} />}>
|
||||
@@ -287,7 +366,7 @@ function App() {
|
||||
</Suspense>
|
||||
)
|
||||
} catch (error) {
|
||||
console.error(`Failed to render page ${page.id}:`, error)
|
||||
console.error('[APP] ❌ Failed to render page', page.id, ':', error)
|
||||
return (
|
||||
<div className="flex items-center justify-center h-full">
|
||||
<div className="text-center">
|
||||
@@ -299,6 +378,10 @@ function App() {
|
||||
}
|
||||
}
|
||||
|
||||
console.log('[APP] 🎨 Rendering App component UI')
|
||||
console.log('[APP] App state - appReady:', appReady, 'activeTab:', activeTab)
|
||||
console.timeEnd('[APP] App render')
|
||||
|
||||
return (
|
||||
<div className="h-screen flex flex-col bg-background">
|
||||
{!appReady && (
|
||||
@@ -372,4 +455,7 @@ function App() {
|
||||
)
|
||||
}
|
||||
|
||||
console.log('[APP] ✅ App component defined')
|
||||
console.timeEnd('[APP] Component initialization')
|
||||
|
||||
export default App
|
||||
|
||||
@@ -38,19 +38,31 @@ export interface PagesConfig {
|
||||
}
|
||||
|
||||
export function getPageConfig(): PagesConfig {
|
||||
return pagesConfig as PagesConfig
|
||||
console.log('[CONFIG] 📄 getPageConfig called')
|
||||
const config = pagesConfig as PagesConfig
|
||||
console.log('[CONFIG] ✅ Pages config loaded:', config.pages.length, 'pages')
|
||||
return config
|
||||
}
|
||||
|
||||
export function getPageById(id: string): PageConfig | undefined {
|
||||
return pagesConfig.pages.find(page => page.id === id)
|
||||
console.log('[CONFIG] 🔍 getPageById called for:', id)
|
||||
const page = pagesConfig.pages.find(page => page.id === id)
|
||||
console.log('[CONFIG]', page ? '✅ Page found' : '❌ Page not found')
|
||||
return page
|
||||
}
|
||||
|
||||
export function getEnabledPages(featureToggles?: FeatureToggles): PageConfig[] {
|
||||
return pagesConfig.pages.filter(page => {
|
||||
if (!page.enabled) return false
|
||||
console.log('[CONFIG] 🔍 getEnabledPages called with toggles:', featureToggles)
|
||||
const enabled = pagesConfig.pages.filter(page => {
|
||||
if (!page.enabled) {
|
||||
console.log('[CONFIG] ⏭️ Skipping disabled page:', page.id)
|
||||
return false
|
||||
}
|
||||
if (!page.toggleKey) return true
|
||||
return featureToggles?.[page.toggleKey as keyof FeatureToggles] !== false
|
||||
}).sort((a, b) => a.order - b.order)
|
||||
console.log('[CONFIG] ✅ Enabled pages:', enabled.map(p => p.id).join(', '))
|
||||
return enabled
|
||||
}
|
||||
|
||||
export function getPageShortcuts(featureToggles?: FeatureToggles): Array<{
|
||||
@@ -60,7 +72,8 @@ export function getPageShortcuts(featureToggles?: FeatureToggles): Array<{
|
||||
description: string
|
||||
action: string
|
||||
}> {
|
||||
return getEnabledPages(featureToggles)
|
||||
console.log('[CONFIG] ⌨️ getPageShortcuts called')
|
||||
const shortcuts = getEnabledPages(featureToggles)
|
||||
.filter(page => page.shortcut)
|
||||
.map(page => {
|
||||
const parts = page.shortcut!.toLowerCase().split('+')
|
||||
@@ -76,15 +89,22 @@ export function getPageShortcuts(featureToggles?: FeatureToggles): Array<{
|
||||
action: page.id
|
||||
}
|
||||
})
|
||||
console.log('[CONFIG] ✅ Shortcuts configured:', shortcuts.length)
|
||||
return shortcuts
|
||||
}
|
||||
|
||||
export function resolveProps(propConfig: PropConfig | undefined, stateContext: Record<string, any>, actionContext: Record<string, any>): Record<string, any> {
|
||||
if (!propConfig) return {}
|
||||
console.log('[CONFIG] 🔧 resolveProps called')
|
||||
if (!propConfig) {
|
||||
console.log('[CONFIG] ⏭️ No prop config provided')
|
||||
return {}
|
||||
}
|
||||
|
||||
const resolvedProps: Record<string, any> = {}
|
||||
|
||||
try {
|
||||
if (propConfig.state) {
|
||||
console.log('[CONFIG] 📦 Resolving', propConfig.state.length, 'state props')
|
||||
for (const stateKey of propConfig.state) {
|
||||
try {
|
||||
const [propName, contextKey] = stateKey.includes(':')
|
||||
@@ -93,29 +113,37 @@ export function resolveProps(propConfig: PropConfig | undefined, stateContext: R
|
||||
|
||||
if (stateContext[contextKey] !== undefined) {
|
||||
resolvedProps[propName] = stateContext[contextKey]
|
||||
console.log('[CONFIG] ✅ Resolved state prop:', propName)
|
||||
} else {
|
||||
console.log('[CONFIG] ⚠️ State prop not found:', contextKey)
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn(`Failed to resolve state prop: ${stateKey}`, err)
|
||||
console.warn('[CONFIG] ❌ Failed to resolve state prop:', stateKey, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (propConfig.actions) {
|
||||
console.log('[CONFIG] 🎬 Resolving', propConfig.actions.length, 'action props')
|
||||
for (const actionKey of propConfig.actions) {
|
||||
try {
|
||||
const [propName, contextKey] = actionKey.split(':')
|
||||
|
||||
if (actionContext[contextKey]) {
|
||||
resolvedProps[propName] = actionContext[contextKey]
|
||||
console.log('[CONFIG] ✅ Resolved action prop:', propName)
|
||||
} else {
|
||||
console.log('[CONFIG] ⚠️ Action prop not found:', contextKey)
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn(`Failed to resolve action prop: ${actionKey}`, err)
|
||||
console.warn('[CONFIG] ❌ Failed to resolve action prop:', actionKey, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to resolve props:', err)
|
||||
console.error('[CONFIG] ❌ Failed to resolve props:', err)
|
||||
}
|
||||
|
||||
console.log('[CONFIG] ✅ Props resolved:', Object.keys(resolvedProps).length, 'props')
|
||||
return resolvedProps
|
||||
}
|
||||
|
||||
@@ -2,75 +2,108 @@ import { useCallback, useState } from 'react'
|
||||
import seedDataConfig from '@/config/seed-data.json'
|
||||
|
||||
export function useSeedData() {
|
||||
console.log('[SEED] 🌱 useSeedData hook initializing')
|
||||
const [isLoaded, setIsLoaded] = useState(false)
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
|
||||
const loadSeedData = useCallback(async () => {
|
||||
if (isLoading || isLoaded) return
|
||||
console.log('[SEED] 🔍 loadSeedData called - isLoading:', isLoading, 'isLoaded:', isLoaded)
|
||||
|
||||
if (isLoading || isLoaded) {
|
||||
console.log('[SEED] ⏭️ Skipping seed data load (already loading or loaded)')
|
||||
return
|
||||
}
|
||||
|
||||
console.log('[SEED] 🚀 Starting seed data load')
|
||||
setIsLoading(true)
|
||||
console.time('[SEED] Seed data load duration')
|
||||
|
||||
try {
|
||||
console.log('[SEED] 🔌 Checking Spark KV availability')
|
||||
if (!window.spark?.kv) {
|
||||
console.warn('Spark KV not available, skipping seed data')
|
||||
console.warn('[SEED] ⚠️ Spark KV not available, skipping seed data')
|
||||
return
|
||||
}
|
||||
console.log('[SEED] ✅ Spark KV is available')
|
||||
|
||||
console.log('[SEED] 📋 Fetching existing keys from KV store')
|
||||
const keys = await window.spark.kv.keys()
|
||||
console.log('[SEED] 📊 Found', keys.length, 'existing keys:', keys)
|
||||
|
||||
console.log('[SEED] 📦 Seed data config entries:', Object.keys(seedDataConfig).length)
|
||||
let seededCount = 0
|
||||
let skippedCount = 0
|
||||
|
||||
for (const [key, value] of Object.entries(seedDataConfig)) {
|
||||
if (!keys.includes(key)) {
|
||||
console.log('[SEED] ➕ Seeding key:', key)
|
||||
await window.spark.kv.set(key, value)
|
||||
seededCount++
|
||||
} else {
|
||||
console.log('[SEED] ⏭️ Skipping existing key:', key)
|
||||
skippedCount++
|
||||
}
|
||||
}
|
||||
|
||||
console.log('[SEED] ✅ Seed data load complete - seeded:', seededCount, 'skipped:', skippedCount)
|
||||
setIsLoaded(true)
|
||||
} catch (error) {
|
||||
console.error('Failed to load seed data:', error)
|
||||
console.error('[SEED] ❌ Failed to load seed data:', error)
|
||||
setIsLoaded(true)
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
console.timeEnd('[SEED] Seed data load duration')
|
||||
}
|
||||
}, [isLoading, isLoaded])
|
||||
|
||||
const resetSeedData = useCallback(async () => {
|
||||
console.log('[SEED] 🔄 Resetting seed data')
|
||||
setIsLoading(true)
|
||||
try {
|
||||
if (!window.spark?.kv) {
|
||||
console.warn('Spark KV not available')
|
||||
console.warn('[SEED] ⚠️ Spark KV not available')
|
||||
return
|
||||
}
|
||||
|
||||
console.log('[SEED] 🔄 Overwriting all seed data keys')
|
||||
for (const [key, value] of Object.entries(seedDataConfig)) {
|
||||
console.log('[SEED] 📝 Setting key:', key)
|
||||
await window.spark.kv.set(key, value)
|
||||
}
|
||||
console.log('[SEED] ✅ Seed data reset complete')
|
||||
setIsLoaded(true)
|
||||
} catch (error) {
|
||||
console.error('Failed to reset seed data:', error)
|
||||
console.error('[SEED] ❌ Failed to reset seed data:', error)
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const clearAllData = useCallback(async () => {
|
||||
console.log('[SEED] 🗑️ Clearing all data')
|
||||
setIsLoading(true)
|
||||
try {
|
||||
if (!window.spark?.kv) {
|
||||
console.warn('Spark KV not available')
|
||||
console.warn('[SEED] ⚠️ Spark KV not available')
|
||||
return
|
||||
}
|
||||
|
||||
const keys = await window.spark.kv.keys()
|
||||
console.log('[SEED] 📋 Deleting', keys.length, 'keys')
|
||||
for (const key of keys) {
|
||||
console.log('[SEED] 🗑️ Deleting key:', key)
|
||||
await window.spark.kv.delete(key)
|
||||
}
|
||||
console.log('[SEED] ✅ All data cleared')
|
||||
setIsLoaded(false)
|
||||
} catch (error) {
|
||||
console.error('Failed to clear data:', error)
|
||||
console.error('[SEED] ❌ Failed to clear data:', error)
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
console.log('[SEED] 📤 Returning seed data hook methods')
|
||||
return {
|
||||
isLoaded,
|
||||
isLoading,
|
||||
|
||||
@@ -134,9 +134,22 @@ const DEFAULT_FILES: ProjectFile[] = [
|
||||
]
|
||||
|
||||
export function useProjectState() {
|
||||
console.log('[STATE] 🔧 useProjectState hook initializing')
|
||||
console.time('[STATE] Project state initialization')
|
||||
|
||||
console.log('[STATE] 📁 Loading files from KV')
|
||||
const [files, setFiles] = useKV<ProjectFile[]>('project-files', DEFAULT_FILES)
|
||||
console.log('[STATE] ✅ Files loaded:', files?.length || 0, 'files')
|
||||
|
||||
console.log('[STATE] 🗃️ Loading models from KV')
|
||||
const [models, setModels] = useKV<PrismaModel[]>('project-models', [])
|
||||
console.log('[STATE] ✅ Models loaded:', models?.length || 0, 'models')
|
||||
|
||||
console.log('[STATE] 🧩 Loading components from KV')
|
||||
const [components, setComponents] = useKV<ComponentNode[]>('project-components', [])
|
||||
console.log('[STATE] ✅ Components loaded:', components?.length || 0, 'components')
|
||||
|
||||
console.log('[STATE] 🌳 Loading component trees from KV')
|
||||
const [componentTrees, setComponentTrees] = useKV<ComponentTree[]>('project-component-trees', [
|
||||
{
|
||||
id: 'default-tree',
|
||||
@@ -147,17 +160,49 @@ export function useProjectState() {
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
])
|
||||
console.log('[STATE] ✅ Component trees loaded:', componentTrees?.length || 0, 'trees')
|
||||
|
||||
console.log('[STATE] 🔄 Loading workflows from KV')
|
||||
const [workflows, setWorkflows] = useKV<Workflow[]>('project-workflows', [])
|
||||
console.log('[STATE] ✅ Workflows loaded:', workflows?.length || 0, 'workflows')
|
||||
|
||||
console.log('[STATE] λ Loading lambdas from KV')
|
||||
const [lambdas, setLambdas] = useKV<Lambda[]>('project-lambdas', [])
|
||||
console.log('[STATE] ✅ Lambdas loaded:', lambdas?.length || 0, 'lambdas')
|
||||
|
||||
console.log('[STATE] 🎨 Loading theme from KV')
|
||||
const [theme, setTheme] = useKV<ThemeConfig>('project-theme', DEFAULT_THEME)
|
||||
console.log('[STATE] ✅ Theme loaded')
|
||||
|
||||
console.log('[STATE] 🎭 Loading Playwright tests from KV')
|
||||
const [playwrightTests, setPlaywrightTests] = useKV<PlaywrightTest[]>('project-playwright-tests', [])
|
||||
console.log('[STATE] ✅ Playwright tests loaded:', playwrightTests?.length || 0, 'tests')
|
||||
|
||||
console.log('[STATE] 📚 Loading Storybook stories from KV')
|
||||
const [storybookStories, setStorybookStories] = useKV<StorybookStory[]>('project-storybook-stories', [])
|
||||
console.log('[STATE] ✅ Storybook stories loaded:', storybookStories?.length || 0, 'stories')
|
||||
|
||||
console.log('[STATE] 🧪 Loading unit tests from KV')
|
||||
const [unitTests, setUnitTests] = useKV<UnitTest[]>('project-unit-tests', [])
|
||||
console.log('[STATE] ✅ Unit tests loaded:', unitTests?.length || 0, 'tests')
|
||||
|
||||
console.log('[STATE] 🐍 Loading Flask config from KV')
|
||||
const [flaskConfig, setFlaskConfig] = useKV<FlaskConfig>('project-flask-config', DEFAULT_FLASK_CONFIG)
|
||||
console.log('[STATE] ✅ Flask config loaded')
|
||||
|
||||
console.log('[STATE] ⚛️ Loading Next.js config from KV')
|
||||
const [nextjsConfig, setNextjsConfig] = useKV<NextJsConfig>('project-nextjs-config', DEFAULT_NEXTJS_CONFIG)
|
||||
console.log('[STATE] ✅ Next.js config loaded')
|
||||
|
||||
console.log('[STATE] 📦 Loading NPM settings from KV')
|
||||
const [npmSettings, setNpmSettings] = useKV<NpmSettings>('project-npm-settings', DEFAULT_NPM_SETTINGS)
|
||||
console.log('[STATE] ✅ NPM settings loaded')
|
||||
|
||||
console.log('[STATE] 🎚️ Loading feature toggles from KV')
|
||||
const [featureToggles, setFeatureToggles] = useKV<FeatureToggles>('project-feature-toggles', DEFAULT_FEATURE_TOGGLES)
|
||||
console.log('[STATE] ✅ Feature toggles loaded')
|
||||
|
||||
console.log('[STATE] 🛡️ Creating safe array wrappers')
|
||||
const safeFiles = Array.isArray(files) ? files : []
|
||||
const safeModels = Array.isArray(models) ? models : []
|
||||
const safeComponents = Array.isArray(components) ? components : []
|
||||
@@ -172,7 +217,11 @@ export function useProjectState() {
|
||||
const safeNextjsConfig = nextjsConfig || DEFAULT_NEXTJS_CONFIG
|
||||
const safeNpmSettings = npmSettings || DEFAULT_NPM_SETTINGS
|
||||
const safeFeatureToggles = featureToggles || DEFAULT_FEATURE_TOGGLES
|
||||
console.log('[STATE] ✅ Safe wrappers created')
|
||||
|
||||
console.log('[STATE] 📤 Returning project state object')
|
||||
console.timeEnd('[STATE] Project state initialization')
|
||||
|
||||
return {
|
||||
files: safeFiles,
|
||||
setFiles,
|
||||
|
||||
53
src/main.tsx
53
src/main.tsx
@@ -1,15 +1,40 @@
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import { ErrorBoundary } from "react-error-boundary";
|
||||
import "@github/spark/spark"
|
||||
console.log('[INIT] 🚀 main.tsx starting - BEGIN')
|
||||
console.time('[INIT] Total initialization time')
|
||||
|
||||
console.log('[INIT] 📦 Importing React DOM')
|
||||
import { createRoot } from 'react-dom/client'
|
||||
console.log('[INIT] ✅ React DOM imported')
|
||||
|
||||
console.log('[INIT] 📦 Importing ErrorBoundary')
|
||||
import { ErrorBoundary } from "react-error-boundary";
|
||||
console.log('[INIT] ✅ ErrorBoundary imported')
|
||||
|
||||
console.log('[INIT] 📦 Importing Spark SDK')
|
||||
import "@github/spark/spark"
|
||||
console.log('[INIT] ✅ Spark SDK imported')
|
||||
|
||||
console.log('[INIT] 📦 Importing App component')
|
||||
import App from './App.tsx'
|
||||
console.log('[INIT] ✅ App component imported')
|
||||
|
||||
console.log('[INIT] 📦 Importing ErrorFallback')
|
||||
import { ErrorFallback } from './ErrorFallback.tsx'
|
||||
console.log('[INIT] ✅ ErrorFallback imported')
|
||||
|
||||
console.log('[INIT] 📦 Importing UI components')
|
||||
import { Toaster } from './components/ui/sonner.tsx'
|
||||
import { TooltipProvider } from './components/ui/tooltip.tsx'
|
||||
console.log('[INIT] ✅ UI components imported')
|
||||
|
||||
console.log('[INIT] 🎨 Loading CSS files')
|
||||
import "./main.css"
|
||||
console.log('[INIT] ✅ main.css loaded')
|
||||
import "./styles/theme.css"
|
||||
console.log('[INIT] ✅ theme.css loaded')
|
||||
import "./index.css"
|
||||
console.log('[INIT] ✅ index.css loaded')
|
||||
|
||||
console.log('[INIT] 🛡️ Setting up error handlers')
|
||||
|
||||
const isResizeObserverError = (message: string | undefined): boolean => {
|
||||
if (!message) return false
|
||||
@@ -42,6 +67,7 @@ console.warn = (...args) => {
|
||||
}
|
||||
|
||||
window.addEventListener('error', (e) => {
|
||||
console.log('[INIT] ⚠️ Global error caught:', e.message)
|
||||
if (isResizeObserverError(e.message)) {
|
||||
e.stopImmediatePropagation()
|
||||
e.preventDefault()
|
||||
@@ -50,13 +76,29 @@ window.addEventListener('error', (e) => {
|
||||
}, true)
|
||||
|
||||
window.addEventListener('unhandledrejection', (e) => {
|
||||
console.log('[INIT] ⚠️ Unhandled rejection caught:', e.reason)
|
||||
if (e.reason && e.reason.message && isResizeObserverError(e.reason.message)) {
|
||||
e.preventDefault()
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
createRoot(document.getElementById('root')!).render(
|
||||
console.log('[INIT] ✅ Error handlers configured')
|
||||
|
||||
console.log('[INIT] 🎯 Finding root element')
|
||||
const rootElement = document.getElementById('root')
|
||||
if (!rootElement) {
|
||||
console.error('[INIT] ❌ Root element not found!')
|
||||
throw new Error('Root element not found')
|
||||
}
|
||||
console.log('[INIT] ✅ Root element found:', rootElement)
|
||||
|
||||
console.log('[INIT] 🏗️ Creating React root')
|
||||
const root = createRoot(rootElement)
|
||||
console.log('[INIT] ✅ React root created')
|
||||
|
||||
console.log('[INIT] 🎨 Rendering application')
|
||||
root.render(
|
||||
<ErrorBoundary FallbackComponent={ErrorFallback}>
|
||||
<TooltipProvider>
|
||||
<App />
|
||||
@@ -64,3 +106,6 @@ createRoot(document.getElementById('root')!).render(
|
||||
</TooltipProvider>
|
||||
</ErrorBoundary>
|
||||
)
|
||||
console.log('[INIT] ✅ Application rendered')
|
||||
console.timeEnd('[INIT] Total initialization time')
|
||||
console.log('[INIT] 🎉 main.tsx complete - END')
|
||||
|
||||
Reference in New Issue
Block a user