viewlogic 1.2.8 → 1.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/plugins/I18nManager.js", "../src/plugins/AuthManager.js", "../src/plugins/CacheManager.js", "../src/plugins/QueryManager.js", "../src/core/FormHandler.js", "../src/core/ApiHandler.js", "../src/core/ComponentLoader.js", "../src/core/RouteLoader.js", "../src/core/ErrorHandler.js", "../src/core/StateHandler.js", "../src/viewlogic-router.js"],
4
- "sourcesContent": ["/**\r\n * ViewLogic Internationalization System\r\n * \uB2E4\uAD6D\uC5B4 \uC9C0\uC6D0 \uC2DC\uC2A4\uD15C\r\n */\r\nexport class I18nManager {\r\n constructor(router, options = {}) {\r\n this.config = {\r\n enabled: options.useI18n !== undefined ? options.useI18n : true,\r\n defaultLanguage: options.defaultLanguage || 'en',\r\n fallbackLanguage: options.defaultLanguage || 'en'\r\n };\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870 (\uD544\uC694\uC2DC \uC5B8\uC5B4 \uBCC0\uACBD \uC2DC \uB77C\uC6B0\uD130 \uC0C1\uD0DC \uC5C5\uB370\uC774\uD2B8)\r\n this.router = router;\r\n \r\n this.messages = new Map();\r\n this.currentLanguage = this.config.defaultLanguage;\r\n this.isLoading = false;\r\n this.loadPromises = new Map();\r\n \r\n // \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108\uB4E4\r\n this.listeners = {\r\n languageChanged: []\r\n };\r\n \r\n // \uBE44\uB3D9\uAE30 \uCD08\uAE30\uD654 \uC2DC\uC791 (constructor \uB0B4\uC5D0\uC11C\uB294 await \uBD88\uAC00)\r\n this.initPromise = this.init();\r\n }\r\n\r\n async init() {\r\n // i18n\uC774 \uBE44\uD65C\uC131\uD654\uB41C \uACBD\uC6B0 \uCD08\uAE30\uD654\uD558\uC9C0 \uC54A\uC74C\r\n if (!this.config.enabled) {\r\n this.log('info', 'I18n system disabled');\r\n return;\r\n }\r\n \r\n // \uCE90\uC2DC\uC5D0\uC11C \uC5B8\uC5B4 \uC124\uC815 \uB85C\uB4DC\r\n this.loadLanguageFromCache();\r\n\r\n // \uCD08\uAE30 \uC5B8\uC5B4 \uD30C\uC77C \uC790\uB3D9 \uB85C\uB4DC (\uC544\uC9C1 \uB85C\uB4DC\uB418\uC9C0 \uC54A\uC740 \uACBD\uC6B0\uC5D0\uB9CC)\r\n if (!this.messages.has(this.currentLanguage)) {\r\n try {\r\n await this.loadMessages(this.currentLanguage);\r\n } catch (error) {\r\n this.log('error', 'Failed to load initial language file:', error);\r\n // \uD3F4\uBC31\uC73C\uB85C \uBE48 \uBA54\uC2DC\uC9C0 \uAC1D\uCCB4 \uC124\uC815\uD558\uC5EC \uC2DC\uC2A4\uD15C\uC774 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D\r\n this.messages.set(this.currentLanguage, {});\r\n this.log('info', 'Using empty message object as fallback');\r\n }\r\n } else {\r\n this.log('debug', 'Language messages already loaded:', this.currentLanguage);\r\n }\r\n }\r\n\r\n /**\r\n * \uCE90\uC2DC\uC5D0\uC11C \uC5B8\uC5B4 \uC124\uC815 \uB85C\uB4DC\r\n */\r\n loadLanguageFromCache() {\r\n try {\r\n const cachedLang = this.router.cacheManager?.get('viewlogic_lang');\r\n if (cachedLang && this.isValidLanguage(cachedLang)) {\r\n this.currentLanguage = cachedLang;\r\n this.log('debug', 'Language loaded from cache:', cachedLang);\r\n }\r\n } catch (error) {\r\n this.log('warn', 'Failed to load language from cache:', error);\r\n }\r\n }\r\n\r\n\r\n /**\r\n * \uC5B8\uC5B4 \uC720\uD6A8\uC131 \uAC80\uC0AC\r\n */\r\n isValidLanguage(lang) {\r\n return typeof lang === 'string' && /^[a-z]{2}$/.test(lang);\r\n }\r\n\r\n /**\r\n * \uD604\uC7AC \uC5B8\uC5B4 \uBC18\uD658\r\n */\r\n getCurrentLanguage() {\r\n return this.currentLanguage;\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4 \uBCC0\uACBD\r\n */\r\n async setLanguage(language) {\r\n if (!this.isValidLanguage(language)) {\r\n this.log('warn', 'Invalid language code:', language);\r\n return false;\r\n }\r\n\r\n if (this.currentLanguage === language) {\r\n this.log('debug', 'Language already set to:', language);\r\n return true;\r\n }\r\n\r\n const oldLanguage = this.currentLanguage;\r\n this.currentLanguage = language;\r\n\r\n try {\r\n // \uC5B8\uC5B4 \uD30C\uC77C \uB85C\uB4DC (\uC2E4\uD328\uD574\uB3C4 \uBE48 \uAC1D\uCCB4\uB77C\uB3C4 \uBC1B\uC744 \uC218 \uC788\uB3C4\uB85D)\r\n await this.loadMessages(language);\r\n \r\n // \uCE90\uC2DC\uC5D0 \uC800\uC7A5\r\n this.saveLanguageToCache(language);\r\n \r\n // \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n this.emit('languageChanged', {\r\n from: oldLanguage,\r\n to: language,\r\n messages: this.messages.get(language)\r\n });\r\n \r\n this.log('info', 'Language changed successfully', { from: oldLanguage, to: language });\r\n return true;\r\n } catch (error) {\r\n // \uC2E4\uD328\uD574\uB3C4 \uC5B8\uC5B4\uB294 \uBCC0\uACBD\uD558\uB418, \uBE48 \uBA54\uC2DC\uC9C0 \uAC1D\uCCB4 \uC0AC\uC6A9\r\n this.log('error', 'Failed to load messages for language change, using empty messages:', error);\r\n this.messages.set(language, {});\r\n \r\n // \uCE90\uC2DC\uC5D0 \uC800\uC7A5\r\n this.saveLanguageToCache(language);\r\n \r\n // \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n this.emit('languageChanged', {\r\n from: oldLanguage,\r\n to: language,\r\n messages: {},\r\n error: true\r\n });\r\n \r\n this.log('warn', 'Language changed with empty messages', { from: oldLanguage, to: language });\r\n return true; // true \uBC18\uD658\uD558\uC5EC \uB77C\uC6B0\uD130\uAC00 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D\r\n }\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4\uB97C \uCE90\uC2DC\uC5D0 \uC800\uC7A5\r\n */\r\n saveLanguageToCache(language) {\r\n try {\r\n this.router.cacheManager?.set('viewlogic_lang', language);\r\n this.log('debug', 'Language saved to cache:', language);\r\n } catch (error) {\r\n this.log('warn', 'Failed to save language to cache:', error);\r\n }\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4 \uBA54\uC2DC\uC9C0 \uD30C\uC77C \uB85C\uB4DC\r\n */\r\n async loadMessages(language) {\r\n // \uC774\uBBF8 \uB85C\uB4DC\uB41C \uACBD\uC6B0\r\n if (this.messages.has(language)) {\r\n this.log('debug', 'Messages already loaded for:', language);\r\n return this.messages.get(language);\r\n }\r\n\r\n // \uC774\uBBF8 \uB85C\uB529 \uC911\uC778 \uACBD\uC6B0\r\n if (this.loadPromises.has(language)) {\r\n this.log('debug', 'Messages loading in progress for:', language);\r\n return await this.loadPromises.get(language);\r\n }\r\n\r\n const loadPromise = this._loadMessagesFromFile(language);\r\n this.loadPromises.set(language, loadPromise);\r\n\r\n try {\r\n const messages = await loadPromise;\r\n this.messages.set(language, messages);\r\n this.loadPromises.delete(language);\r\n this.log('debug', 'Messages loaded successfully for:', language);\r\n return messages;\r\n } catch (error) {\r\n this.loadPromises.delete(language);\r\n // \uC2E4\uD328\uD574\uB3C4 \uBE48 \uAC1D\uCCB4 \uC124\uC815\uD558\uC5EC \uC2DC\uC2A4\uD15C\uC774 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D\r\n this.log('error', 'Failed to load messages, using empty fallback for:', language, error);\r\n const emptyMessages = {};\r\n this.messages.set(language, emptyMessages);\r\n return emptyMessages;\r\n }\r\n }\r\n\r\n /**\r\n * \uD30C\uC77C\uC5D0\uC11C \uBA54\uC2DC\uC9C0 \uB85C\uB4DC (\uCE90\uC2F1 \uC9C0\uC6D0)\r\n */\r\n async _loadMessagesFromFile(language) {\r\n // \uCE90\uC2DC\uC5D0\uC11C \uBA3C\uC800 \uC2DC\uB3C4\r\n const cacheKey = `i18n_${language}`;\r\n const cachedData = this.router.cacheManager?.get(cacheKey);\r\n if (cachedData) {\r\n this.log('debug', 'Messages loaded from cache:', language);\r\n return cachedData;\r\n }\r\n\r\n try {\r\n // JSON \uD30C\uC77C\uB85C \uBCC0\uACBD - config\uC758 i18nPath \uC0AC\uC6A9\r\n const i18nPath = `${this.router.config.i18nPath}/${language}.json`;\r\n const response = await fetch(i18nPath);\r\n if (!response.ok) {\r\n throw new Error(`HTTP error! status: ${response.status}`);\r\n }\r\n const messages = await response.json();\r\n\r\n // \uCE90\uC2DC\uC5D0 \uC800\uC7A5\r\n this.router.cacheManager?.set(cacheKey, messages);\r\n\r\n return messages;\r\n } catch (error) {\r\n this.log('error', 'Failed to load messages file for:', language, error);\r\n\r\n // \uD3F4\uBC31 \uC5B8\uC5B4 \uC2DC\uB3C4\r\n if (language !== this.config.fallbackLanguage) {\r\n this.log('info', 'Trying fallback language:', this.config.fallbackLanguage);\r\n try {\r\n return await this._loadMessagesFromFile(this.config.fallbackLanguage);\r\n } catch (fallbackError) {\r\n this.log('error', 'Fallback language also failed:', fallbackError);\r\n // \uD3F4\uBC31\uB3C4 \uC2E4\uD328\uD558\uBA74 \uBE48 \uAC1D\uCCB4 \uBC18\uD658\uD558\uC5EC \uC2DC\uC2A4\uD15C\uC774 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D\r\n return {};\r\n }\r\n }\r\n\r\n // \uB9C8\uC9C0\uB9C9 \uD3F4\uBC31: \uBE48 \uAC1D\uCCB4 \uBC18\uD658\r\n this.log('warn', `No messages available for language: ${language}, using empty fallback`);\r\n return {};\r\n }\r\n }\r\n \r\n\r\n /**\r\n * \uBA54\uC2DC\uC9C0 \uBC88\uC5ED\r\n */\r\n t(key, params = {}) {\r\n // i18n\uC774 \uBE44\uD65C\uC131\uD654\uB41C \uACBD\uC6B0 \uD0A4 \uC790\uCCB4\uB97C \uBC18\uD658\r\n if (!this.config.enabled) {\r\n return key;\r\n }\r\n \r\n const messages = this.messages.get(this.currentLanguage);\r\n if (!messages) {\r\n this.log('warn', 'No messages loaded for current language:', this.currentLanguage);\r\n return key;\r\n }\r\n\r\n const message = this.getNestedValue(messages, key);\r\n if (message === undefined) {\r\n this.log('warn', 'Translation not found for key:', key);\r\n \r\n // \uD3F4\uBC31 \uC5B8\uC5B4\uC5D0\uC11C \uCC3E\uAE30\r\n const fallbackMessages = this.messages.get(this.config.fallbackLanguage);\r\n if (fallbackMessages && this.currentLanguage !== this.config.fallbackLanguage) {\r\n const fallbackMessage = this.getNestedValue(fallbackMessages, key);\r\n if (fallbackMessage !== undefined) {\r\n return this.interpolate(fallbackMessage, params);\r\n }\r\n }\r\n \r\n return key;\r\n }\r\n\r\n return this.interpolate(message, params);\r\n }\r\n\r\n /**\r\n * \uC911\uCCA9\uB41C \uAC1D\uCCB4\uC5D0\uC11C \uAC12 \uAC00\uC838\uC624\uAE30\r\n */\r\n getNestedValue(obj, path) {\r\n return path.split('.').reduce((current, key) => {\r\n return current && current[key] !== undefined ? current[key] : undefined;\r\n }, obj);\r\n }\r\n\r\n /**\r\n * \uBB38\uC790\uC5F4 \uBCF4\uAC04 \uCC98\uB9AC\r\n */\r\n interpolate(message, params) {\r\n if (typeof message !== 'string') {\r\n return message;\r\n }\r\n\r\n return message.replace(/\\{(\\w+)\\}/g, (match, key) => {\r\n return params.hasOwnProperty(key) ? params[key] : match;\r\n });\r\n }\r\n\r\n /**\r\n * \uBCF5\uC218\uD615 \uCC98\uB9AC\r\n */\r\n plural(key, count, params = {}) {\r\n const pluralKey = count === 1 ? `${key}.singular` : `${key}.plural`;\r\n return this.t(pluralKey, { ...params, count });\r\n }\r\n\r\n\r\n /**\r\n * \uC5B8\uC5B4 \uBCC0\uACBD \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uB4F1\uB85D\r\n */\r\n on(event, callback) {\r\n if (this.listeners[event]) {\r\n this.listeners[event].push(callback);\r\n }\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4 \uBCC0\uACBD \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uC81C\uAC70\r\n */\r\n off(event, callback) {\r\n if (this.listeners[event]) {\r\n const index = this.listeners[event].indexOf(callback);\r\n if (index > -1) {\r\n this.listeners[event].splice(index, 1);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n */\r\n emit(event, data) {\r\n if (this.listeners[event]) {\r\n this.listeners[event].forEach(callback => {\r\n try {\r\n callback(data);\r\n } catch (error) {\r\n this.log('error', 'Error in event listener:', error);\r\n }\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * \uD604\uC7AC \uC5B8\uC5B4\uC758 \uBAA8\uB4E0 \uBA54\uC2DC\uC9C0 \uBC18\uD658\r\n */\r\n getMessages() {\r\n return this.messages.get(this.currentLanguage) || {};\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4\uBCC4 \uB0A0\uC9DC \uD3EC\uB9F7\uD305\r\n */\r\n formatDate(date, options = {}) {\r\n const locale = this.currentLanguage === 'ko' ? 'ko-KR' : 'en-US';\r\n return new Intl.DateTimeFormat(locale, options).format(new Date(date));\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4\uBCC4 \uC22B\uC790 \uD3EC\uB9F7\uD305\r\n */\r\n formatNumber(number, options = {}) {\r\n const locale = this.currentLanguage === 'ko' ? 'ko-KR' : 'en-US';\r\n return new Intl.NumberFormat(locale, options).format(number);\r\n }\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'I18nManager', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * i18n \uD65C\uC131\uD654 \uC5EC\uBD80 \uD655\uC778\r\n */\r\n isEnabled() {\r\n return this.config.enabled;\r\n }\r\n \r\n /**\r\n * \uCD08\uAE30 \uB85C\uB529\uC774 \uC644\uB8CC\uB418\uC5C8\uB294\uC9C0 \uD655\uC778\r\n */\r\n async isReady() {\r\n if (!this.config.enabled) {\r\n return true;\r\n }\r\n \r\n try {\r\n await this.initPromise;\r\n return true;\r\n } catch (error) {\r\n this.log('error', 'I18n initialization failed:', error);\r\n // \uC2E4\uD328\uD574\uB3C4 \uB77C\uC6B0\uD130\uAC00 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D true \uBC18\uD658\r\n this.log('info', 'I18n system ready with fallback behavior');\r\n return true;\r\n }\r\n }\r\n \r\n /**\r\n * \uCE90\uC2DC \uCD08\uAE30\uD654\r\n */\r\n clearCache() {\r\n try {\r\n const clearedCount = this.router.cacheManager?.deleteByPattern('i18n_');\r\n this.log('debug', 'Cache cleared, removed', clearedCount, 'items');\r\n } catch (error) {\r\n this.log('warn', 'Failed to clear cache:', error);\r\n }\r\n }\r\n \r\n /**\r\n * \uC2DC\uC2A4\uD15C \uCD08\uAE30\uD654 (\uD604\uC7AC \uC5B8\uC5B4\uC758 \uBA54\uC2DC\uC9C0 \uB85C\uB4DC)\r\n */\r\n async initialize() {\r\n if (!this.config.enabled) {\r\n this.log('info', 'I18n system is disabled, skipping initialization');\r\n return true;\r\n }\r\n \r\n try {\r\n // \uCD08\uAE30 \uC124\uC815\uC774 \uC644\uB8CC\uB420 \uB54C\uAE4C\uC9C0 \uB300\uAE30\r\n await this.initPromise;\r\n this.log('info', 'I18n system fully initialized');\r\n return true;\r\n } catch (error) {\r\n this.log('error', 'Failed to initialize I18n system:', error);\r\n // \uC2E4\uD328\uD574\uB3C4 \uC2DC\uC2A4\uD15C\uC740 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D true \uBC18\uD658\r\n this.log('info', 'I18n system will continue with fallback behavior');\r\n return true;\r\n }\r\n }\r\n}", "/**\r\n * ViewLogic Authentication Management System\r\n * \uC778\uC99D \uAD00\uB9AC \uC2DC\uC2A4\uD15C\r\n */\r\nexport class AuthManager {\r\n constructor(router, options = {}) {\r\n this.config = {\r\n enabled: options.authEnabled || false,\r\n loginRoute: options.loginRoute || 'login',\r\n protectedRoutes: options.protectedRoutes || [],\r\n protectedPrefixes: options.protectedPrefixes || [],\r\n publicRoutes: options.publicRoutes || ['login', 'register', 'home'],\r\n checkAuthFunction: options.checkAuthFunction || null,\r\n redirectAfterLogin: options.redirectAfterLogin || 'home',\r\n authCookieName: options.authCookieName || 'authToken',\r\n authStorage: options.authStorage || 'localStorage'\r\n };\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870 (\uD544\uC218 \uC758\uC874\uC131)\r\n this.router = router;\r\n \r\n // \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108\uB4E4\r\n this.eventListeners = new Map();\r\n \r\n this.log('info', 'AuthManager initialized', { enabled: this.config.enabled });\r\n }\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'AuthManager', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * \uB77C\uC6B0\uD2B8 \uC778\uC99D \uD655\uC778\r\n */\r\n async checkAuthentication(routeName) {\r\n // \uC778\uC99D \uC2DC\uC2A4\uD15C\uC774 \uBE44\uD65C\uC131\uD654\uB41C \uACBD\uC6B0\r\n if (!this.config.enabled) {\r\n return { allowed: true, reason: 'auth_disabled' };\r\n }\r\n\r\n this.log('debug', `\uD83D\uDD10 Checking authentication for route: ${routeName}`);\r\n\r\n // \uACF5\uAC1C \uB77C\uC6B0\uD2B8\uC778\uC9C0 \uD655\uC778\r\n if (this.isPublicRoute(routeName)) {\r\n return { allowed: true, reason: 'public_route' };\r\n }\r\n\r\n // \uBCF4\uD638\uB41C \uB77C\uC6B0\uD2B8\uC778\uC9C0 \uD655\uC778\r\n const isProtected = this.isProtectedRoute(routeName);\r\n if (!isProtected) {\r\n return { allowed: true, reason: 'not_protected' };\r\n }\r\n\r\n // \uC0AC\uC6A9\uC790 \uC815\uC758 \uC778\uC99D \uCCB4\uD06C \uD568\uC218\uAC00 \uC788\uB294 \uACBD\uC6B0\r\n if (typeof this.config.checkAuthFunction === 'function') {\r\n try {\r\n // \uAC00\uBCBC\uC6B4 route \uAC1D\uCCB4 \uC0DD\uC131 (\uCEF4\uD3EC\uB10C\uD2B8\uC640 \uB3D9\uC77C\uD55C API \uACBD\uD5D8 \uC81C\uACF5)\r\n const route = {\r\n name: routeName,\r\n $api: this.router.routeLoader.apiHandler.bindToComponent({}),\r\n $state: this.router.stateHandler\r\n };\r\n\r\n const isAuthenticated = await this.config.checkAuthFunction(route);\r\n return {\r\n allowed: isAuthenticated, \r\n reason: isAuthenticated ? 'custom_auth_success' : 'custom_auth_failed',\r\n routeName\r\n };\r\n } catch (error) {\r\n this.log('error', 'Custom auth function failed:', error);\r\n return { allowed: false, reason: 'custom_auth_error', error };\r\n }\r\n }\r\n\r\n // \uAE30\uBCF8 \uC778\uC99D \uD655\uC778\r\n const isAuthenticated = this.isAuthenticated();\r\n return {\r\n allowed: isAuthenticated, \r\n reason: isAuthenticated ? 'authenticated' : 'not_authenticated',\r\n routeName\r\n };\r\n }\r\n\r\n /**\r\n * JWT \uD1A0\uD070 \uAC80\uC99D\r\n */\r\n isTokenValid(token) {\r\n if (!token) return false;\r\n\r\n try {\r\n if (token.includes('.')) {\r\n const payload = JSON.parse(atob(token.split('.')[1]));\r\n if (payload.exp && Date.now() >= payload.exp * 1000) {\r\n return false; // \uB9CC\uB8CC\uB428\r\n }\r\n }\r\n return true;\r\n } catch (error) {\r\n this.log('warn', 'Token validation failed:', error);\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * \uC0AC\uC6A9\uC790 \uC778\uC99D \uC0C1\uD0DC \uD655\uC778\r\n */\r\n isAuthenticated() {\r\n this.log('debug', '\uD83D\uDD0D Checking user authentication status');\r\n\r\n const token = this.getAccessToken();\r\n if (!token) {\r\n this.log('debug', '\u274C No token found');\r\n return false;\r\n }\r\n\r\n if (!this.isTokenValid(token)) {\r\n this.log('debug', 'Token expired, removing...');\r\n this.removeAccessToken();\r\n return false;\r\n }\r\n\r\n this.log('debug', '\u2705 Valid token found');\r\n return true;\r\n }\r\n\r\n /**\r\n * \uACF5\uAC1C \uB77C\uC6B0\uD2B8\uC778\uC9C0 \uD655\uC778\r\n */\r\n isPublicRoute(routeName) {\r\n return this.config.publicRoutes.includes(routeName);\r\n }\r\n\r\n /**\r\n * \uBCF4\uD638\uB41C \uB77C\uC6B0\uD2B8\uC778\uC9C0 \uD655\uC778\r\n */\r\n isProtectedRoute(routeName) {\r\n // \uD2B9\uC815 \uB77C\uC6B0\uD2B8\uAC00 \uBCF4\uD638\uB41C \uB77C\uC6B0\uD2B8 \uBAA9\uB85D\uC5D0 \uC788\uB294\uC9C0 \uD655\uC778\r\n if (this.config.protectedRoutes.includes(routeName)) {\r\n return true;\r\n }\r\n\r\n // prefix\uB85C \uBCF4\uD638\uB41C \uB77C\uC6B0\uD2B8\uC778\uC9C0 \uD655\uC778\r\n for (const prefix of this.config.protectedPrefixes) {\r\n if (routeName.startsWith(prefix)) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * \uC778\uC99D \uCFE0\uD0A4 \uAC00\uC838\uC624\uAE30\r\n */\r\n getAuthCookie() {\r\n return this.getCookieValue(this.config.authCookieName);\r\n }\r\n\r\n /**\r\n * \uCFE0\uD0A4 \uAC12 \uAC00\uC838\uC624\uAE30\r\n */\r\n getCookieValue(name) {\r\n const value = `; ${document.cookie}`;\r\n const parts = value.split(`; ${name}=`);\r\n if (parts.length === 2) {\r\n return decodeURIComponent(parts.pop().split(';').shift());\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * \uC778\uC99D \uCFE0\uD0A4 \uC81C\uAC70\r\n */\r\n removeAuthCookie() {\r\n document.cookie = `${this.config.authCookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;\r\n this.log('debug', 'Auth cookie removed');\r\n }\r\n\r\n /**\r\n * \uC561\uC138\uC2A4 \uD1A0\uD070 \uAC00\uC838\uC624\uAE30\r\n */\r\n getAccessToken() {\r\n // localStorage \uC6B0\uC120 \uD655\uC778\r\n let token = localStorage.getItem('authToken');\r\n if (token) return token;\r\n\r\n // sessionStorage \uD655\uC778\r\n token = sessionStorage.getItem('authToken');\r\n if (token) return token;\r\n\r\n // \uCFE0\uD0A4 \uD655\uC778\r\n return this.getAuthCookie();\r\n }\r\n\r\n /**\r\n * \uC561\uC138\uC2A4 \uD1A0\uD070 \uC124\uC815\r\n */\r\n setAccessToken(token, options = {}) {\r\n if (!token) {\r\n this.log('warn', 'Empty token provided');\r\n return false;\r\n }\r\n\r\n const {\r\n storage = this.config.authStorage,\r\n cookieOptions = this.config.authCookieOptions\r\n } = options;\r\n\r\n try {\r\n // \uD1A0\uD070 \uAC80\uC99D\r\n if (!this.isTokenValid(token)) {\r\n this.log('warn', '\u274C Token is expired or invalid');\r\n return false;\r\n }\r\n\r\n // \uC2A4\uD1A0\uB9AC\uC9C0\uBCC4 \uC800\uC7A5\r\n switch (storage) {\r\n case 'localStorage':\r\n localStorage.setItem('authToken', token);\r\n this.log('debug', 'Token saved to localStorage');\r\n break;\r\n\r\n case 'sessionStorage':\r\n sessionStorage.setItem('authToken', token);\r\n this.log('debug', 'Token saved to sessionStorage');\r\n break;\r\n\r\n case 'cookie':\r\n this.setAuthCookie(token);\r\n break;\r\n\r\n default:\r\n localStorage.setItem('authToken', token);\r\n this.log('debug', 'Token saved to localStorage (default)');\r\n }\r\n\r\n this.emitAuthEvent('token_set', { \r\n storage,\r\n tokenLength: token.length,\r\n hasExpiration: token.includes('.')\r\n });\r\n\r\n return true;\r\n\r\n } catch (error) {\r\n this.log('error', 'Failed to set token:', error);\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * \uC778\uC99D \uCFE0\uD0A4 \uC124\uC815\r\n */\r\n setAuthCookie(token) {\r\n const secure = window.location.protocol === 'https:';\r\n let cookieString = `${this.config.authCookieName}=${encodeURIComponent(token)}; path=/; SameSite=Strict`;\r\n\r\n if (secure) {\r\n cookieString += '; Secure';\r\n }\r\n\r\n // JWT\uC5D0\uC11C \uB9CC\uB8CC \uC2DC\uAC04 \uCD94\uCD9C\r\n if (token.includes('.')) {\r\n try {\r\n const payload = JSON.parse(atob(token.split('.')[1]));\r\n if (payload.exp) {\r\n const expireDate = new Date(payload.exp * 1000);\r\n cookieString += `; Expires=${expireDate.toUTCString()}`;\r\n }\r\n } catch (error) {\r\n this.log('warn', 'Could not extract expiration from JWT token');\r\n }\r\n }\r\n\r\n document.cookie = cookieString;\r\n this.log('debug', 'Auth cookie set');\r\n }\r\n\r\n /**\r\n * \uD1A0\uD070 \uC81C\uAC70\r\n */\r\n removeAccessToken(storage = 'all') {\r\n switch (storage) {\r\n case 'localStorage':\r\n localStorage.removeItem('authToken');\r\n localStorage.removeItem('accessToken');\r\n break;\r\n\r\n case 'sessionStorage':\r\n sessionStorage.removeItem('authToken');\r\n sessionStorage.removeItem('accessToken');\r\n break;\r\n\r\n case 'cookie':\r\n this.removeAuthCookie();\r\n break;\r\n\r\n case 'all':\r\n default:\r\n localStorage.removeItem('authToken');\r\n sessionStorage.removeItem('authToken');\r\n this.removeAuthCookie();\r\n break;\r\n }\r\n\r\n this.emitAuthEvent('token_removed', { storage });\r\n this.log('debug', `Token removed from: ${storage}`);\r\n }\r\n\r\n /**\r\n * \uB85C\uADF8\uC778 \uC131\uACF5 \uCC98\uB9AC\r\n */\r\n loginSuccess(targetRoute = null) {\r\n const redirectRoute = targetRoute || this.config.redirectAfterLogin;\r\n \r\n this.log('info', `\uD83C\uDF89 Login success, redirecting to: ${redirectRoute}`);\r\n \r\n this.emitAuthEvent('login_success', { targetRoute: redirectRoute });\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4\uAC00 \uC788\uC73C\uBA74 \uC9C1\uC811 \uB124\uBE44\uAC8C\uC774\uC158\r\n if (this.router && typeof this.router.navigateTo === 'function') {\r\n this.router.navigateTo(redirectRoute);\r\n }\r\n \r\n return redirectRoute;\r\n }\r\n\r\n /**\r\n * \uB85C\uADF8\uC544\uC6C3 \uCC98\uB9AC\r\n */\r\n logout() {\r\n this.log('info', '\uD83D\uDC4B Logging out user');\r\n \r\n // \uBAA8\uB4E0 \uC800\uC7A5\uC18C\uC5D0\uC11C \uD1A0\uD070 \uC81C\uAC70\r\n this.removeAccessToken();\r\n \r\n \r\n this.emitAuthEvent('logout', {});\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4\uAC00 \uC788\uC73C\uBA74 \uC9C1\uC811 \uB124\uBE44\uAC8C\uC774\uC158\r\n if (this.router && typeof this.router.navigateTo === 'function') {\r\n this.router.navigateTo(this.config.loginRoute);\r\n }\r\n \r\n return this.config.loginRoute;\r\n }\r\n\r\n /**\r\n * \uC778\uC99D \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n */\r\n emitAuthEvent(eventType, data) {\r\n const event = new CustomEvent('router:auth', {\r\n detail: {\r\n type: eventType,\r\n timestamp: Date.now(),\r\n ...data\r\n }\r\n });\r\n \r\n document.dispatchEvent(event);\r\n \r\n // \uB0B4\uBD80 \uB9AC\uC2A4\uB108\uB4E4\uC5D0\uAC8C\uB3C4 \uC54C\uB9BC\r\n if (this.eventListeners.has(eventType)) {\r\n this.eventListeners.get(eventType).forEach(listener => {\r\n try {\r\n listener(data);\r\n } catch (error) {\r\n this.log('error', 'Event listener error:', error);\r\n }\r\n });\r\n }\r\n \r\n this.log('debug', `\uD83D\uDD14 Auth event emitted: ${eventType}`, data);\r\n }\r\n\r\n /**\r\n * \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uB4F1\uB85D\r\n */\r\n on(eventType, listener) {\r\n if (!this.eventListeners.has(eventType)) {\r\n this.eventListeners.set(eventType, []);\r\n }\r\n this.eventListeners.get(eventType).push(listener);\r\n }\r\n\r\n /**\r\n * \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uC81C\uAC70\r\n */\r\n off(eventType, listener) {\r\n if (this.eventListeners.has(eventType)) {\r\n const listeners = this.eventListeners.get(eventType);\r\n const index = listeners.indexOf(listener);\r\n if (index > -1) {\r\n listeners.splice(index, 1);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * \uC778\uC99D \uC0C1\uD0DC \uD1B5\uACC4\r\n */\r\n getAuthStats() {\r\n return {\r\n enabled: this.config.enabled,\r\n isAuthenticated: this.isAuthenticated(),\r\n hasToken: !!this.getAccessToken(),\r\n protectedRoutesCount: this.config.protectedRoutes.length,\r\n protectedPrefixesCount: this.config.protectedPrefixes.length,\r\n publicRoutesCount: this.config.publicRoutes.length,\r\n storage: this.config.authStorage,\r\n loginRoute: this.config.loginRoute\r\n };\r\n }\r\n\r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n this.eventListeners.clear();\r\n this.log('debug', 'AuthManager destroyed');\r\n }\r\n}", "/**\r\n * ViewLogic Cache Management System\r\n * \uCE90\uC2DC \uAD00\uB9AC \uC2DC\uC2A4\uD15C\r\n */\r\nexport class CacheManager {\r\n constructor(router, options = {}) {\r\n this.config = {\r\n cacheMode: options.cacheMode || 'memory', // 'memory' \uB610\uB294 'lru'\r\n cacheTTL: options.cacheTTL || 300000, // 5\uBD84 (\uBC00\uB9AC\uCD08)\r\n maxCacheSize: options.maxCacheSize || 50 // LRU \uCE90\uC2DC \uCD5C\uB300 \uD06C\uAE30\r\n };\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870 (\uD544\uC694\uC2DC \uB77C\uC6B0\uD130 \uC0C1\uD0DC \uD655\uC778\uC6A9)\r\n this.router = router;\r\n \r\n // \uCE90\uC2DC \uC800\uC7A5\uC18C\uB4E4\r\n this.cache = new Map();\r\n this.cacheTimestamps = new Map();\r\n this.lruOrder = []; // LRU \uC21C\uC11C \uCD94\uC801\r\n \r\n this.log('info', 'CacheManager initialized with config:', this.config);\r\n }\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'CacheManager', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * \uCE90\uC2DC\uC5D0 \uAC12 \uC800\uC7A5\r\n */\r\n set(key, value) {\r\n const now = Date.now();\r\n \r\n if (this.config.cacheMode === 'lru') {\r\n // LRU \uCE90\uC2DC \uAD00\uB9AC\r\n if (this.cache.size >= this.config.maxCacheSize && !this.cache.has(key)) {\r\n const oldestKey = this.lruOrder.shift();\r\n if (oldestKey) {\r\n this.cache.delete(oldestKey);\r\n this.cacheTimestamps.delete(oldestKey);\r\n this.log('debug', `\uD83D\uDDD1\uFE0F LRU evicted cache key: ${oldestKey}`);\r\n }\r\n }\r\n \r\n // \uAE30\uC874 \uD0A4\uAC00 \uC788\uC73C\uBA74 LRU \uC21C\uC11C\uC5D0\uC11C \uC81C\uAC70\r\n const existingIndex = this.lruOrder.indexOf(key);\r\n if (existingIndex > -1) {\r\n this.lruOrder.splice(existingIndex, 1);\r\n }\r\n \r\n // \uCD5C\uC2E0 \uC21C\uC11C\uB85C \uCD94\uAC00\r\n this.lruOrder.push(key);\r\n }\r\n \r\n this.cache.set(key, value);\r\n this.cacheTimestamps.set(key, now);\r\n \r\n this.log('debug', `\uD83D\uDCBE Cached: ${key} (size: ${this.cache.size})`);\r\n }\r\n \r\n /**\r\n * \uCE90\uC2DC\uC5D0\uC11C \uAC12 \uAC00\uC838\uC624\uAE30\r\n */\r\n get(key) {\r\n const now = Date.now();\r\n const timestamp = this.cacheTimestamps.get(key);\r\n \r\n // TTL \uCCB4\uD06C\r\n if (timestamp && (now - timestamp) > this.config.cacheTTL) {\r\n this.cache.delete(key);\r\n this.cacheTimestamps.delete(key);\r\n \r\n if (this.config.cacheMode === 'lru') {\r\n const index = this.lruOrder.indexOf(key);\r\n if (index > -1) {\r\n this.lruOrder.splice(index, 1);\r\n }\r\n }\r\n \r\n this.log('debug', `\u23F0 Cache expired and removed: ${key}`);\r\n return null;\r\n }\r\n \r\n const value = this.cache.get(key);\r\n \r\n if (value && this.config.cacheMode === 'lru') {\r\n // LRU \uC21C\uC11C \uC5C5\uB370\uC774\uD2B8\r\n const index = this.lruOrder.indexOf(key);\r\n if (index > -1) {\r\n this.lruOrder.splice(index, 1);\r\n this.lruOrder.push(key);\r\n }\r\n }\r\n \r\n if (value) {\r\n this.log('debug', `\uD83C\uDFAF Cache hit: ${key}`);\r\n } else {\r\n this.log('debug', `\u274C Cache miss: ${key}`);\r\n }\r\n \r\n return value;\r\n }\r\n \r\n /**\r\n * \uCE90\uC2DC\uC5D0 \uD0A4\uAC00 \uC788\uB294\uC9C0 \uD655\uC778\r\n */\r\n has(key) {\r\n return this.cache.has(key) && this.get(key) !== null;\r\n }\r\n \r\n /**\r\n * \uD2B9\uC815 \uD0A4 \uD328\uD134\uC758 \uCE90\uC2DC \uC0AD\uC81C\r\n */\r\n deleteByPattern(pattern) {\r\n const keysToDelete = [];\r\n \r\n for (const key of this.cache.keys()) {\r\n if (key.includes(pattern) || key.startsWith(pattern)) {\r\n keysToDelete.push(key);\r\n }\r\n }\r\n \r\n keysToDelete.forEach(key => {\r\n this.cache.delete(key);\r\n this.cacheTimestamps.delete(key);\r\n \r\n if (this.config.cacheMode === 'lru') {\r\n const index = this.lruOrder.indexOf(key);\r\n if (index > -1) {\r\n this.lruOrder.splice(index, 1);\r\n }\r\n }\r\n });\r\n \r\n this.log('debug', `\uD83E\uDDF9 Deleted ${keysToDelete.length} cache entries matching: ${pattern}`);\r\n return keysToDelete.length;\r\n }\r\n \r\n /**\r\n * \uD2B9\uC815 \uCEF4\uD3EC\uB10C\uD2B8 \uCE90\uC2DC \uC0AD\uC81C\r\n */\r\n deleteComponent(routeName) {\r\n const patterns = [\r\n `component_${routeName}`,\r\n `script_${routeName}`,\r\n `template_${routeName}`,\r\n `style_${routeName}`,\r\n `layout_${routeName}`\r\n ];\r\n \r\n let totalInvalidated = 0;\r\n patterns.forEach(pattern => {\r\n totalInvalidated += this.deleteByPattern(pattern);\r\n });\r\n \r\n this.log('debug', `\uD83D\uDD04 Deleted component cache for route: ${routeName} (${totalInvalidated} entries)`);\r\n return totalInvalidated;\r\n }\r\n \r\n /**\r\n * \uBAA8\uB4E0 \uCEF4\uD3EC\uB10C\uD2B8 \uCE90\uC2DC \uC0AD\uC81C\r\n */\r\n deleteAllComponents() {\r\n const componentPatterns = ['component_', 'script_', 'template_', 'style_', 'layout_'];\r\n let totalCleared = 0;\r\n \r\n componentPatterns.forEach(pattern => {\r\n totalCleared += this.deleteByPattern(pattern);\r\n });\r\n \r\n this.log('debug', `\uD83E\uDDFD Deleted all component caches (${totalCleared} entries)`);\r\n return totalCleared;\r\n }\r\n \r\n /**\r\n * \uC804\uCCB4 \uCE90\uC2DC \uC0AD\uC81C\r\n */\r\n clearAll() {\r\n const size = this.cache.size;\r\n this.cache.clear();\r\n this.cacheTimestamps.clear();\r\n this.lruOrder = [];\r\n \r\n this.log('debug', `\uD83D\uDD25 Cleared all cache (${size} entries)`);\r\n return size;\r\n }\r\n \r\n /**\r\n * \uB9CC\uB8CC\uB41C \uCE90\uC2DC \uD56D\uBAA9\uB4E4 \uC815\uB9AC\r\n */\r\n cleanExpired() {\r\n const now = Date.now();\r\n const expiredKeys = [];\r\n \r\n for (const [key, timestamp] of this.cacheTimestamps.entries()) {\r\n if ((now - timestamp) > this.config.cacheTTL) {\r\n expiredKeys.push(key);\r\n }\r\n }\r\n \r\n expiredKeys.forEach(key => {\r\n this.cache.delete(key);\r\n this.cacheTimestamps.delete(key);\r\n \r\n if (this.config.cacheMode === 'lru') {\r\n const index = this.lruOrder.indexOf(key);\r\n if (index > -1) {\r\n this.lruOrder.splice(index, 1);\r\n }\r\n }\r\n });\r\n \r\n if (expiredKeys.length > 0) {\r\n this.log('debug', `\u23F1\uFE0F Cleaned ${expiredKeys.length} expired cache entries`);\r\n }\r\n \r\n return expiredKeys.length;\r\n }\r\n \r\n /**\r\n * \uCE90\uC2DC \uD1B5\uACC4 \uC815\uBCF4\r\n */\r\n getStats() {\r\n return {\r\n size: this.cache.size,\r\n maxSize: this.config.maxCacheSize,\r\n mode: this.config.cacheMode,\r\n ttl: this.config.cacheTTL,\r\n memoryUsage: this.getMemoryUsage(),\r\n hitRatio: this.getHitRate(),\r\n categories: this.getStatsByCategory()\r\n };\r\n }\r\n \r\n /**\r\n * \uBA54\uBAA8\uB9AC \uC0AC\uC6A9\uB7C9 \uCD94\uC815\r\n */\r\n getMemoryUsage() {\r\n let estimatedBytes = 0;\r\n \r\n for (const [key, value] of this.cache.entries()) {\r\n // \uD0A4 \uD06C\uAE30\r\n estimatedBytes += key.length * 2; // UTF-16\r\n \r\n // \uAC12 \uD06C\uAE30 \uCD94\uC815\r\n if (typeof value === 'string') {\r\n estimatedBytes += value.length * 2;\r\n } else if (typeof value === 'object' && value !== null) {\r\n estimatedBytes += JSON.stringify(value).length * 2;\r\n } else {\r\n estimatedBytes += 8; // \uB300\uB7B5\uC801\uC778 \uD06C\uAE30\r\n }\r\n }\r\n \r\n return {\r\n bytes: estimatedBytes,\r\n kb: Math.round(estimatedBytes / 1024 * 100) / 100,\r\n mb: Math.round(estimatedBytes / (1024 * 1024) * 100) / 100\r\n };\r\n }\r\n \r\n /**\r\n * \uD788\uD2B8 \uBE44\uC728 \uACC4\uC0B0 (\uAC04\uB2E8\uD55C \uCD94\uC815)\r\n */\r\n getHitRate() {\r\n // \uC2E4\uC81C \uD788\uD2B8/\uBBF8\uC2A4 \uCD94\uC801\uC744 \uC704\uD574\uC11C\uB294 \uBCC4\uB3C4\uC758 \uCE74\uC6B4\uD130\uAC00 \uD544\uC694\r\n // \uD604\uC7AC\uB294 \uCE90\uC2DC \uD06C\uAE30 \uAE30\uBC18 \uCD94\uC815\uCE58 \uBC18\uD658\r\n const ratio = this.cache.size > 0 ? Math.min(this.cache.size / this.config.maxCacheSize, 1) : 0;\r\n return Math.round(ratio * 100);\r\n }\r\n \r\n /**\r\n * \uCE74\uD14C\uACE0\uB9AC\uBCC4 \uCE90\uC2DC \uD1B5\uACC4\r\n */\r\n getStatsByCategory() {\r\n const categories = {\r\n components: 0,\r\n scripts: 0,\r\n templates: 0,\r\n styles: 0,\r\n layouts: 0,\r\n others: 0\r\n };\r\n \r\n for (const key of this.cache.keys()) {\r\n if (key.startsWith('component_')) categories.components++;\r\n else if (key.startsWith('script_')) categories.scripts++;\r\n else if (key.startsWith('template_')) categories.templates++;\r\n else if (key.startsWith('style_')) categories.styles++;\r\n else if (key.startsWith('layout_')) categories.layouts++;\r\n else categories.others++;\r\n }\r\n \r\n return categories;\r\n }\r\n \r\n /**\r\n * \uCE90\uC2DC \uD0A4 \uBAA9\uB85D \uBC18\uD658\r\n */\r\n getKeys() {\r\n return Array.from(this.cache.keys());\r\n }\r\n \r\n /**\r\n * \uD2B9\uC815 \uD328\uD134\uC758 \uCE90\uC2DC \uD0A4\uB4E4 \uBC18\uD658\r\n */\r\n getKeysByPattern(pattern) {\r\n return this.getKeys().filter(key => \r\n key.includes(pattern) || key.startsWith(pattern)\r\n );\r\n }\r\n \r\n /**\r\n * \uC790\uB3D9 \uC815\uB9AC \uC2DC\uC791 (\uBC31\uADF8\uB77C\uC6B4\uB4DC\uC5D0\uC11C \uB9CC\uB8CC\uB41C \uCE90\uC2DC \uC815\uB9AC)\r\n */\r\n startAutoCleanup(interval = 60000) { // \uAE30\uBCF8 1\uBD84 \uAC04\uACA9\r\n if (this.cleanupInterval) {\r\n clearInterval(this.cleanupInterval);\r\n }\r\n \r\n this.cleanupInterval = setInterval(() => {\r\n this.cleanExpired();\r\n }, interval);\r\n \r\n this.log('debug', `\uD83E\uDD16 Auto cleanup started (interval: ${interval}ms)`);\r\n }\r\n \r\n /**\r\n * \uC790\uB3D9 \uC815\uB9AC \uC911\uC9C0\r\n */\r\n stopAutoCleanup() {\r\n if (this.cleanupInterval) {\r\n clearInterval(this.cleanupInterval);\r\n this.cleanupInterval = null;\r\n this.log('debug', '\uD83D\uDED1 Auto cleanup stopped');\r\n }\r\n }\r\n \r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n this.stopAutoCleanup();\r\n this.clearAll();\r\n this.log('debug', 'CacheManager destroyed');\r\n }\r\n}", "/**\r\n * ViewLogic Query Management System\r\n * URL \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uAD00\uB9AC \uC2DC\uC2A4\uD15C\r\n */\r\nexport class QueryManager {\r\n constructor(router) {\r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870\r\n this.router = router;\r\n\r\n // \uD604\uC7AC \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uC0C1\uD0DC\r\n this.currentQueryParams = {};\r\n\r\n // \uD604\uC7AC \uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130 \uC0C1\uD0DC (navigateTo\uB85C \uC804\uB2EC\uB41C params)\r\n this.currentRouteParams = {};\r\n\r\n this.log('debug', 'QueryManager initialized');\r\n }\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'QueryManager', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC\uC2A4\uD2B8\uB9C1 \uD30C\uC2F1\r\n */\r\n parseQueryString(queryString) {\r\n const params = {};\r\n if (!queryString) return params;\r\n\r\n const pairs = queryString.split('&');\r\n for (const pair of pairs) {\r\n const [rawKey, rawValue] = pair.split('=');\r\n if (!rawKey) continue;\r\n\r\n try {\r\n const key = decodeURIComponent(rawKey);\r\n const value = rawValue ? decodeURIComponent(rawValue) : '';\r\n\r\n // \uBC30\uC5F4 \uD615\uD0DC\uC758 \uD30C\uB77C\uBBF8\uD130 \uCC98\uB9AC (\uC608: tags[]=a&tags[]=b)\r\n if (key.endsWith('[]')) {\r\n const arrayKey = key.slice(0, -2);\r\n if (!params[arrayKey]) params[arrayKey] = [];\r\n params[arrayKey].push(value);\r\n } else {\r\n params[key] = value;\r\n }\r\n } catch (error) {\r\n this.log('warn', 'Failed to decode query parameter:', pair);\r\n }\r\n }\r\n\r\n return params;\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC\uC2A4\uD2B8\uB9C1 \uC0DD\uC131\r\n */\r\n buildQueryString(params) {\r\n if (!params || Object.keys(params).length === 0) return '';\r\n\r\n const pairs = [];\r\n for (const [key, value] of Object.entries(params)) {\r\n if (Array.isArray(value)) {\r\n // \uBC30\uC5F4 \uD30C\uB77C\uBBF8\uD130 \uCC98\uB9AC\r\n for (const item of value) {\r\n pairs.push(`${encodeURIComponent(key)}[]=${encodeURIComponent(item)}`);\r\n }\r\n } else if (value !== undefined && value !== null) {\r\n pairs.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);\r\n }\r\n }\r\n return pairs.join('&');\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uBCC0\uACBD \uAC10\uC9C0\r\n */\r\n hasQueryParamsChanged(newParams) {\r\n if (!this.currentQueryParams && !newParams) return false;\r\n if (!this.currentQueryParams || !newParams) return true;\r\n\r\n const oldKeys = Object.keys(this.currentQueryParams);\r\n const newKeys = Object.keys(newParams);\r\n\r\n if (oldKeys.length !== newKeys.length) return true;\r\n\r\n for (const key of oldKeys) {\r\n if (JSON.stringify(this.currentQueryParams[key]) !== JSON.stringify(newParams[key])) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * \uD604\uC7AC \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uC804\uCCB4 \uAC00\uC838\uC624\uAE30\r\n */\r\n getQueryParams() {\r\n return { ...this.currentQueryParams };\r\n }\r\n\r\n /**\r\n * \uD2B9\uC815 \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uAC00\uC838\uC624\uAE30\r\n */\r\n getQueryParam(key, defaultValue = undefined) {\r\n const value = this.currentQueryParams ? this.currentQueryParams[key] : undefined;\r\n return value !== undefined ? value : defaultValue;\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uC124\uC815\r\n */\r\n setQueryParams(params, replace = false) {\r\n if (!params || typeof params !== 'object') {\r\n this.log('warn', 'Invalid parameters object provided to setQueryParams');\r\n return;\r\n }\r\n\r\n const currentParams = replace ? {} : { ...this.currentQueryParams };\r\n\r\n // \uD30C\uB77C\uBBF8\uD130 \uC5C5\uB370\uC774\uD2B8\r\n for (const [key, value] of Object.entries(params)) {\r\n if (value !== undefined && value !== null && value !== '') {\r\n currentParams[key] = value;\r\n } else {\r\n delete currentParams[key];\r\n }\r\n }\r\n\r\n this.currentQueryParams = currentParams;\r\n this.updateURL();\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uC81C\uAC70\r\n */\r\n removeQueryParams(keys) {\r\n if (!keys) return;\r\n\r\n const keysToRemove = Array.isArray(keys) ? keys : [keys];\r\n for (const key of keysToRemove) {\r\n delete this.currentQueryParams[key];\r\n }\r\n\r\n this.updateURL();\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uCD08\uAE30\uD654\r\n */\r\n clearQueryParams() {\r\n this.currentQueryParams = {};\r\n this.updateURL();\r\n }\r\n\r\n /**\r\n * \uD604\uC7AC \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uC124\uC815 (\uB77C\uC6B0\uD130\uC5D0\uC11C \uD638\uCD9C)\r\n */\r\n setCurrentQueryParams(params) {\r\n this.currentQueryParams = params || {};\r\n }\r\n\r\n /**\r\n * \uD604\uC7AC \uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130 \uC124\uC815 (navigateTo\uC5D0\uC11C \uD638\uCD9C)\r\n */\r\n setCurrentRouteParams(params) {\r\n this.currentRouteParams = params || {};\r\n this.log('debug', 'Route params set:', this.currentRouteParams);\r\n }\r\n\r\n /**\r\n * \uD1B5\uD569\uB41C \uD30C\uB77C\uBBF8\uD130 \uBC18\uD658 (\uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130 + \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130)\r\n */\r\n getAllParams() {\r\n return {\r\n ...this.currentRouteParams,\r\n ...this.currentQueryParams\r\n };\r\n }\r\n\r\n /**\r\n * \uD1B5\uD569\uB41C \uD30C\uB77C\uBBF8\uD130\uC5D0\uC11C \uD2B9\uC815 \uD0A4 \uAC12 \uBC18\uD658\r\n */\r\n getParam(key, defaultValue = undefined) {\r\n // \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130\uAC00 \uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130\uBCF4\uB2E4 \uC6B0\uC120\uC21C\uC704 \uB192\uC74C\r\n const value = this.currentQueryParams[key] !== undefined ?\r\n this.currentQueryParams[key] :\r\n this.currentRouteParams[key];\r\n return value !== undefined ? value : defaultValue;\r\n }\r\n\r\n /**\r\n * \uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130\uB9CC \uBC18\uD658\r\n */\r\n getRouteParams() {\r\n return { ...this.currentRouteParams };\r\n }\r\n\r\n /**\r\n * \uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130\uC5D0\uC11C \uD2B9\uC815 \uD0A4 \uAC12 \uBC18\uD658\r\n */\r\n getRouteParam(key, defaultValue = undefined) {\r\n const value = this.currentRouteParams[key];\r\n return value !== undefined ? value : defaultValue;\r\n }\r\n\r\n /**\r\n * URL \uC5C5\uB370\uC774\uD2B8 (\uB77C\uC6B0\uD130\uC758 updateURL \uBA54\uC18C\uB4DC \uD638\uCD9C)\r\n */\r\n updateURL() {\r\n if (this.router && typeof this.router.updateURL === 'function') {\r\n const route = this.router.currentHash || 'home';\r\n this.router.updateURL(route, this.currentQueryParams);\r\n }\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uD1B5\uACC4\r\n */\r\n getStats() {\r\n return {\r\n currentParams: Object.keys(this.currentQueryParams).length,\r\n currentQueryString: this.buildQueryString(this.currentQueryParams)\r\n };\r\n }\r\n\r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n this.currentQueryParams = {};\r\n this.currentRouteParams = {};\r\n this.router = null;\r\n this.log('debug', 'QueryManager destroyed');\r\n }\r\n}", "/**\r\n * FormHandler\r\n * \uC790\uB3D9 \uD3FC \uCC98\uB9AC \uBC0F \uAC80\uC99D \uC2DC\uC2A4\uD15C\r\n */\r\nexport class FormHandler {\r\n constructor(router, options = {}) {\r\n this.router = router;\r\n this.requestTimeout = options.requestTimeout || 30000;\r\n this.uploadTimeout = options.uploadTimeout || 300000;\r\n \r\n this.log('debug', 'FormHandler initialized');\r\n }\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'FormHandler', ...args);\r\n }\r\n }\r\n\r\n\r\n /**\r\n * \uC911\uBCF5 \uC694\uCCAD \uCCB4\uD06C\r\n */\r\n isDuplicateRequest(form) {\r\n if (form._isSubmitting) {\r\n this.log('debug', 'Duplicate request blocked');\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * \uD3FC \uC81C\uCD9C \uC2DC\uC791\r\n */\r\n startFormSubmission(form) {\r\n form._isSubmitting = true;\r\n form._abortController = new AbortController();\r\n\r\n // \uD30C\uC77C \uC5C5\uB85C\uB4DC\uAC00 \uD3EC\uD568\uB41C \uACBD\uC6B0 uploadTimeout \uC0AC\uC6A9\r\n const hasFile = Array.from(form.elements).some(el => el.type === 'file' && el.files.length > 0);\r\n const timeout = hasFile ? this.uploadTimeout : this.requestTimeout;\r\n\r\n // \uD0C0\uC784\uC544\uC6C3 \uC124\uC815\r\n form._timeoutId = setTimeout(() => {\r\n if (form._isSubmitting) {\r\n this.abortFormSubmission(form);\r\n }\r\n }, timeout);\r\n }\r\n\r\n /**\r\n * \uD3FC \uC81C\uCD9C \uC644\uB8CC\r\n */\r\n finishFormSubmission(form) {\r\n form._isSubmitting = false;\r\n \r\n if (form._timeoutId) {\r\n clearTimeout(form._timeoutId);\r\n delete form._timeoutId;\r\n }\r\n \r\n delete form._abortController;\r\n }\r\n\r\n /**\r\n * \uD3FC \uC81C\uCD9C \uC911\uB2E8\r\n */\r\n abortFormSubmission(form) {\r\n if (form._abortController) {\r\n form._abortController.abort();\r\n }\r\n this.finishFormSubmission(form);\r\n }\r\n\r\n /**\r\n * \uC790\uB3D9 \uD3FC \uBC14\uC778\uB529\r\n */\r\n bindAutoForms(component) {\r\n const forms = document.querySelectorAll('form.auto-form, form[action]');\r\n \r\n forms.forEach(form => {\r\n // \uAE30\uC874 \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uC81C\uAC70 (\uC911\uBCF5 \uBC29\uC9C0)\r\n form.removeEventListener('submit', form._boundSubmitHandler);\r\n \r\n // \uC0C8 \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uCD94\uAC00\r\n const boundHandler = (e) => this.handleFormSubmit(e, component);\r\n form._boundSubmitHandler = boundHandler;\r\n form.addEventListener('submit', boundHandler);\r\n \r\n this.log('debug', `Form auto-bound: ${form.getAttribute('action')}`);\r\n });\r\n }\r\n\r\n /**\r\n * \uD3FC \uC11C\uBE0C\uBC0B \uD578\uB4E4\uB7EC\r\n */\r\n async handleFormSubmit(event, component) {\r\n event.preventDefault();\r\n \r\n const form = event.target;\r\n let action = form.getAttribute('action');\r\n const method = form.getAttribute('method') || 'POST';\r\n \r\n // \uD578\uB4E4\uB7EC \uD568\uC218\uB4E4 \uAC00\uC838\uC624\uAE30\r\n const successHandler = form.getAttribute('data-success');\r\n const errorHandler = form.getAttribute('data-error');\r\n const loadingHandler = form.getAttribute('data-loading');\r\n const redirectTo = form.getAttribute('data-redirect');\r\n\r\n // \uC561\uC158 URL\uC5D0 \uAC00\uBCC0 \uD30C\uB77C\uBBF8\uD130 \uCC98\uB9AC\r\n action = this.processActionParams(action, component);\r\n\r\n // \uD074\uB77C\uC774\uC5B8\uD2B8 \uC0AC\uC774\uB4DC \uAC80\uC99D\r\n if (!this.validateForm(form, component)) {\r\n return;\r\n }\r\n\r\n // \uC911\uBCF5 \uC694\uCCAD \uCCB4\uD06C\r\n if (this.isDuplicateRequest(form)) {\r\n return;\r\n }\r\n\r\n // \uD3FC \uC81C\uCD9C \uC2DC\uC791\r\n this.startFormSubmission(form);\r\n\r\n // FormData \uC0DD\uC131\r\n const formData = new FormData(form);\r\n const data = Object.fromEntries(formData.entries());\r\n\r\n try {\r\n // \uB85C\uB529 \uC2DC\uC791\r\n if (loadingHandler && component[loadingHandler]) {\r\n component[loadingHandler](true, form);\r\n }\r\n\r\n this.log('debug', `Form submitting to: ${action}`, data);\r\n\r\n // API \uD638\uCD9C (AbortController \uC2E0\uD638 \uD3EC\uD568)\r\n const response = await this.submitFormData(action, method, data, form, component, form._abortController.signal);\r\n \r\n // \uC131\uACF5 \uD578\uB4E4\uB7EC \uD638\uCD9C\r\n if (successHandler && component[successHandler]) {\r\n component[successHandler](response, form);\r\n }\r\n\r\n // \uD3FC \uC81C\uCD9C \uC644\uB8CC (\uC131\uACF5)\r\n this.finishFormSubmission(form);\r\n\r\n // \uC790\uB3D9 \uB9AC\uB2E4\uC774\uB809\uD2B8 (requestAnimationFrame \uC0AC\uC6A9\uC73C\uB85C \uBD80\uB4DC\uB7EC\uC6B4 \uC804\uD658)\r\n if (redirectTo) {\r\n requestAnimationFrame(() => {\r\n setTimeout(() => {\r\n component.navigateTo(redirectTo);\r\n }, 1000);\r\n });\r\n }\r\n\r\n } catch (error) {\r\n // AbortError\uB294 \uC758\uB3C4\uC801\uC778 \uCDE8\uC18C\uC774\uBBC0\uB85C \uD2B9\uBCC4 \uCC98\uB9AC\r\n if (error.name === 'AbortError') {\r\n this.log('debug', 'Form submission aborted');\r\n return;\r\n }\r\n\r\n this.log('warn', 'Form submission error:', error);\r\n this.finishFormSubmission(form);\r\n \r\n // \uC5D0\uB7EC \uD578\uB4E4\uB7EC \uD638\uCD9C\r\n if (errorHandler && component[errorHandler]) {\r\n component[errorHandler](error, form);\r\n } else {\r\n this.log('error', 'Form submission error (no error handler defined):', error);\r\n }\r\n \r\n } finally {\r\n // \uB85C\uB529 \uC885\uB8CC\r\n if (loadingHandler && component[loadingHandler]) {\r\n component[loadingHandler](false, form);\r\n }\r\n }\r\n }\r\n\r\n\r\n /**\r\n * \uC561\uC158 \uD30C\uB77C\uBBF8\uD130 \uCC98\uB9AC (ApiHandler \uC7AC\uC0AC\uC6A9)\r\n */\r\n processActionParams(actionTemplate, component) {\r\n // ApiHandler\uC758 processURLParameters \uC7AC\uC0AC\uC6A9\uD558\uC5EC \uC77C\uAD00\uC131 \uD655\uBCF4\r\n return this.router.routeLoader.apiHandler.processURLParameters(actionTemplate, component);\r\n }\r\n\r\n /**\r\n * \uD3FC \uB370\uC774\uD130 \uC11C\uBE0C\uBC0B (ApiHandler \uD65C\uC6A9)\r\n */\r\n async submitFormData(action, method, data, form, component, signal = null) {\r\n // \uD30C\uC77C \uC5C5\uB85C\uB4DC \uCCB4\uD06C\r\n const hasFile = Array.from(form.elements).some(el => el.type === 'file' && el.files.length > 0);\r\n \r\n // ApiHandler\uB97C \uC0AC\uC6A9\uD558\uC5EC \uC77C\uAD00\uB41C API \uD638\uCD9C \uBC0F \uC5D0\uB7EC \uCC98\uB9AC\r\n const options = {\r\n method: method.toUpperCase(),\r\n headers: {},\r\n signal: signal // AbortController \uC2E0\uD638 \uCD94\uAC00\r\n };\r\n\r\n if (hasFile) {\r\n // \uD30C\uC77C\uC774 \uC788\uC73C\uBA74 FormData \uADF8\uB300\uB85C \uC804\uC1A1 (Content-Type \uC790\uB3D9 \uC124\uC815)\r\n options.data = new FormData(form);\r\n } else {\r\n // JSON\uC73C\uB85C \uC804\uC1A1\r\n options.data = data;\r\n options.headers['Content-Type'] = 'application/json';\r\n }\r\n\r\n // ApiHandler\uC758 fetchData \uC0AC\uC6A9\uD558\uC5EC \uD1B5\uD569\uB41C \uCC98\uB9AC\r\n return await this.router.routeLoader.apiHandler.fetchData(action, component, options);\r\n }\r\n\r\n /**\r\n * \uD074\uB77C\uC774\uC5B8\uD2B8 \uC0AC\uC774\uB4DC \uD3FC \uAC80\uC99D\r\n */\r\n validateForm(form, component) {\r\n let isValid = true;\r\n const inputs = form.querySelectorAll('input, textarea, select');\r\n\r\n inputs.forEach(input => {\r\n // \uAE30\uBCF8 HTML5 \uAC80\uC99D\r\n if (!input.checkValidity()) {\r\n isValid = false;\r\n input.classList.add('error');\r\n return;\r\n }\r\n\r\n // \uCEE4\uC2A4\uD140 \uAC80\uC99D \uD568\uC218 \uD655\uC778\r\n const validationFunction = input.getAttribute('data-validation');\r\n if (validationFunction) {\r\n const isInputValid = this.validateInput(input, validationFunction, component);\r\n if (!isInputValid) {\r\n isValid = false;\r\n input.classList.add('error');\r\n } else {\r\n input.classList.remove('error');\r\n }\r\n } else {\r\n input.classList.remove('error');\r\n }\r\n });\r\n\r\n return isValid;\r\n }\r\n\r\n /**\r\n * \uAC1C\uBCC4 \uC785\uB825 \uAC80\uC99D\r\n */\r\n validateInput(input, validationFunction, component) {\r\n const value = input.value;\r\n \r\n // \uCEE4\uC2A4\uD140 \uAC80\uC99D \uD568\uC218 \uD638\uCD9C\r\n if (typeof component[validationFunction] === 'function') {\r\n try {\r\n return component[validationFunction](value, input);\r\n } catch (error) {\r\n this.log('warn', `Validation function '${validationFunction}' error:`, error);\r\n return false;\r\n }\r\n }\r\n \r\n // \uD568\uC218\uAC00 \uC5C6\uC73C\uBA74 true \uBC18\uD658\r\n this.log('warn', `Validation function '${validationFunction}' not found`);\r\n return true;\r\n }\r\n\r\n /**\r\n * \uBAA8\uB4E0 \uD3FC \uC694\uCCAD \uCDE8\uC18C\r\n */\r\n cancelAllRequests() {\r\n const forms = document.querySelectorAll('form');\r\n forms.forEach(form => {\r\n if (form._isSubmitting) {\r\n this.abortFormSubmission(form);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n // \uBAA8\uB4E0 \uC9C4\uD589 \uC911\uC778 \uC694\uCCAD \uCDE8\uC18C\r\n this.cancelAllRequests();\r\n \r\n // \uB4F1\uB85D\uB41C \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108\uB4E4 \uC815\uB9AC\r\n const forms = document.querySelectorAll('form.auto-form, form[action]');\r\n forms.forEach(form => {\r\n if (form._boundSubmitHandler) {\r\n form.removeEventListener('submit', form._boundSubmitHandler);\r\n delete form._boundSubmitHandler;\r\n }\r\n \r\n // \uD3FC \uC0C1\uD0DC \uC815\uB9AC\r\n this.cleanupFormState(form);\r\n });\r\n \r\n // WeakMap \uC815\uB9AC (\uC790\uB3D9 \uAC00\uBE44\uC9C0 \uCEEC\uB809\uC158\uB428)\r\n \r\n this.log('debug', 'FormHandler destroyed');\r\n this.router = null;\r\n }\r\n\r\n /**\r\n * \uD3FC \uC0C1\uD0DC \uC815\uB9AC\r\n */\r\n cleanupFormState(form) {\r\n delete form._isSubmitting;\r\n delete form._abortController;\r\n \r\n if (form._timeoutId) {\r\n clearTimeout(form._timeoutId);\r\n delete form._timeoutId;\r\n }\r\n }\r\n}", "/**\r\n * ApiHandler\r\n * API \uD638\uCD9C \uBC0F \uB370\uC774\uD130 \uCC98\uB9AC \uC2DC\uC2A4\uD15C\r\n */\r\nexport class ApiHandler {\r\n constructor(router, options = {}) {\r\n this.router = router;\r\n this.apiBaseURL = options.apiBaseURL || '';\r\n \r\n this.log('debug', 'ApiHandler initialized');\r\n }\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'ApiHandler', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * \uCEF4\uD3EC\uB10C\uD2B8 \uB370\uC774\uD130 \uAC00\uC838\uC624\uAE30 (\uD30C\uB77C\uBBF8\uD130 \uCE58\uD658 \uC9C0\uC6D0)\r\n */\r\n async fetchData(dataURL, component = null, options = {}) {\r\n try {\r\n // URL\uC5D0\uC11C \uD30C\uB77C\uBBF8\uD130 \uCE58\uD658\r\n let processedURL = this.processURLParameters(dataURL, component);\r\n\r\n // apiBaseURL\uACFC \uC870\uD569 (\uC808\uB300 URL\uC774 \uC544\uB2CC \uACBD\uC6B0\uC5D0\uB9CC)\r\n if (this.apiBaseURL && !this.isAbsoluteURL(processedURL)) {\r\n processedURL = this.combineURLs(this.apiBaseURL, processedURL);\r\n }\r\n\r\n // \uD604\uC7AC \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130\uB97C URL\uC5D0 \uCD94\uAC00\r\n const queryString = this.router.queryManager?.buildQueryString(this.router.queryManager?.getQueryParams()) || '';\r\n const fullURL = queryString ? `${processedURL}?${queryString}` : processedURL;\r\n \r\n this.log('debug', `Fetching data from: ${fullURL}`);\r\n \r\n // \uC694\uCCAD \uC635\uC158 \uC124\uC815\r\n const requestOptions = {\r\n method: options.method || 'GET',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'application/json',\r\n ...options.headers\r\n },\r\n ...options\r\n };\r\n\r\n // \uC778\uC99D \uD1A0\uD070 \uC790\uB3D9 \uCD94\uAC00\r\n if (component?.$getToken && component.$getToken()) {\r\n requestOptions.headers['Authorization'] = `Bearer ${component.$getToken()}`;\r\n }\r\n\r\n // POST/PUT \uB370\uC774\uD130 \uCC98\uB9AC\r\n if (options.data && ['POST', 'PUT', 'PATCH'].includes(requestOptions.method.toUpperCase())) {\r\n if (options.data instanceof FormData) {\r\n // FormData\uC778 \uACBD\uC6B0 \uADF8\uB300\uB85C \uC804\uC1A1 (Content-Type \uC790\uB3D9 \uC124\uC815)\r\n requestOptions.body = options.data;\r\n // FormData\uC77C \uB54C Content-Type \uD5E4\uB354 \uC81C\uAC70 (\uBE0C\uB77C\uC6B0\uC800\uAC00 \uC790\uB3D9 \uC124\uC815)\r\n delete requestOptions.headers['Content-Type'];\r\n } else {\r\n // \uC77C\uBC18 \uAC1D\uCCB4\uC778 \uACBD\uC6B0 JSON\uC73C\uB85C \uC9C1\uB82C\uD654\r\n requestOptions.body = JSON.stringify(options.data);\r\n }\r\n }\r\n\r\n const response = await fetch(fullURL, requestOptions);\r\n\r\n if (!response.ok) {\r\n let error;\r\n try {\r\n error = await response.json();\r\n } catch (e) {\r\n error = { message: `HTTP ${response.status}: ${response.statusText}` };\r\n }\r\n throw new Error(error.message || `HTTP ${response.status}`);\r\n }\r\n \r\n // \uC751\uB2F5 \uCC98\uB9AC\r\n try {\r\n const data = await response.json();\r\n \r\n // \uB370\uC774\uD130 \uC720\uD6A8\uC131 \uAC80\uC0AC\r\n if (typeof data !== 'object' || data === null) {\r\n throw new Error('Invalid data format: expected object');\r\n }\r\n \r\n return data;\r\n } catch (e) {\r\n // \uC751\uB2F5\uC774 JSON\uC774 \uC544\uB2CC \uACBD\uC6B0 (\uC608: 204 No Content)\r\n return { success: true };\r\n }\r\n\r\n } catch (error) {\r\n this.log('error', 'Failed to fetch data:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * \uC5EC\uB7EC API \uC5D4\uB4DC\uD3EC\uC778\uD2B8\uC5D0\uC11C \uB370\uC774\uD130 \uAC00\uC838\uC624\uAE30\r\n */\r\n async fetchMultipleData(dataConfig, component = null) {\r\n if (!dataConfig || typeof dataConfig !== 'object') {\r\n return {};\r\n }\r\n\r\n const results = {};\r\n const errors = {};\r\n \r\n // \uBCD1\uB82C \uCC98\uB9AC\uB97C \uC704\uD55C Promise \uBC30\uC5F4\r\n const promises = Object.entries(dataConfig).map(async ([key, config]) => {\r\n try {\r\n let url, options = {};\r\n \r\n if (typeof config === 'string') {\r\n url = config;\r\n } else if (typeof config === 'object') {\r\n url = config.url;\r\n options = { ...config };\r\n delete options.url;\r\n }\r\n \r\n if (url) {\r\n const data = await this.fetchData(url, component, options);\r\n results[key] = data;\r\n }\r\n } catch (error) {\r\n errors[key] = error;\r\n this.log('warn', `Failed to fetch data for '${key}':`, error);\r\n }\r\n });\r\n \r\n await Promise.all(promises);\r\n \r\n return { results, errors };\r\n }\r\n \r\n /**\r\n * URL\uC5D0\uC11C \uD30C\uB77C\uBBF8\uD130 \uCE58\uD658 \uCC98\uB9AC ({param} \uD615\uC2DD)\r\n */\r\n processURLParameters(url, component = null) {\r\n if (!url || typeof url !== 'string') return url;\r\n \r\n let processedURL = url;\r\n \r\n // {paramName} \uD328\uD134 \uCC3E\uAE30\r\n const paramMatches = url.match(/\\{([^}]+)\\}/g);\r\n \r\n if (paramMatches && component) {\r\n paramMatches.forEach(match => {\r\n const paramName = match.slice(1, -1); // {id} -> id\r\n \r\n try {\r\n let paramValue = null;\r\n\r\n // 1. computed \uC18D\uC131\uC5D0\uC11C \uCC3E\uAE30 (\uCD5C\uC6B0\uC120)\r\n if (component.$options?.computed?.[paramName]) {\r\n paramValue = component[paramName];\r\n }\r\n\r\n // 2. \uCEF4\uD3EC\uB10C\uD2B8 data\uC5D0\uC11C \uCC3E\uAE30\r\n if (paramValue === null || paramValue === undefined) {\r\n paramValue = component[paramName];\r\n }\r\n\r\n // 3. \uB77C\uC6B0\uD2B8/\uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130\uC5D0\uC11C \uCC3E\uAE30\r\n if (paramValue === null || paramValue === undefined) {\r\n if (component.getParam) {\r\n paramValue = component.getParam(paramName);\r\n }\r\n }\r\n\r\n // 4. QueryManager\uC5D0\uC11C \uC9C1\uC811 \uAC00\uC838\uC624\uAE30 (fallback)\r\n if (paramValue === null || paramValue === undefined) {\r\n paramValue = this.router.queryManager?.getParam(paramName);\r\n }\r\n \r\n if (paramValue !== null && paramValue !== undefined) {\r\n // \uD30C\uB77C\uBBF8\uD130 \uCE58\uD658: {id} -> \uC2E4\uC81C\uAC12\r\n processedURL = processedURL.replace(\r\n match, \r\n encodeURIComponent(paramValue)\r\n );\r\n \r\n this.log('debug', `URL parameter resolved: ${paramName} = ${paramValue}`);\r\n } else {\r\n this.log('warn', `URL parameter '${paramName}' not found, keeping original: ${match}`);\r\n }\r\n } catch (error) {\r\n this.log('warn', `Error processing URL parameter '${paramName}':`, error);\r\n }\r\n });\r\n }\r\n \r\n return processedURL;\r\n }\r\n\r\n /**\r\n * HTTP \uBA54\uC11C\uB4DC\uBCC4 \uD5EC\uD37C \uD568\uC218\uB4E4\r\n */\r\n async get(url, component = null, options = {}) {\r\n return this.fetchData(url, component, { ...options, method: 'GET' });\r\n }\r\n\r\n async post(url, data, component = null, options = {}) {\r\n return this.fetchData(url, component, { ...options, method: 'POST', data });\r\n }\r\n\r\n async put(url, data, component = null, options = {}) {\r\n return this.fetchData(url, component, { ...options, method: 'PUT', data });\r\n }\r\n\r\n async patch(url, data, component = null, options = {}) {\r\n return this.fetchData(url, component, { ...options, method: 'PATCH', data });\r\n }\r\n\r\n async delete(url, component = null, options = {}) {\r\n return this.fetchData(url, component, { ...options, method: 'DELETE' });\r\n }\r\n\r\n /**\r\n * \uCEF4\uD3EC\uB10C\uD2B8\uC5D0 \uBC14\uC778\uB529\uB41C API \uAC1D\uCCB4 \uC0DD\uC131\r\n */\r\n bindToComponent(component) {\r\n return {\r\n get: (url, options = {}) => this.get(url, component, options),\r\n post: (url, data, options = {}) => this.post(url, data, component, options),\r\n put: (url, data, options = {}) => this.put(url, data, component, options),\r\n patch: (url, data, options = {}) => this.patch(url, data, component, options),\r\n delete: (url, options = {}) => this.delete(url, component, options),\r\n fetchData: (url, options = {}) => this.fetchData(url, component, options),\r\n fetchMultipleData: (dataConfig) => this.fetchMultipleData(dataConfig, component)\r\n };\r\n }\r\n\r\n /**\r\n * \uC808\uB300 URL\uC778\uC9C0 \uD655\uC778\r\n */\r\n isAbsoluteURL(url) {\r\n return /^https?:\\/\\//.test(url) || url.startsWith('//');\r\n }\r\n\r\n /**\r\n * \uB450 URL\uC744 \uC870\uD569\r\n */\r\n combineURLs(baseURL, relativeURL) {\r\n // \uBCA0\uC774\uC2A4 URL \uB05D\uC758 \uC2AC\uB798\uC2DC \uC81C\uAC70\r\n const cleanBase = baseURL.replace(/\\/$/, '');\r\n // \uC0C1\uB300 URL \uC55E\uC758 \uC2AC\uB798\uC2DC \uD655\uC778\r\n const cleanRelative = relativeURL.startsWith('/') ? relativeURL : `/${relativeURL}`;\r\n return `${cleanBase}${cleanRelative}`;\r\n }\r\n\r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n this.log('debug', 'ApiHandler destroyed');\r\n this.router = null;\r\n }\r\n}", "/**\r\n * ComponentLoader\r\n * \uB3D9\uC801\uC73C\uB85C \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uB85C\uB4DC\uD558\uACE0 \uB4F1\uB85D\uD558\uB294 \uC2DC\uC2A4\uD15C\r\n */\r\nexport class ComponentLoader {\r\n constructor(router = null, options = {}) {\r\n\r\n this.config = {\r\n componentsPath: options.componentsPath || '/components', // srcPath \uAE30\uC900 \uC0C1\uB300 \uACBD\uB85C\r\n environment: options.environment || 'development',\r\n ...options\r\n };\r\n \r\n this.router = router;\r\n this.loadingPromises = new Map();\r\n this.unifiedComponents = null;\r\n }\r\n \r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'ComponentLoader', ...args);\r\n }\r\n }\r\n \r\n /**\r\n * \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uBE44\uB3D9\uAE30\uB85C \uB85C\uB4DC (\uCE90\uC2DC \uC9C0\uC6D0)\r\n */\r\n async loadComponent(componentName) {\r\n if (!componentName || typeof componentName !== 'string') {\r\n throw new Error('Component name must be a non-empty string');\r\n }\r\n \r\n // \uCE90\uC2DC\uC5D0\uC11C \uCEF4\uD3EC\uB10C\uD2B8 \uD655\uC778\r\n const cacheKey = `component_${componentName}`;\r\n const cachedComponent = this.router?.cacheManager?.get(cacheKey);\r\n if (cachedComponent) {\r\n this.log('debug', `Component '${componentName}' loaded from cache`);\r\n return cachedComponent;\r\n }\r\n \r\n // \uC774\uBBF8 \uB85C\uB529 \uC911\uC778 \uACBD\uC6B0 \uAE30\uC874 Promise \uBC18\uD658\r\n if (this.loadingPromises.has(componentName)) {\r\n return this.loadingPromises.get(componentName);\r\n }\r\n \r\n const loadPromise = this._loadComponentFromFile(componentName);\r\n this.loadingPromises.set(componentName, loadPromise);\r\n \r\n try {\r\n const component = await loadPromise;\r\n \r\n // \uCE90\uC2DC\uC5D0 \uC800\uC7A5\r\n if (component && this.router?.cacheManager) {\r\n this.router.cacheManager.set(cacheKey, component);\r\n this.log('debug', `Component '${componentName}' cached successfully`);\r\n }\r\n \r\n return component;\r\n } catch (error) {\r\n throw error;\r\n } finally {\r\n this.loadingPromises.delete(componentName);\r\n }\r\n }\r\n \r\n /**\r\n * \uD30C\uC77C\uC5D0\uC11C \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB4DC\r\n */\r\n async _loadComponentFromFile(componentName) {\r\n // srcPath + componentsPath\uB97C \uC870\uD569\uD558\uC5EC \uCEF4\uD3EC\uB10C\uD2B8 \uACBD\uB85C \uC0DD\uC131\r\n const componentRelativePath = `${this.config.componentsPath}/${componentName}.js`;\r\n \r\n let componentPath;\r\n if (this.router && this.router.config.srcPath) {\r\n // srcPath\uB294 \uC774\uBBF8 \uC804\uCCB4 URL\uC774\uBBC0\uB85C \uC9C1\uC811 \uC870\uD569\r\n const srcPath = this.router.config.srcPath;\r\n if (srcPath.startsWith('http')) {\r\n // \uC774\uC911 \uC2AC\uB798\uC2DC \uBC29\uC9C0\r\n const cleanSrcPath = srcPath.endsWith('/') ? srcPath.slice(0, -1) : srcPath;\r\n const cleanComponentPath = componentRelativePath.startsWith('/') ? componentRelativePath : `/${componentRelativePath}`;\r\n componentPath = `${cleanSrcPath}${cleanComponentPath}`;\r\n } else {\r\n componentPath = this.router.resolvePath(`${srcPath}${componentRelativePath}`);\r\n }\r\n } else {\r\n // \uD3F4\uBC31: \uAE30\uBCF8 \uACBD\uB85C \uC0AC\uC6A9 (\uC808\uB300 \uACBD\uB85C)\r\n componentPath = this.router ?\r\n this.router.resolvePath(`/src${componentRelativePath}`) :\r\n `/src${componentRelativePath}`;\r\n }\r\n \r\n try {\r\n const module = await import(componentPath);\r\n const component = module.default;\r\n \r\n if (!component) {\r\n throw new Error(`Component '${componentName}' has no default export`);\r\n }\r\n \r\n if (!component.name) {\r\n component.name = componentName;\r\n }\r\n \r\n this.log('debug', `Component '${componentName}' loaded successfully`);\r\n return component;\r\n \r\n } catch (error) {\r\n this.log('error', `Failed to load component '${componentName}':`, error);\r\n throw new Error(`Component '${componentName}' not found: ${error.message}`);\r\n }\r\n }\r\n \r\n /**\r\n * \uCEF4\uD3EC\uB10C\uD2B8 \uBAA8\uB4C8 \uD074\uB9AC\uC5B4\r\n */\r\n clearComponents() {\r\n this.loadingPromises.clear();\r\n this.unifiedComponents = null;\r\n this.log('debug', 'All components cleared');\r\n }\r\n \r\n /**\r\n * \uD658\uACBD\uC5D0 \uB530\uB978 \uBAA8\uB4E0 \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB529 (\uCE90\uC2F1 \uC9C0\uC6D0)\r\n */\r\n async loadAllComponents(componentNames = null) {\r\n let components;\r\n \r\n // \uC6B4\uC601 \uBAA8\uB4DC: \uD1B5\uD569 \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB529 \uC2DC\uB3C4\r\n if (this.config.environment === 'production') {\r\n // \uC6B4\uC601 \uBAA8\uB4DC\uC5D0\uC11C\uB9CC unifiedComponents \uCE90\uC2DC \uC0AC\uC6A9\r\n if (this.unifiedComponents) {\r\n this.log('debug', 'Using existing unified components');\r\n return this.unifiedComponents;\r\n }\r\n components = await this._loadProductionComponents();\r\n } else {\r\n // \uAC1C\uBC1C \uBAA8\uB4DC: \uCE90\uC2DC \uC5C6\uC774 \uAC1C\uBCC4 \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB529\r\n components = await this._loadDevelopmentComponents(componentNames);\r\n }\r\n \r\n return components;\r\n }\r\n \r\n /**\r\n * \uC6B4\uC601 \uBAA8\uB4DC: \uD1B5\uD569 \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB529\r\n */\r\n async _loadProductionComponents() {\r\n try {\r\n const componentsPath = `${this.router?.config?.routesPath || '/routes'}/_components.js`;\r\n this.log('debug', '[PRODUCTION] Loading unified components from:', componentsPath);\r\n \r\n const componentsModule = await import(componentsPath);\r\n \r\n if (typeof componentsModule.registerComponents === 'function') {\r\n this.unifiedComponents = componentsModule.components || {};\r\n this.log('debug', `[PRODUCTION] Unified components loaded: ${Object.keys(this.unifiedComponents).length} components`);\r\n return this.unifiedComponents;\r\n } else {\r\n throw new Error('registerComponents function not found in components module');\r\n }\r\n } catch (error) {\r\n this.log('warn', '[PRODUCTION] Failed to load unified components:', error.message);\r\n this.unifiedComponents = {};\r\n return {};\r\n }\r\n }\r\n \r\n /**\r\n * \uAC1C\uBC1C \uBAA8\uB4DC: \uAC1C\uBCC4 \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB529\r\n */\r\n async _loadDevelopmentComponents(componentNames = null) {\r\n // \uCEF4\uD3EC\uB10C\uD2B8 \uC774\uB984 \uBAA9\uB85D\uC774 \uC81C\uACF5\uB418\uC9C0 \uC54A\uC73C\uBA74 \uD3F4\uBC31 \uC0AC\uC6A9\r\n const namesToLoad = componentNames || [];\r\n const components = {};\r\n \r\n if (namesToLoad.length === 0) {\r\n this.log('debug', '[DEVELOPMENT] No components to load');\r\n return components;\r\n }\r\n \r\n this.log('debug', `[DEVELOPMENT] Loading individual components: ${namesToLoad.join(', ')}`);\r\n \r\n for (const name of namesToLoad) {\r\n try {\r\n const component = await this.loadComponent(name);\r\n if (component) {\r\n components[name] = component;\r\n }\r\n } catch (loadError) {\r\n this.log('warn', `[DEVELOPMENT] Failed to load component ${name}:`, loadError.message);\r\n }\r\n }\r\n \r\n this.log('debug', `[DEVELOPMENT] Individual components loaded: ${Object.keys(components).length} components`);\r\n return components;\r\n }\r\n \r\n /**\r\n * \uD15C\uD50C\uB9BF\uACFC \uB808\uC774\uC544\uC6C3\uC5D0\uC11C \uC0AC\uC6A9\uB41C \uCEF4\uD3EC\uB10C\uD2B8 \uCD94\uCD9C\r\n */\r\n getComponentNames(template, layout = null, layoutName = null) {\r\n // \uB808\uC774\uC544\uC6C3 \uCEF4\uD3EC\uB10C\uD2B8\uB85C \uCD08\uAE30\uD654 (\uCE90\uC2DC \uD65C\uC6A9)\r\n const componentSet = layout ? \r\n this._getLayoutComponents(layout, layoutName) : \r\n new Set();\r\n \r\n // \uD15C\uD50C\uB9BF\uC5D0\uC11C \uCEF4\uD3EC\uB10C\uD2B8 \uCD94\uCD9C\r\n if (template) {\r\n this._extractComponentsFromContent(template, componentSet);\r\n }\r\n \r\n const components = Array.from(componentSet);\r\n this.log('debug', `Discovered ${components.length} components:`, components);\r\n \r\n return components;\r\n }\r\n \r\n /**\r\n * \uB808\uC774\uC544\uC6C3\uC5D0\uC11C \uCEF4\uD3EC\uB10C\uD2B8 \uCD94\uCD9C (\uCE90\uC2DC \uD65C\uC6A9)\r\n */\r\n _getLayoutComponents(layout, layoutName) {\r\n if (!layout || typeof layout !== 'string') return new Set();\r\n if (!layoutName || typeof layoutName !== 'string') return new Set();\r\n \r\n // \uB808\uC774\uC544\uC6C3 \uC774\uB984\uC744 \uCE90\uC2DC \uD0A4\uB85C \uC0AC\uC6A9\r\n const cacheKey = `layout_components_${layoutName}`;\r\n \r\n // \uCE90\uC2DC\uC5D0\uC11C \uD655\uC778\r\n const cachedComponents = this.router?.cacheManager?.get(cacheKey);\r\n if (cachedComponents) {\r\n this.log('debug', `Using cached layout components for '${layoutName}'`);\r\n return cachedComponents;\r\n }\r\n \r\n // \uB808\uC774\uC544\uC6C3\uC5D0\uC11C \uCEF4\uD3EC\uB10C\uD2B8 \uCD94\uCD9C\r\n const componentSet = new Set();\r\n this._extractComponentsFromContent(layout, componentSet);\r\n \r\n // \uCE90\uC2DC\uC5D0 \uC800\uC7A5 (Set \uADF8\uB300\uB85C)\r\n if (this.router?.cacheManager) {\r\n this.router.cacheManager.set(cacheKey, componentSet);\r\n this.log('debug', `Cached layout components for '${layoutName}': ${Array.from(componentSet).join(', ')}`);\r\n }\r\n \r\n return componentSet;\r\n }\r\n \r\n /**\r\n * HTML \uCEE8\uD150\uCE20\uC5D0\uC11C Vue \uCEF4\uD3EC\uB10C\uD2B8 \uCD94\uCD9C\r\n */\r\n _extractComponentsFromContent(content, componentSet) {\r\n if (!content || typeof content !== 'string') return;\r\n \r\n // \uB354 \uD6A8\uC728\uC801\uC778 \uD328\uD134: PascalCase \uCEF4\uD3EC\uB10C\uD2B8 \uD0DC\uADF8 \uCD94\uCD9C\r\n // \uC2DC\uC791 \uD0DC\uADF8 <Component>\uC640 \uC790\uCCB4 \uB2EB\uD798 \uD0DC\uADF8 <Component/>\uB97C \uBAA8\uB450 \uAC10\uC9C0\r\n // dotAll \uD50C\uB798\uADF8(s)\uB85C \uAC1C\uD589 \uBB38\uC790\uB3C4 \uCC98\uB9AC\r\n const componentPattern = /<([A-Z][a-zA-Z0-9]*)(?:\\s[^>]*)?\\/?>|<\\/([A-Z][a-zA-Z0-9]*)\\s*>/gs;\r\n let match;\r\n \r\n while ((match = componentPattern.exec(content)) !== null) {\r\n // match[1]\uC740 \uC2DC\uC791/\uC790\uCCB4\uB2EB\uD798 \uD0DC\uADF8, match[2]\uB294 \uB2EB\uB294 \uD0DC\uADF8\r\n const componentName = match[1] || match[2];\r\n \r\n if (componentName && !this._isHtmlTag(componentName)) {\r\n componentSet.add(componentName);\r\n this.log('debug', `Found component: ${componentName}`);\r\n }\r\n }\r\n }\r\n \r\n /**\r\n * HTML \uAE30\uBCF8 \uD0DC\uADF8\uC778\uC9C0 \uD655\uC778\r\n */\r\n _isHtmlTag(tagName) {\r\n const htmlTags = [\r\n 'div', 'span', 'p', 'a', 'img', 'ul', 'ol', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\r\n 'table', 'tr', 'td', 'th', 'form', 'select', 'option', 'textarea',\r\n 'nav', 'header', 'footer', 'main', 'section', 'article', 'aside', 'figure', 'figcaption',\r\n 'video', 'audio', 'canvas', 'svg', 'iframe', 'script', 'style', 'link', 'meta', 'title',\r\n 'body', 'html', 'head', 'template', 'slot'\r\n ];\r\n \r\n return htmlTags.includes(tagName);\r\n }\r\n\r\n /**\r\n * \uBA54\uBAA8\uB9AC \uC815\uB9AC\r\n */\r\n dispose() {\r\n this.clearComponents();\r\n this.log('debug', 'ComponentLoader disposed');\r\n this.router = null;\r\n }\r\n}", "/**\r\n * ViewLogic Route Loading System\r\n * \uB77C\uC6B0\uD2B8 \uB85C\uB529 \uBC0F \uCEF4\uD3EC\uB10C\uD2B8 \uAD00\uB9AC \uC2DC\uC2A4\uD15C\r\n */\r\nimport { FormHandler } from './FormHandler.js';\r\nimport { ApiHandler } from './ApiHandler.js';\r\nimport { ComponentLoader } from './ComponentLoader.js';\r\n\r\nexport class RouteLoader {\r\n constructor(router, options = {}) {\r\n this.config = {\r\n srcPath: options.srcPath || router.config.srcPath || '/src', // \uC18C\uC2A4 \uD30C\uC77C \uACBD\uB85C\r\n routesPath: options.routesPath || router.config.routesPath || '/routes', // \uD504\uB85C\uB355\uC158 \uB77C\uC6B0\uD2B8 \uACBD\uB85C\r\n environment: options.environment || 'development',\r\n useLayout: options.useLayout !== false,\r\n defaultLayout: options.defaultLayout || 'default'\r\n };\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870\r\n this.router = router;\r\n \r\n // FormHandler \uC778\uC2A4\uD134\uC2A4 \uC0DD\uC131\r\n this.formHandler = new FormHandler(router, this.config);\r\n \r\n // ApiHandler \uC778\uC2A4\uD134\uC2A4 \uC0DD\uC131\r\n this.apiHandler = new ApiHandler(router, this.config);\r\n \r\n // ComponentLoader \uC778\uC2A4\uD134\uC2A4 \uC0DD\uC131 (\uAE30\uBCF8\uC73C\uB85C \uD65C\uC131\uD654)\r\n this.componentLoader = new ComponentLoader(router, this.config);\r\n \r\n this.log('debug', 'RouteLoader initialized with config:', this.config);\r\n }\r\n\r\n /**\r\n * \uC2A4\uD06C\uB9BD\uD2B8 \uD30C\uC77C \uB85C\uB4DC\r\n */\r\n async loadScript(routeName) {\r\n let script;\r\n try {\r\n if (this.config.environment === 'production') {\r\n // \uD504\uB85C\uB355\uC158 \uBAA8\uB4DC: routes \uD3F4\uB354\uC5D0\uC11C \uBE4C\uB4DC\uB41C JS \uB85C\uB4DC (\uC808\uB300 \uACBD\uB85C)\r\n const importPath = `${this.config.routesPath}/${routeName}.js`;\r\n this.log('debug', `Loading production route: ${importPath}`);\r\n const module = await import(importPath);\r\n script = module.default;\r\n } else {\r\n // \uAC1C\uBC1C \uBAA8\uB4DC: srcPath \uC0AC\uC6A9\uD558\uC5EC \uC18C\uC2A4 \uD30C\uC77C \uACBD\uB85C \uAD6C\uC131\r\n const importPath = `${this.config.srcPath}/logic/${routeName}.js`;\r\n this.log('debug', `Loading development route: ${importPath}`);\r\n const module = await import(importPath);\r\n script = module.default;\r\n }\r\n \r\n if (!script) {\r\n throw new Error(`Route '${routeName}' not found - no default export`);\r\n }\r\n \r\n } catch (error) {\r\n // import \uC5D0\uB7EC\uB97C 404\uB85C \uBD84\uB958\r\n if (error.message.includes('Failed to resolve') || \r\n error.message.includes('Failed to fetch') ||\r\n error.message.includes('not found') ||\r\n error.name === 'TypeError') {\r\n throw new Error(`Route '${routeName}' not found - 404`);\r\n }\r\n // \uB2E4\uB978 \uC5D0\uB7EC\uB294 \uADF8\uB300\uB85C \uC804\uD30C\r\n throw error;\r\n }\r\n \r\n return script;\r\n }\r\n\r\n /**\r\n * \uD15C\uD50C\uB9BF \uD30C\uC77C \uB85C\uB4DC (\uC2E4\uD328\uC2DC \uAE30\uBCF8\uAC12 \uBC18\uD658)\r\n */\r\n async loadTemplate(routeName) {\r\n try {\r\n const templatePath = `${this.config.srcPath}/views/${routeName}.html`;\r\n const response = await fetch(templatePath);\r\n if (!response.ok) throw new Error(`Template not found: ${response.status}`);\r\n const template = await response.text();\r\n this.log('debug', `Template '${routeName}' loaded successfully`);\r\n return template;\r\n } catch (error) {\r\n this.log('warn', `Template '${routeName}' not found, using default:`, error.message);\r\n // \uAE30\uBCF8 \uD15C\uD50C\uB9BF \uBC18\uD658\r\n return this.generateDefaultTemplate(routeName);\r\n }\r\n }\r\n\r\n /**\r\n * \uC2A4\uD0C0\uC77C \uD30C\uC77C \uB85C\uB4DC (\uC2E4\uD328\uC2DC \uBE48 \uBB38\uC790\uC5F4 \uBC18\uD658)\r\n */\r\n async loadStyle(routeName) {\r\n try {\r\n const stylePath = `${this.config.srcPath}/styles/${routeName}.css`;\r\n const response = await fetch(stylePath);\r\n if (!response.ok) throw new Error(`Style not found: ${response.status}`);\r\n const style = await response.text();\r\n this.log('debug', `Style '${routeName}' loaded successfully`);\r\n return style;\r\n } catch (error) {\r\n this.log('debug', `Style '${routeName}' not found, no styles applied:`, error.message);\r\n // \uC2A4\uD0C0\uC77C\uC774 \uC5C6\uC73C\uBA74 \uBE48 \uBB38\uC790\uC5F4 \uBC18\uD658\r\n return '';\r\n }\r\n }\r\n\r\n /**\r\n * \uB808\uC774\uC544\uC6C3 \uD30C\uC77C \uB85C\uB4DC (\uC2E4\uD328\uC2DC null \uBC18\uD658)\r\n */\r\n async loadLayout(layoutName) {\r\n try {\r\n const layoutPath = `${this.config.srcPath}/layouts/${layoutName}.html`;\r\n const response = await fetch(layoutPath);\r\n if (!response.ok) throw new Error(`Layout not found: ${response.status}`);\r\n const layout = await response.text();\r\n \r\n this.log('debug', `Layout '${layoutName}' loaded successfully`);\r\n return layout;\r\n } catch (error) {\r\n this.log('debug', `Layout '${layoutName}' not found, no layout applied:`, error.message);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * \uB808\uC774\uC544\uC6C3\uACFC \uD15C\uD50C\uB9BF \uBCD1\uD569\r\n */\r\n mergeLayoutWithTemplate(routeName, layout, template) {\r\n let result;\r\n // \uB808\uC774\uC544\uC6C3\uC5D0\uC11C <slot name=\"content\"> \uBD80\uBD84\uC744 \uD15C\uD50C\uB9BF\uC73C\uB85C \uAD50\uCCB4\r\n if (layout.includes('{{ content }}')) {\r\n result = layout.replace(\r\n /{{ content }}/s,\r\n template\r\n );\r\n }\r\n // slot\uC774 \uC5C6\uC73C\uBA74 main-content \uD074\uB798\uC2A4 \uB0B4\uC6A9 \uAD50\uCCB4\r\n else if (layout.includes('class=\"main-content\"')) {\r\n this.log('debug', 'Using main-content replacement');\r\n result = layout.replace(\r\n /(<div class=\"container\">).*?(<\\/div>\\s*<\\/main>)/s,\r\n `$1${template}$2`\r\n );\r\n }\r\n // \uB9C8\uC9C0\uB9C9 \uB300\uC548: \uC804\uCCB4 \uB808\uC774\uC544\uC6C3\uC744 \uD15C\uD50C\uB9BF\uC73C\uB85C \uAC10\uC2F8\uAE30\r\n else {\r\n this.log('debug', 'Wrapping template with layout');\r\n result = `${layout}\\n${template}`;\r\n }\r\n \r\n return result;\r\n }\r\n\r\n\r\n /**\r\n * Vue \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131\r\n */\r\n async createVueComponent(routeName) {\r\n // \uCE90\uC2DC\uB41C Vue \uCEF4\uD3EC\uB10C\uD2B8\uAC00 \uC788\uB294\uC9C0 \uD655\uC778\r\n const cacheKey = `component_${routeName}`;\r\n const cached = this.router.cacheManager?.get(cacheKey);\r\n if (cached) {\r\n return cached;\r\n }\r\n \r\n const script = await this.loadScript(routeName);\r\n const router = this.router;\r\n const isProduction = this.config.environment === 'production';\r\n \r\n // \uD658\uACBD\uBCC4 \uB9AC\uC18C\uC2A4 \uB85C\uB529\r\n let template, style = '', layout = null;\r\n \r\n if (isProduction) {\r\n // \uD504\uB85C\uB355\uC158: \uC2A4\uD06C\uB9BD\uD2B8\uC5D0 \uC788\uB294 \uD15C\uD50C\uB9BF \uC0AC\uC6A9 \uB610\uB294 \uAE30\uBCF8\uAC12\r\n template = script.template || this.generateDefaultTemplate(routeName);\r\n } else {\r\n // \uAC1C\uBC1C: \uAC1C\uBCC4 \uD30C\uC77C\uB4E4 \uBCD1\uB82C \uB85C\uB4DC\r\n const loadPromises = [\r\n this.loadTemplate(routeName),\r\n this.loadStyle(routeName)\r\n ];\r\n \r\n // \uB808\uC774\uC544\uC6C3 \uB85C\uB529 \uC870\uAC74\uBD80 \uCD94\uAC00\r\n if (this.config.useLayout && script.layout !== null) {\r\n loadPromises.push(this.loadLayout(script.layout || this.config.defaultLayout));\r\n } else {\r\n loadPromises.push(Promise.resolve(null));\r\n }\r\n \r\n // \uBCD1\uB82C \uC2E4\uD589\r\n const [loadedTemplate, loadedStyle, loadedLayout] = await Promise.all(loadPromises);\r\n \r\n template = loadedTemplate;\r\n style = loadedStyle;\r\n layout = loadedLayout;\r\n \r\n // \uB808\uC774\uC544\uC6C3\uACFC \uD15C\uD50C\uB9BF \uBCD1\uD569\r\n if (layout) {\r\n template = this.mergeLayoutWithTemplate(routeName, layout, template);\r\n }\r\n }\r\n \r\n // \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB529 (\uC2E4\uD328\uD574\uB3C4 \uB77C\uC6B0\uD130\uB294 \uACC4\uC18D \uC791\uB3D9)\r\n let loadedComponents = {};\r\n if (this.componentLoader) {\r\n try {\r\n let componentNames = null;\r\n \r\n // \uAC1C\uBC1C \uBAA8\uB4DC\uC5D0\uC11C\uB9CC \uB3D9\uC801 \uCEF4\uD3EC\uB10C\uD2B8 \uBC1C\uACAC\r\n if (!isProduction) {\r\n const layoutName = script.layout || this.config.defaultLayout;\r\n componentNames = this.componentLoader.getComponentNames(template, layout, layoutName);\r\n this.log('debug', `[DEVELOPMENT] Discovered components for route '${routeName}':`, componentNames);\r\n }\r\n \r\n loadedComponents = await this.componentLoader.loadAllComponents(componentNames);\r\n this.log('debug', `Components loaded successfully for route: ${routeName}`);\r\n } catch (error) {\r\n this.log('warn', `Component loading failed for route '${routeName}', continuing without components:`, error.message);\r\n loadedComponents = {}; // \uBE48 \uAC1D\uCCB4\uB85C \uD3F4\uBC31\r\n }\r\n }\r\n\r\n // \uB2E8\uC77C \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131\r\n const component = {\r\n ...script,\r\n name: script.name || this.toPascalCase(routeName),\r\n template,\r\n components: loadedComponents,\r\n data() {\r\n const originalData = script.data ? script.data() : {};\r\n const commonData = {\r\n ...originalData,\r\n currentRoute: routeName,\r\n $query: router.queryManager?.getQueryParams() || {},\r\n $params: router.queryManager?.getRouteParams() || {},\r\n $lang: (() => {\r\n try {\r\n return router.i18nManager?.getCurrentLanguage() || router.config.i18nDefaultLanguage || router.config.defaultLanguage || 'ko';\r\n } catch (error) {\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', 'Failed to get current language:', error);\r\n return router.config.defaultLanguage || 'ko';\r\n }\r\n })(),\r\n $dataLoading: false\r\n };\r\n \r\n return commonData;\r\n },\r\n computed: {\r\n ...(script.computed || {}),\r\n // \uD558\uC704 \uD638\uD658\uC131\uC744 \uC704\uD574 params\uB294 \uC720\uC9C0\uD558\uB418 getAllParams \uC0AC\uC6A9\r\n params() {\r\n return router.queryManager?.getAllParams() || {};\r\n }\r\n },\r\n async mounted() {\r\n // API \uAC1D\uCCB4 \uCD08\uAE30\uD654\r\n this.$api = router.routeLoader.apiHandler.bindToComponent(this);\r\n\r\n // \uC0C1\uD0DC \uAD00\uB9AC \uCD08\uAE30\uD654\r\n this.$state = router.stateHandler;\r\n\r\n if (script.mounted) {\r\n await script.mounted.call(this);\r\n }\r\n if (script.dataURL) {\r\n // \uD1B5\uD569\uB41C \uB370\uC774\uD130 fetch (\uB2E8\uC77C/\uB2E4\uC911 API \uC790\uB3D9 \uCC98\uB9AC)\r\n await this.fetchData();\r\n }\r\n \r\n // \uD83C\uDD95 \uC790\uB3D9 \uD3FC \uBC14\uC778\uB529\r\n await this.$nextTick(); // DOM\uC774 \uC644\uC804\uD788 \uB80C\uB354\uB9C1\uB41C \uD6C4\r\n router.routeLoader.formHandler.bindAutoForms(this);\r\n },\r\n methods: {\r\n ...script.methods,\r\n // \uB77C\uC6B0\uD305 \uAD00\uB828\r\n navigateTo: (route, params) => router.navigateTo(route, params),\r\n getCurrentRoute: () => router.getCurrentRoute(),\r\n \r\n // \uD1B5\uD569\uB41C \uD30C\uB77C\uBBF8\uD130 \uAD00\uB9AC (\uB77C\uC6B0\uD305 + \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130)\r\n getParams: () => router.queryManager?.getAllParams() || {},\r\n getParam: (key, defaultValue) => router.queryManager?.getParam(key, defaultValue),\r\n \r\n // i18n \uAD00\uB828 (resilient - i18n \uC2E4\uD328\uD574\uB3C4 key \uBC18\uD658)\r\n $t: (key, params) => {\r\n try {\r\n return router.i18nManager?.t(key, params) || key;\r\n } catch (error) {\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', 'i18n translation failed, returning key:', error);\r\n return key;\r\n }\r\n },\r\n\r\n // \uC778\uC99D \uAD00\uB828 (\uD575\uC2EC 4\uAC1C \uBA54\uC18C\uB4DC\uB9CC)\r\n isAuth: () => router.authManager?.isAuthenticated() || false,\r\n logout: () => router.authManager ? router.navigateTo(router.authManager.logout()) : null,\r\n getToken: () => router.authManager?.getAccessToken() || null,\r\n setToken: (token, options) => router.authManager?.setAccessToken(token, options) || false,\r\n\r\n // i18n \uC5B8\uC5B4 \uAD00\uB9AC\r\n getLanguage: () => router.i18nManager?.getCurrentLanguage() || router.config.defaultLanguage || 'ko',\r\n setLanguage: (lang) => router.i18nManager?.setLanguage(lang),\r\n\r\n // \uB85C\uAE45 \uBC0F \uC5D0\uB7EC \uCC98\uB9AC\r\n log: (level, ...args) => {\r\n if (router.errorHandler) {\r\n router.errorHandler.log(level, `[${routeName}]`, ...args);\r\n }\r\n },\r\n\r\n\r\n // \uB370\uC774\uD130 fetch (ApiHandler \uB798\uD37C)\r\n async fetchData(dataConfig = null) {\r\n // dataConfig\uAC00 \uC81C\uACF5\uB418\uBA74 \uC0AC\uC6A9, \uC544\uB2C8\uBA74 script.dataURL \uC0AC\uC6A9\r\n const configToUse = dataConfig || script.dataURL;\r\n if (!configToUse) return null;\r\n \r\n this.$dataLoading = true;\r\n try {\r\n if (typeof configToUse === 'string') {\r\n // \uB2E8\uC77C API \uBC29\uC2DD\r\n const data = await router.routeLoader.apiHandler.fetchData(configToUse, this);\r\n Object.assign(this, data);\r\n this.$emit('data-loaded', data);\r\n return data;\r\n \r\n } else if (typeof configToUse === 'object') {\r\n // \uB2E4\uC911 API \uBC29\uC2DD - ApiHandler\uC758 fetchMultipleData \uC0AC\uC6A9\r\n const { results, errors } = await router.routeLoader.apiHandler.fetchMultipleData(configToUse, this);\r\n \r\n // \uC131\uACF5\uD55C \uACB0\uACFC\uB97C \uCEF4\uD3EC\uB10C\uD2B8 \uB370\uC774\uD130\uC5D0 \uBCD1\uD569\r\n Object.assign(this, results);\r\n \r\n // \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n if (Object.keys(results).length > 0) {\r\n this.$emit('data-loaded', results);\r\n }\r\n if (Object.keys(errors).length > 0) {\r\n this.$emit('data-error', errors);\r\n }\r\n \r\n return results;\r\n }\r\n \r\n return null;\r\n } catch (error) {\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', `Failed to fetch data for ${routeName}:`, error);\r\n this.$emit('data-error', error);\r\n throw error;\r\n } finally {\r\n this.$dataLoading = false;\r\n }\r\n },\r\n\r\n // \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131 (RouteLoader\uC758 createVueComponent \uB798\uD37C)\r\n async $createComponent(componentName) {\r\n try {\r\n return await router.routeLoader.createVueComponent(componentName);\r\n } catch (error) {\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', `Failed to create component '${componentName}':`, error);\r\n throw error;\r\n }\r\n }\r\n },\r\n _routeName: routeName\r\n };\r\n \r\n // \uAC1C\uBC1C \uBAA8\uB4DC\uC5D0\uC11C\uB9CC \uC2A4\uD0C0\uC77C \uBA54\uD0C0\uB370\uC774\uD130 \uC800\uC7A5 (\uB80C\uB354\uB9C1 \uC2DC \uC8FC\uC785\uC6A9)\r\n if (!isProduction && style) {\r\n component._style = style;\r\n }\r\n \r\n // \uCE90\uC2DC\uC5D0 \uC800\uC7A5\r\n this.router.cacheManager?.set(cacheKey, component);\r\n \r\n return component;\r\n }\r\n\r\n /**\r\n * \uBB38\uC790\uC5F4\uC744 PascalCase\uB85C \uBCC0\uD658\r\n */\r\n toPascalCase(str) {\r\n return str\r\n .split(/[-_\\s]+/) // \uD558\uC774\uD508, \uC5B8\uB354\uC2A4\uCF54\uC5B4, \uACF5\uBC31\uC73C\uB85C \uBD84\uB9AC\r\n .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\r\n .join('');\r\n }\r\n\r\n /**\r\n * \uAE30\uBCF8 \uD15C\uD50C\uB9BF \uC0DD\uC131\r\n */\r\n generateDefaultTemplate(routeName) {\r\n return `<div class=\"route-${routeName}\"><h1>Route: ${routeName}</h1></div>`;\r\n }\r\n\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'RouteLoader', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n // FormHandler \uC815\uB9AC\r\n if (this.formHandler) {\r\n this.formHandler.destroy();\r\n this.formHandler = null;\r\n }\r\n \r\n // ApiHandler \uC815\uB9AC\r\n if (this.apiHandler) {\r\n this.apiHandler.destroy();\r\n this.apiHandler = null;\r\n }\r\n \r\n // ComponentLoader \uC815\uB9AC\r\n if (this.componentLoader) {\r\n this.componentLoader.dispose();\r\n this.componentLoader = null;\r\n }\r\n \r\n this.log('debug', 'RouteLoader destroyed');\r\n this.router = null;\r\n }\r\n}", "/**\r\n * ViewLogic Error Handling System\r\n * \uB77C\uC6B0\uD2B8 \uBC0F \uC2DC\uC2A4\uD15C \uC5D0\uB7EC \uCC98\uB9AC \uC2DC\uC2A4\uD15C\r\n */\r\nexport class ErrorHandler {\r\n constructor(router, options = {}) {\r\n this.config = {\r\n logLevel: options.logLevel || 'info',\r\n environment: options.environment || 'development'\r\n };\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870\r\n this.router = router;\r\n \r\n // \uB85C\uADF8 \uB808\uBCA8 \uB9E4\uD551\r\n this.logLevels = {\r\n error: 0,\r\n warn: 1, \r\n info: 2,\r\n debug: 3\r\n };\r\n \r\n this.log('debug', 'ErrorHandler', 'ErrorHandler initialized with config:', this.config);\r\n }\r\n\r\n /**\r\n * \uB77C\uC6B0\uD2B8 \uC5D0\uB7EC \uCC98\uB9AC\r\n */\r\n async handleRouteError(routeName, error) {\r\n let errorCode = 500;\r\n let errorMessage = '\uD398\uC774\uC9C0\uB97C \uB85C\uB4DC\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.';\r\n \r\n this.debug('ErrorHandler', '\uC5D0\uB7EC \uC0C1\uC138:', error.message, error.name);\r\n \r\n // \uC5D0\uB7EC \uD0C0\uC785 \uBD84\uC11D (\uB354 \uC815\uD655\uD55C 404 \uAC10\uC9C0)\r\n if (error.message.includes('not found') || \r\n error.message.includes('404') ||\r\n error.message.includes('Failed to resolve') ||\r\n error.message.includes('Failed to fetch') ||\r\n (error.name === 'TypeError' && error.message.includes('resolve'))) {\r\n errorCode = 404;\r\n errorMessage = `'${routeName}' \uD398\uC774\uC9C0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.`;\r\n } else if (error.message.includes('network') && !error.message.includes('not found')) {\r\n errorCode = 503;\r\n errorMessage = '\uB124\uD2B8\uC6CC\uD06C \uC5F0\uACB0\uC744 \uD655\uC778\uD574 \uC8FC\uC138\uC694.';\r\n } else if (error.message.includes('permission') || error.message.includes('403')) {\r\n errorCode = 403;\r\n errorMessage = '\uD398\uC774\uC9C0\uC5D0 \uC811\uADFC\uD560 \uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.';\r\n }\r\n \r\n this.debug('ErrorHandler', `\uC5D0\uB7EC \uCF54\uB4DC \uACB0\uC815: ${errorCode} (\uB77C\uC6B0\uD2B8: ${routeName})`);\r\n\r\n // \uC5D0\uB7EC \uB9AC\uD3EC\uD305\r\n this.reportError(routeName, error, errorCode);\r\n \r\n try {\r\n // 404 \uD398\uC774\uC9C0 \uC804\uC6A9 \uCC98\uB9AC\r\n if (errorCode === 404) {\r\n await this.load404Page();\r\n } else {\r\n // \uC77C\uBC18 \uC5D0\uB7EC \uD398\uC774\uC9C0\r\n await this.loadErrorPage(errorCode, errorMessage);\r\n }\r\n } catch (fallbackError) {\r\n this.error('ErrorHandler', '\uC5D0\uB7EC \uD398\uC774\uC9C0 \uB85C\uB529 \uC2E4\uD328:', fallbackError);\r\n // \uBAA8\uB4E0 \uC5D0\uB7EC \uD398\uC774\uC9C0\uAC00 \uC2E4\uD328\uD588\uC744 \uB54C \uCD5C\uD6C4\uC758 \uD3F4\uBC31 \uD398\uC774\uC9C0 \uD45C\uC2DC\r\n this.showFallbackErrorPage(errorCode, errorMessage);\r\n }\r\n }\r\n\r\n /**\r\n * 404 \uD398\uC774\uC9C0 \uB85C\uB529\r\n */\r\n async load404Page() {\r\n try {\r\n this.info('ErrorHandler', 'Loading 404 page...');\r\n const component = await this.createVueComponent('404');\r\n await this.renderComponentWithTransition(component, '404');\r\n this.info('ErrorHandler', '404 page loaded successfully');\r\n } catch (error) {\r\n this.error('ErrorHandler', '404 page loading failed:', error);\r\n // 404 \uD398\uC774\uC9C0\uB3C4 \uC5C6\uC73C\uBA74 \uAC04\uB2E8\uD55C \uC5D0\uB7EC \uBA54\uC2DC\uC9C0 \uD45C\uC2DC\r\n this.showFallbackErrorPage('404', '\uD398\uC774\uC9C0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.');\r\n }\r\n }\r\n\r\n /**\r\n * \uC5D0\uB7EC \uD398\uC774\uC9C0 \uB85C\uB529\r\n */\r\n async loadErrorPage(errorCode, errorMessage) {\r\n try {\r\n this.info('ErrorHandler', `Loading error page for ${errorCode}...`);\r\n \r\n // \uC5D0\uB7EC \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131\r\n const errorComponent = await this.createErrorComponent(errorCode, errorMessage);\r\n await this.renderComponentWithTransition(errorComponent, 'error');\r\n this.info('ErrorHandler', `Error page ${errorCode} loaded successfully`);\r\n } catch (error) {\r\n this.error('ErrorHandler', `Error page ${errorCode} loading failed:`, error);\r\n // \uC5D0\uB7EC \uD398\uC774\uC9C0\uB3C4 \uB85C\uB529 \uC2E4\uD328\uD558\uBA74 \uD3F4\uBC31 \uD45C\uC2DC\r\n this.showFallbackErrorPage(errorCode, errorMessage);\r\n }\r\n }\r\n\r\n /**\r\n * \uC5D0\uB7EC \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131\r\n */\r\n async createErrorComponent(errorCode, errorMessage) {\r\n try {\r\n // \uC5D0\uB7EC \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uB3D9\uC801\uC73C\uB85C \uB85C\uB4DC\r\n const component = await this.createVueComponent('error');\r\n \r\n // \uC5D0\uB7EC \uC815\uBCF4\uB97C props\uB85C \uC804\uB2EC\r\n const errorComponent = {\r\n ...component,\r\n data() {\r\n const originalData = component.data ? component.data() : {};\r\n return {\r\n ...originalData,\r\n errorCode,\r\n errorMessage,\r\n showRetry: true,\r\n showGoHome: true\r\n };\r\n }\r\n };\r\n \r\n return errorComponent;\r\n } catch (error) {\r\n // \uC5D0\uB7EC \uCEF4\uD3EC\uB10C\uD2B8\uB3C4 \uB85C\uB4DC\uD560 \uC218 \uC5C6\uB294 \uACBD\uC6B0 \uAC04\uB2E8\uD55C \uC5D0\uB7EC \uD45C\uC2DC\r\n this.error('ErrorHandler', 'Error component load failed:', error);\r\n throw new Error(`Cannot load error page: ${error.message}`);\r\n }\r\n }\r\n\r\n /**\r\n * \uD3F4\uBC31 \uC5D0\uB7EC \uD398\uC774\uC9C0 \uD45C\uC2DC (\uBAA8\uB4E0 \uC5D0\uB7EC \uD398\uC774\uC9C0\uAC00 \uC2E4\uD328\uD588\uC744 \uB54C)\r\n */\r\n showFallbackErrorPage(errorCode, errorMessage) {\r\n const appElement = document.getElementById('app');\r\n if (!appElement) return;\r\n\r\n const fallbackHTML = `<div style=\"text-align:center;padding:2rem;font-family:sans-serif\"><h1>${errorCode}</h1><p>${errorMessage}</p><button onclick=\"location.reload()\">Retry</button></div>`;\r\n\r\n // \uAE30\uC874 \uCEE8\uD14C\uC774\uB108\uB4E4 \uC815\uB9AC\r\n appElement.innerHTML = fallbackHTML;\r\n \r\n this.info('ErrorHandler', `Fallback error page displayed for ${errorCode}`);\r\n }\r\n\r\n /**\r\n * \uC5D0\uB7EC \uB9AC\uD3EC\uD305\r\n */\r\n reportError(routeName, error, errorCode) {\r\n const errorReport = {\r\n route: routeName,\r\n errorCode,\r\n errorMessage: error.message,\r\n stack: error.stack,\r\n url: window.location.href,\r\n userAgent: navigator.userAgent,\r\n timestamp: new Date().toISOString(),\r\n routerConfig: {\r\n environment: this.router?.config?.environment || 'unknown',\r\n mode: this.router?.config?.mode || 'unknown'\r\n }\r\n };\r\n \r\n this.error('ErrorHandler', '\uB77C\uC6B0\uD130 \uC5D0\uB7EC \uB9AC\uD3EC\uD2B8:', errorReport);\r\n \r\n // \uCD94\uD6C4 \uC5D0\uB7EC \uCD94\uC801 \uC11C\uBE44\uC2A4\uB85C \uC804\uC1A1\uD560 \uC218 \uC788\uC74C\r\n // \uC608: analytics.track('router_error', errorReport);\r\n }\r\n\r\n /**\r\n * Vue \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131 (RouteLoader \uC704\uC784)\r\n */\r\n async createVueComponent(routeName) {\r\n if (this.router.routeLoader) {\r\n return await this.router.routeLoader.createVueComponent(routeName);\r\n }\r\n throw new Error('RouteLoader not available');\r\n }\r\n\r\n /**\r\n * \uCEF4\uD3EC\uB10C\uD2B8 \uB80C\uB354\uB9C1 (ViewManager \uC704\uC784)\r\n */\r\n async renderComponentWithTransition(component, routeName) {\r\n if (this.router.renderComponentWithTransition) {\r\n return await this.router.renderComponentWithTransition(component, routeName);\r\n }\r\n throw new Error('Render function not available');\r\n }\r\n\r\n /**\r\n * \uD1B5\uD569 \uB85C\uAE45 \uC2DC\uC2A4\uD15C\r\n * @param {string} level - \uB85C\uADF8 \uB808\uBCA8 (error, warn, info, debug)\r\n * @param {string} component - \uCEF4\uD3EC\uB10C\uD2B8 \uC774\uB984 (\uC120\uD0DD\uC801)\r\n * @param {...any} args - \uB85C\uADF8 \uBA54\uC2DC\uC9C0\r\n */\r\n log(level, component, ...args) {\r\n // \uD558\uC704 \uD638\uD658\uC131: \uAE30\uC874 \uBC29\uC2DD\uB3C4 \uC9C0\uC6D0\r\n if (typeof level !== 'string' || !this.logLevels.hasOwnProperty(level)) {\r\n args = [component, ...args];\r\n component = level;\r\n level = 'info';\r\n }\r\n \r\n // \uB85C\uADF8 \uB808\uBCA8 \uD655\uC778\r\n const currentLevelValue = this.logLevels[this.config.logLevel] || this.logLevels.info;\r\n const messageLevelValue = this.logLevels[level] || this.logLevels.info;\r\n \r\n if (messageLevelValue > currentLevelValue) {\r\n return; // \uD604\uC7AC \uC124\uC815\uB41C \uB808\uBCA8\uBCF4\uB2E4 \uB192\uC73C\uBA74 \uCD9C\uB825 \uC548\uD568\r\n }\r\n \r\n // \uD504\uB85C\uB355\uC158 \uD658\uACBD\uC5D0\uC11C\uB294 error\uC640 warn\uB9CC \uCD9C\uB825\r\n if (this.config.environment === 'production' && messageLevelValue > this.logLevels.warn) {\r\n return;\r\n }\r\n \r\n const prefix = component ? `[${component}]` : '[ViewLogic]';\r\n const timestamp = new Date().toISOString().substring(11, 23); // HH:MM:SS.mmm\r\n \r\n switch (level) {\r\n case 'error':\r\n console.error(`${timestamp} ${prefix}`, ...args);\r\n break;\r\n case 'warn':\r\n console.warn(`${timestamp} ${prefix}`, ...args);\r\n break;\r\n case 'info':\r\n console.info(`${timestamp} ${prefix}`, ...args);\r\n break;\r\n case 'debug':\r\n console.log(`${timestamp} ${prefix}`, ...args);\r\n break;\r\n default:\r\n console.log(`${timestamp} ${prefix}`, ...args);\r\n }\r\n }\r\n \r\n /**\r\n * \uC5D0\uB7EC \uB85C\uADF8 (\uD56D\uC0C1 \uCD9C\uB825)\r\n */\r\n error(component, ...args) {\r\n this.log('error', component, ...args);\r\n }\r\n \r\n /**\r\n * \uACBD\uACE0 \uB85C\uADF8\r\n */\r\n warn(component, ...args) {\r\n this.log('warn', component, ...args);\r\n }\r\n \r\n /**\r\n * \uC815\uBCF4 \uB85C\uADF8\r\n */\r\n info(component, ...args) {\r\n this.log('info', component, ...args);\r\n }\r\n \r\n /**\r\n * \uB514\uBC84\uADF8 \uB85C\uADF8\r\n */\r\n debug(component, ...args) {\r\n this.log('debug', component, ...args);\r\n }\r\n\r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n this.router = null;\r\n this.info('ErrorHandler', 'ErrorHandler destroyed');\r\n }\r\n}", "/**\r\n * ViewLogic State Management System\r\n * \uC804\uC5ED \uC0C1\uD0DC \uAD00\uB9AC \uC2DC\uC2A4\uD15C\r\n */\r\nexport class StateHandler {\r\n constructor(router) {\r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870\r\n this.router = router;\r\n\r\n // \uBC18\uC751\uD615 \uC0C1\uD0DC \uC800\uC7A5\uC18C\r\n this.state = {};\r\n\r\n // \uC0C1\uD0DC \uBCC0\uACBD \uB9AC\uC2A4\uB108\uB4E4\r\n this.listeners = new Map();\r\n\r\n this.log('debug', 'StateHandler initialized');\r\n }\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'StateHandler', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * \uC0C1\uD0DC \uAC12 \uC124\uC815\r\n */\r\n set(key, value) {\r\n const oldValue = this.state[key];\r\n this.state[key] = value;\r\n\r\n // \uBCC0\uACBD \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n this.emitChange(key, value, oldValue);\r\n\r\n this.log('debug', `State set: ${key}`, value);\r\n return value;\r\n }\r\n\r\n /**\r\n * \uC0C1\uD0DC \uAC12 \uAC00\uC838\uC624\uAE30\r\n */\r\n get(key, defaultValue = undefined) {\r\n const value = this.state.hasOwnProperty(key) ? this.state[key] : defaultValue;\r\n this.log('debug', `State get: ${key}`, value);\r\n return value;\r\n }\r\n\r\n /**\r\n * \uC0C1\uD0DC \uC874\uC7AC \uD655\uC778\r\n */\r\n has(key) {\r\n return this.state.hasOwnProperty(key);\r\n }\r\n\r\n /**\r\n * \uC0C1\uD0DC \uC0AD\uC81C\r\n */\r\n delete(key) {\r\n if (this.has(key)) {\r\n const oldValue = this.state[key];\r\n delete this.state[key];\r\n\r\n // \uC0AD\uC81C \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n this.emitChange(key, undefined, oldValue);\r\n\r\n this.log('debug', `State deleted: ${key}`);\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * \uBAA8\uB4E0 \uC0C1\uD0DC \uCD08\uAE30\uD654\r\n */\r\n clear() {\r\n const keys = Object.keys(this.state);\r\n this.state = {};\r\n\r\n // \uAC01 \uD0A4\uC5D0 \uB300\uD574 \uC0AD\uC81C \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n keys.forEach(key => {\r\n this.emitChange(key, undefined, this.state[key]);\r\n });\r\n\r\n this.log('debug', 'All state cleared');\r\n return keys.length;\r\n }\r\n\r\n /**\r\n * \uC5EC\uB7EC \uC0C1\uD0DC \uD55C \uBC88\uC5D0 \uC124\uC815\r\n */\r\n update(updates) {\r\n if (!updates || typeof updates !== 'object') {\r\n this.log('warn', 'Invalid updates object provided');\r\n return;\r\n }\r\n\r\n Object.entries(updates).forEach(([key, value]) => {\r\n this.set(key, value);\r\n });\r\n }\r\n\r\n /**\r\n * \uBAA8\uB4E0 \uC0C1\uD0DC \uBC18\uD658\r\n */\r\n getAll() {\r\n return { ...this.state };\r\n }\r\n\r\n /**\r\n * \uC0C1\uD0DC \uBCC0\uACBD \uB9AC\uC2A4\uB108 \uB4F1\uB85D\r\n */\r\n watch(key, callback) {\r\n if (!this.listeners.has(key)) {\r\n this.listeners.set(key, []);\r\n }\r\n this.listeners.get(key).push(callback);\r\n\r\n this.log('debug', `Watcher added for: ${key}`);\r\n }\r\n\r\n /**\r\n * \uC0C1\uD0DC \uBCC0\uACBD \uB9AC\uC2A4\uB108 \uC81C\uAC70\r\n */\r\n unwatch(key, callback) {\r\n if (this.listeners.has(key)) {\r\n const callbacks = this.listeners.get(key);\r\n const index = callbacks.indexOf(callback);\r\n if (index > -1) {\r\n callbacks.splice(index, 1);\r\n this.log('debug', `Watcher removed for: ${key}`);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * \uC0C1\uD0DC \uBCC0\uACBD \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n */\r\n emitChange(key, newValue, oldValue) {\r\n if (this.listeners.has(key)) {\r\n this.listeners.get(key).forEach(callback => {\r\n try {\r\n callback(newValue, oldValue, key);\r\n } catch (error) {\r\n this.log('error', 'State watcher error:', error);\r\n }\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * \uC0C1\uD0DC \uD1B5\uACC4\r\n */\r\n getStats() {\r\n return {\r\n stateCount: Object.keys(this.state).length,\r\n watcherCount: Array.from(this.listeners.values()).reduce((sum, arr) => sum + arr.length, 0),\r\n keys: Object.keys(this.state)\r\n };\r\n }\r\n\r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n this.state = {};\r\n this.listeners.clear();\r\n this.log('debug', 'StateHandler destroyed');\r\n }\r\n}", "// ViewLogic Router - ES6 Module\r\nimport { I18nManager } from './plugins/I18nManager.js';\r\nimport { AuthManager } from './plugins/AuthManager.js';\r\nimport { CacheManager } from './plugins/CacheManager.js';\r\nimport { QueryManager } from './plugins/QueryManager.js';\r\nimport { RouteLoader } from './core/RouteLoader.js';\r\nimport { ErrorHandler } from './core/ErrorHandler.js';\r\nimport { StateHandler } from './core/StateHandler.js';\r\n\r\nexport class ViewLogicRouter {\r\n constructor(options = {}) {\r\n // \uBC84\uC804 \uC815\uBCF4\r\n this.version = options.version || '1.0.0';\r\n \r\n // \uAE30\uBCF8 \uD658\uACBD\uC124\uC815 \uCD5C\uC801\uD654\r\n this.config = this._buildConfig(options);\r\n \r\n this.currentHash = '';\r\n this.currentVueApp = null;\r\n this.previousVueApp = null; // \uC774\uC804 Vue \uC571 (\uC804\uD658 \uD6A8\uACFC\uB97C \uC704\uD574 \uBCF4\uAD00)\r\n\r\n // LoadingManager\uAC00 \uC5C6\uC744 \uB54C\uB97C \uC704\uD55C \uAE30\uBCF8 \uC804\uD658 \uC0C1\uD0DC\r\n this.transitionInProgress = false;\r\n \r\n // \uCD08\uAE30\uD654 \uC900\uBE44 \uC0C1\uD0DC\r\n this.isReady = false;\r\n this.readyPromise = null;\r\n \r\n // \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uBC14\uC778\uB529 \uCD5C\uC801\uD654\r\n this._boundHandleRouteChange = this.handleRouteChange.bind(this);\r\n \r\n // \uBAA8\uB4E0 \uCD08\uAE30\uD654\uB97C \uD55C\uBC88\uC5D0 \uCC98\uB9AC\r\n this.readyPromise = this.initialize();\r\n }\r\n\r\n /**\r\n * \uC124\uC815 \uBE4C\uB4DC (\uBD84\uB9AC\uD558\uC5EC \uAC00\uB3C5\uC131 \uD5A5\uC0C1)\r\n */\r\n _buildConfig(options) {\r\n const currentOrigin = window.location.origin;\r\n \r\n const defaults = {\r\n basePath: '/', // \uC560\uD50C\uB9AC\uCF00\uC774\uC158 \uAE30\uBCF8 \uACBD\uB85C (\uC11C\uBE0C\uD3F4\uB354 \uBC30\uD3EC\uC6A9)\r\n srcPath: '/src', // \uC18C\uC2A4 \uD30C\uC77C \uACBD\uB85C\r\n mode: 'hash',\r\n cacheMode: 'memory',\r\n cacheTTL: 300000,\r\n maxCacheSize: 50,\r\n useLayout: true,\r\n defaultLayout: 'default',\r\n environment: 'development',\r\n routesPath: '/routes', // \uD504\uB85C\uB355\uC158 \uB77C\uC6B0\uD2B8 \uACBD\uB85C\r\n enableErrorReporting: true,\r\n useI18n: false,\r\n defaultLanguage: 'ko',\r\n i18nPath: '/i18n', // \uB2E4\uAD6D\uC5B4 \uD30C\uC77C \uACBD\uB85C\r\n logLevel: 'info',\r\n apiBaseURL: '',\r\n requestTimeout: 30000,\r\n uploadTimeout: 300000,\r\n authEnabled: false,\r\n loginRoute: 'login',\r\n protectedRoutes: [],\r\n protectedPrefixes: [],\r\n publicRoutes: ['login', 'register', 'home'],\r\n checkAuthFunction: null,\r\n redirectAfterLogin: 'home',\r\n authCookieName: 'authToken',\r\n authStorage: 'localStorage'\r\n };\r\n \r\n const config = { ...defaults, ...options };\r\n\r\n // \uC808\uB300 \uACBD\uB85C\uB4E4\uC744 basePath \uAE30\uC900\uC73C\uB85C \uD574\uACB0\r\n config.srcPath = this.resolvePath(config.srcPath, config.basePath);\r\n config.routesPath = this.resolvePath(config.routesPath, config.basePath);\r\n config.i18nPath = this.resolvePath(config.i18nPath, config.basePath);\r\n\r\n return config;\r\n }\r\n\r\n /**\r\n * \uB450 \uACBD\uB85C\uB97C \uC548\uC804\uD558\uAC8C \uC870\uD569 \uBC0F \uC815\uADDC\uD654 (\uAE30\uBCF8 \uC720\uD2F8\uB9AC\uD2F0)\r\n * @param {string} basePath - \uAE30\uBCF8 \uACBD\uB85C\r\n * @param {string} relativePath - \uC0C1\uB300 \uACBD\uB85C\r\n * @returns {string} \uC870\uD569\uB41C \uACBD\uB85C (\uC608: '/examples' + '/about' \u2192 '/examples/about')\r\n */\r\n combinePaths(basePath, relativePath) {\r\n if (!basePath || basePath === '/') {\r\n return relativePath.replace(/\\/+/g, '/');\r\n }\r\n\r\n const cleanBase = basePath.endsWith('/') ? basePath.slice(0, -1) : basePath;\r\n const cleanRelative = relativePath.startsWith('/') ? relativePath : `/${relativePath}`;\r\n const combined = `${cleanBase}${cleanRelative}`;\r\n\r\n // \uC774\uC911 \uC2AC\uB798\uC2DC \uC81C\uAC70\r\n return combined.replace(/\\/+/g, '/');\r\n }\r\n\r\n\r\n /**\r\n * \uC0C1\uB300 \uACBD\uB85C\uB97C \uC644\uC804\uD55C \uC808\uB300 URL\uB85C \uBCC0\uD658 (\uD30C\uC77C \uC2DC\uC2A4\uD15C \uC804\uC6A9)\r\n * @param {string} path - \uBCC0\uD658\uD560 \uACBD\uB85C\r\n * @param {string} basePath - \uAE30\uBCF8 \uACBD\uB85C (\uC635\uC158)\r\n * @returns {string} \uC644\uC804\uD55C \uC808\uB300 URL (\uC608: 'http://localhost:3000/examples/about')\r\n */\r\n resolvePath(path, basePath = null) {\r\n // basePath\uAC00 \uC81C\uACF5\uB418\uC9C0 \uC54A\uC73C\uBA74 config\uC5D0\uC11C \uAC00\uC838\uC624\uAE30\r\n if (basePath === null) {\r\n basePath = this.config?.basePath || '/';\r\n }\r\n const currentOrigin = window.location.origin;\r\n \r\n // \uC774\uBBF8 \uC644\uC804\uD55C HTTP URL\uC778 \uACBD\uC6B0 \uBCC0\uD658 \uBD88\uD544\uC694\r\n if (path.startsWith('http')) {\r\n return path;\r\n }\r\n\r\n // \uC808\uB300 \uACBD\uB85C \u2192 \uC644\uC804\uD55C URL \uBCC0\uD658\r\n if (path.startsWith('/')) {\r\n const combinedPath = this.combinePaths(basePath, path);\r\n return `${currentOrigin}${combinedPath}`;\r\n }\r\n \r\n // \uC0C1\uB300 \uACBD\uB85C\uC778 \uACBD\uC6B0 \uD604\uC7AC \uACBD\uB85C \uAE30\uC900\uC73C\uB85C \uD574\uACB0\r\n const currentPathname = window.location.pathname;\r\n const currentBase = currentPathname.endsWith('/') \r\n ? currentPathname \r\n : currentPathname.substring(0, currentPathname.lastIndexOf('/') + 1);\r\n \r\n // \uC0C1\uB300 \uACBD\uB85C \uC815\uADDC\uD654\r\n const resolvedPath = this.combinePaths(currentBase, path);\r\n \r\n return `${currentOrigin}${resolvedPath}`;\r\n }\r\n\r\n\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.errorHandler) {\r\n this.errorHandler.log(level, 'Router', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * \uD1B5\uD569 \uCD08\uAE30\uD654 - \uB9E4\uB2C8\uC800 \uC0DD\uC131 \u2192 \uBE44\uB3D9\uAE30 \uB85C\uB529 \u2192 \uB77C\uC6B0\uD130 \uC2DC\uC791\r\n */\r\n async initialize() {\r\n try {\r\n // 1. \uB9E4\uB2C8\uC800 \uCD08\uAE30\uD654 (\uB3D9\uAE30)\r\n // \uD56D\uC0C1 \uD544\uC694\uD55C \uB9E4\uB2C8\uC800\uB4E4\r\n this.cacheManager = new CacheManager(this, this.config);\r\n this.stateHandler = new StateHandler(this);\r\n this.routeLoader = new RouteLoader(this, this.config);\r\n this.queryManager = new QueryManager(this);\r\n this.errorHandler = new ErrorHandler(this, this.config);\r\n \r\n // \uC870\uAC74\uBD80 \uB9E4\uB2C8\uC800\uB4E4\r\n if (this.config.useI18n) {\r\n try {\r\n this.i18nManager = new I18nManager(this, this.config);\r\n if (this.i18nManager.initPromise) {\r\n await this.i18nManager.initPromise;\r\n }\r\n this.log('info', 'I18nManager initialized successfully');\r\n } catch (i18nError) {\r\n this.log('warn', 'I18nManager initialization failed, continuing without i18n:', i18nError.message);\r\n this.i18nManager = null; // i18n \uB9E4\uB2C8\uC800 \uBE44\uD65C\uC131\uD654\r\n this.config.useI18n = false; // i18n \uBE44\uD65C\uC131\uD654\r\n }\r\n }\r\n \r\n if (this.config.authEnabled) {\r\n this.authManager = new AuthManager(this, this.config);\r\n }\r\n \r\n \r\n // 2. \uB77C\uC6B0\uD130 \uC2DC\uC791\r\n this.isReady = true;\r\n this.init();\r\n \r\n } catch (error) {\r\n this.log('error', 'Router initialization failed:', error);\r\n // \uC2E4\uD328\uD574\uB3C4 \uB77C\uC6B0\uD130\uB294 \uC2DC\uC791 (graceful degradation)\r\n this.isReady = true;\r\n this.init();\r\n }\r\n }\r\n\r\n /**\r\n * \uB77C\uC6B0\uD130\uAC00 \uC900\uBE44\uB420 \uB54C\uAE4C\uC9C0 \uB300\uAE30\r\n */\r\n async waitForReady() {\r\n if (this.isReady) return true;\r\n if (this.readyPromise) {\r\n await this.readyPromise;\r\n }\r\n return this.isReady;\r\n }\r\n\r\n\r\n init() {\r\n const isHashMode = this.config.mode === 'hash';\r\n \r\n // \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uB4F1\uB85D (\uBA54\uBAA8\uB9AC \uCD5C\uC801\uD654)\r\n window.addEventListener(\r\n isHashMode ? 'hashchange' : 'popstate',\r\n this._boundHandleRouteChange\r\n );\r\n \r\n // DOM \uB85C\uB4DC \uCC98\uB9AC \uD1B5\uD569\r\n const initRoute = () => {\r\n if (isHashMode && !window.location.hash) {\r\n window.location.hash = '#/';\r\n } else if (!isHashMode && window.location.pathname === '/') {\r\n this.navigateTo('home');\r\n } else {\r\n this.handleRouteChange();\r\n }\r\n };\r\n \r\n if (document.readyState === 'loading') {\r\n document.addEventListener('DOMContentLoaded', initRoute);\r\n } else {\r\n // requestAnimationFrame\uC73C\uB85C \uC131\uB2A5 \uAC1C\uC120\r\n requestAnimationFrame(initRoute);\r\n }\r\n }\r\n\r\n handleRouteChange() {\r\n const { route, queryParams } = this._parseCurrentLocation();\r\n \r\n // Store current query parameters in QueryManager\r\n this.queryManager?.setCurrentQueryParams(queryParams);\r\n \r\n // \uBCC0\uACBD\uC0AC\uD56D\uC774 \uC788\uC744 \uB54C\uB9CC \uB85C\uB4DC (\uC131\uB2A5 \uCD5C\uC801\uD654)\r\n if (route !== this.currentHash || this.queryManager?.hasQueryParamsChanged(queryParams)) {\r\n this.currentHash = route;\r\n this.loadRoute(route);\r\n }\r\n }\r\n\r\n /**\r\n * \uD604\uC7AC \uC704\uCE58 \uD30C\uC2F1 (\uBD84\uB9AC\uD558\uC5EC \uAC00\uB3C5\uC131 \uD5A5\uC0C1)\r\n */\r\n _parseCurrentLocation() {\r\n if (this.config.mode === 'hash') {\r\n const hashPath = window.location.hash.slice(1) || '/';\r\n const [pathPart, queryPart] = hashPath.split('?');\r\n \r\n // \uACBD\uB85C \uD30C\uC2F1 \uCD5C\uC801\uD654\r\n let route = 'home';\r\n if (pathPart && pathPart !== '/') {\r\n route = pathPart.startsWith('/') ? pathPart.slice(1) : pathPart;\r\n }\r\n \r\n return {\r\n route: route || 'home',\r\n queryParams: this.queryManager?.parseQueryString(queryPart || window.location.search.slice(1)) || {}\r\n };\r\n } else {\r\n // History Mode - \uC11C\uBE0C\uD3F4\uB354 \uBC30\uD3EC \uC9C0\uC6D0\r\n const fullPath = window.location.pathname;\r\n const basePath = this.config.basePath || '/';\r\n \r\n // base path \uC81C\uAC70\uD558\uC5EC \uC2E4\uC81C route \uCD94\uCD9C\r\n let route = fullPath;\r\n if (basePath !== '/' && fullPath.startsWith(basePath)) {\r\n route = fullPath.slice(basePath.length);\r\n }\r\n \r\n // \uB9E8 \uC55E\uC758 / \uC81C\uAC70\r\n if (route.startsWith('/')) {\r\n route = route.slice(1);\r\n }\r\n \r\n return {\r\n route: route || 'home',\r\n queryParams: this.queryManager?.parseQueryString(window.location.search.slice(1)) || {}\r\n };\r\n }\r\n }\r\n\r\n async loadRoute(routeName) {\r\n // \uC804\uD658\uC774 \uC9C4\uD589 \uC911\uC774\uBA74 \uBB34\uC2DC\r\n const inProgress = this.transitionInProgress;\r\n \r\n if (inProgress) {\r\n return;\r\n }\r\n\r\n try {\r\n this.transitionInProgress = true;\r\n \r\n // \uC778\uC99D \uCCB4\uD06C\r\n const authResult = this.authManager ? \r\n await this.authManager.checkAuthentication(routeName) :\r\n { allowed: true, reason: 'auth_disabled' };\r\n if (!authResult.allowed) {\r\n // \uC778\uC99D \uC2E4\uD328 \uC2DC \uB85C\uADF8\uC778 \uD398\uC774\uC9C0\uB85C \uB9AC\uB2E4\uC774\uB809\uD2B8\r\n if (this.authManager) {\r\n this.authManager.emitAuthEvent('auth_required', { \r\n originalRoute: routeName,\r\n loginRoute: this.config.loginRoute \r\n });\r\n \r\n // navigateTo\uB97C \uC0AC\uC6A9\uD558\uC5EC \uC774\uC804 \uD398\uC774\uC9C0\uB85C \uB3CC\uC544\uAC00\uAE30 \uC9C0\uC6D0\r\n if (routeName !== this.config.loginRoute) {\r\n this.navigateTo(this.config.loginRoute, { redirect: routeName });\r\n } else {\r\n this.navigateTo(this.config.loginRoute);\r\n }\r\n }\r\n return;\r\n }\r\n \r\n const appElement = document.getElementById('app');\r\n if (!appElement) {\r\n throw new Error('App element not found');\r\n }\r\n\r\n // Vue \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131 (\uBC31\uADF8\uB77C\uC6B4\uB4DC\uC5D0\uC11C)\r\n const component = await this.routeLoader.createVueComponent(routeName);\r\n \r\n // \uC0C8\uB85C\uC6B4 \uD398\uC774\uC9C0\uB97C \uC624\uBC84\uB808\uC774\uB85C \uB80C\uB354\uB9C1\r\n await this.renderComponentWithTransition(component, routeName);\r\n \r\n // \uB85C\uB529 \uC644\uB8CC\r\n \r\n } catch (error) {\r\n this.log('error', `Route loading failed [${routeName}]:`, error.message);\r\n \r\n \r\n // \uC5D0\uB7EC \uD0C0\uC785\uC5D0 \uB530\uB978 \uCC98\uB9AC\r\n if (this.errorHandler) {\r\n await this.errorHandler.handleRouteError(routeName, error);\r\n } else {\r\n // ErrorHandler\uAC00 \uC5C6\uB294 \uADF9\uB2E8\uC801 \uC0C1\uD669 - \uCD5C\uC18C\uD55C\uC758 \uC5D0\uB7EC \uD45C\uC2DC\r\n console.error('[Router] Critical: No error handler available for route error:', error);\r\n }\r\n } finally {\r\n // \uBAA8\uB4E0 \uCC98\uB9AC\uAC00 \uC644\uB8CC\uB41C \uD6C4 \uC804\uD658 \uC0C1\uD0DC \uB9AC\uC14B\r\n this.transitionInProgress = false;\r\n }\r\n }\r\n\r\n async renderComponentWithTransition(vueComponent, routeName) {\r\n const appElement = document.getElementById('app');\r\n if (!appElement) return;\r\n\r\n // \uC0C8\uB85C\uC6B4 \uD398\uC774\uC9C0 \uCEE8\uD14C\uC774\uB108 \uC0DD\uC131\r\n const newPageContainer = document.createElement('div');\r\n newPageContainer.className = 'page-container page-entered';\r\n newPageContainer.id = `page-${routeName}-${Date.now()}`;\r\n \r\n // \uAE30\uC874 \uCEE8\uD14C\uC774\uB108\uAC00 \uC788\uB2E4\uBA74 \uC989\uC2DC \uC228\uAE30\uAE30\r\n const existingContainers = appElement.querySelectorAll('.page-container');\r\n existingContainers.forEach(container => {\r\n container.classList.remove('page-entered');\r\n container.classList.add('page-exiting');\r\n });\r\n\r\n // \uC0C8 \uCEE8\uD14C\uC774\uB108\uB97C \uC571\uC5D0 \uCD94\uAC00\r\n appElement.appendChild(newPageContainer);\r\n\r\n // \uAC1C\uBC1C \uBAA8\uB4DC\uC5D0\uC11C\uB9CC \uC2A4\uD0C0\uC77C \uC801\uC6A9 (\uD504\uB85C\uB355\uC158 \uBAA8\uB4DC\uB294 \uBE4C\uB4DC\uB41C JS\uC5D0\uC11C \uC790\uB3D9 \uCC98\uB9AC)\r\n if (this.config.environment === 'development' && vueComponent._style) {\r\n this.applyStyle(vueComponent._style, routeName);\r\n }\r\n \r\n // \uC0C8\uB85C\uC6B4 Vue \uC571\uC744 \uC0C8 \uCEE8\uD14C\uC774\uB108\uC5D0 \uB9C8\uC6B4\uD2B8\r\n const { createApp } = Vue;\r\n const newVueApp = createApp(vueComponent);\r\n\r\n // Vue 3 \uC804\uC5ED \uC18D\uC131 \uC124\uC815\r\n newVueApp.config.globalProperties.$router = {\r\n navigateTo: (route, params) => this.navigateTo(route, params),\r\n getCurrentRoute: () => this.getCurrentRoute(),\r\n\r\n // \uD1B5\uD569\uB41C \uD30C\uB77C\uBBF8\uD130 \uAD00\uB9AC (\uB77C\uC6B0\uD305 + \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130)\r\n getParams: () => this.queryManager?.getAllParams() || {},\r\n getParam: (key, defaultValue) => this.queryManager?.getParam(key, defaultValue),\r\n\r\n // \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uC804\uC6A9 \uBA54\uC11C\uB4DC (\uD558\uC704 \uD638\uD658\uC131)\r\n getQueryParams: () => this.queryManager?.getQueryParams() || {},\r\n getQueryParam: (key, defaultValue) => this.queryManager?.getQueryParam(key, defaultValue),\r\n setQueryParams: (params, replace) => this.queryManager?.setQueryParams(params, replace),\r\n removeQueryParams: (keys) => this.queryManager?.removeQueryParams(keys),\r\n\r\n // \uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130 \uC804\uC6A9 \uBA54\uC11C\uB4DC\r\n getRouteParams: () => this.queryManager?.getRouteParams() || {},\r\n getRouteParam: (key, defaultValue) => this.queryManager?.getRouteParam(key, defaultValue),\r\n\r\n currentRoute: this.currentHash,\r\n currentQuery: this.queryManager?.getQueryParams() || {}\r\n };\r\n\r\n // \uBAA8\uBC14\uC77C \uBA54\uB274 \uC804\uC5ED \uD568\uC218 \uCD94\uAC00\r\n\r\n newVueApp.mount(`#${newPageContainer.id}`);\r\n\r\n // \uB77C\uC6B0\uD2B8 \uC774\uB3D9 \uC2DC \uC2A4\uD06C\uB864\uC744 \uB9E8 \uC704\uB85C \uC774\uB3D9\r\n window.scrollTo(0, 0);\r\n\r\n // requestAnimationFrame\uC73C\uB85C \uC131\uB2A5 \uAC1C\uC120\r\n requestAnimationFrame(() => {\r\n this.cleanupPreviousPages();\r\n this.transitionInProgress = false;\r\n });\r\n\r\n // \uC774\uC804 \uC571 \uC815\uB9AC \uC900\uBE44\r\n if (this.currentVueApp) {\r\n this.previousVueApp = this.currentVueApp;\r\n }\r\n \r\n this.currentVueApp = newVueApp;\r\n }\r\n\r\n cleanupPreviousPages() {\r\n const appElement = document.getElementById('app');\r\n if (!appElement) return;\r\n\r\n // \uBC30\uCE58 DOM \uC870\uC791\uC73C\uB85C \uC131\uB2A5 \uAC1C\uC120\r\n const fragment = document.createDocumentFragment();\r\n const exitingContainers = appElement.querySelectorAll('.page-container.page-exiting');\r\n \r\n // \uD55C\uBC88\uC5D0 \uC81C\uAC70\r\n exitingContainers.forEach(container => container.remove());\r\n\r\n // \uC774\uC804 Vue \uC571 \uC815\uB9AC\r\n if (this.previousVueApp) {\r\n try {\r\n this.previousVueApp.unmount();\r\n } catch (error) {\r\n // \uBB34\uC2DC (\uC774\uBBF8 \uC5B8\uB9C8\uC6B4\uD2B8\uB41C \uACBD\uC6B0)\r\n }\r\n this.previousVueApp = null;\r\n }\r\n\r\n // \uB85C\uB529 \uC5D8\uB9AC\uBA3C\uD2B8 \uC81C\uAC70\r\n \r\n appElement.querySelector('.loading')?.remove();\r\n }\r\n\r\n applyStyle(css, routeName) {\r\n // \uAE30\uC874 \uC2A4\uD0C0\uC77C \uC81C\uAC70\r\n const existing = document.querySelector(`style[data-route=\"${routeName}\"]`);\r\n if (existing) existing.remove();\r\n\r\n if (css) {\r\n const style = document.createElement('style');\r\n style.textContent = css;\r\n style.setAttribute('data-route', routeName);\r\n document.head.appendChild(style);\r\n }\r\n }\r\n\r\n\r\n navigateTo(routeName, params = null) {\r\n // If routeName is an object, treat it as {route, params}\r\n if (typeof routeName === 'object') {\r\n params = routeName.params || null;\r\n routeName = routeName.route;\r\n }\r\n \r\n // Clear current query params if navigating to a different route\r\n if (routeName !== this.currentHash && this.queryManager) {\r\n this.queryManager.clearQueryParams();\r\n }\r\n \r\n // Set route parameters\r\n if (this.queryManager) {\r\n this.queryManager.setCurrentRouteParams(params);\r\n }\r\n \r\n // Update URL with new route and params\r\n this.updateURL(routeName, params);\r\n }\r\n\r\n getCurrentRoute() {\r\n return this.currentHash;\r\n }\r\n\r\n\r\n updateURL(route, params = null) {\r\n const queryParams = params || this.queryManager?.getQueryParams() || {};\r\n const queryString = this.queryManager?.buildQueryString(queryParams) || '';\r\n\r\n // URL \uC0DD\uC131\r\n let base = route === 'home' ? '/' : `/${route}`;\r\n\r\n if (this.config.mode === 'hash') {\r\n // \uD574\uC2DC \uBAA8\uB4DC: basePath \uC81C\uC678\r\n const url = queryString ? `${base}?${queryString}` : base;\r\n const newHash = `#${url}`;\r\n\r\n // \uB3D9\uC77C\uD55C URL\uC774\uBA74 \uC5C5\uB370\uC774\uD2B8\uD558\uC9C0 \uC54A\uC74C (\uC131\uB2A5 \uCD5C\uC801\uD654)\r\n if (window.location.hash !== newHash) {\r\n window.location.hash = newHash;\r\n }\r\n } else {\r\n // \uD788\uC2A4\uD1A0\uB9AC \uBAA8\uB4DC: basePath \uD3EC\uD568\r\n base = this.combinePaths(this.config.basePath, base);\r\n const url = queryString ? `${base}?${queryString}` : base;\r\n\r\n // \uBAA8\uB4E0 \uB77C\uC6B0\uD2B8 \uBCC0\uACBD\uC5D0 \uB300\uD574 \uB4A4\uB85C\uAC00\uAE30 \uC9C0\uC6D0\r\n window.history.pushState({}, '', url);\r\n this.handleRouteChange();\r\n }\r\n }\r\n\r\n /**\r\n * \uB77C\uC6B0\uD130 \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n // \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uC81C\uAC70\r\n window.removeEventListener(\r\n this.config.mode === 'hash' ? 'hashchange' : 'popstate',\r\n this._boundHandleRouteChange\r\n );\r\n \r\n // \uD604\uC7AC Vue \uC571 \uC5B8\uB9C8\uC6B4\uD2B8\r\n if (this.currentVueApp) {\r\n this.currentVueApp.unmount();\r\n this.currentVueApp = null;\r\n }\r\n \r\n // \uC774\uC804 Vue \uC571 \uC5B8\uB9C8\uC6B4\uD2B8\r\n if (this.previousVueApp) {\r\n this.previousVueApp.unmount();\r\n this.previousVueApp = null;\r\n }\r\n \r\n // \uB9E4\uB2C8\uC800 \uC815\uB9AC\r\n Object.values(this).forEach(manager => {\r\n if (manager && typeof manager.destroy === 'function') {\r\n manager.destroy();\r\n }\r\n });\r\n \r\n // \uCE90\uC2DC \uD074\uB9AC\uC5B4\r\n this.cacheManager?.clearAll();\r\n \r\n // DOM \uC815\uB9AC\r\n const appElement = document.getElementById('app');\r\n if (appElement) {\r\n appElement.innerHTML = '';\r\n }\r\n \r\n this.log('info', 'Router destroyed');\r\n }\r\n}\r\n// \uC804\uC5ED \uB77C\uC6B0\uD130\uB294 index.html\uC5D0\uC11C \uD658\uACBD\uC124\uC815\uACFC \uD568\uAED8 \uC0DD\uC131\uB428"],
5
- "mappings": "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",
6
- "names": ["I18nManager", "router", "options", "error", "cachedLang", "lang", "language", "oldLanguage", "loadPromise", "messages", "emptyMessages", "cacheKey", "cachedData", "i18nPath", "response", "fallbackError", "key", "params", "message", "fallbackMessages", "fallbackMessage", "obj", "path", "current", "match", "count", "pluralKey", "event", "callback", "index", "data", "date", "locale", "number", "level", "args", "clearedCount", "AuthManager", "router", "options", "level", "args", "routeName", "route", "isAuthenticated", "error", "token", "payload", "prefix", "name", "parts", "storage", "cookieOptions", "secure", "cookieString", "expireDate", "targetRoute", "redirectRoute", "eventType", "data", "event", "listener", "listeners", "index", "CacheManager", "router", "options", "level", "args", "key", "value", "now", "oldestKey", "existingIndex", "timestamp", "index", "pattern", "keysToDelete", "routeName", "patterns", "totalInvalidated", "componentPatterns", "totalCleared", "size", "expiredKeys", "estimatedBytes", "ratio", "categories", "interval", "QueryManager", "router", "level", "args", "queryString", "params", "pairs", "pair", "rawKey", "rawValue", "key", "value", "arrayKey", "item", "newParams", "oldKeys", "newKeys", "defaultValue", "replace", "currentParams", "keys", "keysToRemove", "route", "FormHandler", "router", "options", "level", "args", "form", "timeout", "el", "component", "boundHandler", "e", "event", "action", "method", "successHandler", "errorHandler", "loadingHandler", "redirectTo", "formData", "data", "response", "error", "actionTemplate", "signal", "hasFile", "isValid", "input", "validationFunction", "value", "ApiHandler", "router", "options", "level", "args", "dataURL", "component", "processedURL", "queryString", "fullURL", "requestOptions", "response", "error", "data", "dataConfig", "results", "errors", "promises", "key", "config", "url", "paramMatches", "match", "paramName", "paramValue", "baseURL", "relativeURL", "cleanBase", "cleanRelative", "ComponentLoader", "router", "options", "level", "args", "componentName", "cacheKey", "cachedComponent", "loadPromise", "component", "error", "componentRelativePath", "componentPath", "srcPath", "cleanSrcPath", "cleanComponentPath", "componentNames", "components", "componentsPath", "componentsModule", "namesToLoad", "name", "loadError", "template", "layout", "layoutName", "componentSet", "cachedComponents", "content", "componentPattern", "match", "tagName", "RouteLoader", "router", "options", "FormHandler", "ApiHandler", "ComponentLoader", "routeName", "script", "importPath", "error", "templatePath", "response", "template", "stylePath", "style", "layoutName", "layoutPath", "layout", "result", "cacheKey", "cached", "isProduction", "loadPromises", "loadedTemplate", "loadedStyle", "loadedLayout", "loadedComponents", "componentNames", "component", "route", "params", "key", "defaultValue", "token", "lang", "level", "args", "dataConfig", "configToUse", "data", "results", "errors", "componentName", "str", "word", "ErrorHandler", "router", "options", "routeName", "error", "errorCode", "errorMessage", "fallbackError", "component", "errorComponent", "appElement", "fallbackHTML", "errorReport", "level", "args", "currentLevelValue", "messageLevelValue", "prefix", "timestamp", "StateHandler", "router", "level", "args", "key", "value", "oldValue", "defaultValue", "keys", "updates", "callback", "callbacks", "index", "newValue", "error", "sum", "arr", "ViewLogicRouter", "options", "currentOrigin", "config", "basePath", "relativePath", "cleanBase", "cleanRelative", "path", "combinedPath", "currentPathname", "currentBase", "resolvedPath", "level", "args", "CacheManager", "StateHandler", "RouteLoader", "QueryManager", "ErrorHandler", "I18nManager", "i18nError", "AuthManager", "error", "isHashMode", "initRoute", "route", "queryParams", "hashPath", "pathPart", "queryPart", "fullPath", "routeName", "component", "vueComponent", "appElement", "newPageContainer", "container", "createApp", "newVueApp", "params", "key", "defaultValue", "replace", "keys", "fragment", "css", "existing", "style", "queryString", "base", "newHash", "url", "manager"]
4
+ "sourcesContent": ["/**\r\n * ViewLogic Internationalization System\r\n * \uB2E4\uAD6D\uC5B4 \uC9C0\uC6D0 \uC2DC\uC2A4\uD15C\r\n */\r\nexport class I18nManager {\r\n constructor(router, options = {}) {\r\n this.config = {\r\n enabled: options.useI18n !== undefined ? options.useI18n : true,\r\n defaultLanguage: options.defaultLanguage || 'en',\r\n fallbackLanguage: options.defaultLanguage || 'en'\r\n };\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870 (\uD544\uC694\uC2DC \uC5B8\uC5B4 \uBCC0\uACBD \uC2DC \uB77C\uC6B0\uD130 \uC0C1\uD0DC \uC5C5\uB370\uC774\uD2B8)\r\n this.router = router;\r\n \r\n this.messages = new Map();\r\n this.currentLanguage = this.config.defaultLanguage;\r\n this.isLoading = false;\r\n this.loadPromises = new Map();\r\n \r\n // \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108\uB4E4\r\n this.listeners = {\r\n languageChanged: []\r\n };\r\n \r\n // \uBE44\uB3D9\uAE30 \uCD08\uAE30\uD654 \uC2DC\uC791 (constructor \uB0B4\uC5D0\uC11C\uB294 await \uBD88\uAC00)\r\n this.initPromise = this.init();\r\n }\r\n\r\n async init() {\r\n // i18n\uC774 \uBE44\uD65C\uC131\uD654\uB41C \uACBD\uC6B0 \uCD08\uAE30\uD654\uD558\uC9C0 \uC54A\uC74C\r\n if (!this.config.enabled) {\r\n this.log('info', 'I18n system disabled');\r\n return;\r\n }\r\n \r\n // \uCE90\uC2DC\uC5D0\uC11C \uC5B8\uC5B4 \uC124\uC815 \uB85C\uB4DC\r\n this.loadLanguageFromCache();\r\n\r\n // \uCD08\uAE30 \uC5B8\uC5B4 \uD30C\uC77C \uC790\uB3D9 \uB85C\uB4DC (\uC544\uC9C1 \uB85C\uB4DC\uB418\uC9C0 \uC54A\uC740 \uACBD\uC6B0\uC5D0\uB9CC)\r\n if (!this.messages.has(this.currentLanguage)) {\r\n try {\r\n await this.loadMessages(this.currentLanguage);\r\n } catch (error) {\r\n this.log('error', 'Failed to load initial language file:', error);\r\n // \uD3F4\uBC31\uC73C\uB85C \uBE48 \uBA54\uC2DC\uC9C0 \uAC1D\uCCB4 \uC124\uC815\uD558\uC5EC \uC2DC\uC2A4\uD15C\uC774 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D\r\n this.messages.set(this.currentLanguage, {});\r\n this.log('info', 'Using empty message object as fallback');\r\n }\r\n } else {\r\n this.log('debug', 'Language messages already loaded:', this.currentLanguage);\r\n }\r\n }\r\n\r\n /**\r\n * \uCE90\uC2DC\uC5D0\uC11C \uC5B8\uC5B4 \uC124\uC815 \uB85C\uB4DC\r\n */\r\n loadLanguageFromCache() {\r\n try {\r\n const cachedLang = this.router.cacheManager?.get('viewlogic_lang');\r\n if (cachedLang && this.isValidLanguage(cachedLang)) {\r\n this.currentLanguage = cachedLang;\r\n this.log('debug', 'Language loaded from cache:', cachedLang);\r\n }\r\n } catch (error) {\r\n this.log('warn', 'Failed to load language from cache:', error);\r\n }\r\n }\r\n\r\n\r\n /**\r\n * \uC5B8\uC5B4 \uC720\uD6A8\uC131 \uAC80\uC0AC\r\n */\r\n isValidLanguage(lang) {\r\n return typeof lang === 'string' && /^[a-z]{2}$/.test(lang);\r\n }\r\n\r\n /**\r\n * \uD604\uC7AC \uC5B8\uC5B4 \uBC18\uD658\r\n */\r\n getCurrentLanguage() {\r\n return this.currentLanguage;\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4 \uBCC0\uACBD\r\n */\r\n async setLanguage(language) {\r\n if (!this.isValidLanguage(language)) {\r\n this.log('warn', 'Invalid language code:', language);\r\n return false;\r\n }\r\n\r\n if (this.currentLanguage === language) {\r\n this.log('debug', 'Language already set to:', language);\r\n return true;\r\n }\r\n\r\n const oldLanguage = this.currentLanguage;\r\n this.currentLanguage = language;\r\n\r\n try {\r\n // \uC5B8\uC5B4 \uD30C\uC77C \uB85C\uB4DC (\uC2E4\uD328\uD574\uB3C4 \uBE48 \uAC1D\uCCB4\uB77C\uB3C4 \uBC1B\uC744 \uC218 \uC788\uB3C4\uB85D)\r\n await this.loadMessages(language);\r\n \r\n // \uCE90\uC2DC\uC5D0 \uC800\uC7A5\r\n this.saveLanguageToCache(language);\r\n \r\n // \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n this.emit('languageChanged', {\r\n from: oldLanguage,\r\n to: language,\r\n messages: this.messages.get(language)\r\n });\r\n \r\n this.log('info', 'Language changed successfully', { from: oldLanguage, to: language });\r\n return true;\r\n } catch (error) {\r\n // \uC2E4\uD328\uD574\uB3C4 \uC5B8\uC5B4\uB294 \uBCC0\uACBD\uD558\uB418, \uBE48 \uBA54\uC2DC\uC9C0 \uAC1D\uCCB4 \uC0AC\uC6A9\r\n this.log('error', 'Failed to load messages for language change, using empty messages:', error);\r\n this.messages.set(language, {});\r\n \r\n // \uCE90\uC2DC\uC5D0 \uC800\uC7A5\r\n this.saveLanguageToCache(language);\r\n \r\n // \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n this.emit('languageChanged', {\r\n from: oldLanguage,\r\n to: language,\r\n messages: {},\r\n error: true\r\n });\r\n \r\n this.log('warn', 'Language changed with empty messages', { from: oldLanguage, to: language });\r\n return true; // true \uBC18\uD658\uD558\uC5EC \uB77C\uC6B0\uD130\uAC00 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D\r\n }\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4\uB97C \uCE90\uC2DC\uC5D0 \uC800\uC7A5\r\n */\r\n saveLanguageToCache(language) {\r\n try {\r\n this.router.cacheManager?.set('viewlogic_lang', language);\r\n this.log('debug', 'Language saved to cache:', language);\r\n } catch (error) {\r\n this.log('warn', 'Failed to save language to cache:', error);\r\n }\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4 \uBA54\uC2DC\uC9C0 \uD30C\uC77C \uB85C\uB4DC\r\n */\r\n async loadMessages(language) {\r\n // \uC774\uBBF8 \uB85C\uB4DC\uB41C \uACBD\uC6B0\r\n if (this.messages.has(language)) {\r\n this.log('debug', 'Messages already loaded for:', language);\r\n return this.messages.get(language);\r\n }\r\n\r\n // \uC774\uBBF8 \uB85C\uB529 \uC911\uC778 \uACBD\uC6B0\r\n if (this.loadPromises.has(language)) {\r\n this.log('debug', 'Messages loading in progress for:', language);\r\n return await this.loadPromises.get(language);\r\n }\r\n\r\n const loadPromise = this._loadMessagesFromFile(language);\r\n this.loadPromises.set(language, loadPromise);\r\n\r\n try {\r\n const messages = await loadPromise;\r\n this.messages.set(language, messages);\r\n this.loadPromises.delete(language);\r\n this.log('debug', 'Messages loaded successfully for:', language);\r\n return messages;\r\n } catch (error) {\r\n this.loadPromises.delete(language);\r\n // \uC2E4\uD328\uD574\uB3C4 \uBE48 \uAC1D\uCCB4 \uC124\uC815\uD558\uC5EC \uC2DC\uC2A4\uD15C\uC774 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D\r\n this.log('error', 'Failed to load messages, using empty fallback for:', language, error);\r\n const emptyMessages = {};\r\n this.messages.set(language, emptyMessages);\r\n return emptyMessages;\r\n }\r\n }\r\n\r\n /**\r\n * \uD30C\uC77C\uC5D0\uC11C \uBA54\uC2DC\uC9C0 \uB85C\uB4DC (\uCE90\uC2F1 \uC9C0\uC6D0)\r\n */\r\n async _loadMessagesFromFile(language) {\r\n // \uCE90\uC2DC\uC5D0\uC11C \uBA3C\uC800 \uC2DC\uB3C4\r\n const cacheKey = `i18n_${language}`;\r\n const cachedData = this.router.cacheManager?.get(cacheKey);\r\n if (cachedData) {\r\n this.log('debug', 'Messages loaded from cache:', language);\r\n return cachedData;\r\n }\r\n\r\n try {\r\n // JSON \uD30C\uC77C\uB85C \uBCC0\uACBD - config\uC758 i18nPath \uC0AC\uC6A9\r\n const i18nPath = `${this.router.config.i18nPath}/${language}.json`;\r\n const response = await fetch(i18nPath);\r\n if (!response.ok) {\r\n throw new Error(`HTTP error! status: ${response.status}`);\r\n }\r\n const messages = await response.json();\r\n\r\n // \uCE90\uC2DC\uC5D0 \uC800\uC7A5\r\n this.router.cacheManager?.set(cacheKey, messages);\r\n\r\n return messages;\r\n } catch (error) {\r\n this.log('error', 'Failed to load messages file for:', language, error);\r\n\r\n // \uD3F4\uBC31 \uC5B8\uC5B4 \uC2DC\uB3C4\r\n if (language !== this.config.fallbackLanguage) {\r\n this.log('info', 'Trying fallback language:', this.config.fallbackLanguage);\r\n try {\r\n return await this._loadMessagesFromFile(this.config.fallbackLanguage);\r\n } catch (fallbackError) {\r\n this.log('error', 'Fallback language also failed:', fallbackError);\r\n // \uD3F4\uBC31\uB3C4 \uC2E4\uD328\uD558\uBA74 \uBE48 \uAC1D\uCCB4 \uBC18\uD658\uD558\uC5EC \uC2DC\uC2A4\uD15C\uC774 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D\r\n return {};\r\n }\r\n }\r\n\r\n // \uB9C8\uC9C0\uB9C9 \uD3F4\uBC31: \uBE48 \uAC1D\uCCB4 \uBC18\uD658\r\n this.log('warn', `No messages available for language: ${language}, using empty fallback`);\r\n return {};\r\n }\r\n }\r\n \r\n\r\n /**\r\n * \uBA54\uC2DC\uC9C0 \uBC88\uC5ED\r\n */\r\n t(key, params = {}) {\r\n // i18n\uC774 \uBE44\uD65C\uC131\uD654\uB41C \uACBD\uC6B0 \uD0A4 \uC790\uCCB4\uB97C \uBC18\uD658\r\n if (!this.config.enabled) {\r\n return key;\r\n }\r\n \r\n const messages = this.messages.get(this.currentLanguage);\r\n if (!messages) {\r\n this.log('warn', 'No messages loaded for current language:', this.currentLanguage);\r\n return key;\r\n }\r\n\r\n const message = this.getNestedValue(messages, key);\r\n if (message === undefined) {\r\n this.log('warn', 'Translation not found for key:', key);\r\n \r\n // \uD3F4\uBC31 \uC5B8\uC5B4\uC5D0\uC11C \uCC3E\uAE30\r\n const fallbackMessages = this.messages.get(this.config.fallbackLanguage);\r\n if (fallbackMessages && this.currentLanguage !== this.config.fallbackLanguage) {\r\n const fallbackMessage = this.getNestedValue(fallbackMessages, key);\r\n if (fallbackMessage !== undefined) {\r\n return this.interpolate(fallbackMessage, params);\r\n }\r\n }\r\n \r\n return key;\r\n }\r\n\r\n return this.interpolate(message, params);\r\n }\r\n\r\n /**\r\n * \uC911\uCCA9\uB41C \uAC1D\uCCB4\uC5D0\uC11C \uAC12 \uAC00\uC838\uC624\uAE30\r\n */\r\n getNestedValue(obj, path) {\r\n return path.split('.').reduce((current, key) => {\r\n return current && current[key] !== undefined ? current[key] : undefined;\r\n }, obj);\r\n }\r\n\r\n /**\r\n * \uBB38\uC790\uC5F4 \uBCF4\uAC04 \uCC98\uB9AC\r\n */\r\n interpolate(message, params) {\r\n if (typeof message !== 'string') {\r\n return message;\r\n }\r\n\r\n return message.replace(/\\{(\\w+)\\}/g, (match, key) => {\r\n return params.hasOwnProperty(key) ? params[key] : match;\r\n });\r\n }\r\n\r\n /**\r\n * \uBCF5\uC218\uD615 \uCC98\uB9AC\r\n */\r\n plural(key, count, params = {}) {\r\n const pluralKey = count === 1 ? `${key}.singular` : `${key}.plural`;\r\n return this.t(pluralKey, { ...params, count });\r\n }\r\n\r\n\r\n /**\r\n * \uC5B8\uC5B4 \uBCC0\uACBD \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uB4F1\uB85D\r\n */\r\n on(event, callback) {\r\n if (this.listeners[event]) {\r\n this.listeners[event].push(callback);\r\n }\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4 \uBCC0\uACBD \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uC81C\uAC70\r\n */\r\n off(event, callback) {\r\n if (this.listeners[event]) {\r\n const index = this.listeners[event].indexOf(callback);\r\n if (index > -1) {\r\n this.listeners[event].splice(index, 1);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n */\r\n emit(event, data) {\r\n if (this.listeners[event]) {\r\n this.listeners[event].forEach(callback => {\r\n try {\r\n callback(data);\r\n } catch (error) {\r\n this.log('error', 'Error in event listener:', error);\r\n }\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * \uD604\uC7AC \uC5B8\uC5B4\uC758 \uBAA8\uB4E0 \uBA54\uC2DC\uC9C0 \uBC18\uD658\r\n */\r\n getMessages() {\r\n return this.messages.get(this.currentLanguage) || {};\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4\uBCC4 \uB0A0\uC9DC \uD3EC\uB9F7\uD305\r\n */\r\n formatDate(date, options = {}) {\r\n const locale = this.currentLanguage === 'ko' ? 'ko-KR' : 'en-US';\r\n return new Intl.DateTimeFormat(locale, options).format(new Date(date));\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4\uBCC4 \uC22B\uC790 \uD3EC\uB9F7\uD305\r\n */\r\n formatNumber(number, options = {}) {\r\n const locale = this.currentLanguage === 'ko' ? 'ko-KR' : 'en-US';\r\n return new Intl.NumberFormat(locale, options).format(number);\r\n }\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'I18nManager', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * i18n \uD65C\uC131\uD654 \uC5EC\uBD80 \uD655\uC778\r\n */\r\n isEnabled() {\r\n return this.config.enabled;\r\n }\r\n \r\n /**\r\n * \uCD08\uAE30 \uB85C\uB529\uC774 \uC644\uB8CC\uB418\uC5C8\uB294\uC9C0 \uD655\uC778\r\n */\r\n async isReady() {\r\n if (!this.config.enabled) {\r\n return true;\r\n }\r\n \r\n try {\r\n await this.initPromise;\r\n return true;\r\n } catch (error) {\r\n this.log('error', 'I18n initialization failed:', error);\r\n // \uC2E4\uD328\uD574\uB3C4 \uB77C\uC6B0\uD130\uAC00 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D true \uBC18\uD658\r\n this.log('info', 'I18n system ready with fallback behavior');\r\n return true;\r\n }\r\n }\r\n \r\n /**\r\n * \uCE90\uC2DC \uCD08\uAE30\uD654\r\n */\r\n clearCache() {\r\n try {\r\n const clearedCount = this.router.cacheManager?.deleteByPattern('i18n_');\r\n this.log('debug', 'Cache cleared, removed', clearedCount, 'items');\r\n } catch (error) {\r\n this.log('warn', 'Failed to clear cache:', error);\r\n }\r\n }\r\n \r\n /**\r\n * \uC2DC\uC2A4\uD15C \uCD08\uAE30\uD654 (\uD604\uC7AC \uC5B8\uC5B4\uC758 \uBA54\uC2DC\uC9C0 \uB85C\uB4DC)\r\n */\r\n async initialize() {\r\n if (!this.config.enabled) {\r\n this.log('info', 'I18n system is disabled, skipping initialization');\r\n return true;\r\n }\r\n \r\n try {\r\n // \uCD08\uAE30 \uC124\uC815\uC774 \uC644\uB8CC\uB420 \uB54C\uAE4C\uC9C0 \uB300\uAE30\r\n await this.initPromise;\r\n this.log('info', 'I18n system fully initialized');\r\n return true;\r\n } catch (error) {\r\n this.log('error', 'Failed to initialize I18n system:', error);\r\n // \uC2E4\uD328\uD574\uB3C4 \uC2DC\uC2A4\uD15C\uC740 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D true \uBC18\uD658\r\n this.log('info', 'I18n system will continue with fallback behavior');\r\n return true;\r\n }\r\n }\r\n}", "/**\r\n * ViewLogic Authentication Management System\r\n * \uC778\uC99D \uAD00\uB9AC \uC2DC\uC2A4\uD15C\r\n */\r\nexport class AuthManager {\r\n constructor(router, options = {}) {\r\n this.config = {\r\n enabled: options.authEnabled || false,\r\n loginRoute: options.loginRoute || 'login',\r\n protectedRoutes: options.protectedRoutes || [],\r\n protectedPrefixes: options.protectedPrefixes || [],\r\n publicRoutes: options.publicRoutes || ['login', 'register', 'home'],\r\n checkAuthFunction: options.checkAuthFunction || null,\r\n redirectAfterLogin: options.redirectAfterLogin || 'home',\r\n authCookieName: options.authCookieName || 'authToken',\r\n authStorage: options.authStorage || 'localStorage'\r\n };\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870 (\uD544\uC218 \uC758\uC874\uC131)\r\n this.router = router;\r\n \r\n // \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108\uB4E4\r\n this.eventListeners = new Map();\r\n \r\n this.log('info', 'AuthManager initialized', { enabled: this.config.enabled });\r\n }\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'AuthManager', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * \uB77C\uC6B0\uD2B8 \uC778\uC99D \uD655\uC778\r\n */\r\n async checkAuthentication(routeName) {\r\n // \uC778\uC99D \uC2DC\uC2A4\uD15C\uC774 \uBE44\uD65C\uC131\uD654\uB41C \uACBD\uC6B0\r\n if (!this.config.enabled) {\r\n return { allowed: true, reason: 'auth_disabled' };\r\n }\r\n\r\n this.log('debug', `\uD83D\uDD10 Checking authentication for route: ${routeName}`);\r\n\r\n // \uACF5\uAC1C \uB77C\uC6B0\uD2B8\uC778\uC9C0 \uD655\uC778\r\n if (this.isPublicRoute(routeName)) {\r\n return { allowed: true, reason: 'public_route' };\r\n }\r\n\r\n // \uBCF4\uD638\uB41C \uB77C\uC6B0\uD2B8\uC778\uC9C0 \uD655\uC778\r\n const isProtected = this.isProtectedRoute(routeName);\r\n if (!isProtected) {\r\n return { allowed: true, reason: 'not_protected' };\r\n }\r\n\r\n // \uC0AC\uC6A9\uC790 \uC815\uC758 \uC778\uC99D \uCCB4\uD06C \uD568\uC218\uAC00 \uC788\uB294 \uACBD\uC6B0\r\n if (typeof this.config.checkAuthFunction === 'function') {\r\n try {\r\n // \uAC00\uBCBC\uC6B4 route \uAC1D\uCCB4 \uC0DD\uC131 (\uCEF4\uD3EC\uB10C\uD2B8\uC640 \uB3D9\uC77C\uD55C API \uACBD\uD5D8 \uC81C\uACF5)\r\n const route = {\r\n name: routeName,\r\n $api: this.router.routeLoader.apiHandler.bindToComponent({}),\r\n $state: this.router.stateHandler\r\n };\r\n\r\n const isAuthenticated = await this.config.checkAuthFunction(route);\r\n return {\r\n allowed: isAuthenticated, \r\n reason: isAuthenticated ? 'custom_auth_success' : 'custom_auth_failed',\r\n routeName\r\n };\r\n } catch (error) {\r\n this.log('error', 'Custom auth function failed:', error);\r\n return { allowed: false, reason: 'custom_auth_error', error };\r\n }\r\n }\r\n\r\n // \uAE30\uBCF8 \uC778\uC99D \uD655\uC778\r\n const isAuthenticated = this.isAuthenticated();\r\n return {\r\n allowed: isAuthenticated, \r\n reason: isAuthenticated ? 'authenticated' : 'not_authenticated',\r\n routeName\r\n };\r\n }\r\n\r\n /**\r\n * JWT \uD1A0\uD070 \uAC80\uC99D\r\n */\r\n isTokenValid(token) {\r\n if (!token) return false;\r\n\r\n try {\r\n if (token.includes('.')) {\r\n const payload = JSON.parse(atob(token.split('.')[1]));\r\n if (payload.exp && Date.now() >= payload.exp * 1000) {\r\n return false; // \uB9CC\uB8CC\uB428\r\n }\r\n }\r\n return true;\r\n } catch (error) {\r\n this.log('warn', 'Token validation failed:', error);\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * \uC0AC\uC6A9\uC790 \uC778\uC99D \uC0C1\uD0DC \uD655\uC778\r\n */\r\n isAuthenticated() {\r\n this.log('debug', '\uD83D\uDD0D Checking user authentication status');\r\n\r\n const token = this.getAccessToken();\r\n if (!token) {\r\n this.log('debug', '\u274C No token found');\r\n return false;\r\n }\r\n\r\n if (!this.isTokenValid(token)) {\r\n this.log('debug', 'Token expired, removing...');\r\n this.removeAccessToken();\r\n return false;\r\n }\r\n\r\n this.log('debug', '\u2705 Valid token found');\r\n return true;\r\n }\r\n\r\n /**\r\n * \uACF5\uAC1C \uB77C\uC6B0\uD2B8\uC778\uC9C0 \uD655\uC778\r\n */\r\n isPublicRoute(routeName) {\r\n return this.config.publicRoutes.includes(routeName);\r\n }\r\n\r\n /**\r\n * \uBCF4\uD638\uB41C \uB77C\uC6B0\uD2B8\uC778\uC9C0 \uD655\uC778\r\n */\r\n isProtectedRoute(routeName) {\r\n // \uD2B9\uC815 \uB77C\uC6B0\uD2B8\uAC00 \uBCF4\uD638\uB41C \uB77C\uC6B0\uD2B8 \uBAA9\uB85D\uC5D0 \uC788\uB294\uC9C0 \uD655\uC778\r\n if (this.config.protectedRoutes.includes(routeName)) {\r\n return true;\r\n }\r\n\r\n // prefix\uB85C \uBCF4\uD638\uB41C \uB77C\uC6B0\uD2B8\uC778\uC9C0 \uD655\uC778\r\n for (const prefix of this.config.protectedPrefixes) {\r\n if (routeName.startsWith(prefix)) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * \uC778\uC99D \uCFE0\uD0A4 \uAC00\uC838\uC624\uAE30\r\n */\r\n getAuthCookie() {\r\n return this.getCookieValue(this.config.authCookieName);\r\n }\r\n\r\n /**\r\n * \uCFE0\uD0A4 \uAC12 \uAC00\uC838\uC624\uAE30\r\n */\r\n getCookieValue(name) {\r\n const value = `; ${document.cookie}`;\r\n const parts = value.split(`; ${name}=`);\r\n if (parts.length === 2) {\r\n return decodeURIComponent(parts.pop().split(';').shift());\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * \uC778\uC99D \uCFE0\uD0A4 \uC81C\uAC70\r\n */\r\n removeAuthCookie() {\r\n document.cookie = `${this.config.authCookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;\r\n this.log('debug', 'Auth cookie removed');\r\n }\r\n\r\n /**\r\n * \uC561\uC138\uC2A4 \uD1A0\uD070 \uAC00\uC838\uC624\uAE30\r\n */\r\n getAccessToken() {\r\n // localStorage \uC6B0\uC120 \uD655\uC778\r\n let token = localStorage.getItem('authToken');\r\n if (token) return token;\r\n\r\n // sessionStorage \uD655\uC778\r\n token = sessionStorage.getItem('authToken');\r\n if (token) return token;\r\n\r\n // \uCFE0\uD0A4 \uD655\uC778\r\n return this.getAuthCookie();\r\n }\r\n\r\n /**\r\n * \uC561\uC138\uC2A4 \uD1A0\uD070 \uC124\uC815\r\n */\r\n setAccessToken(token, options = {}) {\r\n if (!token) {\r\n this.log('warn', 'Empty token provided');\r\n return false;\r\n }\r\n\r\n const {\r\n storage = this.config.authStorage,\r\n cookieOptions = this.config.authCookieOptions\r\n } = options;\r\n\r\n try {\r\n // \uD1A0\uD070 \uAC80\uC99D\r\n if (!this.isTokenValid(token)) {\r\n this.log('warn', '\u274C Token is expired or invalid');\r\n return false;\r\n }\r\n\r\n // \uC2A4\uD1A0\uB9AC\uC9C0\uBCC4 \uC800\uC7A5\r\n switch (storage) {\r\n case 'localStorage':\r\n localStorage.setItem('authToken', token);\r\n this.log('debug', 'Token saved to localStorage');\r\n break;\r\n\r\n case 'sessionStorage':\r\n sessionStorage.setItem('authToken', token);\r\n this.log('debug', 'Token saved to sessionStorage');\r\n break;\r\n\r\n case 'cookie':\r\n this.setAuthCookie(token);\r\n break;\r\n\r\n default:\r\n localStorage.setItem('authToken', token);\r\n this.log('debug', 'Token saved to localStorage (default)');\r\n }\r\n\r\n this.emitAuthEvent('token_set', { \r\n storage,\r\n tokenLength: token.length,\r\n hasExpiration: token.includes('.')\r\n });\r\n\r\n return true;\r\n\r\n } catch (error) {\r\n this.log('error', 'Failed to set token:', error);\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * \uC778\uC99D \uCFE0\uD0A4 \uC124\uC815\r\n */\r\n setAuthCookie(token) {\r\n const secure = window.location.protocol === 'https:';\r\n let cookieString = `${this.config.authCookieName}=${encodeURIComponent(token)}; path=/; SameSite=Strict`;\r\n\r\n if (secure) {\r\n cookieString += '; Secure';\r\n }\r\n\r\n // JWT\uC5D0\uC11C \uB9CC\uB8CC \uC2DC\uAC04 \uCD94\uCD9C\r\n if (token.includes('.')) {\r\n try {\r\n const payload = JSON.parse(atob(token.split('.')[1]));\r\n if (payload.exp) {\r\n const expireDate = new Date(payload.exp * 1000);\r\n cookieString += `; Expires=${expireDate.toUTCString()}`;\r\n }\r\n } catch (error) {\r\n this.log('warn', 'Could not extract expiration from JWT token');\r\n }\r\n }\r\n\r\n document.cookie = cookieString;\r\n this.log('debug', 'Auth cookie set');\r\n }\r\n\r\n /**\r\n * \uD1A0\uD070 \uC81C\uAC70\r\n */\r\n removeAccessToken(storage = 'all') {\r\n switch (storage) {\r\n case 'localStorage':\r\n localStorage.removeItem('authToken');\r\n localStorage.removeItem('accessToken');\r\n break;\r\n\r\n case 'sessionStorage':\r\n sessionStorage.removeItem('authToken');\r\n sessionStorage.removeItem('accessToken');\r\n break;\r\n\r\n case 'cookie':\r\n this.removeAuthCookie();\r\n break;\r\n\r\n case 'all':\r\n default:\r\n localStorage.removeItem('authToken');\r\n sessionStorage.removeItem('authToken');\r\n this.removeAuthCookie();\r\n break;\r\n }\r\n\r\n this.emitAuthEvent('token_removed', { storage });\r\n this.log('debug', `Token removed from: ${storage}`);\r\n }\r\n\r\n /**\r\n * \uB85C\uADF8\uC778 \uC131\uACF5 \uCC98\uB9AC\r\n */\r\n loginSuccess(targetRoute = null) {\r\n const redirectRoute = targetRoute || this.config.redirectAfterLogin;\r\n \r\n this.log('info', `\uD83C\uDF89 Login success, redirecting to: ${redirectRoute}`);\r\n \r\n this.emitAuthEvent('login_success', { targetRoute: redirectRoute });\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4\uAC00 \uC788\uC73C\uBA74 \uC9C1\uC811 \uB124\uBE44\uAC8C\uC774\uC158\r\n if (this.router && typeof this.router.navigateTo === 'function') {\r\n this.router.navigateTo(redirectRoute);\r\n }\r\n \r\n return redirectRoute;\r\n }\r\n\r\n /**\r\n * \uB85C\uADF8\uC544\uC6C3 \uCC98\uB9AC\r\n */\r\n logout() {\r\n this.log('info', '\uD83D\uDC4B Logging out user');\r\n \r\n // \uBAA8\uB4E0 \uC800\uC7A5\uC18C\uC5D0\uC11C \uD1A0\uD070 \uC81C\uAC70\r\n this.removeAccessToken();\r\n \r\n \r\n this.emitAuthEvent('logout', {});\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4\uAC00 \uC788\uC73C\uBA74 \uC9C1\uC811 \uB124\uBE44\uAC8C\uC774\uC158\r\n if (this.router && typeof this.router.navigateTo === 'function') {\r\n this.router.navigateTo(this.config.loginRoute);\r\n }\r\n \r\n return this.config.loginRoute;\r\n }\r\n\r\n /**\r\n * \uC778\uC99D \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n */\r\n emitAuthEvent(eventType, data) {\r\n const event = new CustomEvent('router:auth', {\r\n detail: {\r\n type: eventType,\r\n timestamp: Date.now(),\r\n ...data\r\n }\r\n });\r\n \r\n document.dispatchEvent(event);\r\n \r\n // \uB0B4\uBD80 \uB9AC\uC2A4\uB108\uB4E4\uC5D0\uAC8C\uB3C4 \uC54C\uB9BC\r\n if (this.eventListeners.has(eventType)) {\r\n this.eventListeners.get(eventType).forEach(listener => {\r\n try {\r\n listener(data);\r\n } catch (error) {\r\n this.log('error', 'Event listener error:', error);\r\n }\r\n });\r\n }\r\n \r\n this.log('debug', `\uD83D\uDD14 Auth event emitted: ${eventType}`, data);\r\n }\r\n\r\n /**\r\n * \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uB4F1\uB85D\r\n */\r\n on(eventType, listener) {\r\n if (!this.eventListeners.has(eventType)) {\r\n this.eventListeners.set(eventType, []);\r\n }\r\n this.eventListeners.get(eventType).push(listener);\r\n }\r\n\r\n /**\r\n * \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uC81C\uAC70\r\n */\r\n off(eventType, listener) {\r\n if (this.eventListeners.has(eventType)) {\r\n const listeners = this.eventListeners.get(eventType);\r\n const index = listeners.indexOf(listener);\r\n if (index > -1) {\r\n listeners.splice(index, 1);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * \uC778\uC99D \uC0C1\uD0DC \uD1B5\uACC4\r\n */\r\n getAuthStats() {\r\n return {\r\n enabled: this.config.enabled,\r\n isAuthenticated: this.isAuthenticated(),\r\n hasToken: !!this.getAccessToken(),\r\n protectedRoutesCount: this.config.protectedRoutes.length,\r\n protectedPrefixesCount: this.config.protectedPrefixes.length,\r\n publicRoutesCount: this.config.publicRoutes.length,\r\n storage: this.config.authStorage,\r\n loginRoute: this.config.loginRoute\r\n };\r\n }\r\n\r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n this.eventListeners.clear();\r\n this.log('debug', 'AuthManager destroyed');\r\n }\r\n}", "/**\r\n * ViewLogic Cache Management System\r\n * \uCE90\uC2DC \uAD00\uB9AC \uC2DC\uC2A4\uD15C\r\n */\r\nexport class CacheManager {\r\n constructor(router, options = {}) {\r\n this.config = {\r\n cacheMode: options.cacheMode || 'memory', // 'memory' \uB610\uB294 'lru'\r\n cacheTTL: options.cacheTTL || 300000, // 5\uBD84 (\uBC00\uB9AC\uCD08)\r\n maxCacheSize: options.maxCacheSize || 50 // LRU \uCE90\uC2DC \uCD5C\uB300 \uD06C\uAE30\r\n };\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870 (\uD544\uC694\uC2DC \uB77C\uC6B0\uD130 \uC0C1\uD0DC \uD655\uC778\uC6A9)\r\n this.router = router;\r\n \r\n // \uCE90\uC2DC \uC800\uC7A5\uC18C\uB4E4\r\n this.cache = new Map();\r\n this.cacheTimestamps = new Map();\r\n this.lruOrder = []; // LRU \uC21C\uC11C \uCD94\uC801\r\n \r\n this.log('info', 'CacheManager initialized with config:', this.config);\r\n }\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'CacheManager', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * \uCE90\uC2DC\uC5D0 \uAC12 \uC800\uC7A5\r\n */\r\n set(key, value) {\r\n const now = Date.now();\r\n \r\n if (this.config.cacheMode === 'lru') {\r\n // LRU \uCE90\uC2DC \uAD00\uB9AC\r\n if (this.cache.size >= this.config.maxCacheSize && !this.cache.has(key)) {\r\n const oldestKey = this.lruOrder.shift();\r\n if (oldestKey) {\r\n this.cache.delete(oldestKey);\r\n this.cacheTimestamps.delete(oldestKey);\r\n this.log('debug', `\uD83D\uDDD1\uFE0F LRU evicted cache key: ${oldestKey}`);\r\n }\r\n }\r\n \r\n // \uAE30\uC874 \uD0A4\uAC00 \uC788\uC73C\uBA74 LRU \uC21C\uC11C\uC5D0\uC11C \uC81C\uAC70\r\n const existingIndex = this.lruOrder.indexOf(key);\r\n if (existingIndex > -1) {\r\n this.lruOrder.splice(existingIndex, 1);\r\n }\r\n \r\n // \uCD5C\uC2E0 \uC21C\uC11C\uB85C \uCD94\uAC00\r\n this.lruOrder.push(key);\r\n }\r\n \r\n this.cache.set(key, value);\r\n this.cacheTimestamps.set(key, now);\r\n \r\n this.log('debug', `\uD83D\uDCBE Cached: ${key} (size: ${this.cache.size})`);\r\n }\r\n \r\n /**\r\n * \uCE90\uC2DC\uC5D0\uC11C \uAC12 \uAC00\uC838\uC624\uAE30\r\n */\r\n get(key) {\r\n const now = Date.now();\r\n const timestamp = this.cacheTimestamps.get(key);\r\n \r\n // TTL \uCCB4\uD06C\r\n if (timestamp && (now - timestamp) > this.config.cacheTTL) {\r\n this.cache.delete(key);\r\n this.cacheTimestamps.delete(key);\r\n \r\n if (this.config.cacheMode === 'lru') {\r\n const index = this.lruOrder.indexOf(key);\r\n if (index > -1) {\r\n this.lruOrder.splice(index, 1);\r\n }\r\n }\r\n \r\n this.log('debug', `\u23F0 Cache expired and removed: ${key}`);\r\n return null;\r\n }\r\n \r\n const value = this.cache.get(key);\r\n \r\n if (value && this.config.cacheMode === 'lru') {\r\n // LRU \uC21C\uC11C \uC5C5\uB370\uC774\uD2B8\r\n const index = this.lruOrder.indexOf(key);\r\n if (index > -1) {\r\n this.lruOrder.splice(index, 1);\r\n this.lruOrder.push(key);\r\n }\r\n }\r\n \r\n if (value) {\r\n this.log('debug', `\uD83C\uDFAF Cache hit: ${key}`);\r\n } else {\r\n this.log('debug', `\u274C Cache miss: ${key}`);\r\n }\r\n \r\n return value;\r\n }\r\n \r\n /**\r\n * \uCE90\uC2DC\uC5D0 \uD0A4\uAC00 \uC788\uB294\uC9C0 \uD655\uC778\r\n */\r\n has(key) {\r\n return this.cache.has(key) && this.get(key) !== null;\r\n }\r\n \r\n /**\r\n * \uD2B9\uC815 \uD0A4 \uD328\uD134\uC758 \uCE90\uC2DC \uC0AD\uC81C\r\n */\r\n deleteByPattern(pattern) {\r\n const keysToDelete = [];\r\n \r\n for (const key of this.cache.keys()) {\r\n if (key.includes(pattern) || key.startsWith(pattern)) {\r\n keysToDelete.push(key);\r\n }\r\n }\r\n \r\n keysToDelete.forEach(key => {\r\n this.cache.delete(key);\r\n this.cacheTimestamps.delete(key);\r\n \r\n if (this.config.cacheMode === 'lru') {\r\n const index = this.lruOrder.indexOf(key);\r\n if (index > -1) {\r\n this.lruOrder.splice(index, 1);\r\n }\r\n }\r\n });\r\n \r\n this.log('debug', `\uD83E\uDDF9 Deleted ${keysToDelete.length} cache entries matching: ${pattern}`);\r\n return keysToDelete.length;\r\n }\r\n \r\n /**\r\n * \uD2B9\uC815 \uCEF4\uD3EC\uB10C\uD2B8 \uCE90\uC2DC \uC0AD\uC81C\r\n */\r\n deleteComponent(routeName) {\r\n const patterns = [\r\n `component_${routeName}`,\r\n `script_${routeName}`,\r\n `template_${routeName}`,\r\n `style_${routeName}`,\r\n `layout_${routeName}`\r\n ];\r\n \r\n let totalInvalidated = 0;\r\n patterns.forEach(pattern => {\r\n totalInvalidated += this.deleteByPattern(pattern);\r\n });\r\n \r\n this.log('debug', `\uD83D\uDD04 Deleted component cache for route: ${routeName} (${totalInvalidated} entries)`);\r\n return totalInvalidated;\r\n }\r\n \r\n /**\r\n * \uBAA8\uB4E0 \uCEF4\uD3EC\uB10C\uD2B8 \uCE90\uC2DC \uC0AD\uC81C\r\n */\r\n deleteAllComponents() {\r\n const componentPatterns = ['component_', 'script_', 'template_', 'style_', 'layout_'];\r\n let totalCleared = 0;\r\n \r\n componentPatterns.forEach(pattern => {\r\n totalCleared += this.deleteByPattern(pattern);\r\n });\r\n \r\n this.log('debug', `\uD83E\uDDFD Deleted all component caches (${totalCleared} entries)`);\r\n return totalCleared;\r\n }\r\n \r\n /**\r\n * \uC804\uCCB4 \uCE90\uC2DC \uC0AD\uC81C\r\n */\r\n clearAll() {\r\n const size = this.cache.size;\r\n this.cache.clear();\r\n this.cacheTimestamps.clear();\r\n this.lruOrder = [];\r\n \r\n this.log('debug', `\uD83D\uDD25 Cleared all cache (${size} entries)`);\r\n return size;\r\n }\r\n \r\n /**\r\n * \uB9CC\uB8CC\uB41C \uCE90\uC2DC \uD56D\uBAA9\uB4E4 \uC815\uB9AC\r\n */\r\n cleanExpired() {\r\n const now = Date.now();\r\n const expiredKeys = [];\r\n \r\n for (const [key, timestamp] of this.cacheTimestamps.entries()) {\r\n if ((now - timestamp) > this.config.cacheTTL) {\r\n expiredKeys.push(key);\r\n }\r\n }\r\n \r\n expiredKeys.forEach(key => {\r\n this.cache.delete(key);\r\n this.cacheTimestamps.delete(key);\r\n \r\n if (this.config.cacheMode === 'lru') {\r\n const index = this.lruOrder.indexOf(key);\r\n if (index > -1) {\r\n this.lruOrder.splice(index, 1);\r\n }\r\n }\r\n });\r\n \r\n if (expiredKeys.length > 0) {\r\n this.log('debug', `\u23F1\uFE0F Cleaned ${expiredKeys.length} expired cache entries`);\r\n }\r\n \r\n return expiredKeys.length;\r\n }\r\n \r\n /**\r\n * \uCE90\uC2DC \uD1B5\uACC4 \uC815\uBCF4\r\n */\r\n getStats() {\r\n return {\r\n size: this.cache.size,\r\n maxSize: this.config.maxCacheSize,\r\n mode: this.config.cacheMode,\r\n ttl: this.config.cacheTTL,\r\n memoryUsage: this.getMemoryUsage(),\r\n hitRatio: this.getHitRate(),\r\n categories: this.getStatsByCategory()\r\n };\r\n }\r\n \r\n /**\r\n * \uBA54\uBAA8\uB9AC \uC0AC\uC6A9\uB7C9 \uCD94\uC815\r\n */\r\n getMemoryUsage() {\r\n let estimatedBytes = 0;\r\n \r\n for (const [key, value] of this.cache.entries()) {\r\n // \uD0A4 \uD06C\uAE30\r\n estimatedBytes += key.length * 2; // UTF-16\r\n \r\n // \uAC12 \uD06C\uAE30 \uCD94\uC815\r\n if (typeof value === 'string') {\r\n estimatedBytes += value.length * 2;\r\n } else if (typeof value === 'object' && value !== null) {\r\n estimatedBytes += JSON.stringify(value).length * 2;\r\n } else {\r\n estimatedBytes += 8; // \uB300\uB7B5\uC801\uC778 \uD06C\uAE30\r\n }\r\n }\r\n \r\n return {\r\n bytes: estimatedBytes,\r\n kb: Math.round(estimatedBytes / 1024 * 100) / 100,\r\n mb: Math.round(estimatedBytes / (1024 * 1024) * 100) / 100\r\n };\r\n }\r\n \r\n /**\r\n * \uD788\uD2B8 \uBE44\uC728 \uACC4\uC0B0 (\uAC04\uB2E8\uD55C \uCD94\uC815)\r\n */\r\n getHitRate() {\r\n // \uC2E4\uC81C \uD788\uD2B8/\uBBF8\uC2A4 \uCD94\uC801\uC744 \uC704\uD574\uC11C\uB294 \uBCC4\uB3C4\uC758 \uCE74\uC6B4\uD130\uAC00 \uD544\uC694\r\n // \uD604\uC7AC\uB294 \uCE90\uC2DC \uD06C\uAE30 \uAE30\uBC18 \uCD94\uC815\uCE58 \uBC18\uD658\r\n const ratio = this.cache.size > 0 ? Math.min(this.cache.size / this.config.maxCacheSize, 1) : 0;\r\n return Math.round(ratio * 100);\r\n }\r\n \r\n /**\r\n * \uCE74\uD14C\uACE0\uB9AC\uBCC4 \uCE90\uC2DC \uD1B5\uACC4\r\n */\r\n getStatsByCategory() {\r\n const categories = {\r\n components: 0,\r\n scripts: 0,\r\n templates: 0,\r\n styles: 0,\r\n layouts: 0,\r\n others: 0\r\n };\r\n \r\n for (const key of this.cache.keys()) {\r\n if (key.startsWith('component_')) categories.components++;\r\n else if (key.startsWith('script_')) categories.scripts++;\r\n else if (key.startsWith('template_')) categories.templates++;\r\n else if (key.startsWith('style_')) categories.styles++;\r\n else if (key.startsWith('layout_')) categories.layouts++;\r\n else categories.others++;\r\n }\r\n \r\n return categories;\r\n }\r\n \r\n /**\r\n * \uCE90\uC2DC \uD0A4 \uBAA9\uB85D \uBC18\uD658\r\n */\r\n getKeys() {\r\n return Array.from(this.cache.keys());\r\n }\r\n \r\n /**\r\n * \uD2B9\uC815 \uD328\uD134\uC758 \uCE90\uC2DC \uD0A4\uB4E4 \uBC18\uD658\r\n */\r\n getKeysByPattern(pattern) {\r\n return this.getKeys().filter(key => \r\n key.includes(pattern) || key.startsWith(pattern)\r\n );\r\n }\r\n \r\n /**\r\n * \uC790\uB3D9 \uC815\uB9AC \uC2DC\uC791 (\uBC31\uADF8\uB77C\uC6B4\uB4DC\uC5D0\uC11C \uB9CC\uB8CC\uB41C \uCE90\uC2DC \uC815\uB9AC)\r\n */\r\n startAutoCleanup(interval = 60000) { // \uAE30\uBCF8 1\uBD84 \uAC04\uACA9\r\n if (this.cleanupInterval) {\r\n clearInterval(this.cleanupInterval);\r\n }\r\n \r\n this.cleanupInterval = setInterval(() => {\r\n this.cleanExpired();\r\n }, interval);\r\n \r\n this.log('debug', `\uD83E\uDD16 Auto cleanup started (interval: ${interval}ms)`);\r\n }\r\n \r\n /**\r\n * \uC790\uB3D9 \uC815\uB9AC \uC911\uC9C0\r\n */\r\n stopAutoCleanup() {\r\n if (this.cleanupInterval) {\r\n clearInterval(this.cleanupInterval);\r\n this.cleanupInterval = null;\r\n this.log('debug', '\uD83D\uDED1 Auto cleanup stopped');\r\n }\r\n }\r\n \r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n this.stopAutoCleanup();\r\n this.clearAll();\r\n this.log('debug', 'CacheManager destroyed');\r\n }\r\n}", "/**\r\n * ViewLogic Query Management System\r\n * URL \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uAD00\uB9AC \uC2DC\uC2A4\uD15C\r\n */\r\nexport class QueryManager {\r\n constructor(router) {\r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870\r\n this.router = router;\r\n\r\n // \uD604\uC7AC \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uC0C1\uD0DC\r\n this.currentQueryParams = {};\r\n\r\n // \uD604\uC7AC \uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130 \uC0C1\uD0DC (navigateTo\uB85C \uC804\uB2EC\uB41C params)\r\n this.currentRouteParams = {};\r\n\r\n this.log('debug', 'QueryManager initialized');\r\n }\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'QueryManager', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC\uC2A4\uD2B8\uB9C1 \uD30C\uC2F1\r\n */\r\n parseQueryString(queryString) {\r\n const params = {};\r\n if (!queryString) return params;\r\n\r\n const pairs = queryString.split('&');\r\n for (const pair of pairs) {\r\n const [rawKey, rawValue] = pair.split('=');\r\n if (!rawKey) continue;\r\n\r\n try {\r\n const key = decodeURIComponent(rawKey);\r\n const value = rawValue ? decodeURIComponent(rawValue) : '';\r\n\r\n // \uBC30\uC5F4 \uD615\uD0DC\uC758 \uD30C\uB77C\uBBF8\uD130 \uCC98\uB9AC (\uC608: tags[]=a&tags[]=b)\r\n if (key.endsWith('[]')) {\r\n const arrayKey = key.slice(0, -2);\r\n if (!params[arrayKey]) params[arrayKey] = [];\r\n params[arrayKey].push(value);\r\n } else {\r\n params[key] = value;\r\n }\r\n } catch (error) {\r\n this.log('warn', 'Failed to decode query parameter:', pair);\r\n }\r\n }\r\n\r\n return params;\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC\uC2A4\uD2B8\uB9C1 \uC0DD\uC131\r\n */\r\n buildQueryString(params) {\r\n if (!params || Object.keys(params).length === 0) return '';\r\n\r\n const pairs = [];\r\n for (const [key, value] of Object.entries(params)) {\r\n if (Array.isArray(value)) {\r\n // \uBC30\uC5F4 \uD30C\uB77C\uBBF8\uD130 \uCC98\uB9AC\r\n for (const item of value) {\r\n pairs.push(`${encodeURIComponent(key)}[]=${encodeURIComponent(item)}`);\r\n }\r\n } else if (value !== undefined && value !== null) {\r\n pairs.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);\r\n }\r\n }\r\n return pairs.join('&');\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uBCC0\uACBD \uAC10\uC9C0\r\n */\r\n hasQueryParamsChanged(newParams) {\r\n if (!this.currentQueryParams && !newParams) return false;\r\n if (!this.currentQueryParams || !newParams) return true;\r\n\r\n const oldKeys = Object.keys(this.currentQueryParams);\r\n const newKeys = Object.keys(newParams);\r\n\r\n if (oldKeys.length !== newKeys.length) return true;\r\n\r\n for (const key of oldKeys) {\r\n if (JSON.stringify(this.currentQueryParams[key]) !== JSON.stringify(newParams[key])) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * \uD604\uC7AC \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uC804\uCCB4 \uAC00\uC838\uC624\uAE30\r\n */\r\n getQueryParams() {\r\n return { ...this.currentQueryParams };\r\n }\r\n\r\n /**\r\n * \uD2B9\uC815 \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uAC00\uC838\uC624\uAE30\r\n */\r\n getQueryParam(key, defaultValue = undefined) {\r\n const value = this.currentQueryParams ? this.currentQueryParams[key] : undefined;\r\n return value !== undefined ? value : defaultValue;\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uC124\uC815\r\n */\r\n setQueryParams(params, replace = false) {\r\n if (!params || typeof params !== 'object') {\r\n this.log('warn', 'Invalid parameters object provided to setQueryParams');\r\n return;\r\n }\r\n\r\n const currentParams = replace ? {} : { ...this.currentQueryParams };\r\n\r\n // \uD30C\uB77C\uBBF8\uD130 \uC5C5\uB370\uC774\uD2B8\r\n for (const [key, value] of Object.entries(params)) {\r\n if (value !== undefined && value !== null && value !== '') {\r\n currentParams[key] = value;\r\n } else {\r\n delete currentParams[key];\r\n }\r\n }\r\n\r\n this.currentQueryParams = currentParams;\r\n this.updateURL();\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uC81C\uAC70\r\n */\r\n removeQueryParams(keys) {\r\n if (!keys) return;\r\n\r\n const keysToRemove = Array.isArray(keys) ? keys : [keys];\r\n for (const key of keysToRemove) {\r\n delete this.currentQueryParams[key];\r\n }\r\n\r\n this.updateURL();\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uCD08\uAE30\uD654\r\n */\r\n clearQueryParams() {\r\n this.currentQueryParams = {};\r\n this.updateURL();\r\n }\r\n\r\n /**\r\n * \uD604\uC7AC \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uC124\uC815 (\uB77C\uC6B0\uD130\uC5D0\uC11C \uD638\uCD9C)\r\n */\r\n setCurrentQueryParams(params) {\r\n this.currentQueryParams = params || {};\r\n }\r\n\r\n /**\r\n * \uD604\uC7AC \uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130 \uC124\uC815 (navigateTo\uC5D0\uC11C \uD638\uCD9C)\r\n */\r\n setCurrentRouteParams(params) {\r\n this.currentRouteParams = params || {};\r\n this.log('debug', 'Route params set:', this.currentRouteParams);\r\n }\r\n\r\n /**\r\n * \uD1B5\uD569\uB41C \uD30C\uB77C\uBBF8\uD130 \uBC18\uD658 (\uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130 + \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130)\r\n */\r\n getAllParams() {\r\n return {\r\n ...this.currentRouteParams,\r\n ...this.currentQueryParams\r\n };\r\n }\r\n\r\n /**\r\n * \uD1B5\uD569\uB41C \uD30C\uB77C\uBBF8\uD130\uC5D0\uC11C \uD2B9\uC815 \uD0A4 \uAC12 \uBC18\uD658\r\n */\r\n getParam(key, defaultValue = undefined) {\r\n // \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130\uAC00 \uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130\uBCF4\uB2E4 \uC6B0\uC120\uC21C\uC704 \uB192\uC74C\r\n const value = this.currentQueryParams[key] !== undefined ?\r\n this.currentQueryParams[key] :\r\n this.currentRouteParams[key];\r\n return value !== undefined ? value : defaultValue;\r\n }\r\n\r\n /**\r\n * \uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130\uB9CC \uBC18\uD658\r\n */\r\n getRouteParams() {\r\n return { ...this.currentRouteParams };\r\n }\r\n\r\n /**\r\n * \uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130\uC5D0\uC11C \uD2B9\uC815 \uD0A4 \uAC12 \uBC18\uD658\r\n */\r\n getRouteParam(key, defaultValue = undefined) {\r\n const value = this.currentRouteParams[key];\r\n return value !== undefined ? value : defaultValue;\r\n }\r\n\r\n /**\r\n * URL \uC5C5\uB370\uC774\uD2B8 (\uB77C\uC6B0\uD130\uC758 updateURL \uBA54\uC18C\uB4DC \uD638\uCD9C)\r\n */\r\n updateURL() {\r\n if (this.router && typeof this.router.updateURL === 'function') {\r\n const route = this.router.currentHash || 'home';\r\n this.router.updateURL(route, this.currentQueryParams);\r\n }\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uD1B5\uACC4\r\n */\r\n getStats() {\r\n return {\r\n currentParams: Object.keys(this.currentQueryParams).length,\r\n currentQueryString: this.buildQueryString(this.currentQueryParams)\r\n };\r\n }\r\n\r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n this.currentQueryParams = {};\r\n this.currentRouteParams = {};\r\n this.router = null;\r\n this.log('debug', 'QueryManager destroyed');\r\n }\r\n}", "/**\r\n * FormHandler\r\n * \uC790\uB3D9 \uD3FC \uCC98\uB9AC \uBC0F \uAC80\uC99D \uC2DC\uC2A4\uD15C\r\n */\r\nexport class FormHandler {\r\n constructor(router, options = {}) {\r\n this.router = router;\r\n this.requestTimeout = options.requestTimeout || 30000;\r\n this.uploadTimeout = options.uploadTimeout || 300000;\r\n \r\n this.log('debug', 'FormHandler initialized');\r\n }\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'FormHandler', ...args);\r\n }\r\n }\r\n\r\n\r\n /**\r\n * \uC911\uBCF5 \uC694\uCCAD \uCCB4\uD06C\r\n */\r\n isDuplicateRequest(form) {\r\n if (form._isSubmitting) {\r\n this.log('debug', 'Duplicate request blocked');\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * \uD3FC \uC81C\uCD9C \uC2DC\uC791\r\n */\r\n startFormSubmission(form) {\r\n form._isSubmitting = true;\r\n form._abortController = new AbortController();\r\n\r\n // \uD30C\uC77C \uC5C5\uB85C\uB4DC\uAC00 \uD3EC\uD568\uB41C \uACBD\uC6B0 uploadTimeout \uC0AC\uC6A9\r\n const hasFile = Array.from(form.elements).some(el => el.type === 'file' && el.files.length > 0);\r\n const timeout = hasFile ? this.uploadTimeout : this.requestTimeout;\r\n\r\n // \uD0C0\uC784\uC544\uC6C3 \uC124\uC815\r\n form._timeoutId = setTimeout(() => {\r\n if (form._isSubmitting) {\r\n this.abortFormSubmission(form);\r\n }\r\n }, timeout);\r\n }\r\n\r\n /**\r\n * \uD3FC \uC81C\uCD9C \uC644\uB8CC\r\n */\r\n finishFormSubmission(form) {\r\n form._isSubmitting = false;\r\n \r\n if (form._timeoutId) {\r\n clearTimeout(form._timeoutId);\r\n delete form._timeoutId;\r\n }\r\n \r\n delete form._abortController;\r\n }\r\n\r\n /**\r\n * \uD3FC \uC81C\uCD9C \uC911\uB2E8\r\n */\r\n abortFormSubmission(form) {\r\n if (form._abortController) {\r\n form._abortController.abort();\r\n }\r\n this.finishFormSubmission(form);\r\n }\r\n\r\n /**\r\n * \uC790\uB3D9 \uD3FC \uBC14\uC778\uB529\r\n */\r\n bindAutoForms(component) {\r\n const forms = document.querySelectorAll('form.auto-form, form[action]');\r\n \r\n forms.forEach(form => {\r\n // \uAE30\uC874 \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uC81C\uAC70 (\uC911\uBCF5 \uBC29\uC9C0)\r\n form.removeEventListener('submit', form._boundSubmitHandler);\r\n \r\n // \uC0C8 \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uCD94\uAC00\r\n const boundHandler = (e) => this.handleFormSubmit(e, component);\r\n form._boundSubmitHandler = boundHandler;\r\n form.addEventListener('submit', boundHandler);\r\n \r\n this.log('debug', `Form auto-bound: ${form.getAttribute('action')}`);\r\n });\r\n }\r\n\r\n /**\r\n * \uD3FC \uC11C\uBE0C\uBC0B \uD578\uB4E4\uB7EC\r\n */\r\n async handleFormSubmit(event, component) {\r\n event.preventDefault();\r\n \r\n const form = event.target;\r\n let action = form.getAttribute('action');\r\n const method = form.getAttribute('method') || 'POST';\r\n \r\n // \uD578\uB4E4\uB7EC \uD568\uC218\uB4E4 \uAC00\uC838\uC624\uAE30\r\n const successHandler = form.getAttribute('data-success');\r\n const errorHandler = form.getAttribute('data-error');\r\n const loadingHandler = form.getAttribute('data-loading');\r\n const redirectTo = form.getAttribute('data-redirect');\r\n\r\n // \uC561\uC158 URL\uC5D0 \uAC00\uBCC0 \uD30C\uB77C\uBBF8\uD130 \uCC98\uB9AC\r\n action = this.processActionParams(action, component);\r\n\r\n // \uD074\uB77C\uC774\uC5B8\uD2B8 \uC0AC\uC774\uB4DC \uAC80\uC99D\r\n if (!this.validateForm(form, component)) {\r\n return;\r\n }\r\n\r\n // \uC911\uBCF5 \uC694\uCCAD \uCCB4\uD06C\r\n if (this.isDuplicateRequest(form)) {\r\n return;\r\n }\r\n\r\n // \uD3FC \uC81C\uCD9C \uC2DC\uC791\r\n this.startFormSubmission(form);\r\n\r\n // FormData \uC0DD\uC131\r\n const formData = new FormData(form);\r\n const data = Object.fromEntries(formData.entries());\r\n\r\n try {\r\n // \uB85C\uB529 \uC2DC\uC791\r\n if (loadingHandler && component[loadingHandler]) {\r\n component[loadingHandler](true, form);\r\n }\r\n\r\n this.log('debug', `Form submitting to: ${action}`, data);\r\n\r\n // API \uD638\uCD9C (AbortController \uC2E0\uD638 \uD3EC\uD568)\r\n const response = await this.submitFormData(action, method, data, form, component, form._abortController.signal);\r\n \r\n // \uC131\uACF5 \uD578\uB4E4\uB7EC \uD638\uCD9C\r\n if (successHandler && component[successHandler]) {\r\n component[successHandler](response, form);\r\n }\r\n\r\n // \uD3FC \uC81C\uCD9C \uC644\uB8CC (\uC131\uACF5)\r\n this.finishFormSubmission(form);\r\n\r\n // \uC790\uB3D9 \uB9AC\uB2E4\uC774\uB809\uD2B8 (requestAnimationFrame \uC0AC\uC6A9\uC73C\uB85C \uBD80\uB4DC\uB7EC\uC6B4 \uC804\uD658)\r\n if (redirectTo) {\r\n requestAnimationFrame(() => {\r\n setTimeout(() => {\r\n component.navigateTo(redirectTo);\r\n }, 1000);\r\n });\r\n }\r\n\r\n } catch (error) {\r\n // AbortError\uB294 \uC758\uB3C4\uC801\uC778 \uCDE8\uC18C\uC774\uBBC0\uB85C \uD2B9\uBCC4 \uCC98\uB9AC\r\n if (error.name === 'AbortError') {\r\n this.log('debug', 'Form submission aborted');\r\n return;\r\n }\r\n\r\n this.log('warn', 'Form submission error:', error);\r\n this.finishFormSubmission(form);\r\n \r\n // \uC5D0\uB7EC \uD578\uB4E4\uB7EC \uD638\uCD9C\r\n if (errorHandler && component[errorHandler]) {\r\n component[errorHandler](error, form);\r\n } else {\r\n this.log('error', 'Form submission error (no error handler defined):', error);\r\n }\r\n \r\n } finally {\r\n // \uB85C\uB529 \uC885\uB8CC\r\n if (loadingHandler && component[loadingHandler]) {\r\n component[loadingHandler](false, form);\r\n }\r\n }\r\n }\r\n\r\n\r\n /**\r\n * \uC561\uC158 \uD30C\uB77C\uBBF8\uD130 \uCC98\uB9AC (ApiHandler \uC7AC\uC0AC\uC6A9)\r\n */\r\n processActionParams(actionTemplate, component) {\r\n // ApiHandler\uC758 processURLParameters \uC7AC\uC0AC\uC6A9\uD558\uC5EC \uC77C\uAD00\uC131 \uD655\uBCF4\r\n return this.router.routeLoader.apiHandler.processURLParameters(actionTemplate, component);\r\n }\r\n\r\n /**\r\n * \uD3FC \uB370\uC774\uD130 \uC11C\uBE0C\uBC0B (ApiHandler \uD65C\uC6A9)\r\n */\r\n async submitFormData(action, method, data, form, component, signal = null) {\r\n // \uD30C\uC77C \uC5C5\uB85C\uB4DC \uCCB4\uD06C\r\n const hasFile = Array.from(form.elements).some(el => el.type === 'file' && el.files.length > 0);\r\n \r\n // ApiHandler\uB97C \uC0AC\uC6A9\uD558\uC5EC \uC77C\uAD00\uB41C API \uD638\uCD9C \uBC0F \uC5D0\uB7EC \uCC98\uB9AC\r\n const options = {\r\n method: method.toUpperCase(),\r\n headers: {},\r\n signal: signal // AbortController \uC2E0\uD638 \uCD94\uAC00\r\n };\r\n\r\n if (hasFile) {\r\n // \uD30C\uC77C\uC774 \uC788\uC73C\uBA74 FormData \uADF8\uB300\uB85C \uC804\uC1A1 (Content-Type \uC790\uB3D9 \uC124\uC815)\r\n options.data = new FormData(form);\r\n } else {\r\n // JSON\uC73C\uB85C \uC804\uC1A1\r\n options.data = data;\r\n options.headers['Content-Type'] = 'application/json';\r\n }\r\n\r\n // ApiHandler\uC758 fetchData \uC0AC\uC6A9\uD558\uC5EC \uD1B5\uD569\uB41C \uCC98\uB9AC\r\n return await this.router.routeLoader.apiHandler.fetchData(action, component, options);\r\n }\r\n\r\n /**\r\n * \uD074\uB77C\uC774\uC5B8\uD2B8 \uC0AC\uC774\uB4DC \uD3FC \uAC80\uC99D\r\n */\r\n validateForm(form, component) {\r\n let isValid = true;\r\n const inputs = form.querySelectorAll('input, textarea, select');\r\n\r\n inputs.forEach(input => {\r\n // \uAE30\uBCF8 HTML5 \uAC80\uC99D\r\n if (!input.checkValidity()) {\r\n isValid = false;\r\n input.classList.add('error');\r\n return;\r\n }\r\n\r\n // \uCEE4\uC2A4\uD140 \uAC80\uC99D \uD568\uC218 \uD655\uC778\r\n const validationFunction = input.getAttribute('data-validation');\r\n if (validationFunction) {\r\n const isInputValid = this.validateInput(input, validationFunction, component);\r\n if (!isInputValid) {\r\n isValid = false;\r\n input.classList.add('error');\r\n } else {\r\n input.classList.remove('error');\r\n }\r\n } else {\r\n input.classList.remove('error');\r\n }\r\n });\r\n\r\n return isValid;\r\n }\r\n\r\n /**\r\n * \uAC1C\uBCC4 \uC785\uB825 \uAC80\uC99D\r\n */\r\n validateInput(input, validationFunction, component) {\r\n const value = input.value;\r\n \r\n // \uCEE4\uC2A4\uD140 \uAC80\uC99D \uD568\uC218 \uD638\uCD9C\r\n if (typeof component[validationFunction] === 'function') {\r\n try {\r\n return component[validationFunction](value, input);\r\n } catch (error) {\r\n this.log('warn', `Validation function '${validationFunction}' error:`, error);\r\n return false;\r\n }\r\n }\r\n \r\n // \uD568\uC218\uAC00 \uC5C6\uC73C\uBA74 true \uBC18\uD658\r\n this.log('warn', `Validation function '${validationFunction}' not found`);\r\n return true;\r\n }\r\n\r\n /**\r\n * \uBAA8\uB4E0 \uD3FC \uC694\uCCAD \uCDE8\uC18C\r\n */\r\n cancelAllRequests() {\r\n const forms = document.querySelectorAll('form');\r\n forms.forEach(form => {\r\n if (form._isSubmitting) {\r\n this.abortFormSubmission(form);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n // \uBAA8\uB4E0 \uC9C4\uD589 \uC911\uC778 \uC694\uCCAD \uCDE8\uC18C\r\n this.cancelAllRequests();\r\n \r\n // \uB4F1\uB85D\uB41C \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108\uB4E4 \uC815\uB9AC\r\n const forms = document.querySelectorAll('form.auto-form, form[action]');\r\n forms.forEach(form => {\r\n if (form._boundSubmitHandler) {\r\n form.removeEventListener('submit', form._boundSubmitHandler);\r\n delete form._boundSubmitHandler;\r\n }\r\n \r\n // \uD3FC \uC0C1\uD0DC \uC815\uB9AC\r\n this.cleanupFormState(form);\r\n });\r\n \r\n // WeakMap \uC815\uB9AC (\uC790\uB3D9 \uAC00\uBE44\uC9C0 \uCEEC\uB809\uC158\uB428)\r\n \r\n this.log('debug', 'FormHandler destroyed');\r\n this.router = null;\r\n }\r\n\r\n /**\r\n * \uD3FC \uC0C1\uD0DC \uC815\uB9AC\r\n */\r\n cleanupFormState(form) {\r\n delete form._isSubmitting;\r\n delete form._abortController;\r\n \r\n if (form._timeoutId) {\r\n clearTimeout(form._timeoutId);\r\n delete form._timeoutId;\r\n }\r\n }\r\n}", "/**\r\n * ApiHandler\r\n * API \uD638\uCD9C \uBC0F \uB370\uC774\uD130 \uCC98\uB9AC \uC2DC\uC2A4\uD15C\r\n */\r\nexport class ApiHandler {\r\n constructor(router, options = {}) {\r\n this.router = router;\r\n this.apiBaseURL = options.apiBaseURL || '';\r\n \r\n this.log('debug', 'ApiHandler initialized');\r\n }\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'ApiHandler', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * \uCEF4\uD3EC\uB10C\uD2B8 \uB370\uC774\uD130 \uAC00\uC838\uC624\uAE30 (\uD30C\uB77C\uBBF8\uD130 \uCE58\uD658 \uC9C0\uC6D0)\r\n */\r\n async fetchData(dataURL, component = null, options = {}) {\r\n try {\r\n // URL\uC5D0\uC11C \uD30C\uB77C\uBBF8\uD130 \uCE58\uD658\r\n let processedURL = this.processURLParameters(dataURL, component);\r\n\r\n // apiBaseURL\uACFC \uC870\uD569 (\uC808\uB300 URL\uC774 \uC544\uB2CC \uACBD\uC6B0\uC5D0\uB9CC)\r\n if (this.apiBaseURL && !this.isAbsoluteURL(processedURL)) {\r\n processedURL = this.combineURLs(this.apiBaseURL, processedURL);\r\n }\r\n\r\n // \uD604\uC7AC \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130\uB97C URL\uC5D0 \uCD94\uAC00\r\n const queryString = this.router.queryManager?.buildQueryString(this.router.queryManager?.getQueryParams()) || '';\r\n const fullURL = queryString ? `${processedURL}?${queryString}` : processedURL;\r\n \r\n this.log('debug', `Fetching data from: ${fullURL}`);\r\n \r\n // \uC694\uCCAD \uC635\uC158 \uC124\uC815\r\n const requestOptions = {\r\n method: options.method || 'GET',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'application/json',\r\n ...options.headers\r\n },\r\n ...options\r\n };\r\n\r\n // \uC778\uC99D \uD1A0\uD070 \uC790\uB3D9 \uCD94\uAC00\r\n if (component?.$getToken && component.$getToken()) {\r\n requestOptions.headers['Authorization'] = `Bearer ${component.$getToken()}`;\r\n }\r\n\r\n // POST/PUT \uB370\uC774\uD130 \uCC98\uB9AC\r\n if (options.data && ['POST', 'PUT', 'PATCH'].includes(requestOptions.method.toUpperCase())) {\r\n if (options.data instanceof FormData) {\r\n // FormData\uC778 \uACBD\uC6B0 \uADF8\uB300\uB85C \uC804\uC1A1 (Content-Type \uC790\uB3D9 \uC124\uC815)\r\n requestOptions.body = options.data;\r\n // FormData\uC77C \uB54C Content-Type \uD5E4\uB354 \uC81C\uAC70 (\uBE0C\uB77C\uC6B0\uC800\uAC00 \uC790\uB3D9 \uC124\uC815)\r\n delete requestOptions.headers['Content-Type'];\r\n } else {\r\n // \uC77C\uBC18 \uAC1D\uCCB4\uC778 \uACBD\uC6B0 JSON\uC73C\uB85C \uC9C1\uB82C\uD654\r\n requestOptions.body = JSON.stringify(options.data);\r\n }\r\n }\r\n\r\n const response = await fetch(fullURL, requestOptions);\r\n\r\n if (!response.ok) {\r\n let error;\r\n try {\r\n error = await response.json();\r\n } catch (e) {\r\n error = { message: `HTTP ${response.status}: ${response.statusText}` };\r\n }\r\n throw new Error(error.message || `HTTP ${response.status}`);\r\n }\r\n \r\n // \uC751\uB2F5 \uCC98\uB9AC\r\n try {\r\n const data = await response.json();\r\n \r\n // \uB370\uC774\uD130 \uC720\uD6A8\uC131 \uAC80\uC0AC\r\n if (typeof data !== 'object' || data === null) {\r\n throw new Error('Invalid data format: expected object');\r\n }\r\n \r\n return data;\r\n } catch (e) {\r\n // \uC751\uB2F5\uC774 JSON\uC774 \uC544\uB2CC \uACBD\uC6B0 (\uC608: 204 No Content)\r\n return { success: true };\r\n }\r\n\r\n } catch (error) {\r\n this.log('error', 'Failed to fetch data:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * \uC5EC\uB7EC API \uC5D4\uB4DC\uD3EC\uC778\uD2B8\uC5D0\uC11C \uB370\uC774\uD130 \uAC00\uC838\uC624\uAE30\r\n */\r\n async fetchMultipleData(dataConfig, component = null) {\r\n if (!dataConfig || typeof dataConfig !== 'object') {\r\n return {};\r\n }\r\n\r\n const results = {};\r\n const errors = {};\r\n \r\n // \uBCD1\uB82C \uCC98\uB9AC\uB97C \uC704\uD55C Promise \uBC30\uC5F4\r\n const promises = Object.entries(dataConfig).map(async ([key, config]) => {\r\n try {\r\n let url, options = {};\r\n \r\n if (typeof config === 'string') {\r\n url = config;\r\n } else if (typeof config === 'object') {\r\n url = config.url;\r\n options = { ...config };\r\n delete options.url;\r\n }\r\n \r\n if (url) {\r\n const data = await this.fetchData(url, component, options);\r\n results[key] = data;\r\n }\r\n } catch (error) {\r\n errors[key] = error;\r\n this.log('warn', `Failed to fetch data for '${key}':`, error);\r\n }\r\n });\r\n \r\n await Promise.all(promises);\r\n \r\n return { results, errors };\r\n }\r\n \r\n /**\r\n * URL\uC5D0\uC11C \uD30C\uB77C\uBBF8\uD130 \uCE58\uD658 \uCC98\uB9AC ({param} \uD615\uC2DD)\r\n */\r\n processURLParameters(url, component = null) {\r\n if (!url || typeof url !== 'string') return url;\r\n \r\n let processedURL = url;\r\n \r\n // {paramName} \uD328\uD134 \uCC3E\uAE30\r\n const paramMatches = url.match(/\\{([^}]+)\\}/g);\r\n \r\n if (paramMatches && component) {\r\n paramMatches.forEach(match => {\r\n const paramName = match.slice(1, -1); // {id} -> id\r\n \r\n try {\r\n let paramValue = null;\r\n\r\n // 1. computed \uC18D\uC131\uC5D0\uC11C \uCC3E\uAE30 (\uCD5C\uC6B0\uC120)\r\n if (component.$options?.computed?.[paramName]) {\r\n paramValue = component[paramName];\r\n }\r\n\r\n // 2. \uCEF4\uD3EC\uB10C\uD2B8 data\uC5D0\uC11C \uCC3E\uAE30\r\n if (paramValue === null || paramValue === undefined) {\r\n paramValue = component[paramName];\r\n }\r\n\r\n // 3. \uB77C\uC6B0\uD2B8/\uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130\uC5D0\uC11C \uCC3E\uAE30\r\n if (paramValue === null || paramValue === undefined) {\r\n if (component.getParam) {\r\n paramValue = component.getParam(paramName);\r\n }\r\n }\r\n\r\n // 4. QueryManager\uC5D0\uC11C \uC9C1\uC811 \uAC00\uC838\uC624\uAE30 (fallback)\r\n if (paramValue === null || paramValue === undefined) {\r\n paramValue = this.router.queryManager?.getParam(paramName);\r\n }\r\n \r\n if (paramValue !== null && paramValue !== undefined) {\r\n // \uD30C\uB77C\uBBF8\uD130 \uCE58\uD658: {id} -> \uC2E4\uC81C\uAC12\r\n processedURL = processedURL.replace(\r\n match, \r\n encodeURIComponent(paramValue)\r\n );\r\n \r\n this.log('debug', `URL parameter resolved: ${paramName} = ${paramValue}`);\r\n } else {\r\n this.log('warn', `URL parameter '${paramName}' not found, keeping original: ${match}`);\r\n }\r\n } catch (error) {\r\n this.log('warn', `Error processing URL parameter '${paramName}':`, error);\r\n }\r\n });\r\n }\r\n \r\n return processedURL;\r\n }\r\n\r\n /**\r\n * HTTP \uBA54\uC11C\uB4DC\uBCC4 \uD5EC\uD37C \uD568\uC218\uB4E4\r\n */\r\n async get(url, component = null, options = {}) {\r\n return this.fetchData(url, component, { ...options, method: 'GET' });\r\n }\r\n\r\n async post(url, data, component = null, options = {}) {\r\n return this.fetchData(url, component, { ...options, method: 'POST', data });\r\n }\r\n\r\n async put(url, data, component = null, options = {}) {\r\n return this.fetchData(url, component, { ...options, method: 'PUT', data });\r\n }\r\n\r\n async patch(url, data, component = null, options = {}) {\r\n return this.fetchData(url, component, { ...options, method: 'PATCH', data });\r\n }\r\n\r\n async delete(url, component = null, options = {}) {\r\n return this.fetchData(url, component, { ...options, method: 'DELETE' });\r\n }\r\n\r\n /**\r\n * \uCEF4\uD3EC\uB10C\uD2B8\uC5D0 \uBC14\uC778\uB529\uB41C API \uAC1D\uCCB4 \uC0DD\uC131\r\n */\r\n bindToComponent(component) {\r\n return {\r\n get: (url, options = {}) => this.get(url, component, options),\r\n post: (url, data, options = {}) => this.post(url, data, component, options),\r\n put: (url, data, options = {}) => this.put(url, data, component, options),\r\n patch: (url, data, options = {}) => this.patch(url, data, component, options),\r\n delete: (url, options = {}) => this.delete(url, component, options),\r\n fetchData: (url, options = {}) => this.fetchData(url, component, options),\r\n fetchMultipleData: (dataConfig) => this.fetchMultipleData(dataConfig, component)\r\n };\r\n }\r\n\r\n /**\r\n * \uC808\uB300 URL\uC778\uC9C0 \uD655\uC778\r\n */\r\n isAbsoluteURL(url) {\r\n return /^https?:\\/\\//.test(url) || url.startsWith('//');\r\n }\r\n\r\n /**\r\n * \uB450 URL\uC744 \uC870\uD569\r\n */\r\n combineURLs(baseURL, relativeURL) {\r\n // \uBCA0\uC774\uC2A4 URL \uB05D\uC758 \uC2AC\uB798\uC2DC \uC81C\uAC70\r\n const cleanBase = baseURL.replace(/\\/$/, '');\r\n // \uC0C1\uB300 URL \uC55E\uC758 \uC2AC\uB798\uC2DC \uD655\uC778\r\n const cleanRelative = relativeURL.startsWith('/') ? relativeURL : `/${relativeURL}`;\r\n return `${cleanBase}${cleanRelative}`;\r\n }\r\n\r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n this.log('debug', 'ApiHandler destroyed');\r\n this.router = null;\r\n }\r\n}", "/**\r\n * ComponentLoader\r\n * \uB3D9\uC801\uC73C\uB85C \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uB85C\uB4DC\uD558\uACE0 \uB4F1\uB85D\uD558\uB294 \uC2DC\uC2A4\uD15C\r\n */\r\nexport class ComponentLoader {\r\n constructor(router = null, options = {}) {\r\n\r\n this.config = {\r\n componentsPath: options.componentsPath || '/components', // srcPath \uAE30\uC900 \uC0C1\uB300 \uACBD\uB85C\r\n environment: options.environment || 'development',\r\n ...options\r\n };\r\n \r\n this.router = router;\r\n this.loadingPromises = new Map();\r\n this.unifiedComponents = null;\r\n }\r\n \r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'ComponentLoader', ...args);\r\n }\r\n }\r\n \r\n /**\r\n * \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uBE44\uB3D9\uAE30\uB85C \uB85C\uB4DC (\uCE90\uC2DC \uC9C0\uC6D0)\r\n */\r\n async loadComponent(componentName) {\r\n if (!componentName || typeof componentName !== 'string') {\r\n throw new Error('Component name must be a non-empty string');\r\n }\r\n \r\n // \uCE90\uC2DC\uC5D0\uC11C \uCEF4\uD3EC\uB10C\uD2B8 \uD655\uC778\r\n const cacheKey = `component_${componentName}`;\r\n const cachedComponent = this.router?.cacheManager?.get(cacheKey);\r\n if (cachedComponent) {\r\n this.log('debug', `Component '${componentName}' loaded from cache`);\r\n return cachedComponent;\r\n }\r\n \r\n // \uC774\uBBF8 \uB85C\uB529 \uC911\uC778 \uACBD\uC6B0 \uAE30\uC874 Promise \uBC18\uD658\r\n if (this.loadingPromises.has(componentName)) {\r\n return this.loadingPromises.get(componentName);\r\n }\r\n \r\n const loadPromise = this._loadComponentFromFile(componentName);\r\n this.loadingPromises.set(componentName, loadPromise);\r\n \r\n try {\r\n const component = await loadPromise;\r\n \r\n // \uCE90\uC2DC\uC5D0 \uC800\uC7A5\r\n if (component && this.router?.cacheManager) {\r\n this.router.cacheManager.set(cacheKey, component);\r\n this.log('debug', `Component '${componentName}' cached successfully`);\r\n }\r\n \r\n return component;\r\n } catch (error) {\r\n throw error;\r\n } finally {\r\n this.loadingPromises.delete(componentName);\r\n }\r\n }\r\n \r\n /**\r\n * \uD30C\uC77C\uC5D0\uC11C \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB4DC\r\n */\r\n async _loadComponentFromFile(componentName) {\r\n // srcPath + componentsPath\uB97C \uC870\uD569\uD558\uC5EC \uCEF4\uD3EC\uB10C\uD2B8 \uACBD\uB85C \uC0DD\uC131\r\n const componentRelativePath = `${this.config.componentsPath}/${componentName}.js`;\r\n \r\n let componentPath;\r\n if (this.router && this.router.config.srcPath) {\r\n // srcPath\uB294 \uC774\uBBF8 \uC804\uCCB4 URL\uC774\uBBC0\uB85C \uC9C1\uC811 \uC870\uD569\r\n const srcPath = this.router.config.srcPath;\r\n if (srcPath.startsWith('http')) {\r\n // \uC774\uC911 \uC2AC\uB798\uC2DC \uBC29\uC9C0\r\n const cleanSrcPath = srcPath.endsWith('/') ? srcPath.slice(0, -1) : srcPath;\r\n const cleanComponentPath = componentRelativePath.startsWith('/') ? componentRelativePath : `/${componentRelativePath}`;\r\n componentPath = `${cleanSrcPath}${cleanComponentPath}`;\r\n } else {\r\n componentPath = this.router.resolvePath(`${srcPath}${componentRelativePath}`);\r\n }\r\n } else {\r\n // \uD3F4\uBC31: \uAE30\uBCF8 \uACBD\uB85C \uC0AC\uC6A9 (\uC808\uB300 \uACBD\uB85C)\r\n componentPath = this.router ?\r\n this.router.resolvePath(`/src${componentRelativePath}`) :\r\n `/src${componentRelativePath}`;\r\n }\r\n \r\n try {\r\n const module = await import(componentPath);\r\n const component = module.default;\r\n \r\n if (!component) {\r\n throw new Error(`Component '${componentName}' has no default export`);\r\n }\r\n \r\n if (!component.name) {\r\n component.name = componentName;\r\n }\r\n \r\n this.log('debug', `Component '${componentName}' loaded successfully`);\r\n return component;\r\n \r\n } catch (error) {\r\n this.log('error', `Failed to load component '${componentName}':`, error);\r\n throw new Error(`Component '${componentName}' not found: ${error.message}`);\r\n }\r\n }\r\n \r\n /**\r\n * \uCEF4\uD3EC\uB10C\uD2B8 \uBAA8\uB4C8 \uD074\uB9AC\uC5B4\r\n */\r\n clearComponents() {\r\n this.loadingPromises.clear();\r\n this.unifiedComponents = null;\r\n this.log('debug', 'All components cleared');\r\n }\r\n \r\n /**\r\n * \uD658\uACBD\uC5D0 \uB530\uB978 \uBAA8\uB4E0 \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB529 (\uCE90\uC2F1 \uC9C0\uC6D0)\r\n */\r\n async loadAllComponents(componentNames = null) {\r\n let components;\r\n \r\n // \uC6B4\uC601 \uBAA8\uB4DC: \uD1B5\uD569 \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB529 \uC2DC\uB3C4\r\n if (this.config.environment === 'production') {\r\n // \uC6B4\uC601 \uBAA8\uB4DC\uC5D0\uC11C\uB9CC unifiedComponents \uCE90\uC2DC \uC0AC\uC6A9\r\n if (this.unifiedComponents) {\r\n this.log('debug', 'Using existing unified components');\r\n return this.unifiedComponents;\r\n }\r\n components = await this._loadProductionComponents();\r\n } else {\r\n // \uAC1C\uBC1C \uBAA8\uB4DC: \uCE90\uC2DC \uC5C6\uC774 \uAC1C\uBCC4 \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB529\r\n components = await this._loadDevelopmentComponents(componentNames);\r\n }\r\n \r\n return components;\r\n }\r\n \r\n /**\r\n * \uC6B4\uC601 \uBAA8\uB4DC: \uD1B5\uD569 \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB529\r\n */\r\n async _loadProductionComponents() {\r\n try {\r\n const componentsPath = `${this.router?.config?.routesPath || '/routes'}/_components.js`;\r\n this.log('debug', '[PRODUCTION] Loading unified components from:', componentsPath);\r\n \r\n const componentsModule = await import(componentsPath);\r\n \r\n if (typeof componentsModule.registerComponents === 'function') {\r\n this.unifiedComponents = componentsModule.components || {};\r\n this.log('debug', `[PRODUCTION] Unified components loaded: ${Object.keys(this.unifiedComponents).length} components`);\r\n return this.unifiedComponents;\r\n } else {\r\n throw new Error('registerComponents function not found in components module');\r\n }\r\n } catch (error) {\r\n this.log('warn', '[PRODUCTION] Failed to load unified components:', error.message);\r\n this.unifiedComponents = {};\r\n return {};\r\n }\r\n }\r\n \r\n /**\r\n * \uAC1C\uBC1C \uBAA8\uB4DC: \uAC1C\uBCC4 \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB529\r\n */\r\n async _loadDevelopmentComponents(componentNames = null) {\r\n // \uCEF4\uD3EC\uB10C\uD2B8 \uC774\uB984 \uBAA9\uB85D\uC774 \uC81C\uACF5\uB418\uC9C0 \uC54A\uC73C\uBA74 \uD3F4\uBC31 \uC0AC\uC6A9\r\n const namesToLoad = componentNames || [];\r\n const components = {};\r\n \r\n if (namesToLoad.length === 0) {\r\n this.log('debug', '[DEVELOPMENT] No components to load');\r\n return components;\r\n }\r\n \r\n this.log('debug', `[DEVELOPMENT] Loading individual components: ${namesToLoad.join(', ')}`);\r\n \r\n for (const name of namesToLoad) {\r\n try {\r\n const component = await this.loadComponent(name);\r\n if (component) {\r\n components[name] = component;\r\n }\r\n } catch (loadError) {\r\n this.log('warn', `[DEVELOPMENT] Failed to load component ${name}:`, loadError.message);\r\n }\r\n }\r\n \r\n this.log('debug', `[DEVELOPMENT] Individual components loaded: ${Object.keys(components).length} components`);\r\n return components;\r\n }\r\n \r\n /**\r\n * \uD15C\uD50C\uB9BF\uACFC \uB808\uC774\uC544\uC6C3\uC5D0\uC11C \uC0AC\uC6A9\uB41C \uCEF4\uD3EC\uB10C\uD2B8 \uCD94\uCD9C\r\n */\r\n getComponentNames(template, layout = null, layoutName = null) {\r\n // \uB808\uC774\uC544\uC6C3 \uCEF4\uD3EC\uB10C\uD2B8\uB85C \uCD08\uAE30\uD654 (\uCE90\uC2DC \uD65C\uC6A9)\r\n const componentSet = layout ? \r\n this._getLayoutComponents(layout, layoutName) : \r\n new Set();\r\n \r\n // \uD15C\uD50C\uB9BF\uC5D0\uC11C \uCEF4\uD3EC\uB10C\uD2B8 \uCD94\uCD9C\r\n if (template) {\r\n this._extractComponentsFromContent(template, componentSet);\r\n }\r\n \r\n const components = Array.from(componentSet);\r\n this.log('debug', `Discovered ${components.length} components:`, components);\r\n \r\n return components;\r\n }\r\n \r\n /**\r\n * \uB808\uC774\uC544\uC6C3\uC5D0\uC11C \uCEF4\uD3EC\uB10C\uD2B8 \uCD94\uCD9C (\uCE90\uC2DC \uD65C\uC6A9)\r\n */\r\n _getLayoutComponents(layout, layoutName) {\r\n if (!layout || typeof layout !== 'string') return new Set();\r\n if (!layoutName || typeof layoutName !== 'string') return new Set();\r\n \r\n // \uB808\uC774\uC544\uC6C3 \uC774\uB984\uC744 \uCE90\uC2DC \uD0A4\uB85C \uC0AC\uC6A9\r\n const cacheKey = `layout_components_${layoutName}`;\r\n \r\n // \uCE90\uC2DC\uC5D0\uC11C \uD655\uC778\r\n const cachedComponents = this.router?.cacheManager?.get(cacheKey);\r\n if (cachedComponents) {\r\n this.log('debug', `Using cached layout components for '${layoutName}'`);\r\n return cachedComponents;\r\n }\r\n \r\n // \uB808\uC774\uC544\uC6C3\uC5D0\uC11C \uCEF4\uD3EC\uB10C\uD2B8 \uCD94\uCD9C\r\n const componentSet = new Set();\r\n this._extractComponentsFromContent(layout, componentSet);\r\n \r\n // \uCE90\uC2DC\uC5D0 \uC800\uC7A5 (Set \uADF8\uB300\uB85C)\r\n if (this.router?.cacheManager) {\r\n this.router.cacheManager.set(cacheKey, componentSet);\r\n this.log('debug', `Cached layout components for '${layoutName}': ${Array.from(componentSet).join(', ')}`);\r\n }\r\n \r\n return componentSet;\r\n }\r\n \r\n /**\r\n * HTML \uCEE8\uD150\uCE20\uC5D0\uC11C Vue \uCEF4\uD3EC\uB10C\uD2B8 \uCD94\uCD9C\r\n */\r\n _extractComponentsFromContent(content, componentSet) {\r\n if (!content || typeof content !== 'string') return;\r\n \r\n // \uB354 \uD6A8\uC728\uC801\uC778 \uD328\uD134: PascalCase \uCEF4\uD3EC\uB10C\uD2B8 \uD0DC\uADF8 \uCD94\uCD9C\r\n // \uC2DC\uC791 \uD0DC\uADF8 <Component>\uC640 \uC790\uCCB4 \uB2EB\uD798 \uD0DC\uADF8 <Component/>\uB97C \uBAA8\uB450 \uAC10\uC9C0\r\n // dotAll \uD50C\uB798\uADF8(s)\uB85C \uAC1C\uD589 \uBB38\uC790\uB3C4 \uCC98\uB9AC\r\n const componentPattern = /<([A-Z][a-zA-Z0-9]*)(?:\\s[^>]*)?\\/?>|<\\/([A-Z][a-zA-Z0-9]*)\\s*>/gs;\r\n let match;\r\n \r\n while ((match = componentPattern.exec(content)) !== null) {\r\n // match[1]\uC740 \uC2DC\uC791/\uC790\uCCB4\uB2EB\uD798 \uD0DC\uADF8, match[2]\uB294 \uB2EB\uB294 \uD0DC\uADF8\r\n const componentName = match[1] || match[2];\r\n \r\n if (componentName && !this._isHtmlTag(componentName)) {\r\n componentSet.add(componentName);\r\n this.log('debug', `Found component: ${componentName}`);\r\n }\r\n }\r\n }\r\n \r\n /**\r\n * HTML \uAE30\uBCF8 \uD0DC\uADF8\uC778\uC9C0 \uD655\uC778\r\n */\r\n _isHtmlTag(tagName) {\r\n const htmlTags = [\r\n 'div', 'span', 'p', 'a', 'img', 'ul', 'ol', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\r\n 'table', 'tr', 'td', 'th', 'form', 'select', 'option', 'textarea',\r\n 'nav', 'header', 'footer', 'main', 'section', 'article', 'aside', 'figure', 'figcaption',\r\n 'video', 'audio', 'canvas', 'svg', 'iframe', 'script', 'style', 'link', 'meta', 'title',\r\n 'body', 'html', 'head', 'template', 'slot'\r\n ];\r\n \r\n return htmlTags.includes(tagName);\r\n }\r\n\r\n /**\r\n * \uBA54\uBAA8\uB9AC \uC815\uB9AC\r\n */\r\n dispose() {\r\n this.clearComponents();\r\n this.log('debug', 'ComponentLoader disposed');\r\n this.router = null;\r\n }\r\n}", "/**\r\n * ViewLogic Route Loading System\r\n * \uB77C\uC6B0\uD2B8 \uB85C\uB529 \uBC0F \uCEF4\uD3EC\uB10C\uD2B8 \uAD00\uB9AC \uC2DC\uC2A4\uD15C\r\n */\r\nimport { FormHandler } from './FormHandler.js';\r\nimport { ApiHandler } from './ApiHandler.js';\r\nimport { ComponentLoader } from './ComponentLoader.js';\r\n\r\nexport class RouteLoader {\r\n constructor(router, options = {}) {\r\n this.config = {\r\n srcPath: options.srcPath || router.config.srcPath || '/src', // \uC18C\uC2A4 \uD30C\uC77C \uACBD\uB85C\r\n routesPath: options.routesPath || router.config.routesPath || '/routes', // \uD504\uB85C\uB355\uC158 \uB77C\uC6B0\uD2B8 \uACBD\uB85C\r\n environment: options.environment || 'development',\r\n useLayout: options.useLayout !== false,\r\n defaultLayout: options.defaultLayout || 'default'\r\n };\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870\r\n this.router = router;\r\n \r\n // FormHandler \uC778\uC2A4\uD134\uC2A4 \uC0DD\uC131\r\n this.formHandler = new FormHandler(router, this.config);\r\n \r\n // ApiHandler \uC778\uC2A4\uD134\uC2A4 \uC0DD\uC131\r\n this.apiHandler = new ApiHandler(router, this.config);\r\n \r\n // ComponentLoader \uC778\uC2A4\uD134\uC2A4 \uC0DD\uC131 (\uAE30\uBCF8\uC73C\uB85C \uD65C\uC131\uD654)\r\n this.componentLoader = new ComponentLoader(router, this.config);\r\n \r\n this.log('debug', 'RouteLoader initialized with config:', this.config);\r\n }\r\n\r\n /**\r\n * \uC2A4\uD06C\uB9BD\uD2B8 \uD30C\uC77C \uB85C\uB4DC\r\n */\r\n async loadScript(routeName) {\r\n let script;\r\n try {\r\n if (this.config.environment === 'production') {\r\n // \uD504\uB85C\uB355\uC158 \uBAA8\uB4DC: routes \uD3F4\uB354\uC5D0\uC11C \uBE4C\uB4DC\uB41C JS \uB85C\uB4DC (\uC808\uB300 \uACBD\uB85C)\r\n const importPath = `${this.config.routesPath}/${routeName}.js`;\r\n this.log('debug', `Loading production route: ${importPath}`);\r\n const module = await import(importPath);\r\n script = module.default;\r\n } else {\r\n // \uAC1C\uBC1C \uBAA8\uB4DC: srcPath \uC0AC\uC6A9\uD558\uC5EC \uC18C\uC2A4 \uD30C\uC77C \uACBD\uB85C \uAD6C\uC131\r\n const importPath = `${this.config.srcPath}/logic/${routeName}.js`;\r\n this.log('debug', `Loading development route: ${importPath}`);\r\n const module = await import(importPath);\r\n script = module.default;\r\n }\r\n \r\n if (!script) {\r\n throw new Error(`Route '${routeName}' not found - no default export`);\r\n }\r\n \r\n } catch (error) {\r\n // import \uC5D0\uB7EC\uB97C 404\uB85C \uBD84\uB958\r\n if (error.message.includes('Failed to resolve') || \r\n error.message.includes('Failed to fetch') ||\r\n error.message.includes('not found') ||\r\n error.name === 'TypeError') {\r\n throw new Error(`Route '${routeName}' not found - 404`);\r\n }\r\n // \uB2E4\uB978 \uC5D0\uB7EC\uB294 \uADF8\uB300\uB85C \uC804\uD30C\r\n throw error;\r\n }\r\n \r\n return script;\r\n }\r\n\r\n /**\r\n * \uD15C\uD50C\uB9BF \uD30C\uC77C \uB85C\uB4DC (\uC2E4\uD328\uC2DC \uAE30\uBCF8\uAC12 \uBC18\uD658)\r\n */\r\n async loadTemplate(routeName) {\r\n try {\r\n const templatePath = `${this.config.srcPath}/views/${routeName}.html`;\r\n const response = await fetch(templatePath);\r\n if (!response.ok) throw new Error(`Template not found: ${response.status}`);\r\n const template = await response.text();\r\n this.log('debug', `Template '${routeName}' loaded successfully`);\r\n return template;\r\n } catch (error) {\r\n this.log('warn', `Template '${routeName}' not found, using default:`, error.message);\r\n // \uAE30\uBCF8 \uD15C\uD50C\uB9BF \uBC18\uD658\r\n return this.generateDefaultTemplate(routeName);\r\n }\r\n }\r\n\r\n /**\r\n * \uC2A4\uD0C0\uC77C \uD30C\uC77C \uB85C\uB4DC (\uC2E4\uD328\uC2DC \uBE48 \uBB38\uC790\uC5F4 \uBC18\uD658)\r\n */\r\n async loadStyle(routeName) {\r\n try {\r\n const stylePath = `${this.config.srcPath}/styles/${routeName}.css`;\r\n const response = await fetch(stylePath);\r\n if (!response.ok) throw new Error(`Style not found: ${response.status}`);\r\n const style = await response.text();\r\n this.log('debug', `Style '${routeName}' loaded successfully`);\r\n return style;\r\n } catch (error) {\r\n this.log('debug', `Style '${routeName}' not found, no styles applied:`, error.message);\r\n // \uC2A4\uD0C0\uC77C\uC774 \uC5C6\uC73C\uBA74 \uBE48 \uBB38\uC790\uC5F4 \uBC18\uD658\r\n return '';\r\n }\r\n }\r\n\r\n /**\r\n * \uB808\uC774\uC544\uC6C3 \uD30C\uC77C \uB85C\uB4DC (\uC2E4\uD328\uC2DC null \uBC18\uD658)\r\n */\r\n async loadLayout(layoutName) {\r\n try {\r\n const layoutPath = `${this.config.srcPath}/layouts/${layoutName}.html`;\r\n const response = await fetch(layoutPath);\r\n if (!response.ok) throw new Error(`Layout not found: ${response.status}`);\r\n const layout = await response.text();\r\n \r\n this.log('debug', `Layout '${layoutName}' loaded successfully`);\r\n return layout;\r\n } catch (error) {\r\n this.log('debug', `Layout '${layoutName}' not found, no layout applied:`, error.message);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * \uB808\uC774\uC544\uC6C3\uACFC \uD15C\uD50C\uB9BF \uBCD1\uD569\r\n */\r\n mergeLayoutWithTemplate(routeName, layout, template) {\r\n let result;\r\n // \uB808\uC774\uC544\uC6C3\uC5D0\uC11C <slot name=\"content\"> \uBD80\uBD84\uC744 \uD15C\uD50C\uB9BF\uC73C\uB85C \uAD50\uCCB4\r\n if (layout.includes('{{ content }}')) {\r\n result = layout.replace(\r\n /{{ content }}/s,\r\n template\r\n );\r\n }\r\n // slot\uC774 \uC5C6\uC73C\uBA74 main-content \uD074\uB798\uC2A4 \uB0B4\uC6A9 \uAD50\uCCB4\r\n else if (layout.includes('class=\"main-content\"')) {\r\n this.log('debug', 'Using main-content replacement');\r\n result = layout.replace(\r\n /(<div class=\"container\">).*?(<\\/div>\\s*<\\/main>)/s,\r\n `$1${template}$2`\r\n );\r\n }\r\n // \uB9C8\uC9C0\uB9C9 \uB300\uC548: \uC804\uCCB4 \uB808\uC774\uC544\uC6C3\uC744 \uD15C\uD50C\uB9BF\uC73C\uB85C \uAC10\uC2F8\uAE30\r\n else {\r\n this.log('debug', 'Wrapping template with layout');\r\n result = `${layout}\\n${template}`;\r\n }\r\n \r\n return result;\r\n }\r\n\r\n\r\n /**\r\n * Vue \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131\r\n */\r\n async createVueComponent(routeName) {\r\n // \uCE90\uC2DC\uB41C Vue \uCEF4\uD3EC\uB10C\uD2B8\uAC00 \uC788\uB294\uC9C0 \uD655\uC778\r\n const cacheKey = `component_${routeName}`;\r\n const cached = this.router.cacheManager?.get(cacheKey);\r\n if (cached) {\r\n return cached;\r\n }\r\n \r\n const script = await this.loadScript(routeName);\r\n const router = this.router;\r\n const isProduction = this.config.environment === 'production';\r\n \r\n // \uD658\uACBD\uBCC4 \uB9AC\uC18C\uC2A4 \uB85C\uB529\r\n let template, style = '', layout = null;\r\n \r\n if (isProduction) {\r\n // \uD504\uB85C\uB355\uC158: \uC2A4\uD06C\uB9BD\uD2B8\uC5D0 \uC788\uB294 \uD15C\uD50C\uB9BF \uC0AC\uC6A9 \uB610\uB294 \uAE30\uBCF8\uAC12\r\n template = script.template || this.generateDefaultTemplate(routeName);\r\n } else {\r\n // \uAC1C\uBC1C: \uAC1C\uBCC4 \uD30C\uC77C\uB4E4 \uBCD1\uB82C \uB85C\uB4DC\r\n const loadPromises = [\r\n this.loadTemplate(routeName),\r\n this.loadStyle(routeName)\r\n ];\r\n \r\n // \uB808\uC774\uC544\uC6C3 \uB85C\uB529 \uC870\uAC74\uBD80 \uCD94\uAC00\r\n if (this.config.useLayout && script.layout !== null) {\r\n loadPromises.push(this.loadLayout(script.layout || this.config.defaultLayout));\r\n } else {\r\n loadPromises.push(Promise.resolve(null));\r\n }\r\n \r\n // \uBCD1\uB82C \uC2E4\uD589\r\n const [loadedTemplate, loadedStyle, loadedLayout] = await Promise.all(loadPromises);\r\n \r\n template = loadedTemplate;\r\n style = loadedStyle;\r\n layout = loadedLayout;\r\n \r\n // \uB808\uC774\uC544\uC6C3\uACFC \uD15C\uD50C\uB9BF \uBCD1\uD569\r\n if (layout) {\r\n template = this.mergeLayoutWithTemplate(routeName, layout, template);\r\n }\r\n }\r\n \r\n // \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB529 (\uC2E4\uD328\uD574\uB3C4 \uB77C\uC6B0\uD130\uB294 \uACC4\uC18D \uC791\uB3D9)\r\n let loadedComponents = {};\r\n if (this.componentLoader) {\r\n try {\r\n let componentNames = null;\r\n \r\n // \uAC1C\uBC1C \uBAA8\uB4DC\uC5D0\uC11C\uB9CC \uB3D9\uC801 \uCEF4\uD3EC\uB10C\uD2B8 \uBC1C\uACAC\r\n if (!isProduction) {\r\n const layoutName = script.layout || this.config.defaultLayout;\r\n componentNames = this.componentLoader.getComponentNames(template, layout, layoutName);\r\n this.log('debug', `[DEVELOPMENT] Discovered components for route '${routeName}':`, componentNames);\r\n }\r\n \r\n loadedComponents = await this.componentLoader.loadAllComponents(componentNames);\r\n this.log('debug', `Components loaded successfully for route: ${routeName}`);\r\n } catch (error) {\r\n this.log('warn', `Component loading failed for route '${routeName}', continuing without components:`, error.message);\r\n loadedComponents = {}; // \uBE48 \uAC1D\uCCB4\uB85C \uD3F4\uBC31\r\n }\r\n }\r\n\r\n // \uB2E8\uC77C \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131\r\n const component = {\r\n ...script,\r\n name: script.name || this.toPascalCase(routeName),\r\n template,\r\n components: loadedComponents,\r\n data() {\r\n const originalData = script.data ? script.data() : {};\r\n const commonData = {\r\n ...originalData,\r\n currentRoute: routeName,\r\n $query: router.queryManager?.getQueryParams() || {},\r\n $params: router.queryManager?.getRouteParams() || {},\r\n $lang: (() => {\r\n try {\r\n return router.i18nManager?.getCurrentLanguage() || router.config.i18nDefaultLanguage || router.config.defaultLanguage || 'ko';\r\n } catch (error) {\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', 'Failed to get current language:', error);\r\n return router.config.defaultLanguage || 'ko';\r\n }\r\n })(),\r\n $dataLoading: false\r\n };\r\n \r\n return commonData;\r\n },\r\n computed: {\r\n ...(script.computed || {}),\r\n // \uD558\uC704 \uD638\uD658\uC131\uC744 \uC704\uD574 params\uB294 \uC720\uC9C0\uD558\uB418 getAllParams \uC0AC\uC6A9\r\n params() {\r\n return router.queryManager?.getAllParams() || {};\r\n }\r\n },\r\n async mounted() {\r\n // API \uAC1D\uCCB4 \uCD08\uAE30\uD654\r\n this.$api = router.routeLoader.apiHandler.bindToComponent(this);\r\n\r\n // \uC0C1\uD0DC \uAD00\uB9AC \uCD08\uAE30\uD654\r\n this.$state = router.stateHandler;\r\n\r\n if (script.mounted) {\r\n await script.mounted.call(this);\r\n }\r\n if (script.dataURL) {\r\n // \uD1B5\uD569\uB41C \uB370\uC774\uD130 fetch (\uB2E8\uC77C/\uB2E4\uC911 API \uC790\uB3D9 \uCC98\uB9AC)\r\n await this.fetchData();\r\n }\r\n \r\n // \uD83C\uDD95 \uC790\uB3D9 \uD3FC \uBC14\uC778\uB529\r\n await this.$nextTick(); // DOM\uC774 \uC644\uC804\uD788 \uB80C\uB354\uB9C1\uB41C \uD6C4\r\n router.routeLoader.formHandler.bindAutoForms(this);\r\n },\r\n methods: {\r\n ...script.methods,\r\n // \uB77C\uC6B0\uD305 \uAD00\uB828\r\n navigateTo: (route, params) => router.navigateTo(route, params),\r\n getCurrentRoute: () => router.getCurrentRoute(),\r\n \r\n // \uD1B5\uD569\uB41C \uD30C\uB77C\uBBF8\uD130 \uAD00\uB9AC (\uB77C\uC6B0\uD305 + \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130)\r\n getParams: () => router.queryManager?.getAllParams() || {},\r\n getParam: (key, defaultValue) => router.queryManager?.getParam(key, defaultValue),\r\n \r\n // i18n \uAD00\uB828 (resilient - i18n \uC2E4\uD328\uD574\uB3C4 key \uBC18\uD658)\r\n $t: (key, params) => {\r\n try {\r\n return router.i18nManager?.t(key, params) || key;\r\n } catch (error) {\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', 'i18n translation failed, returning key:', error);\r\n return key;\r\n }\r\n },\r\n\r\n // \uC778\uC99D \uAD00\uB828 (\uD575\uC2EC 4\uAC1C \uBA54\uC18C\uB4DC\uB9CC)\r\n isAuth: () => router.authManager?.isAuthenticated() || false,\r\n logout: () => router.authManager ? router.navigateTo(router.authManager.logout()) : null,\r\n getToken: () => router.authManager?.getAccessToken() || null,\r\n setToken: (token, options) => router.authManager?.setAccessToken(token, options) || false,\r\n\r\n // i18n \uC5B8\uC5B4 \uAD00\uB9AC\r\n getLanguage: () => router.i18nManager?.getCurrentLanguage() || router.config.defaultLanguage || 'ko',\r\n setLanguage: (lang) => router.i18nManager?.setLanguage(lang),\r\n\r\n // \uB85C\uAE45 \uBC0F \uC5D0\uB7EC \uCC98\uB9AC\r\n log: (level, ...args) => {\r\n if (router.errorHandler) {\r\n router.errorHandler.log(level, `[${routeName}]`, ...args);\r\n }\r\n },\r\n\r\n\r\n // \uB370\uC774\uD130 fetch (ApiHandler \uB798\uD37C)\r\n async fetchData(dataConfig = null) {\r\n // dataConfig\uAC00 \uC81C\uACF5\uB418\uBA74 \uC0AC\uC6A9, \uC544\uB2C8\uBA74 script.dataURL \uC0AC\uC6A9\r\n const configToUse = dataConfig || script.dataURL;\r\n if (!configToUse) return null;\r\n \r\n this.$dataLoading = true;\r\n try {\r\n if (typeof configToUse === 'string') {\r\n // \uB2E8\uC77C API \uBC29\uC2DD\r\n const data = await router.routeLoader.apiHandler.fetchData(configToUse, this);\r\n Object.assign(this, data);\r\n this.$emit('data-loaded', data);\r\n return data;\r\n \r\n } else if (typeof configToUse === 'object') {\r\n // \uB2E4\uC911 API \uBC29\uC2DD - ApiHandler\uC758 fetchMultipleData \uC0AC\uC6A9\r\n const { results, errors } = await router.routeLoader.apiHandler.fetchMultipleData(configToUse, this);\r\n \r\n // \uC131\uACF5\uD55C \uACB0\uACFC\uB97C \uCEF4\uD3EC\uB10C\uD2B8 \uB370\uC774\uD130\uC5D0 \uBCD1\uD569\r\n Object.assign(this, results);\r\n \r\n // \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n if (Object.keys(results).length > 0) {\r\n this.$emit('data-loaded', results);\r\n }\r\n if (Object.keys(errors).length > 0) {\r\n this.$emit('data-error', errors);\r\n }\r\n \r\n return results;\r\n }\r\n \r\n return null;\r\n } catch (error) {\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', `Failed to fetch data for ${routeName}:`, error);\r\n this.$emit('data-error', error);\r\n throw error;\r\n } finally {\r\n this.$dataLoading = false;\r\n }\r\n }\r\n },\r\n _routeName: routeName\r\n };\r\n \r\n // \uAC1C\uBC1C \uBAA8\uB4DC\uC5D0\uC11C\uB9CC \uC2A4\uD0C0\uC77C \uBA54\uD0C0\uB370\uC774\uD130 \uC800\uC7A5 (\uB80C\uB354\uB9C1 \uC2DC \uC8FC\uC785\uC6A9)\r\n if (!isProduction && style) {\r\n component._style = style;\r\n }\r\n \r\n // \uCE90\uC2DC\uC5D0 \uC800\uC7A5\r\n this.router.cacheManager?.set(cacheKey, component);\r\n \r\n return component;\r\n }\r\n\r\n /**\r\n * \uBB38\uC790\uC5F4\uC744 PascalCase\uB85C \uBCC0\uD658\r\n */\r\n toPascalCase(str) {\r\n return str\r\n .split(/[-_\\s]+/) // \uD558\uC774\uD508, \uC5B8\uB354\uC2A4\uCF54\uC5B4, \uACF5\uBC31\uC73C\uB85C \uBD84\uB9AC\r\n .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\r\n .join('');\r\n }\r\n\r\n /**\r\n * \uAE30\uBCF8 \uD15C\uD50C\uB9BF \uC0DD\uC131\r\n */\r\n generateDefaultTemplate(routeName) {\r\n return `<div class=\"route-${routeName}\"><h1>Route: ${routeName}</h1></div>`;\r\n }\r\n\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'RouteLoader', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n // FormHandler \uC815\uB9AC\r\n if (this.formHandler) {\r\n this.formHandler.destroy();\r\n this.formHandler = null;\r\n }\r\n \r\n // ApiHandler \uC815\uB9AC\r\n if (this.apiHandler) {\r\n this.apiHandler.destroy();\r\n this.apiHandler = null;\r\n }\r\n \r\n // ComponentLoader \uC815\uB9AC\r\n if (this.componentLoader) {\r\n this.componentLoader.dispose();\r\n this.componentLoader = null;\r\n }\r\n \r\n this.log('debug', 'RouteLoader destroyed');\r\n this.router = null;\r\n }\r\n}", "/**\r\n * ViewLogic Error Handling System\r\n * \uB77C\uC6B0\uD2B8 \uBC0F \uC2DC\uC2A4\uD15C \uC5D0\uB7EC \uCC98\uB9AC \uC2DC\uC2A4\uD15C\r\n */\r\nexport class ErrorHandler {\r\n constructor(router, options = {}) {\r\n this.config = {\r\n logLevel: options.logLevel || 'info',\r\n environment: options.environment || 'development'\r\n };\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870\r\n this.router = router;\r\n \r\n // \uB85C\uADF8 \uB808\uBCA8 \uB9E4\uD551\r\n this.logLevels = {\r\n error: 0,\r\n warn: 1, \r\n info: 2,\r\n debug: 3\r\n };\r\n \r\n this.log('debug', 'ErrorHandler', 'ErrorHandler initialized with config:', this.config);\r\n }\r\n\r\n /**\r\n * \uB77C\uC6B0\uD2B8 \uC5D0\uB7EC \uCC98\uB9AC\r\n */\r\n async handleRouteError(routeName, error) {\r\n let errorCode = 500;\r\n let errorMessage = '\uD398\uC774\uC9C0\uB97C \uB85C\uB4DC\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.';\r\n \r\n this.debug('ErrorHandler', '\uC5D0\uB7EC \uC0C1\uC138:', error.message, error.name);\r\n \r\n // \uC5D0\uB7EC \uD0C0\uC785 \uBD84\uC11D (\uB354 \uC815\uD655\uD55C 404 \uAC10\uC9C0)\r\n if (error.message.includes('not found') || \r\n error.message.includes('404') ||\r\n error.message.includes('Failed to resolve') ||\r\n error.message.includes('Failed to fetch') ||\r\n (error.name === 'TypeError' && error.message.includes('resolve'))) {\r\n errorCode = 404;\r\n errorMessage = `'${routeName}' \uD398\uC774\uC9C0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.`;\r\n } else if (error.message.includes('network') && !error.message.includes('not found')) {\r\n errorCode = 503;\r\n errorMessage = '\uB124\uD2B8\uC6CC\uD06C \uC5F0\uACB0\uC744 \uD655\uC778\uD574 \uC8FC\uC138\uC694.';\r\n } else if (error.message.includes('permission') || error.message.includes('403')) {\r\n errorCode = 403;\r\n errorMessage = '\uD398\uC774\uC9C0\uC5D0 \uC811\uADFC\uD560 \uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.';\r\n }\r\n \r\n this.debug('ErrorHandler', `\uC5D0\uB7EC \uCF54\uB4DC \uACB0\uC815: ${errorCode} (\uB77C\uC6B0\uD2B8: ${routeName})`);\r\n\r\n // \uC5D0\uB7EC \uB9AC\uD3EC\uD305\r\n this.reportError(routeName, error, errorCode);\r\n \r\n try {\r\n // 404 \uD398\uC774\uC9C0 \uC804\uC6A9 \uCC98\uB9AC\r\n if (errorCode === 404) {\r\n await this.load404Page();\r\n } else {\r\n // \uC77C\uBC18 \uC5D0\uB7EC \uD398\uC774\uC9C0\r\n await this.loadErrorPage(errorCode, errorMessage);\r\n }\r\n } catch (fallbackError) {\r\n this.error('ErrorHandler', '\uC5D0\uB7EC \uD398\uC774\uC9C0 \uB85C\uB529 \uC2E4\uD328:', fallbackError);\r\n // \uBAA8\uB4E0 \uC5D0\uB7EC \uD398\uC774\uC9C0\uAC00 \uC2E4\uD328\uD588\uC744 \uB54C \uCD5C\uD6C4\uC758 \uD3F4\uBC31 \uD398\uC774\uC9C0 \uD45C\uC2DC\r\n this.showFallbackErrorPage(errorCode, errorMessage);\r\n }\r\n }\r\n\r\n /**\r\n * 404 \uD398\uC774\uC9C0 \uB85C\uB529\r\n */\r\n async load404Page() {\r\n try {\r\n this.info('ErrorHandler', 'Loading 404 page...');\r\n const component = await this.createVueComponent('404');\r\n await this.renderComponentWithTransition(component, '404');\r\n this.info('ErrorHandler', '404 page loaded successfully');\r\n } catch (error) {\r\n this.error('ErrorHandler', '404 page loading failed:', error);\r\n // 404 \uD398\uC774\uC9C0\uB3C4 \uC5C6\uC73C\uBA74 \uAC04\uB2E8\uD55C \uC5D0\uB7EC \uBA54\uC2DC\uC9C0 \uD45C\uC2DC\r\n this.showFallbackErrorPage('404', '\uD398\uC774\uC9C0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.');\r\n }\r\n }\r\n\r\n /**\r\n * \uC5D0\uB7EC \uD398\uC774\uC9C0 \uB85C\uB529\r\n */\r\n async loadErrorPage(errorCode, errorMessage) {\r\n try {\r\n this.info('ErrorHandler', `Loading error page for ${errorCode}...`);\r\n \r\n // \uC5D0\uB7EC \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131\r\n const errorComponent = await this.createErrorComponent(errorCode, errorMessage);\r\n await this.renderComponentWithTransition(errorComponent, 'error');\r\n this.info('ErrorHandler', `Error page ${errorCode} loaded successfully`);\r\n } catch (error) {\r\n this.error('ErrorHandler', `Error page ${errorCode} loading failed:`, error);\r\n // \uC5D0\uB7EC \uD398\uC774\uC9C0\uB3C4 \uB85C\uB529 \uC2E4\uD328\uD558\uBA74 \uD3F4\uBC31 \uD45C\uC2DC\r\n this.showFallbackErrorPage(errorCode, errorMessage);\r\n }\r\n }\r\n\r\n /**\r\n * \uC5D0\uB7EC \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131\r\n */\r\n async createErrorComponent(errorCode, errorMessage) {\r\n try {\r\n // \uC5D0\uB7EC \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uB3D9\uC801\uC73C\uB85C \uB85C\uB4DC\r\n const component = await this.createVueComponent('error');\r\n \r\n // \uC5D0\uB7EC \uC815\uBCF4\uB97C props\uB85C \uC804\uB2EC\r\n const errorComponent = {\r\n ...component,\r\n data() {\r\n const originalData = component.data ? component.data() : {};\r\n return {\r\n ...originalData,\r\n errorCode,\r\n errorMessage,\r\n showRetry: true,\r\n showGoHome: true\r\n };\r\n }\r\n };\r\n \r\n return errorComponent;\r\n } catch (error) {\r\n // \uC5D0\uB7EC \uCEF4\uD3EC\uB10C\uD2B8\uB3C4 \uB85C\uB4DC\uD560 \uC218 \uC5C6\uB294 \uACBD\uC6B0 \uAC04\uB2E8\uD55C \uC5D0\uB7EC \uD45C\uC2DC\r\n this.error('ErrorHandler', 'Error component load failed:', error);\r\n throw new Error(`Cannot load error page: ${error.message}`);\r\n }\r\n }\r\n\r\n /**\r\n * \uD3F4\uBC31 \uC5D0\uB7EC \uD398\uC774\uC9C0 \uD45C\uC2DC (\uBAA8\uB4E0 \uC5D0\uB7EC \uD398\uC774\uC9C0\uAC00 \uC2E4\uD328\uD588\uC744 \uB54C)\r\n */\r\n showFallbackErrorPage(errorCode, errorMessage) {\r\n const appElement = document.getElementById('app');\r\n if (!appElement) return;\r\n\r\n const fallbackHTML = `<div style=\"text-align:center;padding:2rem;font-family:sans-serif\"><h1>${errorCode}</h1><p>${errorMessage}</p><button onclick=\"location.reload()\">Retry</button></div>`;\r\n\r\n // \uAE30\uC874 \uCEE8\uD14C\uC774\uB108\uB4E4 \uC815\uB9AC\r\n appElement.innerHTML = fallbackHTML;\r\n \r\n this.info('ErrorHandler', `Fallback error page displayed for ${errorCode}`);\r\n }\r\n\r\n /**\r\n * \uC5D0\uB7EC \uB9AC\uD3EC\uD305\r\n */\r\n reportError(routeName, error, errorCode) {\r\n const errorReport = {\r\n route: routeName,\r\n errorCode,\r\n errorMessage: error.message,\r\n stack: error.stack,\r\n url: window.location.href,\r\n userAgent: navigator.userAgent,\r\n timestamp: new Date().toISOString(),\r\n routerConfig: {\r\n environment: this.router?.config?.environment || 'unknown',\r\n mode: this.router?.config?.mode || 'unknown'\r\n }\r\n };\r\n \r\n this.error('ErrorHandler', '\uB77C\uC6B0\uD130 \uC5D0\uB7EC \uB9AC\uD3EC\uD2B8:', errorReport);\r\n \r\n // \uCD94\uD6C4 \uC5D0\uB7EC \uCD94\uC801 \uC11C\uBE44\uC2A4\uB85C \uC804\uC1A1\uD560 \uC218 \uC788\uC74C\r\n // \uC608: analytics.track('router_error', errorReport);\r\n }\r\n\r\n /**\r\n * Vue \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131 (RouteLoader \uC704\uC784)\r\n */\r\n async createVueComponent(routeName) {\r\n if (this.router.routeLoader) {\r\n return await this.router.routeLoader.createVueComponent(routeName);\r\n }\r\n throw new Error('RouteLoader not available');\r\n }\r\n\r\n /**\r\n * \uCEF4\uD3EC\uB10C\uD2B8 \uB80C\uB354\uB9C1 (ViewManager \uC704\uC784)\r\n */\r\n async renderComponentWithTransition(component, routeName) {\r\n if (this.router.renderComponentWithTransition) {\r\n return await this.router.renderComponentWithTransition(component, routeName);\r\n }\r\n throw new Error('Render function not available');\r\n }\r\n\r\n /**\r\n * \uD1B5\uD569 \uB85C\uAE45 \uC2DC\uC2A4\uD15C\r\n * @param {string} level - \uB85C\uADF8 \uB808\uBCA8 (error, warn, info, debug)\r\n * @param {string} component - \uCEF4\uD3EC\uB10C\uD2B8 \uC774\uB984 (\uC120\uD0DD\uC801)\r\n * @param {...any} args - \uB85C\uADF8 \uBA54\uC2DC\uC9C0\r\n */\r\n log(level, component, ...args) {\r\n // \uD558\uC704 \uD638\uD658\uC131: \uAE30\uC874 \uBC29\uC2DD\uB3C4 \uC9C0\uC6D0\r\n if (typeof level !== 'string' || !this.logLevels.hasOwnProperty(level)) {\r\n args = [component, ...args];\r\n component = level;\r\n level = 'info';\r\n }\r\n \r\n // \uB85C\uADF8 \uB808\uBCA8 \uD655\uC778\r\n const currentLevelValue = this.logLevels[this.config.logLevel] || this.logLevels.info;\r\n const messageLevelValue = this.logLevels[level] || this.logLevels.info;\r\n \r\n if (messageLevelValue > currentLevelValue) {\r\n return; // \uD604\uC7AC \uC124\uC815\uB41C \uB808\uBCA8\uBCF4\uB2E4 \uB192\uC73C\uBA74 \uCD9C\uB825 \uC548\uD568\r\n }\r\n \r\n // \uD504\uB85C\uB355\uC158 \uD658\uACBD\uC5D0\uC11C\uB294 error\uC640 warn\uB9CC \uCD9C\uB825\r\n if (this.config.environment === 'production' && messageLevelValue > this.logLevels.warn) {\r\n return;\r\n }\r\n \r\n const prefix = component ? `[${component}]` : '[ViewLogic]';\r\n const timestamp = new Date().toISOString().substring(11, 23); // HH:MM:SS.mmm\r\n \r\n switch (level) {\r\n case 'error':\r\n console.error(`${timestamp} ${prefix}`, ...args);\r\n break;\r\n case 'warn':\r\n console.warn(`${timestamp} ${prefix}`, ...args);\r\n break;\r\n case 'info':\r\n console.info(`${timestamp} ${prefix}`, ...args);\r\n break;\r\n case 'debug':\r\n console.log(`${timestamp} ${prefix}`, ...args);\r\n break;\r\n default:\r\n console.log(`${timestamp} ${prefix}`, ...args);\r\n }\r\n }\r\n \r\n /**\r\n * \uC5D0\uB7EC \uB85C\uADF8 (\uD56D\uC0C1 \uCD9C\uB825)\r\n */\r\n error(component, ...args) {\r\n this.log('error', component, ...args);\r\n }\r\n \r\n /**\r\n * \uACBD\uACE0 \uB85C\uADF8\r\n */\r\n warn(component, ...args) {\r\n this.log('warn', component, ...args);\r\n }\r\n \r\n /**\r\n * \uC815\uBCF4 \uB85C\uADF8\r\n */\r\n info(component, ...args) {\r\n this.log('info', component, ...args);\r\n }\r\n \r\n /**\r\n * \uB514\uBC84\uADF8 \uB85C\uADF8\r\n */\r\n debug(component, ...args) {\r\n this.log('debug', component, ...args);\r\n }\r\n\r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n this.router = null;\r\n this.info('ErrorHandler', 'ErrorHandler destroyed');\r\n }\r\n}", "/**\r\n * ViewLogic State Management System\r\n * \uC804\uC5ED \uC0C1\uD0DC \uAD00\uB9AC \uC2DC\uC2A4\uD15C\r\n */\r\nexport class StateHandler {\r\n constructor(router) {\r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870\r\n this.router = router;\r\n\r\n // \uBC18\uC751\uD615 \uC0C1\uD0DC \uC800\uC7A5\uC18C\r\n this.state = {};\r\n\r\n // \uC0C1\uD0DC \uBCC0\uACBD \uB9AC\uC2A4\uB108\uB4E4\r\n this.listeners = new Map();\r\n\r\n this.log('debug', 'StateHandler initialized');\r\n }\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'StateHandler', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * \uC0C1\uD0DC \uAC12 \uC124\uC815\r\n */\r\n set(key, value) {\r\n const oldValue = this.state[key];\r\n this.state[key] = value;\r\n\r\n // \uBCC0\uACBD \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n this.emitChange(key, value, oldValue);\r\n\r\n this.log('debug', `State set: ${key}`, value);\r\n return value;\r\n }\r\n\r\n /**\r\n * \uC0C1\uD0DC \uAC12 \uAC00\uC838\uC624\uAE30\r\n */\r\n get(key, defaultValue = undefined) {\r\n const value = this.state.hasOwnProperty(key) ? this.state[key] : defaultValue;\r\n this.log('debug', `State get: ${key}`, value);\r\n return value;\r\n }\r\n\r\n /**\r\n * \uC0C1\uD0DC \uC874\uC7AC \uD655\uC778\r\n */\r\n has(key) {\r\n return this.state.hasOwnProperty(key);\r\n }\r\n\r\n /**\r\n * \uC0C1\uD0DC \uC0AD\uC81C\r\n */\r\n delete(key) {\r\n if (this.has(key)) {\r\n const oldValue = this.state[key];\r\n delete this.state[key];\r\n\r\n // \uC0AD\uC81C \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n this.emitChange(key, undefined, oldValue);\r\n\r\n this.log('debug', `State deleted: ${key}`);\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * \uBAA8\uB4E0 \uC0C1\uD0DC \uCD08\uAE30\uD654\r\n */\r\n clear() {\r\n const keys = Object.keys(this.state);\r\n this.state = {};\r\n\r\n // \uAC01 \uD0A4\uC5D0 \uB300\uD574 \uC0AD\uC81C \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n keys.forEach(key => {\r\n this.emitChange(key, undefined, this.state[key]);\r\n });\r\n\r\n this.log('debug', 'All state cleared');\r\n return keys.length;\r\n }\r\n\r\n /**\r\n * \uC5EC\uB7EC \uC0C1\uD0DC \uD55C \uBC88\uC5D0 \uC124\uC815\r\n */\r\n update(updates) {\r\n if (!updates || typeof updates !== 'object') {\r\n this.log('warn', 'Invalid updates object provided');\r\n return;\r\n }\r\n\r\n Object.entries(updates).forEach(([key, value]) => {\r\n this.set(key, value);\r\n });\r\n }\r\n\r\n /**\r\n * \uBAA8\uB4E0 \uC0C1\uD0DC \uBC18\uD658\r\n */\r\n getAll() {\r\n return { ...this.state };\r\n }\r\n\r\n /**\r\n * \uC0C1\uD0DC \uBCC0\uACBD \uB9AC\uC2A4\uB108 \uB4F1\uB85D\r\n */\r\n watch(key, callback) {\r\n if (!this.listeners.has(key)) {\r\n this.listeners.set(key, []);\r\n }\r\n this.listeners.get(key).push(callback);\r\n\r\n this.log('debug', `Watcher added for: ${key}`);\r\n }\r\n\r\n /**\r\n * \uC0C1\uD0DC \uBCC0\uACBD \uB9AC\uC2A4\uB108 \uC81C\uAC70\r\n */\r\n unwatch(key, callback) {\r\n if (this.listeners.has(key)) {\r\n const callbacks = this.listeners.get(key);\r\n const index = callbacks.indexOf(callback);\r\n if (index > -1) {\r\n callbacks.splice(index, 1);\r\n this.log('debug', `Watcher removed for: ${key}`);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * \uC0C1\uD0DC \uBCC0\uACBD \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n */\r\n emitChange(key, newValue, oldValue) {\r\n if (this.listeners.has(key)) {\r\n this.listeners.get(key).forEach(callback => {\r\n try {\r\n callback(newValue, oldValue, key);\r\n } catch (error) {\r\n this.log('error', 'State watcher error:', error);\r\n }\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * \uC0C1\uD0DC \uD1B5\uACC4\r\n */\r\n getStats() {\r\n return {\r\n stateCount: Object.keys(this.state).length,\r\n watcherCount: Array.from(this.listeners.values()).reduce((sum, arr) => sum + arr.length, 0),\r\n keys: Object.keys(this.state)\r\n };\r\n }\r\n\r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n this.state = {};\r\n this.listeners.clear();\r\n this.log('debug', 'StateHandler destroyed');\r\n }\r\n}", "// ViewLogic Router - ES6 Module\r\nimport { I18nManager } from './plugins/I18nManager.js';\r\nimport { AuthManager } from './plugins/AuthManager.js';\r\nimport { CacheManager } from './plugins/CacheManager.js';\r\nimport { QueryManager } from './plugins/QueryManager.js';\r\nimport { RouteLoader } from './core/RouteLoader.js';\r\nimport { ErrorHandler } from './core/ErrorHandler.js';\r\nimport { StateHandler } from './core/StateHandler.js';\r\n\r\nexport class ViewLogicRouter {\r\n constructor(options = {}) {\r\n // \uBC84\uC804 \uC815\uBCF4\r\n this.version = options.version || '1.0.0';\r\n \r\n // \uAE30\uBCF8 \uD658\uACBD\uC124\uC815 \uCD5C\uC801\uD654\r\n this.config = this._buildConfig(options);\r\n \r\n this.currentHash = '';\r\n this.currentVueApp = null;\r\n this.previousVueApp = null; // \uC774\uC804 Vue \uC571 (\uC804\uD658 \uD6A8\uACFC\uB97C \uC704\uD574 \uBCF4\uAD00)\r\n\r\n // LoadingManager\uAC00 \uC5C6\uC744 \uB54C\uB97C \uC704\uD55C \uAE30\uBCF8 \uC804\uD658 \uC0C1\uD0DC\r\n this.transitionInProgress = false;\r\n \r\n // \uCD08\uAE30\uD654 \uC900\uBE44 \uC0C1\uD0DC\r\n this.isReady = false;\r\n this.readyPromise = null;\r\n \r\n // \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uBC14\uC778\uB529 \uCD5C\uC801\uD654\r\n this._boundHandleRouteChange = this.handleRouteChange.bind(this);\r\n \r\n // \uBAA8\uB4E0 \uCD08\uAE30\uD654\uB97C \uD55C\uBC88\uC5D0 \uCC98\uB9AC\r\n this.readyPromise = this.initialize();\r\n }\r\n\r\n /**\r\n * \uC124\uC815 \uBE4C\uB4DC (\uBD84\uB9AC\uD558\uC5EC \uAC00\uB3C5\uC131 \uD5A5\uC0C1)\r\n */\r\n _buildConfig(options) {\r\n const currentOrigin = window.location.origin;\r\n \r\n const defaults = {\r\n basePath: '/', // \uC560\uD50C\uB9AC\uCF00\uC774\uC158 \uAE30\uBCF8 \uACBD\uB85C (\uC11C\uBE0C\uD3F4\uB354 \uBC30\uD3EC\uC6A9)\r\n srcPath: '/src', // \uC18C\uC2A4 \uD30C\uC77C \uACBD\uB85C\r\n mode: 'hash',\r\n cacheMode: 'memory',\r\n cacheTTL: 300000,\r\n maxCacheSize: 50,\r\n useLayout: true,\r\n defaultLayout: 'default',\r\n environment: 'development',\r\n routesPath: '/routes', // \uD504\uB85C\uB355\uC158 \uB77C\uC6B0\uD2B8 \uACBD\uB85C\r\n enableErrorReporting: true,\r\n useI18n: false,\r\n defaultLanguage: 'ko',\r\n i18nPath: '/i18n', // \uB2E4\uAD6D\uC5B4 \uD30C\uC77C \uACBD\uB85C\r\n logLevel: 'info',\r\n apiBaseURL: '',\r\n requestTimeout: 30000,\r\n uploadTimeout: 300000,\r\n authEnabled: false,\r\n loginRoute: 'login',\r\n protectedRoutes: [],\r\n protectedPrefixes: [],\r\n publicRoutes: ['login', 'register', 'home'],\r\n checkAuthFunction: null,\r\n redirectAfterLogin: 'home',\r\n authCookieName: 'authToken',\r\n authStorage: 'localStorage'\r\n };\r\n \r\n const config = { ...defaults, ...options };\r\n\r\n // \uC808\uB300 \uACBD\uB85C\uB4E4\uC744 basePath \uAE30\uC900\uC73C\uB85C \uD574\uACB0\r\n config.srcPath = this.resolvePath(config.srcPath, config.basePath);\r\n config.routesPath = this.resolvePath(config.routesPath, config.basePath);\r\n config.i18nPath = this.resolvePath(config.i18nPath, config.basePath);\r\n\r\n return config;\r\n }\r\n\r\n /**\r\n * \uB450 \uACBD\uB85C\uB97C \uC548\uC804\uD558\uAC8C \uC870\uD569 \uBC0F \uC815\uADDC\uD654 (\uAE30\uBCF8 \uC720\uD2F8\uB9AC\uD2F0)\r\n * @param {string} basePath - \uAE30\uBCF8 \uACBD\uB85C\r\n * @param {string} relativePath - \uC0C1\uB300 \uACBD\uB85C\r\n * @returns {string} \uC870\uD569\uB41C \uACBD\uB85C (\uC608: '/examples' + '/about' \u2192 '/examples/about')\r\n */\r\n combinePaths(basePath, relativePath) {\r\n if (!basePath || basePath === '/') {\r\n return relativePath.replace(/\\/+/g, '/');\r\n }\r\n\r\n const cleanBase = basePath.endsWith('/') ? basePath.slice(0, -1) : basePath;\r\n const cleanRelative = relativePath.startsWith('/') ? relativePath : `/${relativePath}`;\r\n const combined = `${cleanBase}${cleanRelative}`;\r\n\r\n // \uC774\uC911 \uC2AC\uB798\uC2DC \uC81C\uAC70\r\n return combined.replace(/\\/+/g, '/');\r\n }\r\n\r\n\r\n /**\r\n * \uC0C1\uB300 \uACBD\uB85C\uB97C \uC644\uC804\uD55C \uC808\uB300 URL\uB85C \uBCC0\uD658 (\uD30C\uC77C \uC2DC\uC2A4\uD15C \uC804\uC6A9)\r\n * @param {string} path - \uBCC0\uD658\uD560 \uACBD\uB85C\r\n * @param {string} basePath - \uAE30\uBCF8 \uACBD\uB85C (\uC635\uC158)\r\n * @returns {string} \uC644\uC804\uD55C \uC808\uB300 URL (\uC608: 'http://localhost:3000/examples/about')\r\n */\r\n resolvePath(path, basePath = null) {\r\n // basePath\uAC00 \uC81C\uACF5\uB418\uC9C0 \uC54A\uC73C\uBA74 config\uC5D0\uC11C \uAC00\uC838\uC624\uAE30\r\n if (basePath === null) {\r\n basePath = this.config?.basePath || '/';\r\n }\r\n const currentOrigin = window.location.origin;\r\n \r\n // \uC774\uBBF8 \uC644\uC804\uD55C HTTP URL\uC778 \uACBD\uC6B0 \uBCC0\uD658 \uBD88\uD544\uC694\r\n if (path.startsWith('http')) {\r\n return path;\r\n }\r\n\r\n // \uC808\uB300 \uACBD\uB85C \u2192 \uC644\uC804\uD55C URL \uBCC0\uD658\r\n if (path.startsWith('/')) {\r\n const combinedPath = this.combinePaths(basePath, path);\r\n return `${currentOrigin}${combinedPath}`;\r\n }\r\n \r\n // \uC0C1\uB300 \uACBD\uB85C\uC778 \uACBD\uC6B0 \uD604\uC7AC \uACBD\uB85C \uAE30\uC900\uC73C\uB85C \uD574\uACB0\r\n const currentPathname = window.location.pathname;\r\n const currentBase = currentPathname.endsWith('/') \r\n ? currentPathname \r\n : currentPathname.substring(0, currentPathname.lastIndexOf('/') + 1);\r\n \r\n // \uC0C1\uB300 \uACBD\uB85C \uC815\uADDC\uD654\r\n const resolvedPath = this.combinePaths(currentBase, path);\r\n \r\n return `${currentOrigin}${resolvedPath}`;\r\n }\r\n\r\n\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.errorHandler) {\r\n this.errorHandler.log(level, 'Router', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * \uD1B5\uD569 \uCD08\uAE30\uD654 - \uB9E4\uB2C8\uC800 \uC0DD\uC131 \u2192 \uBE44\uB3D9\uAE30 \uB85C\uB529 \u2192 \uB77C\uC6B0\uD130 \uC2DC\uC791\r\n */\r\n async initialize() {\r\n try {\r\n // 1. \uB9E4\uB2C8\uC800 \uCD08\uAE30\uD654 (\uB3D9\uAE30)\r\n // \uD56D\uC0C1 \uD544\uC694\uD55C \uB9E4\uB2C8\uC800\uB4E4\r\n this.cacheManager = new CacheManager(this, this.config);\r\n this.stateHandler = new StateHandler(this);\r\n this.routeLoader = new RouteLoader(this, this.config);\r\n this.queryManager = new QueryManager(this);\r\n this.errorHandler = new ErrorHandler(this, this.config);\r\n \r\n // \uC870\uAC74\uBD80 \uB9E4\uB2C8\uC800\uB4E4\r\n if (this.config.useI18n) {\r\n try {\r\n this.i18nManager = new I18nManager(this, this.config);\r\n if (this.i18nManager.initPromise) {\r\n await this.i18nManager.initPromise;\r\n }\r\n this.log('info', 'I18nManager initialized successfully');\r\n } catch (i18nError) {\r\n this.log('warn', 'I18nManager initialization failed, continuing without i18n:', i18nError.message);\r\n this.i18nManager = null; // i18n \uB9E4\uB2C8\uC800 \uBE44\uD65C\uC131\uD654\r\n this.config.useI18n = false; // i18n \uBE44\uD65C\uC131\uD654\r\n }\r\n }\r\n \r\n if (this.config.authEnabled) {\r\n this.authManager = new AuthManager(this, this.config);\r\n }\r\n \r\n \r\n // 2. \uB77C\uC6B0\uD130 \uC2DC\uC791\r\n this.isReady = true;\r\n this.init();\r\n \r\n } catch (error) {\r\n this.log('error', 'Router initialization failed:', error);\r\n // \uC2E4\uD328\uD574\uB3C4 \uB77C\uC6B0\uD130\uB294 \uC2DC\uC791 (graceful degradation)\r\n this.isReady = true;\r\n this.init();\r\n }\r\n }\r\n\r\n /**\r\n * \uB77C\uC6B0\uD130\uAC00 \uC900\uBE44\uB420 \uB54C\uAE4C\uC9C0 \uB300\uAE30\r\n */\r\n async waitForReady() {\r\n if (this.isReady) return true;\r\n if (this.readyPromise) {\r\n await this.readyPromise;\r\n }\r\n return this.isReady;\r\n }\r\n\r\n\r\n init() {\r\n const isHashMode = this.config.mode === 'hash';\r\n \r\n // \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uB4F1\uB85D (\uBA54\uBAA8\uB9AC \uCD5C\uC801\uD654)\r\n window.addEventListener(\r\n isHashMode ? 'hashchange' : 'popstate',\r\n this._boundHandleRouteChange\r\n );\r\n \r\n // DOM \uB85C\uB4DC \uCC98\uB9AC \uD1B5\uD569\r\n const initRoute = () => {\r\n if (isHashMode && !window.location.hash) {\r\n window.location.hash = '#/';\r\n } else if (!isHashMode && window.location.pathname === '/') {\r\n this.navigateTo('home');\r\n } else {\r\n this.handleRouteChange();\r\n }\r\n };\r\n \r\n if (document.readyState === 'loading') {\r\n document.addEventListener('DOMContentLoaded', initRoute);\r\n } else {\r\n // requestAnimationFrame\uC73C\uB85C \uC131\uB2A5 \uAC1C\uC120\r\n requestAnimationFrame(initRoute);\r\n }\r\n }\r\n\r\n handleRouteChange() {\r\n const { route, queryParams } = this._parseCurrentLocation();\r\n \r\n // Store current query parameters in QueryManager\r\n this.queryManager?.setCurrentQueryParams(queryParams);\r\n \r\n // \uBCC0\uACBD\uC0AC\uD56D\uC774 \uC788\uC744 \uB54C\uB9CC \uB85C\uB4DC (\uC131\uB2A5 \uCD5C\uC801\uD654)\r\n if (route !== this.currentHash || this.queryManager?.hasQueryParamsChanged(queryParams)) {\r\n this.currentHash = route;\r\n this.loadRoute(route);\r\n }\r\n }\r\n\r\n /**\r\n * \uD604\uC7AC \uC704\uCE58 \uD30C\uC2F1 (\uBD84\uB9AC\uD558\uC5EC \uAC00\uB3C5\uC131 \uD5A5\uC0C1)\r\n */\r\n _parseCurrentLocation() {\r\n if (this.config.mode === 'hash') {\r\n const hashPath = window.location.hash.slice(1) || '/';\r\n const [pathPart, queryPart] = hashPath.split('?');\r\n \r\n // \uACBD\uB85C \uD30C\uC2F1 \uCD5C\uC801\uD654\r\n let route = 'home';\r\n if (pathPart && pathPart !== '/') {\r\n route = pathPart.startsWith('/') ? pathPart.slice(1) : pathPart;\r\n }\r\n \r\n return {\r\n route: route || 'home',\r\n queryParams: this.queryManager?.parseQueryString(queryPart || window.location.search.slice(1)) || {}\r\n };\r\n } else {\r\n // History Mode - \uC11C\uBE0C\uD3F4\uB354 \uBC30\uD3EC \uC9C0\uC6D0\r\n const fullPath = window.location.pathname;\r\n const basePath = this.config.basePath || '/';\r\n \r\n // base path \uC81C\uAC70\uD558\uC5EC \uC2E4\uC81C route \uCD94\uCD9C\r\n let route = fullPath;\r\n if (basePath !== '/' && fullPath.startsWith(basePath)) {\r\n route = fullPath.slice(basePath.length);\r\n }\r\n \r\n // \uB9E8 \uC55E\uC758 / \uC81C\uAC70\r\n if (route.startsWith('/')) {\r\n route = route.slice(1);\r\n }\r\n \r\n return {\r\n route: route || 'home',\r\n queryParams: this.queryManager?.parseQueryString(window.location.search.slice(1)) || {}\r\n };\r\n }\r\n }\r\n\r\n async loadRoute(routeName) {\r\n // \uC804\uD658\uC774 \uC9C4\uD589 \uC911\uC774\uBA74 \uBB34\uC2DC\r\n const inProgress = this.transitionInProgress;\r\n \r\n if (inProgress) {\r\n return;\r\n }\r\n\r\n try {\r\n this.transitionInProgress = true;\r\n \r\n // \uC778\uC99D \uCCB4\uD06C\r\n const authResult = this.authManager ? \r\n await this.authManager.checkAuthentication(routeName) :\r\n { allowed: true, reason: 'auth_disabled' };\r\n if (!authResult.allowed) {\r\n // \uC778\uC99D \uC2E4\uD328 \uC2DC \uB85C\uADF8\uC778 \uD398\uC774\uC9C0\uB85C \uB9AC\uB2E4\uC774\uB809\uD2B8\r\n if (this.authManager) {\r\n this.authManager.emitAuthEvent('auth_required', { \r\n originalRoute: routeName,\r\n loginRoute: this.config.loginRoute \r\n });\r\n \r\n // navigateTo\uB97C \uC0AC\uC6A9\uD558\uC5EC \uC774\uC804 \uD398\uC774\uC9C0\uB85C \uB3CC\uC544\uAC00\uAE30 \uC9C0\uC6D0\r\n if (routeName !== this.config.loginRoute) {\r\n this.navigateTo(this.config.loginRoute, { redirect: routeName });\r\n } else {\r\n this.navigateTo(this.config.loginRoute);\r\n }\r\n }\r\n return;\r\n }\r\n \r\n const appElement = document.getElementById('app');\r\n if (!appElement) {\r\n throw new Error('App element not found');\r\n }\r\n\r\n // Vue \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131 (\uBC31\uADF8\uB77C\uC6B4\uB4DC\uC5D0\uC11C)\r\n const component = await this.routeLoader.createVueComponent(routeName);\r\n \r\n // \uC0C8\uB85C\uC6B4 \uD398\uC774\uC9C0\uB97C \uC624\uBC84\uB808\uC774\uB85C \uB80C\uB354\uB9C1\r\n await this.renderComponentWithTransition(component, routeName);\r\n \r\n // \uB85C\uB529 \uC644\uB8CC\r\n \r\n } catch (error) {\r\n this.log('error', `Route loading failed [${routeName}]:`, error.message);\r\n \r\n \r\n // \uC5D0\uB7EC \uD0C0\uC785\uC5D0 \uB530\uB978 \uCC98\uB9AC\r\n if (this.errorHandler) {\r\n await this.errorHandler.handleRouteError(routeName, error);\r\n } else {\r\n // ErrorHandler\uAC00 \uC5C6\uB294 \uADF9\uB2E8\uC801 \uC0C1\uD669 - \uCD5C\uC18C\uD55C\uC758 \uC5D0\uB7EC \uD45C\uC2DC\r\n console.error('[Router] Critical: No error handler available for route error:', error);\r\n }\r\n } finally {\r\n // \uBAA8\uB4E0 \uCC98\uB9AC\uAC00 \uC644\uB8CC\uB41C \uD6C4 \uC804\uD658 \uC0C1\uD0DC \uB9AC\uC14B\r\n this.transitionInProgress = false;\r\n }\r\n }\r\n\r\n async renderComponentWithTransition(vueComponent, routeName) {\r\n const appElement = document.getElementById('app');\r\n if (!appElement) return;\r\n\r\n // \uC0C8\uB85C\uC6B4 \uD398\uC774\uC9C0 \uCEE8\uD14C\uC774\uB108 \uC0DD\uC131\r\n const newPageContainer = document.createElement('div');\r\n newPageContainer.className = 'page-container page-entered';\r\n newPageContainer.id = `page-${routeName}-${Date.now()}`;\r\n \r\n // \uAE30\uC874 \uCEE8\uD14C\uC774\uB108\uAC00 \uC788\uB2E4\uBA74 \uC989\uC2DC \uC228\uAE30\uAE30\r\n const existingContainers = appElement.querySelectorAll('.page-container');\r\n existingContainers.forEach(container => {\r\n container.classList.remove('page-entered');\r\n container.classList.add('page-exiting');\r\n });\r\n\r\n // \uC0C8 \uCEE8\uD14C\uC774\uB108\uB97C \uC571\uC5D0 \uCD94\uAC00\r\n appElement.appendChild(newPageContainer);\r\n\r\n // \uAC1C\uBC1C \uBAA8\uB4DC\uC5D0\uC11C\uB9CC \uC2A4\uD0C0\uC77C \uC801\uC6A9 (\uD504\uB85C\uB355\uC158 \uBAA8\uB4DC\uB294 \uBE4C\uB4DC\uB41C JS\uC5D0\uC11C \uC790\uB3D9 \uCC98\uB9AC)\r\n if (this.config.environment === 'development' && vueComponent._style) {\r\n this.applyStyle(vueComponent._style, routeName);\r\n }\r\n \r\n // \uC0C8\uB85C\uC6B4 Vue \uC571\uC744 \uC0C8 \uCEE8\uD14C\uC774\uB108\uC5D0 \uB9C8\uC6B4\uD2B8\r\n const { createApp } = Vue;\r\n const newVueApp = createApp(vueComponent);\r\n\r\n // Vue 3 \uC804\uC5ED \uC18D\uC131 \uC124\uC815\r\n newVueApp.config.globalProperties.$router = {\r\n navigateTo: (route, params) => this.navigateTo(route, params),\r\n getCurrentRoute: () => this.getCurrentRoute(),\r\n\r\n // \uD1B5\uD569\uB41C \uD30C\uB77C\uBBF8\uD130 \uAD00\uB9AC (\uB77C\uC6B0\uD305 + \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130)\r\n getParams: () => this.queryManager?.getAllParams() || {},\r\n getParam: (key, defaultValue) => this.queryManager?.getParam(key, defaultValue),\r\n\r\n // \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uC804\uC6A9 \uBA54\uC11C\uB4DC (\uD558\uC704 \uD638\uD658\uC131)\r\n getQueryParams: () => this.queryManager?.getQueryParams() || {},\r\n getQueryParam: (key, defaultValue) => this.queryManager?.getQueryParam(key, defaultValue),\r\n setQueryParams: (params, replace) => this.queryManager?.setQueryParams(params, replace),\r\n removeQueryParams: (keys) => this.queryManager?.removeQueryParams(keys),\r\n\r\n // \uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130 \uC804\uC6A9 \uBA54\uC11C\uB4DC\r\n getRouteParams: () => this.queryManager?.getRouteParams() || {},\r\n getRouteParam: (key, defaultValue) => this.queryManager?.getRouteParam(key, defaultValue),\r\n\r\n currentRoute: this.currentHash,\r\n currentQuery: this.queryManager?.getQueryParams() || {}\r\n };\r\n\r\n // \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131 \uD568\uC218\uB97C \uC804\uC5ED\uC73C\uB85C \uCD94\uAC00\r\n newVueApp.config.globalProperties.$createComponent = async (componentName) => {\r\n try {\r\n return await this.routeLoader.createVueComponent(componentName);\r\n } catch (error) {\r\n if (this.errorHandler) this.errorHandler.warn('Router', `Failed to create component '${componentName}':`, error);\r\n throw error;\r\n }\r\n };\r\n\r\n // \uBAA8\uBC14\uC77C \uBA54\uB274 \uC804\uC5ED \uD568\uC218 \uCD94\uAC00\r\n\r\n newVueApp.mount(`#${newPageContainer.id}`);\r\n\r\n // \uB77C\uC6B0\uD2B8 \uC774\uB3D9 \uC2DC \uC2A4\uD06C\uB864\uC744 \uB9E8 \uC704\uB85C \uC774\uB3D9\r\n window.scrollTo(0, 0);\r\n\r\n // requestAnimationFrame\uC73C\uB85C \uC131\uB2A5 \uAC1C\uC120\r\n requestAnimationFrame(() => {\r\n this.cleanupPreviousPages();\r\n this.transitionInProgress = false;\r\n });\r\n\r\n // \uC774\uC804 \uC571 \uC815\uB9AC \uC900\uBE44\r\n if (this.currentVueApp) {\r\n this.previousVueApp = this.currentVueApp;\r\n }\r\n \r\n this.currentVueApp = newVueApp;\r\n }\r\n\r\n cleanupPreviousPages() {\r\n const appElement = document.getElementById('app');\r\n if (!appElement) return;\r\n\r\n // \uBC30\uCE58 DOM \uC870\uC791\uC73C\uB85C \uC131\uB2A5 \uAC1C\uC120\r\n const fragment = document.createDocumentFragment();\r\n const exitingContainers = appElement.querySelectorAll('.page-container.page-exiting');\r\n \r\n // \uD55C\uBC88\uC5D0 \uC81C\uAC70\r\n exitingContainers.forEach(container => container.remove());\r\n\r\n // \uC774\uC804 Vue \uC571 \uC815\uB9AC\r\n if (this.previousVueApp) {\r\n try {\r\n this.previousVueApp.unmount();\r\n } catch (error) {\r\n // \uBB34\uC2DC (\uC774\uBBF8 \uC5B8\uB9C8\uC6B4\uD2B8\uB41C \uACBD\uC6B0)\r\n }\r\n this.previousVueApp = null;\r\n }\r\n\r\n // \uB85C\uB529 \uC5D8\uB9AC\uBA3C\uD2B8 \uC81C\uAC70\r\n \r\n appElement.querySelector('.loading')?.remove();\r\n }\r\n\r\n applyStyle(css, routeName) {\r\n // \uAE30\uC874 \uC2A4\uD0C0\uC77C \uC81C\uAC70\r\n const existing = document.querySelector(`style[data-route=\"${routeName}\"]`);\r\n if (existing) existing.remove();\r\n\r\n if (css) {\r\n const style = document.createElement('style');\r\n style.textContent = css;\r\n style.setAttribute('data-route', routeName);\r\n document.head.appendChild(style);\r\n }\r\n }\r\n\r\n\r\n navigateTo(routeName, params = null) {\r\n // If routeName is an object, treat it as {route, params}\r\n if (typeof routeName === 'object') {\r\n params = routeName.params || null;\r\n routeName = routeName.route;\r\n }\r\n \r\n // Clear current query params if navigating to a different route\r\n if (routeName !== this.currentHash && this.queryManager) {\r\n this.queryManager.clearQueryParams();\r\n }\r\n \r\n // Set route parameters\r\n if (this.queryManager) {\r\n this.queryManager.setCurrentRouteParams(params);\r\n }\r\n \r\n // Update URL with new route and params\r\n this.updateURL(routeName, params);\r\n }\r\n\r\n getCurrentRoute() {\r\n return this.currentHash;\r\n }\r\n\r\n\r\n updateURL(route, params = null) {\r\n const queryParams = params || this.queryManager?.getQueryParams() || {};\r\n const queryString = this.queryManager?.buildQueryString(queryParams) || '';\r\n\r\n // URL \uC0DD\uC131\r\n let base = route === 'home' ? '/' : `/${route}`;\r\n\r\n if (this.config.mode === 'hash') {\r\n // \uD574\uC2DC \uBAA8\uB4DC: basePath \uC81C\uC678\r\n const url = queryString ? `${base}?${queryString}` : base;\r\n const newHash = `#${url}`;\r\n\r\n // \uB3D9\uC77C\uD55C URL\uC774\uBA74 \uC5C5\uB370\uC774\uD2B8\uD558\uC9C0 \uC54A\uC74C (\uC131\uB2A5 \uCD5C\uC801\uD654)\r\n if (window.location.hash !== newHash) {\r\n window.location.hash = newHash;\r\n }\r\n } else {\r\n // \uD788\uC2A4\uD1A0\uB9AC \uBAA8\uB4DC: basePath \uD3EC\uD568\r\n base = this.combinePaths(this.config.basePath, base);\r\n const url = queryString ? `${base}?${queryString}` : base;\r\n\r\n // \uBAA8\uB4E0 \uB77C\uC6B0\uD2B8 \uBCC0\uACBD\uC5D0 \uB300\uD574 \uB4A4\uB85C\uAC00\uAE30 \uC9C0\uC6D0\r\n window.history.pushState({}, '', url);\r\n this.handleRouteChange();\r\n }\r\n }\r\n\r\n /**\r\n * \uB77C\uC6B0\uD130 \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n // \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uC81C\uAC70\r\n window.removeEventListener(\r\n this.config.mode === 'hash' ? 'hashchange' : 'popstate',\r\n this._boundHandleRouteChange\r\n );\r\n \r\n // \uD604\uC7AC Vue \uC571 \uC5B8\uB9C8\uC6B4\uD2B8\r\n if (this.currentVueApp) {\r\n this.currentVueApp.unmount();\r\n this.currentVueApp = null;\r\n }\r\n \r\n // \uC774\uC804 Vue \uC571 \uC5B8\uB9C8\uC6B4\uD2B8\r\n if (this.previousVueApp) {\r\n this.previousVueApp.unmount();\r\n this.previousVueApp = null;\r\n }\r\n \r\n // \uB9E4\uB2C8\uC800 \uC815\uB9AC\r\n Object.values(this).forEach(manager => {\r\n if (manager && typeof manager.destroy === 'function') {\r\n manager.destroy();\r\n }\r\n });\r\n \r\n // \uCE90\uC2DC \uD074\uB9AC\uC5B4\r\n this.cacheManager?.clearAll();\r\n \r\n // DOM \uC815\uB9AC\r\n const appElement = document.getElementById('app');\r\n if (appElement) {\r\n appElement.innerHTML = '';\r\n }\r\n \r\n this.log('info', 'Router destroyed');\r\n }\r\n}\r\n// \uC804\uC5ED \uB77C\uC6B0\uD130\uB294 index.html\uC5D0\uC11C \uD658\uACBD\uC124\uC815\uACFC \uD568\uAED8 \uC0DD\uC131\uB428"],
5
+ "mappings": "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",
6
+ "names": ["I18nManager", "router", "options", "error", "cachedLang", "lang", "language", "oldLanguage", "loadPromise", "messages", "emptyMessages", "cacheKey", "cachedData", "i18nPath", "response", "fallbackError", "key", "params", "message", "fallbackMessages", "fallbackMessage", "obj", "path", "current", "match", "count", "pluralKey", "event", "callback", "index", "data", "date", "locale", "number", "level", "args", "clearedCount", "AuthManager", "router", "options", "level", "args", "routeName", "route", "isAuthenticated", "error", "token", "payload", "prefix", "name", "parts", "storage", "cookieOptions", "secure", "cookieString", "expireDate", "targetRoute", "redirectRoute", "eventType", "data", "event", "listener", "listeners", "index", "CacheManager", "router", "options", "level", "args", "key", "value", "now", "oldestKey", "existingIndex", "timestamp", "index", "pattern", "keysToDelete", "routeName", "patterns", "totalInvalidated", "componentPatterns", "totalCleared", "size", "expiredKeys", "estimatedBytes", "ratio", "categories", "interval", "QueryManager", "router", "level", "args", "queryString", "params", "pairs", "pair", "rawKey", "rawValue", "key", "value", "arrayKey", "item", "newParams", "oldKeys", "newKeys", "defaultValue", "replace", "currentParams", "keys", "keysToRemove", "route", "FormHandler", "router", "options", "level", "args", "form", "timeout", "el", "component", "boundHandler", "e", "event", "action", "method", "successHandler", "errorHandler", "loadingHandler", "redirectTo", "formData", "data", "response", "error", "actionTemplate", "signal", "hasFile", "isValid", "input", "validationFunction", "value", "ApiHandler", "router", "options", "level", "args", "dataURL", "component", "processedURL", "queryString", "fullURL", "requestOptions", "response", "error", "data", "dataConfig", "results", "errors", "promises", "key", "config", "url", "paramMatches", "match", "paramName", "paramValue", "baseURL", "relativeURL", "cleanBase", "cleanRelative", "ComponentLoader", "router", "options", "level", "args", "componentName", "cacheKey", "cachedComponent", "loadPromise", "component", "error", "componentRelativePath", "componentPath", "srcPath", "cleanSrcPath", "cleanComponentPath", "componentNames", "components", "componentsPath", "componentsModule", "namesToLoad", "name", "loadError", "template", "layout", "layoutName", "componentSet", "cachedComponents", "content", "componentPattern", "match", "tagName", "RouteLoader", "router", "options", "FormHandler", "ApiHandler", "ComponentLoader", "routeName", "script", "importPath", "error", "templatePath", "response", "template", "stylePath", "style", "layoutName", "layoutPath", "layout", "result", "cacheKey", "cached", "isProduction", "loadPromises", "loadedTemplate", "loadedStyle", "loadedLayout", "loadedComponents", "componentNames", "component", "route", "params", "key", "defaultValue", "token", "lang", "level", "args", "dataConfig", "configToUse", "data", "results", "errors", "str", "word", "ErrorHandler", "router", "options", "routeName", "error", "errorCode", "errorMessage", "fallbackError", "component", "errorComponent", "appElement", "fallbackHTML", "errorReport", "level", "args", "currentLevelValue", "messageLevelValue", "prefix", "timestamp", "StateHandler", "router", "level", "args", "key", "value", "oldValue", "defaultValue", "keys", "updates", "callback", "callbacks", "index", "newValue", "error", "sum", "arr", "ViewLogicRouter", "options", "currentOrigin", "config", "basePath", "relativePath", "cleanBase", "cleanRelative", "path", "combinedPath", "currentPathname", "currentBase", "resolvedPath", "level", "args", "CacheManager", "StateHandler", "RouteLoader", "QueryManager", "ErrorHandler", "I18nManager", "i18nError", "AuthManager", "error", "isHashMode", "initRoute", "route", "queryParams", "hashPath", "pathPart", "queryPart", "fullPath", "routeName", "component", "vueComponent", "appElement", "newPageContainer", "container", "createApp", "newVueApp", "params", "key", "defaultValue", "replace", "keys", "componentName", "fragment", "css", "existing", "style", "queryString", "base", "newHash", "url", "manager"]
7
7
  }