1(function attachInstallWizard(root) { 2 "use strict"; 3 4 var STEP_IDS = ["website", "permissions", "install", "verify", "dashboard"]; 5 var VERIFIED_STATUSES = ["verified_domain", "sdk_active", "connector_active"]; 6 7 function normalizeTargetUrl(raw) { 8 try { 9 var candidate = /^https:\/\//i.test(String(raw || "")) ? String(raw) : "https://" + String(raw || ""); 10 var parsed = new URL(candidate); 11 if (parsed.protocol !== "https:" || !parsed.hostname) return ""; 12 return "https://" + parsed.hostname; 13 } catch (_error) { 14 return ""; 15 } 16 } 17 18 function initialState() { 19 return { 20 currentStep: "website", 21 maxStepIndex: 0, 22 targetUrl: "", 23 manifest: null, 24 installMethod: "javascript", 25 verification: null, 26 error: "" 27 }; 28 } 29 30 function autoLoadTarget(search) { 31 var supplied = new URLSearchParams(String(search || "")).get("url"); 32 return supplied ? normalizeTargetUrl(supplied) : ""; 33 } 34 35 function verified(verification) { 36 return Boolean(verification && VERIFIED_STATUSES.indexOf(String(verification.status || "")) >= 0); 37 } 38 39 function transition(state, action) { 40 var next = Object.assign({}, state); 41 var type = action && action.type; 42 var currentIndex = STEP_IDS.indexOf(state.currentStep); 43 44 if (type === "MANIFEST_LOADED") { 45 var targetUrl = normalizeTargetUrl(action.targetUrl); 46 var manifest = action.manifest || {}; 47 var expectedHost = targetUrl ? new URL(targetUrl).hostname : ""; 48 if ( 49 !targetUrl || 50 manifest.schema !== "xagent-install-manifest-v1" || 51 !manifest.release || manifest.release.ready !== true || 52 !manifest.target || manifest.target.host !== expectedHost 53 ) { 54 next.error = manifest.target && expectedHost && manifest.target.host !== expectedHost ? "target_mismatch" : "manifest_unavailable"; 55 return next; 56 } 57 next.currentStep = "permissions"; 58 next.maxStepIndex = Math.max(state.maxStepIndex, 1); 59 next.targetUrl = targetUrl; 60 next.manifest = manifest; 61 next.verification = null; 62 next.error = ""; 63 return next; 64 } 65 66 if (type === "MANIFEST_FAILED") { 67 next.error = "manifest_unavailable"; 68 return next; 69 } 70 71 if (type === "METHOD_SELECTED" && ["javascript", "python"].indexOf(action.method) >= 0) { 72 next.installMethod = action.method; 73 return next; 74 } 75 76 if (type === "VERIFICATION_LOADED") { 77 next.verification = action.verification || null; 78 next.error = ""; 79 return next; 80 } 81 82 if (type === "CONTINUE") { 83 if (state.currentStep === "website") return next; 84 if (state.currentStep === "verify" && !verified(state.verification)) return next; 85 var nextIndex = Math.min(currentIndex + 1, STEP_IDS.length - 1); 86 next.currentStep = STEP_IDS[nextIndex]; 87 next.maxStepIndex = Math.max(state.maxStepIndex, nextIndex); 88 return next; 89 } 90 91 if (type === "BACK") { 92 next.currentStep = STEP_IDS[Math.max(currentIndex - 1, 0)]; 93 return next; 94 } 95 96 if (type === "GO_TO") { 97 var targetIndex = STEP_IDS.indexOf(action.step); 98 if (targetIndex >= 0 && targetIndex <= state.maxStepIndex) next.currentStep = action.step; 99 return next; 100 } 101 102 return next; 103 } 104 105 function defaultPermissions(modules) { 106 return (Array.isArray(modules) ? modules : []).filter(function (module) { 107 return module && module.default === true && module.id !== "measurement"; 108 }); 109 } 110 111 function workflowStep(manifest, id) { 112 return ((manifest && manifest.workflow) || []).find(function (step) { return step.id === id; }) || null; 113 } 114 115 function mount(documentRef) { 116 var documentObject = documentRef || (root && root.document); 117 if (!documentObject) return null; 118 var container = documentObject.querySelector("[data-install-wizard]"); 119 if (!container) return null; 120 var state = initialState(); 121 var verificationStatus = container.querySelector("[data-verification-status]"); 122 var permissionList = container.querySelector("[data-wizard-permissions]"); 123 function t(source) { 124 return root && root.XAgentI18n && root.XAgentI18n.t ? root.XAgentI18n.t(source) : source; 125 } 126 127 function renderPermissions() { 128 if (!permissionList) return; 129 permissionList.textContent = ""; 130 defaultPermissions((state.manifest || {}
130).modules).forEach(function (permission) { 131 var item = documentObject.createElement("li"); 132 var title = documentObject.createElement("b"); 133 var grant = documentObject.createElement("code"); 134 title.textContent = permission.id; 135 grant.textContent = permission.grant || ""; 136 item.appendChild(title); 137 item.appendChild(grant); 138 permissionList.appendChild(item); 139 }); 140 } 141 142 function renderDashboardCommand() { 143 var command = container.querySelector('[data-workflow-id="dashboard_login"]'); 144 if (!command) return; 145 var step = workflowStep(state.manifest, "dashboard_login"); 146 command.textContent = step && step.command ? step.command : t("Command unavailable"); 147 } 148 149 function render() { 150 var currentIndex = STEP_IDS.indexOf(state.currentStep); 151 container.querySelectorAll("[data-wizard-step]").forEach(function (button) { 152 var index = STEP_IDS.indexOf(button.dataset.wizardStep); 153 var active = index === currentIndex; 154 button.disabled = index > state.maxStepIndex; 155 if (active) button.setAttribute("aria-current", "step"); 156 else button.removeAttribute("aria-current"); 157 button.closest("li").classList.toggle("is-complete", index < currentIndex || index < state.maxStepIndex); 158 }); 159 container.querySelectorAll("[data-wizard-panel]").forEach(function (panel) { 160 panel.hidden = panel.dataset.wizardPanel !== state.currentStep; 161 }); 162 container.querySelectorAll("[data-install-method]").forEach(function (button) { 163 var active = button.dataset.installMethod === state.installMethod; 164 button.setAttribute("aria-selected", active ? "true" : "false"); 165 button.tabIndex = active ? 0 : -1; 166 }); 167 container.querySelectorAll("[data-install-method-panel]").forEach(function (panel) { 168 panel.hidden = panel.dataset.installMethodPanel !== state.installMethod; 169 }); 170 container.querySelectorAll('[data-wizard-next="dashboard"]').forEach(function (button) { 171 button.disabled = !verified(state.verification); 172 }); 173 renderPermissions(); 174 renderDashboardCommand(); 175 } 176 177 function update(action) { 178 state = transition(state, action); 179 render(); 180 } 181 182 container.querySelectorAll("[data-wizard-step]").forEach(function (button) { 183 button.addEventListener("click", function () { update({ type: "GO_TO", step: button.dataset.wizardStep }); }); 184 }); 185 container.querySelectorAll("[data-wizard-next]").forEach(function (button) { 186 button.addEventListener("click", function () { update({ type: "CONTINUE" }); }); 187 }); 188 container.querySelectorAll("[data-wizard-back]").forEach(function (button) { 189 button.addEventListener("click", function () { update({ type: "BACK" }); }); 190 }); 191 container.querySelectorAll("[data-install-method]").forEach(function (button) { 192 button.addEventListener("click", function () { update({ type: "METHOD_SELECTED", method: button.dataset.installMethod }); }); 193 }); 194 container.querySelectorAll("[data-copy-target]").forEach(function (button) { 195 button.addEventListener("click", async function () { 196 var target = container.querySelector(button.dataset.copyTarget); 197 if (!target || !target.textContent) return; 198 try { 199 await root.navigator.clipboard.writeText(target.textContent); 200 button.textContent = t("Copied"); 201 root.setTimeout(function () { button.textContent = t("Copy"); }, 1400); 202 } catch (_error) { 203 if (verificationStatus) verificationStatus.textContent = t("Copy was blocked. Select the command manually."); 204 } 205 }); 206 }); 207 208 var verifyButton = container.querySelector("[data-verify-install]"); 209 if (verifyButton) verifyButton.addEventListener("click", async function () { 210 if (!state.targetUrl) return; 211 verifyButton.disabled = true; 212 if (verificationStatus) verificationStatus.textContent = t("Checking the public installationâ¦"); 213 try { 214 var response = await root.fetch("/api/site_agents/install_status?url=" + encodeURIComponent(state.targetUrl), { 215 headers: { Accept: "application/json" }, credentials: "omit" 216 }); 217 if (!response.ok) throw new Error("verification unavailable"); 218 var verification = await response.json(); 219 update({ type: "VERIFICATION_LOADED", verification: verification }); 220 if (verificationStatus) { 221 verificationStatus.textContent = verified(verification) 222 ? t("Installed and independently verified.") + " " + (verification.host || new URL(state.targetUrl).hostname) 223 : t("Not verified yet. Complete the public proof step, then check again."); 224 verificationStatus.classList.toggle("is-success", verified(verification)); 225 } 226 } catch (_error) { 227 if (verificationStatus) verificationStatus.textContent = t("Verification is unavailable. No installation state was changed."); 228 } finally { 229 verifyButton.disabled = false;
230 } 231 }); 232 233 if (root && root.addEventListener) { 234 root.addEventListener("xagent:manifestloaded", function (event) { 235 update({ type: "MANIFEST_LOADED", targetUrl: event.detail.targetUrl, manifest: event.detail.manifest }); 236 }); 237 root.addEventListener("xagent:manifestfailed", function () { update({ type: "MANIFEST_FAILED" }); }); 238 } 239 render(); 240 return { getState: function () { return Object.assign({}, state); }, update: update }; 241 } 242 243 var api = { 244 STEP_IDS: STEP_IDS, 245 VERIFIED_STATUSES: VERIFIED_STATUSES, 246 autoLoadTarget: autoLoadTarget, 247 defaultPermissions: defaultPermissions, 248 initialState: initialState, 249 mount: mount, 250 normalizeTargetUrl: normalizeTargetUrl, 251 transition: transition, 252 verified: verified 253 }; 254 if (typeof module === "object" && module.exports) module.exports = api; 255 if (root) root.XAgentInstallWizard = api; 256})(typeof window !== "undefined" ? window : null);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.