{"version":3,"file":"init.js","sources":["../../startup.ts","../../softtech-serviceworker-init.ts","../../scriptsLicenseServer/application/init.ts"],"sourcesContent":["/**\r\n * IMPORTANT: This file is for dealer-franchisee app initialization.\r\n * do not use this file for other apps.\r\n * DO not import anything from the main application. this forms a stand alone\r\n * initialization for the dealer-franchisee app.\r\n *\r\n */\r\n\r\nexport function getAssetCdnPath(fileName: string): string {\r\n if (fileName.startsWith('./assets/')) {\r\n fileName = fileName.substring(9);\r\n } else if (fileName.startsWith('/assets/')) {\r\n fileName = fileName.substring(8);\r\n } else if (fileName.startsWith('assets/')) {\r\n fileName = fileName.substring(7);\r\n } else if (fileName.startsWith('./')) {\r\n fileName = fileName.substring(2);\r\n } else if (fileName.startsWith('/')) {\r\n fileName = fileName.substring(1);\r\n }\r\n\r\n return `https://webmodule-softtech.azureedge.net/v6config/site/assets/${fileName}`;\r\n}\r\n\r\nexport function documentReady(fn) {\r\n // see if DOM is already available\r\n if (document.readyState === 'complete' || document.readyState === 'interactive') {\r\n // call on next available tick\r\n setTimeout(fn, 1);\r\n } else {\r\n window.addEventListener('load', fn);\r\n }\r\n}\r\n\r\nlet apiHost;\r\n\r\nexport async function initApiHost() {\r\n updateNote('Fetching Api Server Connection Settings');\r\n apiHost = await getFile('./assets/apiserver.json', 'Cannot Access Api Settings', expiresIn.oneWeek);\r\n if (apiHost === undefined) {\r\n retryPage();\r\n return false;\r\n }\r\n if (apiHost.host === '') apiHost.host = window.location.origin;\r\n return true;\r\n}\r\n\r\nlet info;\r\n\r\nexport function updateNote(note) {\r\n if (!info) info = document.body.querySelector('#loadingNote');\r\n if (info) info.innerHTML = note;\r\n}\r\n\r\nexport let leaveBackground = false;\r\nlet _skipBackgroundProcessing = false;\r\n\r\nexport function skipBackgroundProcessing() {\r\n _skipBackgroundProcessing = true;\r\n}\r\n\r\nexport function retryPage() {\r\n leaveBackground = true;\r\n let counter = 60;\r\n const msg = currentNote();\r\n const countDown = () => {\r\n updateNote(`${msg}\\nAttempting Page Reload in ${counter--} seconds`);\r\n if (counter === 0) {\r\n location.reload();\r\n } else setTimeout(countDown, 1000);\r\n };\r\n setTimeout(countDown, 1000);\r\n}\r\n\r\nexport async function getFile(path, issue, expires = 604800, force = false) {\r\n try {\r\n const response = globalThis.noSqlDb\r\n ? await globalThis.noSqlDb.fetch(path, expires, undefined, force)\r\n : await fetch(path, {\r\n headers: {\r\n 'Access-Control-Allow-Origin': '*'\r\n }\r\n });\r\n if (response) return response;\r\n else updateNote(issue ?? `Could not access \"${path}\"`);\r\n return undefined;\r\n } catch {\r\n updateNote(issue ?? `Could not access \"${path}\"`);\r\n return undefined;\r\n }\r\n}\r\n\r\nexport const expiresIn = {\r\n oneDay: 60 * 60 * 24,\r\n oneWeek: 60 * 60 * 24 * 7,\r\n oneMonth: 60 * 60 * 24 * 30,\r\n nextDay: -100\r\n};\r\n\r\nexport function currentNote() {\r\n if (!info) info = document.body.querySelector('#loadingNote');\r\n return info?.innerHTML;\r\n}\r\n\r\nexport async function checkToClearDB() {\r\n let flushNoSql = localStorage.getItem('flush-no-sql') === 'true';\r\n if (flushNoSql) {\r\n globalThis.noSqlDb?.clear?.();\r\n localStorage.removeItem('flush-no-sql');\r\n }\r\n}\r\n\r\nlet _langDisabled = false;\r\n\r\nexport function disableLanguages() {\r\n _langDisabled = true;\r\n}\r\n\r\nexport async function initializeLanguages() {\r\n if (_langDisabled) {\r\n globalThis.dealerConfiguration.langFile = {};\r\n globalThis.dealerConfiguration.dictItems = defaultDictItems();\r\n return;\r\n }\r\n updateNote('Fetching Language Settings');\r\n let langFile = await getFile(\r\n './assets/lang/lang.json',\r\n 'Cannot Access LangFile, Applying defaults',\r\n expiresIn.oneMonth\r\n );\r\n if (!langFile) langFile = {};\r\n\r\n updateNote('Fetching Technical Dictionary');\r\n const dictItems = await getFile(\r\n `${apiHost.host}/api/lang/dict.json`,\r\n 'Cannot access Technical Dictionary',\r\n expiresIn.oneMonth\r\n );\r\n\r\n globalThis.dealerConfiguration.langFile = langFile;\r\n globalThis.dealerConfiguration.dictItems = dictItems ?? null;\r\n}\r\n\r\nexport async function reloadPageIfOutOfDate(isOutOfDate) {\r\n if (isOutOfDate) {\r\n if (globalThis.runningIsOutOfDate) return;\r\n globalThis.runningIsOutOfDate = true;\r\n try {\r\n await globalThis.noSqlDb?.clear?.();\r\n const cacheNames = await caches.keys();\r\n await Promise.all(cacheNames.map(cacheName => caches.delete(cacheName)));\r\n /*\r\n const msg = `\r\n The Dealer system is now out-of-sync due to a recent scheduled update and will refresh.\r\n \r\n You will lose any unsaved changes. \r\n \r\n Current Server Version: ${globalThis.dealerConfiguration.apiBuildNumberDisplay}\r\n \r\n Current Local Version: ${globalThis.localBuildNumber ?? 'Unknown'}\r\n \r\n Should this not resolve, please contact support for assistance\r\n \r\n **Tip:** To avoid this issue we recommend logging out overnight or when not in use to reduce the risk of data loss during scheduled updates.\r\n `;\r\n \r\n try {\r\n if (globalThis.informAsync) await globalThis.informAsync?.(msg, 'System out-of-date');\r\n else alert(msg);\r\n } catch {\r\n alert(msg);\r\n }\r\n \r\n */\r\n } finally {\r\n window.location.reload();\r\n }\r\n }\r\n}\r\n\r\nglobalThis.reloadPageIfOutOfDate = reloadPageIfOutOfDate;\r\nexport let branding;\r\n\r\nexport async function initBranding() {\r\n let branding = await globalThis.noSqlDb?.getItem('supplier-branding');\r\n if (branding) document.body.style.backgroundImage = `url('${branding.loginImageUrl}')`;\r\n}\r\n\r\nexport async function refreshBranding(licenseServerHost: string, dealerDeploymentId: number) {\r\n updateNote('Fetching Branding for site');\r\n\r\n if (!branding) await updateBranding(licenseServerHost, dealerDeploymentId);\r\n else updateBranding(licenseServerHost, dealerDeploymentId);\r\n}\r\n\r\nasync function updateBranding(licenseServerHost: string, dealerDeploymentId: number) {\r\n try {\r\n branding = await getFile(\r\n `${licenseServerHost}/api/deployment/DomainBranding?id=${dealerDeploymentId}`,\r\n 'Branding could not be accessed',\r\n expiresIn.nextDay\r\n );\r\n //branding doesn't change often. we are going to store the branding for this domain\r\n //here, so that next refresh we can push the value immediately into the background\r\n await globalThis.noSqlDb?.setItem('supplier-branding', branding);\r\n } catch {\r\n branding = {\r\n loginImageUrl: getAssetCdnPath('./assets/images/login-img.png'),\r\n loginBrandLogo: getAssetCdnPath('./assets/images/PoweredBySoftTech-blue.svg'),\r\n footerBrandLogo: getAssetCdnPath('./assets/images/brandingfooterlogo.png'),\r\n operationType: 0\r\n };\r\n }\r\n //this might be happening in the background without awaiting, so make sure we\r\n //only add it, if we need to\r\n if (!_skipBackgroundProcessing || (_skipBackgroundProcessing && leaveBackground))\r\n document.body.style.backgroundImage = `url('${branding.loginImageUrl}')`;\r\n}\r\n\r\nexport async function refreshApiDetailsAndUpdateDealerConfiguration(apiHost: string, force = true) {\r\n const details = await getFile(\r\n `${apiHost}/api/System/ApiDetails`,\r\n 'Cannot Access Api Server, Possibly Offline',\r\n expiresIn.oneDay,\r\n force\r\n );\r\n if (details && globalThis.dealerConfiguration) {\r\n globalThis.dealerConfiguration.v6apiHost = details.otherApiDomains.v6 ?? apiHost;\r\n globalThis.dealerConfiguration.licenseServerHost = details.licenseServerHost;\r\n globalThis.dealerConfiguration.dealerDeploymentId = details.dealerDeploymentId;\r\n globalThis.dealerConfiguration.apiBuildNumber = details.buildNumberAsInt ?? 0;\r\n globalThis.dealerConfiguration.apiBuildNumberDisplay = details.buildNumber ?? '';\r\n }\r\n return details;\r\n}\r\n\r\nexport async function initializeApiDetails(elementName: string, applicationTitle: string) {\r\n globalThis.dealerRefreshApiDetails = () => refreshApiDetailsAndUpdateDealerConfiguration(apiHost.host);\r\n\r\n updateNote('Fetching License Server Connection Settings');\r\n let apiDetails = await refreshApiDetailsAndUpdateDealerConfiguration(apiHost.host, false);\r\n if (!apiDetails) {\r\n retryPage();\r\n return;\r\n }\r\n\r\n if (globalThis.isAppOutOfDate(apiDetails.buildNumber) && globalThis.noSqlDb.lastFetch) {\r\n //there is a chance we think we are out of date, because of a stale DB fetch,\r\n //when a force reload has occurred, so do another refresh with good data\r\n apiDetails = await globalThis.dealerRefreshApiDetails();\r\n }\r\n\r\n await refreshBranding(apiDetails.licenseServerHost, apiDetails.dealerDeploymentId);\r\n try {\r\n globalThis.dealerConfiguration = {\r\n apiHost: apiHost.host,\r\n v6apiHost: apiDetails.otherApiDomains.v6 ?? apiHost.host,\r\n licenseServerHost: apiDetails.licenseServerHost,\r\n dealerDeploymentId: apiDetails.dealerDeploymentId,\r\n apiBuildNumber: apiDetails.buildNumberAsInt ?? 0,\r\n apiBuildNumberDisplay: apiDetails.buildNumber ?? '',\r\n v6apiBuildNumber: 0, //not needed by supplier\r\n v6apiBuildNumberDisplay: '', //not needed by supplier\r\n lang: {},\r\n dictItems: null,\r\n branding: branding\r\n };\r\n globalThis.bindApplicationFeatures?.();\r\n await reloadPageIfOutOfDate(globalThis.isAppOutOfDate());\r\n await initializeLanguages();\r\n\r\n //this will connect to the server to see if the current\r\n //login token is valid, and that the current user is allowed\r\n //to be on this session (ie not in another session)\r\n //if false, then this will disconnect the user\r\n updateNote('Preparing Application');\r\n await globalThis.getApplicationStartupEvents();\r\n //If we got to this point, then everything that needed doing has been done.\r\n //if we need to logoff from here, we should not need to reload the page to do it\r\n const mainElement = document.createElement(elementName);\r\n mainElement.setAttribute('appTitle', applicationTitle);\r\n mainElement.className = 'app-wrapper';\r\n document.body.querySelector('#splash-screen')?.remove();\r\n\r\n document.body.insertBefore(mainElement, mainElement.firstChild);\r\n } finally {\r\n skipBackgroundProcessing();\r\n if (!leaveBackground) document.body.style.backgroundImage = '';\r\n }\r\n}\r\n\r\nfunction defaultDictItems() {\r\n return [\r\n {\r\n name: 'branch',\r\n single: 'Branch',\r\n plural: 'Branches'\r\n },\r\n {\r\n name: 'client',\r\n single: 'Client',\r\n plural: 'Clients'\r\n },\r\n {\r\n name: 'contact',\r\n single: 'Contact',\r\n plural: 'Contacts'\r\n },\r\n {\r\n name: 'franchisee',\r\n single: 'Dealership',\r\n plural: 'Dealerships'\r\n },\r\n {\r\n name: 'supplier',\r\n single: 'Supplier',\r\n plural: 'Suppliers'\r\n },\r\n {\r\n name: 'user',\r\n single: 'User',\r\n plural: 'Users'\r\n }\r\n ];\r\n}\r\n","/**\r\n * IMPORTANT: This file is for dealer-franchisee app initialization.\r\n * do not use this file for other apps.\r\n * DO not import anything from the main application. this forms a stand alone\r\n * initialization for the dealer-franchisee app.\r\n *\r\n */\r\n// @ts-ignore\r\nimport { Workbox } from 'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-window.prod.mjs';\r\n\r\nexport async function intializeServiceWorker(serviceWorkerName: string) {\r\n async function flushCache(): Promise {\r\n localStorage.setItem('flush-no-sql', 'true');\r\n\r\n if ('caches' in window) {\r\n const cacheNames = await caches.keys();\r\n await Promise.all(cacheNames.map(cacheName => caches.delete(cacheName)));\r\n console.log('All caches have been flushed.');\r\n } else {\r\n console.warn('Cache API is not supported in this browser.');\r\n }\r\n }\r\n\r\n function updateServiceWorker(reg, runImmediately = false) {\r\n if (runImmediately)\r\n reg.update().catch(e => {\r\n if (e.message?.includes('An unknown error occurred when fetching the script.')) {\r\n //Getting here, means that the script could not be downloaded (User's network is turned off).\r\n return;\r\n }\r\n\r\n //Getting here means something else happened, and we need it to pass through the normal error handler.\r\n throw e;\r\n });\r\n //polling for an update every 30min\r\n setTimeout(() => updateServiceWorker(reg, true), 30 * 60000);\r\n }\r\n\r\n if ('serviceWorker' in navigator) {\r\n if (navigator.serviceWorker.controller) {\r\n console.log(`This page is currently controlled by: ${navigator.serviceWorker.controller}`);\r\n } else {\r\n console.log('This page is not currently controlled by a service worker.');\r\n await flushCache();\r\n }\r\n\r\n const wb = new Workbox(serviceWorkerName ?? '/softtech-serviceworker.js');\r\n\r\n wb.addEventListener('installed', () => {\r\n console.log('service controlling');\r\n });\r\n wb.addEventListener('controlling', () => {\r\n console.log('service controlling');\r\n });\r\n\r\n const showSkipWaitingPrompt = async _event => {\r\n // Assuming the user accepted the update, set up a listener\r\n // that will reload the page as soon as the previously waiting\r\n // service worker has taken control.\r\n\r\n // When `event.wasWaitingBeforeRegister` is true, a previously\r\n // updated service worker is still waiting.\r\n // You may want to customize the UI prompt accordingly.\r\n\r\n //await flushCache();\r\n wb.messageSkipWaiting();\r\n };\r\n\r\n let refreshing = false;\r\n wb.addEventListener('controllerchange', _event => {\r\n console.log('controller change');\r\n if (refreshing) return;\r\n refreshing = true;\r\n //flushCache();\r\n });\r\n wb.addEventListener('activated', _event => {\r\n console.log('activated');\r\n });\r\n wb.addEventListener('activate', _event => {\r\n console.log('activated');\r\n });\r\n\r\n // Add an event listener to detect when the registered\r\n // service worker has installed but is waiting to activate.\r\n wb.addEventListener('waiting', event => {\r\n console.log('service waiting');\r\n showSkipWaitingPrompt(event);\r\n });\r\n\r\n wb.addEventListener('installing', event => {\r\n console.log('service installing');\r\n event.addEventListener('statechange', event => {\r\n console.log('service state change');\r\n showSkipWaitingPrompt(event);\r\n });\r\n });\r\n wb.addEventListener('installed', _event => {\r\n console.log('service installing');\r\n });\r\n\r\n wb.addEventListener('updatefound', event => {\r\n console.log('service update Found');\r\n showSkipWaitingPrompt(event);\r\n });\r\n navigator.serviceWorker.onmessage = async event => {\r\n // this is triggered by the service worker\r\n if (event.data === 'NEW SERVICE WORKER ACTIVE') {\r\n let serviceCacheMismatch = globalThis.isAppOutOfDate?.(globalThis.dealerServiceWorkerVersion ?? 'x') ?? true;\r\n let serverCacheMismatch = globalThis.isAppOutOfDate?.() ?? true;\r\n\r\n if (serviceCacheMismatch || serverCacheMismatch) {\r\n if (globalThis.reloadPageIfOutOfDate) await globalThis.reloadPageIfOutOfDate(true);\r\n else {\r\n await flushCache();\r\n /*\r\n const localMessage = serviceCacheMismatch ? 'Local Service Cache Mismatch' : '';\r\n const serverMessage = serverCacheMismatch ? 'Server Cache Mismatch' : '';\r\n \r\n const msg = `the software has been updated on the server and must now be refreshed. \r\n \r\n ${localMessage} \r\n \r\n ${serverMessage}\r\n \r\n this page is going to reload now to attempt to get the latest version.\r\n \r\n `;\r\n if (globalThis.informAsync) await globalThis.informAsync?.(msg);\r\n else alert(msg);\r\n \r\n */\r\n }\r\n window.location.reload();\r\n }\r\n }\r\n };\r\n wb.addEventListener('fetch', event => {\r\n event.respondWith(\r\n (async () => {\r\n const reg = await navigator.serviceWorker.getRegistration();\r\n if (\r\n event.request.mode === 'navigate' &&\r\n event.request.method === 'GET' &&\r\n reg.waiting &&\r\n (await wb.clients.matchAll()).length < 2\r\n ) {\r\n wb.messageSkipWaiting();\r\n //We’ll use the HTTP Refresh header to refresh the page after 0 seconds\r\n return new Response('', {\r\n headers: { Refresh: '0' }\r\n });\r\n }\r\n\r\n return (await caches.match(event.request)) || fetch(event.request);\r\n })()\r\n );\r\n });\r\n\r\n await unregisterServiceWorkers(serviceWorkerName);\r\n\r\n try {\r\n const reg = await wb.register();\r\n updateServiceWorker(reg);\r\n } catch (e) {\r\n console.error('Service Worker registration failed', e);\r\n alert('Service Worker registration failed: cannot load software ' + (e as any).message);\r\n window.location.reload();\r\n }\r\n }\r\n}\r\n\r\nasync function unregisterServiceWorkers(exceptName: string) {\r\n if ('serviceWorker' in navigator) {\r\n const registrations = await navigator.serviceWorker.getRegistrations();\r\n for (const registration of registrations) {\r\n if (registration.active?.scriptURL.includes(exceptName)) {\r\n console.log(`Keeping service worker: ${registration.active.scriptURL}`);\r\n } else {\r\n console.log(`Unregistering service worker: ${registration.active?.scriptURL}`);\r\n await registration.unregister();\r\n }\r\n }\r\n } else {\r\n console.warn('Service workers are not supported in this browser.');\r\n }\r\n}\r\n","/**\r\n * IMPORTANT: This file is for dealer-franchisee app initialization.\r\n * do not use this file for other apps.\r\n * DO not import anything from the main application. this forms a stand alone\r\n * initialization for the dealer-franchisee app.\r\n *\r\n */\r\nimport {\r\n checkToClearDB,\r\n disableLanguages,\r\n documentReady,\r\n initApiHost,\r\n initBranding,\r\n initializeApiDetails\r\n} from '../../startup';\r\nimport { intializeServiceWorker } from '../../softtech-serviceworker-init';\r\n\r\ndocumentReady(async () => {\r\n await intializeServiceWorker('/softtech-serviceworker.js');\r\n await checkToClearDB();\r\n globalThis.applyDebugInformation?.();\r\n initBranding();\r\n\r\n if (!(await initApiHost())) {\r\n return;\r\n }\r\n disableLanguages();\r\n await initializeApiDetails('wm-licenseserver-app-index', 'Dealer WebModule License Server');\r\n});\r\n"],"names":["getAssetCdnPath","fileName","startsWith","substring","apiHost","info","updateNote","note","document","body","querySelector","innerHTML","leaveBackground","_skipBackgroundProcessing","retryPage","counter","msg","currentNote","countDown","location","reload","setTimeout","async","getFile","path","issue","expires","force","response","globalThis","noSqlDb","fetch","undefined","headers","expiresIn","oneDay","oneWeek","oneMonth","nextDay","branding","_langDisabled","reloadPageIfOutOfDate","isOutOfDate","runningIsOutOfDate","clear","cacheNames","caches","keys","Promise","all","map","cacheName","delete","window","updateBranding","licenseServerHost","dealerDeploymentId","setItem","loginImageUrl","loginBrandLogo","footerBrandLogo","operationType","style","backgroundImage","refreshApiDetailsAndUpdateDealerConfiguration","details","dealerConfiguration","v6apiHost","otherApiDomains","v6","apiBuildNumber","buildNumberAsInt","apiBuildNumberDisplay","buildNumber","initializeApiDetails","elementName","applicationTitle","dealerRefreshApiDetails","host","apiDetails","isAppOutOfDate","lastFetch","refreshBranding","v6apiBuildNumber","v6apiBuildNumberDisplay","lang","dictItems","bindApplicationFeatures","initializeLanguages","langFile","name","single","plural","getApplicationStartupEvents","mainElement","createElement","setAttribute","className","remove","insertBefore","firstChild","skipBackgroundProcessing","intializeServiceWorker","serviceWorkerName","flushCache","localStorage","console","log","warn","navigator","serviceWorker","controller","wb","Workbox","addEventListener","showSkipWaitingPrompt","_event","messageSkipWaiting","refreshing","event","onmessage","data","serviceCacheMismatch","dealerServiceWorkerVersion","serverCacheMismatch","respondWith","reg","getRegistration","request","mode","method","waiting","clients","matchAll","length","Response","Refresh","match","unregisterServiceWorkers","exceptName","registrations","getRegistrations","registration","active","scriptURL","includes","unregister","updateServiceWorker","runImmediately","update","catch","e","message","register","error","alert","documentReady","fn","readyState","checkToClearDB","getItem","removeItem","applyDebugInformation","initBranding","initApiHost","origin","disableLanguages"],"mappings":"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"}