From c2132ad5285d7537d82dbb1ddcd0ff3a25f09270 Mon Sep 17 00:00:00 2001 From: MojtabaSoumi Date: Tue, 31 Mar 2026 13:55:47 +0330 Subject: [PATCH] 1405/01/11-add urls config in config-loader.js --- src/config-loader.js | 193 ++++++++++++++++++++++++------------------- 1 file changed, 109 insertions(+), 84 deletions(-) diff --git a/src/config-loader.js b/src/config-loader.js index 9c726aa..cdedbf4 100644 --- a/src/config-loader.js +++ b/src/config-loader.js @@ -1,118 +1,145 @@ -(function() { - 'use strict'; +;(function () { + 'use strict' //debugger - // Store config in window object - window.__APP_CONFIG__ = window.__APP_CONFIG__ || {}; - window.__CONFIG_READY__ = false; + window.__APP_CONFIG__ = window.__APP_CONFIG__ || {} + window.__CONFIG_READY__ = false // Create a promise that will be resolved when config is loaded - let configResolve; - let configReject; + let configResolve + let configReject window.__CONFIG_PROMISE__ = new Promise((resolve, reject) => { - configResolve = resolve; - configReject = reject; - }); + configResolve = resolve + configReject = reject + }) + const protocol = window.location.protocol === 'https:' ? 'https:' : 'http:'; - // API endpoint for config - you can change this URL - // You can also set it via a data attribute: - //const scriptTag = document.currentScript || document.querySelector('script[src*="config-loader.js"]'); - //const customUrl = scriptTag ? scriptTag.getAttribute('data-config-url') : null; - const CONFIG_URL = 'https://nerkh.gold/get_user' //customUrl || window.location.origin + '/api/config'; + const CONFIG_URLS = [ + `${protocol}//nerkh.gold/get_user`, + `${protocol}//tablo.talasevin.ir/get_user`, + `${protocol}//abshode-service.montgit.ir/server/get_user`, + `${protocol}//212.23.201.173:8381/get_user`, + `${protocol}//91.212.174.137:4040/server/get_user`, + ] + const CONFIG_Success_URL = localStorage.getItem('CONFIG_Success_URL') + const sortedConfigUrls = [...CONFIG_URLS].sort((a, b) => { + if (a === CONFIG_Success_URL) return -1 + if (b === CONFIG_Success_URL) return 1 + return 0 + }) // Timeout to ensure main.ts loads even if config fails (5 seconds) - const CONFIG_TIMEOUT = 5000; - let configTimeoutId; - let mainScriptLoaded = false; + const CONFIG_TIMEOUT = 5000 + let configTimeoutId + let mainScriptLoaded = false + async function getConfigsFromUrl(url, timeout = 8000) { + const controller = new AbortController() + const id = setTimeout(() => controller.abort(), timeout) + + try { + const response = await fetch(url, { + method: 'GET', + headers: { + Accept: 'application/json', + }, + cache: 'no-cache', + signal: controller.signal, + }) + + return response + } catch (error) { + if (error.name === 'AbortError') { + throw new Error(`Request timeout after ${timeout}ms`) + } + throw error + } finally { + clearTimeout(id) + } + } + + let retryGetConfig = 3; // Fetch config from server async function loadConfig() { try { - const response = await fetch(CONFIG_URL, { - method: 'GET', - headers: { - 'Accept': 'application/json', - }, - cache: 'no-cache' - }); - - if (!response.ok) { - throw new Error('Failed to fetch config: ' + response.status); + let response = undefined + for (let i = 0; i < sortedConfigUrls.length; i++) { + try { + response = await getConfigsFromUrl(sortedConfigUrls[i],i', e) + continue; + } + } + if (!response?.ok) { + if (retryGetConfig>0){ + retryGetConfig--; + return loadConfig() + } + throw new Error('Failed to fetch config: ' + response.status) } - // Check if response is actually JSON - const contentType = response.headers.get('content-type'); + const contentType = response.headers.get('content-type') if (!contentType || !contentType.includes('application/json')) { - const text = await response.text(); - throw new Error('Response is not JSON. Received: ' + text.substring(0, 100)); + const text = await response.text() + throw new Error('Response is not JSON. Received: ' + text.substring(0, 100)) } - const config = await response.json(); + const config = await response.json() // Store config in window object - window.__APP_CONFIG__ = config; - window.__CONFIG_READY__ = true; - if (config?.user?.name_fa) { - document.title = config.user.name + '-'+config.user.name_fa; - } - // ---------- Dynamic Favicon ---------- - if (config?.user?.avatar) { - const faviconUrl = config.user.avatar; + window.__APP_CONFIG__ = config + window.__CONFIG_READY__ = true - // remove existing favicon(s) - const existingIcons = document.querySelectorAll('link[rel*="icon"]'); - existingIcons.forEach(icon => icon.remove()); - - // create new favicon - const link = document.createElement('link'); - link.rel = 'icon'; - link.type = 'image/png'; // یا image/x-icon - link.href = faviconUrl + '?v=' + Date.now(); - - document.head.appendChild(link); - } // Resolve the promise if (configResolve) { - configResolve(config); + configResolve(config) } // Dispatch custom event to notify that config is ready - window.dispatchEvent(new CustomEvent('configReady', { detail: config })); + window.dispatchEvent(new CustomEvent('configReady', { detail: config })) - console.log('Config loaded successfully:', config); + console.log('Config loaded successfully:', config) // Clear timeout if config loaded successfully if (configTimeoutId) { - clearTimeout(configTimeoutId); - configTimeoutId = null; + clearTimeout(configTimeoutId) + configTimeoutId = null } // Load main.ts after config is ready - loadMainScript(); + loadMainScript() } catch (error) { - console.warn('Config loader: Could not fetch config from', CONFIG_URL); - console.warn('Error details:', error.message); - console.warn('This is normal if the endpoint does not exist yet. App will continue with empty config.'); + console.warn('Config loader: Could not fetch config from', CONFIG_URLS) + console.warn('Error details:', error.message) + console.warn( + 'This is normal if the endpoint does not exist yet. App will continue with empty config.' + ) // Set default empty config on error - window.__APP_CONFIG__ = {}; - window.__CONFIG_READY__ = true; + window.__APP_CONFIG__ = {} + window.__CONFIG_READY__ = true // Resolve the promise even on error (with empty config) if (configResolve) { - configResolve({}); + configResolve({}) } - window.dispatchEvent(new CustomEvent('configError', { detail: error })); + window.dispatchEvent(new CustomEvent('configError', { detail: error })) // Clear timeout if error occurred if (configTimeoutId) { - clearTimeout(configTimeoutId); - configTimeoutId = null; + clearTimeout(configTimeoutId) + configTimeoutId = null } // Load main.ts even on error (with empty config) - loadMainScript(); + loadMainScript() } } @@ -121,10 +148,10 @@ //const config= window.__APP_CONFIG__ // Check if main.ts is already loaded if (mainScriptLoaded || document.querySelector('script[src="/src/main.ts"]')) { - return; + return } - mainScriptLoaded = true; + mainScriptLoaded = true /*const manifestLink = document.createElement("link") manifestLink.rel = "manifest" @@ -133,10 +160,9 @@ document.head.appendChild(manifestLink)*/ - import('/src/main.ts').then(() => { - console.log('Main script loaded and executed'); - }); + console.log('Main script loaded and executed') + }) /*const script = document.createElement('script'); script.type = 'module'; @@ -159,23 +185,22 @@ } // Set timeout to ensure main.ts loads even if config fails - configTimeoutId = setTimeout(function() { + configTimeoutId = setTimeout(function () { if (!mainScriptLoaded) { - console.warn('Config loader: Timeout reached. Loading main.ts with empty config.'); + console.warn('Config loader: Timeout reached. Loading main.ts with empty config.') // Set default empty config - window.__APP_CONFIG__ = window.__APP_CONFIG__ || {}; - window.__CONFIG_READY__ = true; + window.__APP_CONFIG__ = window.__APP_CONFIG__ || {} + window.__CONFIG_READY__ = true // Resolve promise with empty config if (configResolve) { - configResolve({}); + configResolve({}) } - loadMainScript(); + loadMainScript() } - }, CONFIG_TIMEOUT); + }, CONFIG_TIMEOUT) // Start loading config immediately - loadConfig(); -})(); - + loadConfig() +})()