UNPKG

spur-monocle-manager

Version:
214 lines (213 loc) 7.15 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { default: () => Monocle }); module.exports = __toCommonJS(index_exports); var MONOCLE_SCRIPT_URL = "https://mcl.spur.us/d/mcl.js"; var Monocle = class { // Debug mode flag /** * @param options Configuration options, requiring a valid token * @throws Error if no token is provided */ constructor(options) { // Timeout for script loading this._initialized = false; this._readyPromise = null; // Promise resolving when script is ready this._script = null; // <script> element reference this._monocle = null; // Global MCL object once loaded this._eventTarget = null; // EventTarget for custom events this._handlers = /* @__PURE__ */ new Map(); if (!options.token) { throw new Error("[Monocle] No token provided"); } this.token = options.token; this.initTimeout = options.initTimeout || 5e3; if (options.debug) { console.warn("[Monocle] Debug mode enabled"); } this._debug = options.debug || false; this._eventTarget = new EventTarget(); } /** * Dispatches a custom Monocle event on the internal EventTarget. */ _dispatch(event, detail) { var _a; (_a = this._eventTarget) == null ? void 0 : _a.dispatchEvent(new CustomEvent(event, { detail })); } /** * Load the Monocle script into the document. * Returns a promise that resolves when the script is loaded or rejects on failure or timeout. */ init() { if (typeof window === "undefined") { return Promise.reject(new Error("[Monocle] init() not supported in SSR")); } if (this._initialized) { if (this._debug) { console.warn("[Monocle] already initialized, init() ignored"); } return this._readyPromise; } this._initialized = true; this._readyPromise = new Promise((resolve, reject) => { const timer = setTimeout(() => { var _a; if ((_a = this._script) == null ? void 0 : _a.parentNode) { document.head.removeChild(this._script); } this._initialized = false; this._readyPromise = null; const err = new Error(`[Monocle] init() timeout after ${this.initTimeout} ms`); this._dispatch("error", err); reject(err); }, this.initTimeout); window._onAssessment = (jwt) => { clearTimeout(timer); this._dispatch("assessment", jwt); resolve(); }; const script = document.createElement("script"); if (!this._script) { this._script = script; } script.id = "_mcl"; script.async = true; script.defer = true; script.src = `${MONOCLE_SCRIPT_URL}?tk=${encodeURIComponent(this.token)}`; script.addEventListener("load", () => { this._monocle = window.MCL; this._dispatch("load"); }); script.addEventListener("error", () => { clearTimeout(timer); try { document.head.removeChild(script); } catch { } this._initialized = false; this._readyPromise = null; const err = new Error("[Monocle] Failed to load script"); this._dispatch("error", err); reject(err); }); script.setAttribute("onassessment", "_onAssessment"); script.setAttribute("onbundle", "_onAssessment"); document.head.appendChild(script); }); return this._readyPromise; } /** * Returns the assessment JWT from Monocle. * This method should only be called after the script is loaded and initialized. * @throws Error if called on the server side or if no data is returned */ async getAssessment() { if (typeof window === "undefined") { throw new Error("[Monocle] getAssessment() is not available on the server side"); } await this.init(); if (!this._monocle) { throw new Error("[Monocle] MCL is not defined"); } try { await this._monocle.refresh(); const assessment = await this._monocle.getAssessment(); if (assessment) { return assessment; } } catch (err) { this._dispatch("error", err); throw err; } const error = new Error("[Monocle] No data returned"); this._dispatch("error", error); throw error; } /** * Register an event listener for Monocle events. */ on(event, handler) { if (typeof window === "undefined") return; if (!this._eventTarget) this._eventTarget = new EventTarget(); const existing = this._handlers.get(event) || []; if (existing.some((e) => e.original === handler)) { if (this._debug) console.warn(`[Monocle] handler already registered for ${event}`); return; } const wrapper = (e) => handler(e.detail); existing.push({ original: handler, wrapper }); this._handlers.set(event, existing); this._eventTarget.addEventListener(event, wrapper); } /** * Unregister a previously added event listener. */ off(event, handler) { if (typeof window === "undefined") return; const list = this._handlers.get(event); if (!list) return; const remaining = []; list.forEach(({ original, wrapper }) => { if (original === handler) { this._eventTarget.removeEventListener(event, wrapper); } else { remaining.push({ original, wrapper }); } }); if (remaining.length) { this._handlers.set(event, remaining); } else { this._handlers.delete(event); } } /** * Clean up the Monocle script and all associated resources. */ destroy() { var _a, _b; if (typeof window === "undefined" || !this._initialized) return; (_b = (_a = this._script) == null ? void 0 : _a.parentNode) == null ? void 0 : _b.removeChild(this._script); document.head.querySelectorAll("script").forEach((s) => { if (s.src.includes("mcl.spur.us")) s.remove(); }); delete window._onAssessment; delete window.MCL; if (this._eventTarget) { this._handlers.forEach((arr, event) => { arr.forEach(({ wrapper }) => this._eventTarget.removeEventListener(event, wrapper)); }); } this._eventTarget = null; this._monocle = null; this._script = null; this._handlers.clear(); this._initialized = false; this._readyPromise = null; } }; //# sourceMappingURL=index.cjs.map