{"version":3,"mappings":"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","names":["AUTH_CONFIG","axiosInstance","axios","response","error","config","originalPath","_a","state","authUrl","firstName","ref","getUserInfo","onMounted","logout","route","useRoute","showNavBar","computed","routes","router","createRouter","createWebHistory","to","from","next","pinia","createPinia","piniaPluginPersistedstate","WebSocketService","__publicField","protocol","host","wsUrl","event","data","timeout","message","callback","listener","websocketService","ModuleRegistry","AllCommunityModule","app","createApp","App","createBootstrap","VueApexCharts","VueSidebarMenu","PrimeVue","Nora"],"ignoreList":[],"sources":["../../src/utils/interceptor.ts","../../src/components/common/NavBar.vue","../../src/App.vue","../../src/router/routes.ts","../../src/router/index.ts","../../src/stores/index.ts","../../src/services/websocketService.ts","../../src/main.ts"],"sourcesContent":["/**\n * Axios interceptor configuration\n * \n * Configures an Axios instance with authentication handling.\n * Automatically redirects to the authentication provider on 401 errors,\n * preserving the original destination path for post-login redirect.\n */\nimport axios, { AxiosInstance, AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios';\n\n// Authentication configuration\nconst AUTH_CONFIG = {\n endpoint: 'https://auth.godswood.au/application/o/authorize/',\n clientId: 'lXsNtZUZorWUmVNGgix5KCnK5gSogKnCFTIRC1jQ',\n responseType: 'code',\n scope: 'open profile email',\n redirectUri: 'https://www.godswood.au/api/v2/auth/callback'\n};\n\n// Create an Axios instance with a response interceptor to handle 401 errors\nconst axiosInstance: AxiosInstance = axios.create({\n withCredentials: true // Include credentials (cookies) with each request\n});\n\naxiosInstance.interceptors.response.use(\n (response: AxiosResponse) => response,\n async (error: AxiosError) => {\n const response = error.response;\n const config = error.config as AxiosRequestConfig & { _retry?: boolean };\n\n // Handle 401 unauthorized errors\n if (response && response.status === 401 && !config._retry) {\n config._retry = true;\n\n // Get original path from custom header\n const originalPath = config.headers?.['X-Original-Path'] as string;\n\n // Construct authentication URL with state for redirect\n const state = encodeURIComponent(originalPath);\n \n const authUrl = `${AUTH_CONFIG.endpoint}?client_id=${AUTH_CONFIG.clientId}`\n + `&response_type=${AUTH_CONFIG.responseType}`\n + `&scope=${AUTH_CONFIG.scope}`\n + `&redirect_uri=${AUTH_CONFIG.redirectUri}`\n + `&state=${state}`;\n \n window.location.href = authUrl;\n }\n\n // For other errors, reject the promise\n return Promise.reject(error);\n }\n);\n\n// Export the instance directly to match the declaration file\nexport { axiosInstance };\nexport default axiosInstance;\n","\n\n\n\n","\n\n\n\n","/**\n * Application routes configuration\n * \n * This file defines all the routes available in the application\n * Each route specifies a path, name, component to render, and metadata.\n * The 'showNavBar' meta property controls navigation bar visibility.\n */\nimport { RouteRecordRaw } from 'vue-router';\n\nconst routes: RouteRecordRaw[] = [\n {\n path: '/',\n redirect: '/home'\n },\n {\n path: '/home',\n name: 'home',\n component: () => import('@/views/HomeView.vue'),\n meta: {\n showNavBar: true,\n }\n },\n {\n path: '/networth',\n name: 'networth',\n component: () => import('@/views/NetworthView.vue'),\n meta: {\n showNavBar: true,\n }\n },\n {\n path: '/scripts',\n name: 'scripts',\n component: () => import('@/views/ScriptsView.vue'),\n meta: {\n showNavBar: true,\n }\n },\n // {\n // path: '/trading',\n // name: 'trading',\n // component: () => import('@/views/TradingView.vue'),\n // meta: {\n // showNavBar: true,\n // }\n // },\n {\n path: '/property',\n name: 'property',\n component: () => import('@/views/PropertyView.vue'),\n meta: {\n showNavBar: true,\n }\n },\n {\n path: '/crypto',\n name: 'crypto',\n component: () => import('@/views/CryptoView.vue'),\n meta: {\n showNavBar: true,\n }\n },\n {\n path: '/algo',\n name: 'algo',\n component: () => import('@/views/AlgoView.vue'),\n meta: {\n showNavBar: true,\n }\n },\n {\n path: '/securities',\n name: 'securities',\n component: () => import('@/views/SecuritiesView.vue'),\n meta: {\n showNavBar: true,\n }\n },\n {\n path: '/log',\n name: 'log',\n component: () => import('@/views/LogView.vue'),\n meta: {\n showNavBar: true,\n }\n },\n];\n\nexport default routes;\n","/**\n * Vue Router configuration\n * \n * Configures application routing with navigation guards for session validation\n * before allowing access to protected routes.\n */\n\nimport { createRouter, createWebHistory, RouteLocationNormalized, NavigationGuardNext } from 'vue-router';\nimport routes from '@/router/routes';\nimport { axiosInstance } from '@/utils/interceptor';\n\nconst router = createRouter({\n history: createWebHistory(import.meta.env.BASE_URL),\n routes\n});\n\n// Validate session before navigation\nrouter.beforeEach(async (\n to: RouteLocationNormalized, \n from: RouteLocationNormalized, \n next: NavigationGuardNext\n): Promise => {\n try {\n await axiosInstance.get('/api/v2/auth/validate', {\n headers: {\n 'X-Original-Path': to.fullPath\n }\n });\n next();\n } catch (error) {\n console.error('Session validation failed:', error);\n next(false);\n }\n});\n\nexport default router;\n","import { createPinia } from 'pinia';\nimport piniaPluginPersistedstate from 'pinia-plugin-persistedstate';\n\n// Create the Pinia store instance\nconst pinia = createPinia();\n\n// Add the persistence plugin to Pinia\npinia.use(piniaPluginPersistedstate);\n\nexport default pinia;\n","/**\n * WebSocketService.ts\n * \n * This service provides a wrapper around the WebSocket API with the following features:\n * - Automatic connection management\n * - Event-based message handling\n * - Automatic reconnection with exponential backoff\n * - Error handling and logging\n * - JSON message parsing\n * \n * The service is implemented as a singleton to ensure a single WebSocket connection\n * is maintained throughout the application.\n */\n\n/**\n * Type definition for WebSocket event callbacks\n */\ntype WebSocketCallback = (data: any) => void;\n\n/**\n * WebSocket event types\n */\nenum WebSocketEvent {\n OPEN = 'open',\n MESSAGE = 'message',\n ERROR = 'error',\n CLOSE = 'close'\n}\n\n/**\n * WebSocketService class providing a robust WebSocket connection handler\n */\nclass WebSocketService {\n private socket: WebSocket | null = null;\n private reconnectAttempts = 0;\n private maxReconnectAttempts = 5;\n private reconnectTimeout: number | null = null;\n private listeners: Record = {};\n\n /**\n * Establishes a WebSocket connection to the server\n * \n * Creates a new WebSocket connection if one doesn't exist or is not in CONNECTING/OPEN state.\n * Sets up event handlers for the connection.\n */\n connect(): void {\n if (this.socket && (this.socket.readyState === WebSocket.OPEN || this.socket.readyState === WebSocket.CONNECTING)) {\n console.log('WebSocket already connected or connecting');\n return;\n }\n\n const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';\n const host = window.location.host;\n const wsUrl = `${protocol}//${host}/api/v2/securities/ws`;\n \n this.socket = new WebSocket(wsUrl);\n \n this.socket.onopen = () => {\n console.log('WebSocket connection established');\n this.reconnectAttempts = 0;\n this.emit(WebSocketEvent.OPEN, null);\n };\n \n this.socket.onmessage = (event) => {\n try {\n const data = JSON.parse(event.data);\n this.emit(WebSocketEvent.MESSAGE, data);\n } catch (error) {\n console.error('Failed to parse WebSocket message:', error);\n this.emit(WebSocketEvent.MESSAGE, event.data);\n }\n };\n \n this.socket.onerror = (error) => {\n console.error('WebSocket error:', error);\n this.emit(WebSocketEvent.ERROR, error);\n };\n \n this.socket.onclose = (event) => {\n console.log('WebSocket connection closed', event.code, event.reason);\n this.emit(WebSocketEvent.CLOSE, event);\n \n // Attempt to reconnect unless the connection was closed deliberately\n if (event.code !== 1000) {\n this.attemptReconnect();\n }\n };\n }\n\n /**\n * Attempts to reconnect to the WebSocket server with exponential backoff\n * \n * @private\n */\n private attemptReconnect(): void {\n if (this.reconnectAttempts < this.maxReconnectAttempts) {\n this.reconnectAttempts++;\n console.log(`Attempting to reconnect (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`);\n \n // Exponential backoff for reconnection attempts\n const timeout = Math.min(1000 * (2 ** this.reconnectAttempts), 30000);\n \n this.reconnectTimeout = window.setTimeout(() => {\n this.connect();\n }, timeout);\n } else {\n console.error('Maximum reconnection attempts reached. Please refresh the page.');\n }\n }\n\n /**\n * Disconnects the WebSocket connection\n * \n * Clears any pending reconnection attempts and closes the connection with a normal closure code.\n */\n disconnect(): void {\n if (this.reconnectTimeout) {\n clearTimeout(this.reconnectTimeout);\n this.reconnectTimeout = null;\n }\n \n if (this.socket && this.socket.readyState === WebSocket.OPEN) {\n // Use 1000 code for normal closure\n this.socket.close(1000, 'User initiated disconnect');\n }\n \n this.socket = null;\n this.listeners = {};\n }\n\n /**\n * Sends data through the WebSocket connection\n * \n * @param data - The data to send (will be stringified if not a string)\n */\n send(data: unknown): void {\n if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {\n console.error('Cannot send message, WebSocket is not connected');\n return;\n }\n \n try {\n const message = typeof data === 'string' ? data : JSON.stringify(data);\n this.socket.send(message);\n } catch (error) {\n console.error('Failed to send WebSocket message:', error);\n }\n }\n\n /**\n * Registers a callback for a specific WebSocket event\n * \n * @param event - The event to listen for\n * @param callback - The function to call when the event occurs\n */\n on(event: string, callback: WebSocketCallback): void {\n if (!this.listeners[event]) {\n this.listeners[event] = [];\n }\n this.listeners[event].push(callback);\n }\n\n /**\n * Removes a callback for a specific WebSocket event\n * \n * @param event - The event to stop listening for\n * @param callback - The function to remove from listeners\n */\n off(event: string, callback: WebSocketCallback): void {\n if (!this.listeners[event]) return;\n \n this.listeners[event] = this.listeners[event].filter(\n listener => listener !== callback\n );\n }\n\n /**\n * Triggers callbacks registered for a specific event\n * \n * @param event - The event that occurred\n * @param data - The data associated with the event\n * @private\n */\n private emit(event: string, data: any): void {\n if (!this.listeners[event]) return;\n \n this.listeners[event].forEach(callback => {\n try {\n callback(data);\n } catch (error) {\n console.error(`Error in WebSocket ${event} listener:`, error);\n }\n });\n }\n\n /**\n * Checks if the WebSocket connection is currently open\n * \n * @returns True if connected, false otherwise\n */\n isConnected(): boolean {\n return !!this.socket && this.socket.readyState === WebSocket.OPEN;\n }\n}\n\n// Create and export a singleton instance\nconst websocketService = new WebSocketService();\nexport default websocketService;\n","// Import the createApp function from Vue for app initialization\nimport { createApp } from 'vue';\n\n// Import the main App component\nimport App from './App.vue';\n\n// Vue Router\nimport router from './router';\n\n// Pinia Store\nimport pinia from './stores';\n\n// Apex Charts\nimport VueApexCharts from \"vue3-apexcharts\";\n\n// BootstrapVue\nimport { createBootstrap } from 'bootstrap-vue-next'\nimport 'bootstrap/dist/css/bootstrap.css'\nimport 'bootstrap-vue-next/dist/bootstrap-vue-next.css'\n\n// PrimeVue\nimport PrimeVue from 'primevue/config';\n// import Aura from '@primeuix/themes/aura';\n// import Material from '@primeuix/themes/material';\n// import Lara from '@primeuix/themes/lara';\nimport Nora from '@primeuix/themes/nora';\n\n// VueSidebarMenu\nimport VueSidebarMenu from 'vue-sidebar-menu'\nimport 'vue-sidebar-menu/dist/vue-sidebar-menu.css'\n\n// AG Grid\nimport { AllCommunityModule, ModuleRegistry } from 'ag-grid-community'; \n\n// Import WebSocket Service\nimport websocketService from './services/websocketService';\n\n// Register all Community features\nModuleRegistry.registerModules([AllCommunityModule]);\n\n// Custom CSS\nimport './assets/styles.css';\n\n// Initialize WebSocket connection\nwebsocketService.connect();\n\n// Create a new Vue application instance with the main App component\nconst app = createApp(App);\n\napp.use(createBootstrap());\napp.use(router);\napp.use(pinia);\napp.use(VueApexCharts);\napp.use(VueSidebarMenu);\napp.use(PrimeVue, {\n // Default theme configuration\n theme: {\n preset: Nora,\n options: {\n prefix: 'p',\n darkModeSelector: 'system',\n cssLayer: false\n }\n }\n});\n\n// Mount the Vue application to the DOM element with the id 'app', effectively starting the app\napp.mount('#app');\n\n// Handle page unload to properly close WebSocket connection\nwindow.addEventListener('beforeunload', () => {\n websocketService.disconnect();\n});\n"],"file":"assets/main-pt01_ziL.js"}