PageSourceSearch

https://xagent.id/assets/install-wizard.js?v=20260819

js xagent.id collected 2026-10-05 06:32:38 UTC 10,423 bytes, 256 lines download raw bytes

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.