(function () { const apiBaseUrlStorageKey = "tarot-time-api-base-url"; const apiKeyStorageKey = "tarot-time-api-key"; const defaultConnectionAccess = Object.freeze({ connected: false, apiKeyRequired: false, authenticated: false, clientId: "", accountId: "", accessLevel: "", roles: Object.freeze([]), scopes: Object.freeze([]), capabilities: Object.freeze({ tarot: false, adminApiManagement: false }) }); function normalizeBaseUrl(value) { return String(value || "") .trim() .replace(/\/+$/, ""); } function normalizeApiKey(value) { return String(value || "").trim(); } function normalizeStringList(values) { return Array.isArray(values) ? values.map((value) => String(value || "").trim()).filter(Boolean) : []; } function normalizeAccessLevel(value) { return String(value || "").trim().toLowerCase(); } function normalizeConnectionAccess(source = null) { const health = source?.health || {}; const auth = health?.auth || source?.auth || {}; const roles = normalizeStringList(auth?.roles); const scopes = normalizeStringList(auth?.scopes); const apiKeyRequired = health?.apiKeyRequired === true || source?.apiKeyRequired === true; const connected = source?.ok === true || source?.connected === true; const accessLevel = normalizeAccessLevel( auth?.accessLevel || source?.accessLevel || (connected && !apiKeyRequired ? "premium" : "") ); const tarotCapability = source?.capabilities?.tarot === true || (connected && !apiKeyRequired) || accessLevel === "premium"; const adminApiManagementCapability = source?.capabilities?.adminApiManagement === true || roles.includes("admin") || scopes.includes("api:admin"); return { connected, apiKeyRequired, authenticated: auth?.authenticated === true, clientId: String(auth?.clientId || source?.clientId || "").trim(), accountId: String(auth?.accountId || source?.accountId || "").trim(), accessLevel, roles, scopes, capabilities: { tarot: tarotCapability, adminApiManagement: adminApiManagementCapability } }; } function sameConnectionAccess(left, right) { return JSON.stringify(left) === JSON.stringify(right); } function normalizeConnectionSettings(settings) { return { apiBaseUrl: normalizeBaseUrl(settings?.apiBaseUrl), apiKey: normalizeApiKey(settings?.apiKey) }; } function stripLegacyCredentialParams() { try { const currentUrl = new URL(window.location.href); const hadApiKeyParam = currentUrl.searchParams.has("apiKey") || currentUrl.searchParams.has("api_key"); if (!hadApiKeyParam) { return; } currentUrl.searchParams.delete("apiKey"); currentUrl.searchParams.delete("api_key"); const nextUrl = `${currentUrl.pathname}${currentUrl.search}${currentUrl.hash}`; window.history.replaceState(window.history.state, "", nextUrl); } catch (_error) { } } function persistConnectionSettings(settings) { let didPersist = true; try { const params = new URLSearchParams(window.location.search || ""); const queryValue = String(params.get("apiBaseUrl") || "").trim(); if (queryValue) { window.localStorage.setItem(apiBaseUrlStorageKey, normalizeBaseUrl(queryValue)); } if (settings.apiBaseUrl) { window.localStorage.setItem(apiBaseUrlStorageKey, settings.apiBaseUrl); } else { window.localStorage.removeItem(apiBaseUrlStorageKey); } if (settings.apiKey) { window.localStorage.setItem(apiKeyStorageKey, settings.apiKey); } else { window.localStorage.removeItem(apiKeyStorageKey); } } catch (_error) { didPersist = false; } return didPersist; } function readConfiguredConnectionSettings() { try { const params = new URLSearchParams(window.location.search || ""); const queryValue = String(params.get("apiBaseUrl") || "").trim(); if (queryValue) { window.localStorage.setItem(apiBaseUrlStorageKey, normalizeBaseUrl(queryValue)); } const storedBaseUrl = String(window.localStorage.getItem(apiBaseUrlStorageKey) || "").trim(); const storedApiKey = String(window.localStorage.getItem(apiKeyStorageKey) || "").trim(); return normalizeConnectionSettings({ apiBaseUrl: storedBaseUrl, apiKey: storedApiKey }); } catch (_error) { return normalizeConnectionSettings({ apiBaseUrl: "", apiKey: "" }); } } stripLegacyCredentialParams(); const initialConnectionSettings = readConfiguredConnectionSettings(); const initialConnectionAccess = normalizeConnectionAccess(null); window.TarotAppConfig = { ...(window.TarotAppConfig || {}), apiBaseUrl: initialConnectionSettings.apiBaseUrl, apiKey: initialConnectionSettings.apiKey, connectionAccess: initialConnectionAccess, getApiBaseUrl() { return normalizeBaseUrl(this.apiBaseUrl); }, getApiKey() { return normalizeApiKey(this.apiKey); }, isConnectionConfigured() { return Boolean(this.getApiBaseUrl()); }, getConnectionSettings() { return { apiBaseUrl: this.getApiBaseUrl(), apiKey: this.getApiKey() }; }, getConnectionAccess() { return normalizeConnectionAccess(this.connectionAccess || defaultConnectionAccess); }, hasTarotAccess() { return this.getConnectionAccess().capabilities.tarot === true; }, hasAdminApiManagementAccess() { return this.getConnectionAccess().capabilities.adminApiManagement === true; }, updateConnectionAccess(nextAccess = null) { const previous = this.getConnectionAccess(); const current = normalizeConnectionAccess(nextAccess); this.connectionAccess = current; if (!sameConnectionAccess(previous, current)) { document.dispatchEvent(new CustomEvent("connection:access-updated", { detail: { previous, current: { ...current, roles: [...current.roles], scopes: [...current.scopes], capabilities: { ...current.capabilities } } } })); } return current; }, updateConnectionSettings(nextSettings = {}) { const previous = this.getConnectionSettings(); const current = normalizeConnectionSettings({ ...previous, ...nextSettings }); const didPersist = persistConnectionSettings(current); this.apiBaseUrl = current.apiBaseUrl; this.apiKey = current.apiKey; if (previous.apiBaseUrl !== current.apiBaseUrl || previous.apiKey !== current.apiKey) { document.dispatchEvent(new CustomEvent("connection:updated", { detail: { previous, current: { ...current } } })); } return { ...current, didPersist }; } }; })();