diff --git a/package.json b/package.json index 4bfa92b..e81cda8 100644 --- a/package.json +++ b/package.json @@ -19,5 +19,6 @@ "hooks": { "pre-commit": "npm run lint" } - } + }, + "packageManager": "pnpm@10.28.0+sha512.05df71d1421f21399e053fde567cea34d446fa02c76571441bfc1c7956e98e363088982d940465fd34480d4d90a0668bc12362f8aa88000a64e83d0b0e47be48" } diff --git a/products/userale/packages/flagon-userale-ext/src/background/messages/config_change.ts b/products/userale/packages/flagon-userale-ext/src/background/messages/config_change.ts index ec6b7c1..eecc7d5 100644 --- a/products/userale/packages/flagon-userale-ext/src/background/messages/config_change.ts +++ b/products/userale/packages/flagon-userale-ext/src/background/messages/config_change.ts @@ -32,6 +32,23 @@ const handler: PlasmoMessaging.MessageHandler = async (req, res) => { export function setOptions(options: StoredOptions) { userale.options({ url: options.loggingUrl }) allowListRegExp = new RegExp(options.allowList) + + switch (options.authMode) { + case "oauth": + userale.options({ + authHeader: options.accessToken ? `Bearer ${options.accessToken}` : null, + apiKey: null + }) + break + case "apikey": + userale.options({ + authHeader: null, + apiKey: options.apiKey || null + }) + break + default: + userale.options({ authHeader: null, apiKey: null }) + } } export function getAllowListRegExp() { diff --git a/products/userale/packages/flagon-userale-ext/src/options/auth.tsx b/products/userale/packages/flagon-userale-ext/src/options/auth.tsx index eea931a..9e26855 100644 --- a/products/userale/packages/flagon-userale-ext/src/options/auth.tsx +++ b/products/userale/packages/flagon-userale-ext/src/options/auth.tsx @@ -18,16 +18,47 @@ */ import pkceChallenge from "pkce-challenge" -import { useState } from "react" +import { useEffect, useState } from "react" import browser from "webextension-polyfill" -import { setStoredOptions } from "~/utils/storage" +import { getStoredOptions, setStoredOptions } from "~/utils/storage" +import type { StoredOptions } from "~/utils/storage" function Auth() { + const [authMode, setAuthMode] = useState("none") + const [apiKey, setApiKey] = useState("") const [issuerUrl, setIssuerUrl] = useState("") const [clientId, setClientId] = useState("") const [message, setMessage] = useState("") + useEffect(() => { + getStoredOptions().then((opts) => { + setAuthMode(opts.authMode) + setApiKey(opts.apiKey) + }) + }, []) + + const handleAuthModeChange = async ( + mode: StoredOptions["authMode"] + ) => { + setAuthMode(mode) + setMessage("") + if (mode === "none") { + await setStoredOptions({ authMode: "none", accessToken: "", apiKey: "" }) + setApiKey("") + setMessage("Auth disabled.") + } + } + + const handleSaveApiKey = async () => { + await setStoredOptions({ + authMode: "apikey", + apiKey, + accessToken: "" + }) + setMessage("API key saved.") + } + const handleLogin = async () => { try { // Generate the PKCE challenge pair (code_verifier and code_challenge) @@ -74,7 +105,11 @@ function Auth() { ) const tokens = await tokenRes.json() - await setStoredOptions({ accessToken: tokens.access_token }) + await setStoredOptions({ + authMode: "oauth", + accessToken: tokens.access_token, + apiKey: "" + }) setMessage("Login successful!") } catch (err) { @@ -85,32 +120,91 @@ function Auth() { return (
-

OAuth Login

-
-
- +

Authentication

+
+
-
- + None + + + +
+ + {authMode === "oauth" && ( +
+

OAuth Login

+ +
+ + setIssuerUrl(e.target.value)} + placeholder="https://issuer.com/realms/myrealm" + required + /> +
+
+ + setClientId(e.target.value)} + placeholder="your-client-id" + required + /> +
+
+ +
+
-
- + )} + + {authMode === "apikey" && ( +
+

API Key

+
+ + setApiKey(e.target.value)} + placeholder="Enter your API key" + /> +
+
+ +
- + )} + {message &&

{message}

}
) diff --git a/products/userale/packages/flagon-userale-ext/src/utils/storage.ts b/products/userale/packages/flagon-userale-ext/src/utils/storage.ts index a8be357..8a61659 100644 --- a/products/userale/packages/flagon-userale-ext/src/utils/storage.ts +++ b/products/userale/packages/flagon-userale-ext/src/utils/storage.ts @@ -23,6 +23,8 @@ import { sendToBackground } from "@plasmohq/messaging" export const STORAGE_KEYS = { accessToken: "accessToken", + apiKey: "apiKey", + authMode: "authMode", allowList: "allowList", loggingUrl: "loggingUrl" } as const @@ -31,12 +33,16 @@ export type StorageKeys = keyof typeof STORAGE_KEYS export type StoredOptions = { accessToken: string + apiKey: string + authMode: "oauth" | "apikey" | "none" allowList: string loggingUrl: string } const DEFAULT_OPTIONS: StoredOptions = { accessToken: "", + apiKey: "", + authMode: "none", allowList: "https://flagon.apache.org/", loggingUrl: "http://localhost:8000" } @@ -48,6 +54,8 @@ export async function getStoredOptions(): Promise { return { accessToken: stored.accessToken ?? DEFAULT_OPTIONS.accessToken, + apiKey: stored.apiKey ?? DEFAULT_OPTIONS.apiKey, + authMode: stored.authMode ?? DEFAULT_OPTIONS.authMode, allowList: stored.allowList ?? DEFAULT_OPTIONS.allowList, loggingUrl: stored.loggingUrl ?? DEFAULT_OPTIONS.loggingUrl } @@ -57,8 +65,8 @@ export async function getStoredOptions(): Promise { export async function setStoredOptions(values: Partial) { // Validate the new options try { - new RegExp(values.allowList) - new URL(values.loggingUrl) + if (values.allowList !== undefined) new RegExp(values.allowList) + if (values.loggingUrl !== undefined) new URL(values.loggingUrl) } catch (error) { return error } diff --git a/products/userale/packages/flagon-userale/build/attachHandlers.d.ts.map b/products/userale/packages/flagon-userale/build/attachHandlers.d.ts.map new file mode 100644 index 0000000..d0e678b --- /dev/null +++ b/products/userale/packages/flagon-userale/build/attachHandlers.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"attachHandlers.d.ts","sourceRoot":"","sources":["../src/attachHandlers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAkB5C;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,UAAU;;;;;;EAShD;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,aAAa;;;;;;;EAStD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,UAAU;;EAIhD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,MAAM,CAAC,WAAW;;EAIzD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,UAAU;;;;EAMhD;AAED;;GAEG;AACH,wBAAgB,oBAAoB;;;EAKnC;AAED;;GAEG;AACH,wBAAgB,oBAAoB;;;EAKnC;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,QAAQ,CAAC,aAAa,GAAG,IAAI,CA+BlE;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,QAAQ,CAAC,aAAa,EAC/B,IAAI,EAAE,MAAM,CAAC,aAAa,GACzB,OAAO,CAAC,qBAAqB,GAAG,IAAI,GAAG,SAAS,CA0BlD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAwE7D"} \ No newline at end of file diff --git a/products/userale/packages/flagon-userale/build/configure.d.ts b/products/userale/packages/flagon-userale/build/configure.d.ts index 488f922..fde1428 100644 --- a/products/userale/packages/flagon-userale/build/configure.d.ts +++ b/products/userale/packages/flagon-userale/build/configure.d.ts @@ -18,6 +18,7 @@ import type { Settings } from "@/types"; export declare class Configuration { [key: string]: Settings.ConfigValueTypes; private static instance; + apiKey: Settings.ApiKey; autostart: boolean; authHeader: Settings.AuthHeader; browserSessionId: Settings.SessionId; diff --git a/products/userale/packages/flagon-userale/build/configure.d.ts.map b/products/userale/packages/flagon-userale/build/configure.d.ts.map new file mode 100644 index 0000000..efb706f --- /dev/null +++ b/products/userale/packages/flagon-userale/build/configure.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGxC,qBAAa,aAAa;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAC,gBAAgB,CAAC;IAEzC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA8B;IAG9C,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAQ;IAC/B,SAAS,EAAE,OAAO,CAAS;IAC3B,UAAU,EAAE,QAAQ,CAAC,UAAU,CAAQ;IACvC,gBAAgB,EAAE,QAAQ,CAAC,SAAS,CAAQ;IAC5C,SAAS,EAAE,QAAQ,CAAC,WAAW,CAAQ;IACvC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAQ;IACjC,aAAa,EAAE,QAAQ,CAAC,SAAS,CAAQ;IACzC,iBAAiB,EAAE,MAAM,CAAK;IAC9B,UAAU,EAAE,OAAO,CAAS;IAC5B,EAAE,EAAE,OAAO,CAAS;IACpB,UAAU,EAAE,MAAM,CAAK;IACvB,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAQ;IACrC,IAAI,EAAE,QAAQ,CAAC,YAAY,CAAoB;IAC/C,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAQ;IACnC,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAQ;IACrC,gBAAgB,EAAE,MAAM,CAAK;IAC7B,GAAG,EAAE,MAAM,CAAM;IACjB,cAAc,EAAE,QAAQ,CAAC,cAAc,CAAQ;IAC/C,cAAc,EAAE,QAAQ,CAAC,OAAO,CAAQ;IACxC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAQ;IAC/B,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAQ;IACjC,iBAAiB,EAAE,OAAO,CAAS;IAG1C,OAAO;WAQO,WAAW,IAAI,aAAa;IAO1C,OAAO,CAAC,UAAU;IAKlB;;OAEG;IACI,KAAK,IAAI,IAAI;IAIpB;;;;OAIG;IACI,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI;IAyBxD;;;;OAIG;WACW,mBAAmB,CAAC,KAAK,EAAE,MAAM;CAUhD"} \ No newline at end of file diff --git a/products/userale/packages/flagon-userale/build/getInitialSettings.d.ts.map b/products/userale/packages/flagon-userale/build/getInitialSettings.d.ts.map new file mode 100644 index 0000000..553fe00 --- /dev/null +++ b/products/userale/packages/flagon-userale/build/getInitialSettings.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"getInitialSettings.d.ts","sourceRoot":"","sources":["../src/getInitialSettings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAKxC;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,QAAQ,CAAC,MAAM,CA8EpD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,OAO1D;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC,YAAY,CA+B9D"} \ No newline at end of file diff --git a/products/userale/packages/flagon-userale/build/main.d.ts.map b/products/userale/packages/flagon-userale/build/main.d.ts.map new file mode 100644 index 0000000..f8cdae1 --- /dev/null +++ b/products/userale/packages/flagon-userale/build/main.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAkBH,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAWjD,eAAO,IAAI,OAAO,SAAQ,CAAC;AAC3B,OAAO,EAAE,mBAAmB,IAAI,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,oBAAoB,IAAI,oBAAoB,EAAE,MAAM,SAAS,CAAC;AACvE,OAAO,EACL,YAAY,IAAI,YAAY,EAC5B,eAAe,IAAI,eAAe,EAClC,UAAU,IAAI,UAAU,EACxB,gBAAgB,IAAI,gBAAgB,EACpC,WAAW,IAAI,WAAW,EAC1B,SAAS,IAAI,SAAS,GACvB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAmDvC,eAAO,MAAM,OAAO,QAAiB,CAAC;AAEtC;;;GAGG;AACH,wBAAgB,KAAK,IAAI,IAAI,CAK5B;AAED;;GAEG;AACH,wBAAgB,IAAI,IAAI,IAAI,CAG3B;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CACrB,SAAS,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,SAAS,GAC9C,QAAQ,CAAC,MAAM,CAMjB;AAED;;;;GAIG;AACH,wBAAgB,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,GAAG,SAAS,WAO3D"} \ No newline at end of file diff --git a/products/userale/packages/flagon-userale/build/main.global.js b/products/userale/packages/flagon-userale/build/main.global.js index 043d727..9b3e5d8 100644 --- a/products/userale/packages/flagon-userale/build/main.global.js +++ b/products/userale/packages/flagon-userale/build/main.global.js @@ -537,6 +537,7 @@ function getInitialSettings() { if (typeof WorkerGlobalScope !== "undefined" && self instanceof WorkerGlobalScope) { const settings2 = { + apiKey: null, authHeader: null, autostart: true, browserSessionId: null, @@ -579,6 +580,7 @@ }; const headers = get("data-headers"); const settings = { + apiKey: get("data-api-key") || null, authHeader: get("data-auth") || null, autostart: get("data-autostart") === "false" ? false : true, browserSessionId: null, @@ -644,6 +646,7 @@ // src/configure.ts var _Configuration = class { constructor() { + this.apiKey = null; this.autostart = false; this.authHeader = null; this.browserSessionId = null; @@ -756,6 +759,9 @@ if (config3.authHeader) { headers.set("Authorization", config3.authHeader.toString()); } + if (config3.apiKey) { + headers.set("x-api-key", config3.apiKey); + } fetch(config3.url, { keepalive: true, method: "POST", @@ -784,6 +790,9 @@ const authHeaderValue = typeof config3.authHeader === "function" ? config3.authHeader() : config3.authHeader; headers.set("Authorization", authHeaderValue); } + if (config3.apiKey) { + headers.set("x-api-key", config3.apiKey); + } updateCustomHeaders(config3); if (config3.headers) { for (const [header, value] of Object.entries(config3.headers)) { diff --git a/products/userale/packages/flagon-userale/build/main.global.js.map b/products/userale/packages/flagon-userale/build/main.global.js.map index 26355dc..b361123 100644 --- a/products/userale/packages/flagon-userale/build/main.global.js.map +++ b/products/userale/packages/flagon-userale/build/main.global.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/packageLogs.ts","../src/attachHandlers.ts","../src/utils/auth/index.ts","../src/utils/headers/index.ts","../src/getInitialSettings.ts","../src/configure.ts","../src/sendLogs.ts","../src/main.ts"],"sourcesContent":["/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Callbacks, Logging } from \"@/types\";\nimport { Configuration } from \"@/configure\";\n\nexport let logs: Array;\nlet config: Configuration;\n\n// Interval Logging Globals\nlet intervalId: string | null;\nlet intervalType: string | null;\nlet intervalPath: string[] | null;\nlet intervalTimer: number | null;\nlet intervalCounter: number | null;\nlet intervalLog: Logging.Log | null;\n\nexport const filterHandler: CallableFunction | null = null;\nexport const mapHandler: CallableFunction | null = null;\nexport let cbHandlers: Callbacks.CallbackMap = {};\n\n/**\n * Adds named callbacks to be executed when logging.\n * @param {Object } newCallbacks An object containing named callback functions.\n */\nexport function addCallbacks(\n ...newCallbacks: Record[]\n) {\n newCallbacks.forEach((source) => {\n let descriptors: { [key in string | symbol]: any } = {};\n\n descriptors = Object.keys(source).reduce((descriptors, key) => {\n descriptors[key] = Object.getOwnPropertyDescriptor(source, key);\n return descriptors;\n }, descriptors);\n\n Object.getOwnPropertySymbols(source).forEach((sym) => {\n const descriptor = Object.getOwnPropertyDescriptor(source, sym);\n if (descriptor?.enumerable) {\n descriptors[sym] = descriptor;\n }\n });\n Object.defineProperties(cbHandlers, descriptors);\n });\n return cbHandlers;\n}\n\n/**\n * Removes callbacks by name.\n * @param {String[]} targetKeys A list of names of functions to remove.\n */\nexport function removeCallbacks(targetKeys: string[]) {\n targetKeys.forEach((key) => {\n if (Object.prototype.hasOwnProperty.call(cbHandlers, key)) {\n delete cbHandlers[key];\n }\n });\n}\n\n/**\n * Assigns the config and log container to be used by the logging functions.\n * @param {Array} newLogs Log container.\n * @param {Object} newConfig Configuration to use while logging.\n */\nexport function initPackager(\n newLogs: Array,\n newConfig: Configuration,\n) {\n logs = newLogs;\n config = newConfig;\n cbHandlers = {};\n intervalId = null;\n intervalType = null;\n intervalPath = null;\n intervalTimer = null;\n intervalCounter = 0;\n intervalLog = null;\n}\n\n/**\n * Transforms the provided HTML event into a log and appends it to the log queue.\n * @param {Event} e The event to be logged.\n * @param {Function} detailFcn The function to extract additional log parameters from the event.\n * @return {boolean} Whether the event was logged.\n */\nexport function packageLog(\n e: Event,\n detailFcn?: Logging.DynamicDetailFunction | null,\n) {\n if (!config.on) {\n return false;\n }\n\n let details = null;\n if (detailFcn) {\n details = detailFcn(e);\n }\n\n const timeFields = extractTimeFields(\n e.timeStamp && e.timeStamp > 0 ? config.time(e.timeStamp) : Date.now(),\n );\n\n let log: Logging.Log = {\n target: e.target ? getSelector(e.target) : null,\n path: buildPath(e),\n pageUrl: self.location.href,\n pageTitle: document.title,\n pageReferrer: document.referrer,\n userAgent: self.navigator.userAgent,\n clientTime: timeFields.milli,\n microTime: timeFields.micro,\n location: getLocation(e),\n scrnRes: getScreenRes(),\n type: e.type,\n logType: \"raw\",\n userAction: true,\n details: details,\n userId: config.userId,\n toolVersion: config.toolVersion,\n toolName: config.toolName,\n useraleVersion: config.useraleVersion,\n sessionId: config.sessionId,\n httpSessionId: config.httpSessionId,\n browserSessionId: config.browserSessionId,\n attributes: buildAttrs(e),\n style: buildCSS(e),\n };\n\n if (typeof filterHandler === \"function\" && !filterHandler(log)) {\n return false;\n }\n\n if (typeof mapHandler === \"function\") {\n log = mapHandler(log, e);\n }\n\n for (const func of Object.values(cbHandlers)) {\n if (typeof func === \"function\") {\n log = func(log, e);\n if (!log) {\n return false;\n }\n }\n }\n\n logs.push(log);\n return true;\n}\n\n/**\n * Packages the provided customLog to include standard meta data and appends it to the log queue.\n * @param {Logging.CustomLog} customLog The behavior to be logged.\n * @param {Logging.DynamicDetailFunction} detailFcn The function to extract additional log parameters from the event.\n * @param {boolean} userAction Indicates user behavior (true) or system behavior (false)\n * @return {boolean} Whether the event was logged.\n */\nexport function packageCustomLog(\n customLog: Logging.CustomLog,\n detailFcn: Logging.DynamicDetailFunction | Logging.StaticDetailFunction,\n userAction: boolean,\n): boolean {\n if (!config.on) {\n return false;\n }\n\n let details = null;\n if (detailFcn.length === 0) {\n // In the case of a union, the type checker will default to the more stringent\n // type, i.e. the DetailFunction that expects an argument for safety purposes.\n // To avoid this, we must explicitly check the type by asserting it receives\n // no arguments (detailFcn.length === 0) and then cast it to the\n // StaticDetailFunction type.\n const staticDetailFcn = detailFcn as Logging.StaticDetailFunction;\n details = staticDetailFcn();\n }\n\n const metaData = {\n pageUrl: self.location.href,\n pageTitle: document.title,\n pageReferrer: document.referrer,\n userAgent: self.navigator.userAgent,\n clientTime: Date.now(),\n scrnRes: getScreenRes(),\n logType: \"custom\",\n userAction: userAction,\n details: details,\n userId: config.userId,\n toolVersion: config.toolVersion,\n toolName: config.toolName,\n useraleVersion: config.useraleVersion,\n sessionId: config.sessionId,\n httpSessionId: config.httpSessionId,\n browserSessionId: config.browserSessionId,\n };\n\n let log = Object.assign(metaData, customLog);\n\n if (typeof filterHandler === \"function\" && !filterHandler(log)) {\n return false;\n }\n\n if (typeof mapHandler === \"function\") {\n log = mapHandler(log);\n }\n\n for (const func of Object.values(cbHandlers)) {\n if (typeof func === \"function\") {\n log = func(log, null);\n if (!log) {\n return false;\n }\n }\n }\n\n logs.push(log);\n\n return true;\n}\n\n/**\n * Extract the millisecond and microsecond portions of a timestamp.\n * @param {Number} timeStamp The timestamp to split into millisecond and microsecond fields.\n * @return {Object} An object containing the millisecond\n * and microsecond portions of the timestamp.\n */\nexport function extractTimeFields(timeStamp: number) {\n return {\n milli: Math.floor(timeStamp),\n micro: Number((timeStamp % 1).toFixed(3)),\n };\n}\n\n/**\n * Track intervals and gather details about it.\n * @param {Object} e\n * @return boolean\n */\nexport function packageIntervalLog(e: Event) {\n try {\n const target = e.target ? getSelector(e.target) : null;\n const path = buildPath(e);\n const type = e.type;\n const timestamp = Math.floor(\n e.timeStamp && e.timeStamp > 0 ? config.time(e.timeStamp) : Date.now(),\n );\n\n // Init - this should only happen once on initialization\n if (intervalId == null) {\n intervalId = target;\n intervalType = type;\n intervalPath = path;\n intervalTimer = timestamp;\n intervalCounter = 0;\n }\n\n if ((intervalId !== target || intervalType !== type) && intervalTimer) {\n // When to create log? On transition end\n // @todo Possible for intervalLog to not be pushed in the event the interval never ends...\n\n intervalLog = {\n target: intervalId,\n path: intervalPath,\n pageUrl: self.location.href,\n pageTitle: document.title,\n pageReferrer: document.referrer,\n userAgent: self.navigator.userAgent,\n count: intervalCounter,\n duration: timestamp - intervalTimer, // microseconds\n startTime: intervalTimer,\n endTime: timestamp,\n type: intervalType,\n logType: \"interval\",\n targetChange: intervalId !== target,\n typeChange: intervalType !== type,\n userAction: false,\n userId: config.userId,\n toolVersion: config.toolVersion,\n toolName: config.toolName,\n useraleVersion: config.useraleVersion,\n sessionId: config.sessionId,\n httpSessionId: config.httpSessionId,\n browserSessionId: config.browserSessionId,\n };\n\n if (typeof filterHandler === \"function\" && !filterHandler(intervalLog)) {\n return false;\n }\n\n if (typeof mapHandler === \"function\") {\n intervalLog = mapHandler(intervalLog, e);\n }\n\n for (const func of Object.values(cbHandlers)) {\n if (typeof func === \"function\") {\n intervalLog = func(intervalLog, null);\n if (!intervalLog) {\n return false;\n }\n }\n }\n\n if (intervalLog) logs.push(intervalLog);\n\n // Reset\n intervalId = target;\n intervalType = type;\n intervalPath = path;\n intervalTimer = timestamp;\n intervalCounter = 0;\n }\n\n // Interval is still occuring, just update counter\n if (intervalId == target && intervalType == type && intervalCounter) {\n intervalCounter = intervalCounter + 1;\n }\n\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Extracts coordinate information from the event\n * depending on a few browser quirks.\n * @param {Event} e The event to extract coordinate information from.\n * @return {Object} An object containing nullable x and y coordinates for the event.\n */\nexport function getLocation(e: Event) {\n if (e instanceof MouseEvent) {\n if (e.pageX != null) {\n return { x: e.pageX, y: e.pageY };\n } else if (e.clientX != null) {\n return {\n x: document.documentElement.scrollLeft + e.clientX,\n y: document.documentElement.scrollTop + e.clientY,\n };\n }\n } else {\n return { x: null, y: null };\n }\n}\n\n/**\n * Extracts innerWidth and innerHeight to provide estimates of screen resolution\n * @return {Object} An object containing the innerWidth and InnerHeight\n */\nexport function getScreenRes() {\n return { width: self.innerWidth, height: self.innerHeight };\n}\n\n/**\n * Builds a string CSS selector from the provided element\n * @param {EventTarget} ele The element from which the selector is built.\n * @return {string} The CSS selector for the element, or Unknown if it can't be determined.\n */\nexport function getSelector(ele: EventTarget) {\n if (ele instanceof HTMLElement || ele instanceof Element) {\n if (ele.localName) {\n return (\n ele.localName +\n (ele.id ? \"#\" + ele.id : \"\") +\n (ele.className ? \".\" + ele.className : \"\")\n );\n } else if (ele.nodeName) {\n return (\n ele.nodeName +\n (ele.id ? \"#\" + ele.id : \"\") +\n (ele.className ? \".\" + ele.className : \"\")\n );\n }\n } else if (ele instanceof Document) {\n return \"#document\";\n } else if (ele === globalThis) {\n return \"Window\";\n }\n return \"Unknown\";\n}\n\n/**\n * Builds an array of elements from the provided event target, to the root element.\n * @param {Event} e Event from which the path should be built.\n * @return {HTMLElement[]} Array of elements, starting at the event target, ending at the root element.\n */\nexport function buildPath(e: Event) {\n const path = e.composedPath();\n return selectorizePath(path);\n}\n\n/**\n * Builds a CSS selector path from the provided list of elements.\n * @param {EventTarget[]} path Array of HTML Elements from which the path should be built.\n * @return {string[]} Array of string CSS selectors.\n */\nexport function selectorizePath(path: EventTarget[]) {\n let i = 0;\n let pathEle;\n const pathSelectors: string[] = [];\n while ((pathEle = path[i])) {\n pathSelectors.push(getSelector(pathEle));\n ++i;\n pathEle = path[i];\n }\n return pathSelectors;\n}\n\n/**\n * Builds an object containing attributes of an element.\n * Attempts to parse all attribute values as JSON text.\n * @param {Event} e Event from which the target element's attributes should be extracted.\n * @return {Record} Object with element attributes as key-value pairs.\n */\nexport function buildAttrs(e: Event): Record {\n const attributes: Record = {};\n const attributeBlackList = [\"style\"];\n\n if (e.target && e.target instanceof Element) {\n for (const attr of e.target.attributes) {\n if (attributeBlackList.includes(attr.name)) continue;\n let val: any = attr.value;\n try {\n val = JSON.parse(val);\n } catch {\n // Ignore parsing errors, fallback to raw string value\n }\n attributes[attr.name] = val;\n }\n }\n\n return attributes;\n}\n\n/**\n * Builds an object containing all CSS properties of an element.\n * @param {Event} e Event from which the target element's properties should be extracted.\n * @return {Record} Object with all CSS properties as key-value pairs.\n */\nexport function buildCSS(e: Event): Record {\n const properties: Record = {};\n if (e.target && e.target instanceof HTMLElement) {\n const styleObj = e.target.style;\n for (let i = 0; i < styleObj.length; i++) {\n const prop = styleObj[i];\n properties[prop] = styleObj.getPropertyValue(prop);\n }\n }\n return properties;\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { packageLog, packageIntervalLog } from \"@/packageLogs\";\nimport { Events, Logging, Settings } from \"@/types\";\nimport { Configuration } from \"@/configure\";\n\n//@todo: Investigate drag events and their behavior\nlet events: Events.EventDetailsMap;\nlet bufferBools: Events.EventBoolMap;\nlet bufferedEvents: Events.EventDetailsMap;\nlet refreshEvents: Events.EventDetailsMap;\nconst intervalEvents: Array = [\n \"click\",\n \"focus\",\n \"blur\",\n \"input\",\n \"change\",\n \"mouseover\",\n \"submit\",\n];\nconst windowEvents: Array = [\"load\", \"blur\", \"focus\"];\n\n/**\n * Maps a MouseEvent to an object containing useful information.\n * @param {MouseEvent} e Event to extract data from\n */\nexport function extractMouseDetails(e: MouseEvent) {\n return {\n clicks: e.detail,\n ctrl: e.ctrlKey,\n alt: e.altKey,\n shift: e.shiftKey,\n meta: e.metaKey,\n // 'text' : e.target.innerHTML\n };\n}\n\n/** Maps a KeyboardEvent to an object containing useful infromation\n * @param {KeyboardEvent} e Event to extract data from\n */\nexport function extractKeyboardDetails(e: KeyboardEvent) {\n return {\n key: e.key,\n code: e.code,\n ctrl: e.ctrlKey,\n alt: e.altKey,\n shift: e.shiftKey,\n meta: e.metaKey,\n };\n}\n\n/**\n * Maps an InputEvent to an object containing useful information.\n * @param {InputEvent} e Event to extract data from\n */\nexport function extractInputDetails(e: InputEvent) {\n return {\n value: (e.target as HTMLInputElement).value,\n };\n}\n\n/**\n * Maps a ChangeEvent to an object containing useful information.\n * @param {Events.ChangeEvent} e Event to extract data from\n */\nexport function extractChangeDetails(e: Events.ChangeEvent) {\n return {\n value: e.target.value,\n };\n}\n\n/**\n * Maps a WheelEvent to an object containing useful information.\n * @param {WheelEvent} e Event to extract data from\n */\nexport function extractWheelDetails(e: WheelEvent) {\n return {\n x: e.deltaX,\n y: e.deltaY,\n z: e.deltaZ,\n };\n}\n\n/**\n * Maps a ScrollEvent to an object containing useful information.\n */\nexport function extractScrollDetails() {\n return {\n x: window.scrollX,\n y: window.scrollY,\n };\n}\n\n/**\n * Maps a ResizeEvent to an object containing useful information.\n */\nexport function extractResizeDetails() {\n return {\n width: window.outerWidth,\n height: window.outerHeight,\n };\n}\n\n/**\n * Defines the way information is extracted from various events.\n * Also defines which events we will listen to.\n * @param {Settings.Config} config Configuration object to read from.\n */\nexport function defineDetails(config: Settings.DefaultConfig): void {\n // Events list\n // Keys are event types\n // Values are functions that return details object if applicable\n events = {\n click: extractMouseDetails,\n dblclick: extractMouseDetails,\n mousedown: extractMouseDetails,\n mouseup: extractMouseDetails,\n focus: null,\n blur: null,\n input: config.logDetails ? extractKeyboardDetails : null,\n change: config.logDetails ? extractChangeDetails : null,\n dragstart: null,\n dragend: null,\n drag: null,\n drop: null,\n keydown: config.logDetails ? extractKeyboardDetails : null,\n mouseover: null,\n };\n\n bufferBools = {};\n bufferedEvents = {\n wheel: extractWheelDetails,\n scroll: extractScrollDetails,\n resize: extractResizeDetails,\n };\n\n refreshEvents = {\n submit: null,\n };\n}\n\n/**\n * Defines the way information is extracted from various events.\n * Also defines which events we will listen to.\n * @param {Settings.Config} options UserALE Configuration object to read from.\n * @param {Events.AllowedEvents} type of html event (e.g., 'click', 'mouseover', etc.), such as passed to addEventListener methods.\n */\nexport function defineCustomDetails(\n options: Settings.DefaultConfig,\n type: Events.AllowedEvents,\n): Logging.DynamicDetailFunction | null | undefined {\n // Events list\n // Keys are event types\n // Values are functions that return details object if applicable\n const eventType: Events.EventDetailsMap = {\n click: extractMouseDetails,\n dblclick: extractMouseDetails,\n mousedown: extractMouseDetails,\n mouseup: extractMouseDetails,\n focus: null,\n blur: null,\n load: null,\n input: options.logDetails ? extractKeyboardDetails : null,\n change: options.logDetails ? extractChangeDetails : null,\n dragstart: null,\n dragend: null,\n drag: null,\n drop: null,\n keydown: options.logDetails ? extractKeyboardDetails : null,\n mouseover: null,\n wheel: extractWheelDetails,\n scroll: extractScrollDetails,\n resize: extractResizeDetails,\n submit: null,\n };\n return eventType[type];\n}\n\n/**\n * Hooks the event handlers for each event type of interest.\n * @param {Configuration} config Configuration singleton to use.\n * @return {boolean} Whether the operation succeeded\n */\nexport function attachHandlers(config: Configuration): boolean {\n try {\n defineDetails(config);\n\n (Object.keys(events) as Events.AllowedEvents[]).forEach(function (ev) {\n document.addEventListener(\n ev,\n function (e) {\n packageLog(e, events[ev]);\n },\n true,\n );\n });\n\n intervalEvents.forEach(function (ev) {\n document.addEventListener(\n ev,\n function (e) {\n packageIntervalLog(e);\n },\n true,\n );\n });\n\n (Object.keys(bufferedEvents) as Events.BufferedEvents[]).forEach(\n function (ev) {\n bufferBools[ev] = true;\n\n self.addEventListener(\n ev,\n function (e) {\n if (bufferBools[ev]) {\n bufferBools[ev] = false;\n packageLog(e, bufferedEvents[ev]);\n setTimeout(function () {\n bufferBools[ev] = true;\n }, config.resolution);\n }\n },\n true,\n );\n },\n );\n\n (Object.keys(refreshEvents) as Events.RefreshEvents[]).forEach(\n function (ev) {\n document.addEventListener(\n ev,\n function (e) {\n packageLog(e, events[ev]);\n },\n true,\n );\n },\n );\n\n windowEvents.forEach(function (ev) {\n self.addEventListener(\n ev,\n function (e) {\n packageLog(e, function () {\n return { window: true };\n });\n },\n true,\n );\n });\n\n return true;\n } catch {\n return false;\n }\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Configuration } from \"@/configure\";\nimport { Callbacks } from \"@/types\";\n\nexport let authCallback: Callbacks.AuthCallback | null = null;\n\n/**\n * Fetches the most up-to-date auth header string from the auth callback\n * and updates the config object with the new value.\n * @param {Configuration} config Configuration object to be updated.\n * @param {Function} authCallback Callback used to fetch the newest header.\n * @returns {void}\n */\nexport function updateAuthHeader(config: Configuration) {\n if (authCallback) {\n try {\n config.authHeader = authCallback();\n } catch (e) {\n // We should emit the error, but otherwise continue as this could be a temporary issue\n // due to network connectivity or some logic inside the authCallback which is the user's\n // responsibility.\n console.error(`Error encountered while setting the auth header: ${e}`);\n }\n }\n}\n\n/**\n * Registers the provided callback to be used when updating the auth header.\n * @param {Callbacks.AuthCallback} callback Callback used to fetch the newest header. Should return a string.\n * @returns {boolean} Whether the operation succeeded.\n */\nexport function registerAuthCallback(callback: Callbacks.AuthCallback) {\n try {\n verifyCallback(callback);\n authCallback = callback;\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Verify that the provided callback is a function which returns a string\n * @param {Function} callback Callback used to fetch the newest header. Should return a string.\n * @throws {Error} If the callback is not a function or does not return a string.\n * @returns {void}\n */\nexport function verifyCallback(callback: Callbacks.AuthCallback) {\n if (typeof callback !== \"function\") {\n throw new Error(\"Userale auth callback must be a function\");\n }\n const result = callback();\n if (typeof result !== \"string\") {\n throw new Error(\"Userale auth callback must return a string\");\n }\n}\n\n/**\n * Resets the authCallback to null. Used for primarily for testing, but could be used\n * to remove the callback in production.\n * @returns {void}\n */\nexport function resetAuthCallback() {\n authCallback = null;\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Configuration } from \"@/configure\";\nimport { Callbacks } from \"@/types\";\n\nexport let headersCallback: Callbacks.HeadersCallback | null = null;\n\n/**\n * Fetches the most up-to-date custom headers object from the headers callback\n * and updates the config object with the new value.\n * @param {Configuration} config Configuration object to be updated.\n * @param {Callbacks.HeadersCallback} headersCallback Callback used to fetch the newest headers.\n * @returns {void}\n */\nexport function updateCustomHeaders(config: Configuration) {\n if (headersCallback) {\n try {\n config.headers = headersCallback();\n } catch (e) {\n // We should emit the error, but otherwise continue as this could be a temporary issue\n // due to network connectivity or some logic inside the headersCallback which is the user's\n // responsibility.\n console.error(`Error encountered while setting the headers: ${e}`);\n }\n }\n}\n\n/**\n * Registers the provided callback to be used when updating the auth header.\n * @param {Callbacks.HeadersCallback} callback Callback used to fetch the newest headers. Should return an object.\n * @returns {boolean} Whether the operation succeeded.\n */\nexport function registerHeadersCallback(callback: Callbacks.HeadersCallback) {\n try {\n verifyCallback(callback);\n headersCallback = callback;\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Verify that the provided callback is a function which returns a string\n * @param {Callbacks.HeadersCallback} callback Callback used to fetch the newest header. Should return an object.\n * @throws {Error} If the callback is not a function or does not return a string.\n * @returns {void}\n */\nexport function verifyCallback(callback: Callbacks.HeadersCallback) {\n if (typeof callback !== \"function\") {\n throw new Error(\"Userale headers callback must be a function\");\n }\n const result = callback();\n if (typeof result !== \"object\") {\n throw new Error(\"Userale headers callback must return an object\");\n }\n for (const [key, value] of Object.entries(result)) {\n if (typeof key !== \"string\" || typeof value !== \"string\") {\n throw new Error(\n \"Userale header callback must return an object with string keys and values\",\n );\n }\n }\n}\n\n/**\n * Resets the authCallback to null. Used for primarily for testing, but could be used\n * to remove the callback in production.\n * @returns {void}\n */\nexport function resetHeadersCallback() {\n headersCallback = null;\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the 'License'); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an 'AS IS' BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { Settings } from \"./types\";\n\nlet sessionId: string | null = null;\nlet httpSessionId: string | null = null;\n\n/**\n * Extracts the initial configuration settings from the\n * currently executing script tag.\n * @return {Object} The extracted configuration object\n */\nexport function getInitialSettings(): Settings.Config {\n if (\n typeof WorkerGlobalScope !== \"undefined\" &&\n self instanceof WorkerGlobalScope\n ) {\n const settings: Settings.Config = {\n authHeader: null,\n autostart: true,\n browserSessionId: null,\n custIndex: null,\n headers: null,\n httpSessionId: null,\n logCountThreshold: +5,\n logDetails: false,\n resolution: +500,\n sessionId: sessionId,\n time: (ts?: number) => (ts !== undefined ? ts : Date.now()),\n toolName: null,\n toolVersion: null,\n transmitInterval: +5000,\n url: \"http://localhost:8000\",\n useraleVersion: null,\n userFromParams: null,\n userId: null,\n };\n return settings;\n }\n\n if (sessionId === null) {\n sessionId = getsessionId(\n \"userAlesessionId\",\n \"session_\" + String(Date.now()),\n );\n }\n\n if (httpSessionId === null) {\n httpSessionId = getsessionId(\n \"userAleHttpSessionId\",\n generatehttpSessionId(),\n );\n }\n\n const script =\n document.currentScript ||\n (function () {\n const scripts = document.getElementsByTagName(\"script\");\n return scripts[scripts.length - 1];\n })();\n\n const get = script\n ? script.getAttribute.bind(script)\n : function () {\n return null;\n };\n const headers = get(\"data-headers\");\n const settings: Settings.Config = {\n authHeader: get(\"data-auth\") || null,\n autostart: get(\"data-autostart\") === \"false\" ? false : true,\n browserSessionId: null,\n custIndex: get(\"data-index\") || null,\n headers: headers ? JSON.parse(headers) : null,\n httpSessionId: httpSessionId,\n logCountThreshold: +(get(\"data-threshold\") || 5),\n logDetails: get(\"data-log-details\") === \"true\" ? true : false,\n resolution: +(get(\"data-resolution\") || 500),\n sessionId: get(\"data-session\") || sessionId,\n time: timeStampScale(document.createEvent(\"CustomEvent\")),\n toolName: get(\"data-tool\") || null,\n toolVersion: get(\"data-version\") || null,\n transmitInterval: +(get(\"data-interval\") || 5000),\n url: get(\"data-url\") || \"http://localhost:8000\",\n useraleVersion: get(\"data-userale-version\") || null,\n userFromParams: get(\"data-user-from-params\") || null,\n userId: get(\"data-user\") || null,\n };\n return settings;\n}\n\n/**\n * defines sessionId, stores it in sessionStorage, checks to see if there is a sessionId in\n * storage when script is started. This prevents events like 'submit', which refresh page data\n * from refreshing the current user session\n *\n */\nexport function getsessionId(sessionKey: string, value: any) {\n if (self.sessionStorage.getItem(sessionKey) === null) {\n self.sessionStorage.setItem(sessionKey, JSON.stringify(value));\n return value;\n }\n\n return JSON.parse(self.sessionStorage.getItem(sessionKey) || \"\");\n}\n\n/**\n * Creates a function to normalize the timestamp of the provided event.\n * @param {Event} e An event containing a timeStamp property.\n * @return {typeof timeStampScale~tsScaler} The timestamp normalizing function.\n */\nexport function timeStampScale(e: Event): Settings.TimeFunction {\n let tsScaler: Settings.TimeFunction;\n if (e.timeStamp && e.timeStamp > 0) {\n const delta = Date.now() - e.timeStamp;\n /**\n * Returns a timestamp depending on various browser quirks.\n * @param {?Number} ts A timestamp to use for normalization.\n * @return {Number} A normalized timestamp.\n */\n\n if (delta < 0) {\n tsScaler = function () {\n return e.timeStamp / 1000;\n };\n } else if (delta > e.timeStamp) {\n const navStart = performance.timeOrigin;\n tsScaler = function (ts) {\n return ts + navStart;\n };\n } else {\n tsScaler = function (ts) {\n return ts;\n };\n }\n } else {\n tsScaler = function () {\n return Date.now();\n };\n }\n\n return tsScaler;\n}\n\n/**\n * Creates a cryptographiclly random string to represent this http session.\n * @return {String} A random 32 digit hex string\n */\nfunction generatehttpSessionId(): string {\n // 32 digit hex -> 128 bits of info -> 2^64 ~= 10^19 sessions needed for 50% chance of collison\n const len = 32;\n const arr = new Uint8Array(len / 2);\n window.crypto.getRandomValues(arr);\n return Array.from(arr, (dec) => {\n return dec.toString(16).padStart(2, \"0\");\n }).join(\"\");\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getInitialSettings } from \"@/getInitialSettings\";\nimport type { Settings } from \"@/types\";\n\n// Singleton Configuration class\nexport class Configuration {\n [key: string]: Settings.ConfigValueTypes;\n // Private static property to hold the singleton instance\n private static instance: Configuration | null = null;\n\n // Public properties corresponding to fields in the Config interface\n public autostart: boolean = false;\n public authHeader: Settings.AuthHeader = null;\n public browserSessionId: Settings.SessionId = null;\n public custIndex: Settings.CustomIndex = null;\n public headers: Settings.Headers = null;\n public httpSessionId: Settings.SessionId = null;\n public logCountThreshold: number = 0;\n public logDetails: boolean = false;\n public on: boolean = false;\n public resolution: number = 0;\n public sessionId: Settings.SessionId = null;\n public time: Settings.TimeFunction = () => Date.now();\n public toolName: Settings.ToolName = null;\n public toolVersion: Settings.Version = null;\n public transmitInterval: number = 0;\n public url: string = \"\";\n public userFromParams: Settings.UserFromParams = null;\n public useraleVersion: Settings.Version = null;\n public userId: Settings.UserId = null;\n public version: Settings.Version = null;\n public websocketsEnabled: boolean = false;\n\n // Private constructor to prevent external instantiation\n private constructor() {\n // Call the initialization method only if it's the first time instantiating\n if (Configuration.instance === null) {\n this.initialize();\n }\n }\n\n // Static method to get the singleton instance\n public static getInstance(): Configuration {\n if (Configuration.instance === null) {\n Configuration.instance = new Configuration();\n }\n return Configuration.instance;\n }\n\n private initialize(): void {\n const settings = getInitialSettings();\n this.update(settings);\n }\n\n /**\n * Resets the configuration to its initial state.\n */\n public reset(): void {\n this.initialize();\n }\n\n /**\n * Shallow merges a newConfig with the configuration class, updating it.\n * Retrieves/updates the userid if userFromParams is provided.\n * @param {Partial} newConfig Configuration object to merge into the current config.\n */\n public update(newConfig: Partial): void {\n Object.keys(newConfig).forEach((option) => {\n if (option === \"userFromParams\") {\n const userParamString = newConfig[option] as Settings.UserFromParams;\n const userId = userParamString\n ? Configuration.getUserIdFromParams(userParamString)\n : null;\n if (userId) {\n this[\"userId\"] = userId;\n }\n }\n const hasNewUserFromParams = newConfig[\"userFromParams\"];\n const willNullifyUserId =\n option === \"userId\" && newConfig[option] === null;\n if (willNullifyUserId && hasNewUserFromParams) {\n return;\n }\n\n const newOption = newConfig[option];\n if (newOption !== undefined) {\n this[option] = newOption;\n }\n });\n }\n\n /**\n * Attempts to extract the userid from the query parameters of the URL.\n * @param {string} param The name of the query parameter containing the userid.\n * @return {string | null} The extracted/decoded userid, or null if none is found.\n */\n public static getUserIdFromParams(param: string) {\n const userField = param;\n const regex = new RegExp(\"[?&]\" + userField + \"(=([^&#]*)|&|#|$)\");\n const results = window.location.href.match(regex);\n\n if (results && results[2]) {\n return decodeURIComponent(results[2].replace(/\\+/g, \" \"));\n }\n return null;\n }\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Configuration } from \"@/configure\";\nimport { Logging } from \"@/types\";\nimport { updateAuthHeader, updateCustomHeaders } from \"@/utils\";\n\nlet sendIntervalId: string | number | NodeJS.Timeout | undefined;\nlet wsock: WebSocket;\n\n/**\n * Initializes the log queue processors.\n * @param {Array} logs Array of logs to append to.\n * @param {Configuration} config Configuration object to use when logging.\n */\nexport function initSender(logs: Array, config: Configuration) {\n if (sendIntervalId) {\n clearInterval(sendIntervalId);\n }\n\n const url = new URL(config.url);\n if (url.protocol === \"ws:\" || url.protocol === \"wss:\") {\n wsock = new WebSocket(config.url);\n }\n\n sendIntervalId = sendOnInterval(logs, config);\n sendOnClose(logs, config);\n}\n\n/**\n * Checks the provided log array on an interval, flushing the logs\n * if the queue has reached the threshold specified by the provided config.\n * @param {Array} logs Array of logs to read from.\n * @param {Configuration} config Configuration singleton to be read from.\n * @return {Number} The newly created interval id.\n */\nexport function sendOnInterval(\n logs: Array,\n config: Configuration,\n): NodeJS.Timeout {\n return setInterval(function () {\n if (!config.on) {\n return;\n }\n\n if (logs.length >= config.logCountThreshold) {\n sendLogs(logs.slice(0), config, 0); // Send a copy\n logs.splice(0); // Clear array reference (no reassignment)\n }\n }, config.transmitInterval);\n}\n\n// /**\n// * Attempts to flush the remaining logs when the window is closed.\n// * @param {Array} logs Array of logs to be flushed.\n// * @param {Configuration} config Configuration singleton to be read from.\n// */\nexport function sendOnClose(\n logs: Array,\n config: Configuration,\n): void {\n self.addEventListener(\"pagehide\", function () {\n if (!config.on) {\n return;\n }\n\n if (logs.length > 0) {\n const url = new URL(config.url);\n\n if (url.protocol === \"ws:\" || url.protocol === \"wss:\") {\n const data = JSON.stringify(logs);\n wsock.send(data);\n } else {\n const headers: HeadersInit = new Headers();\n headers.set(\"Content-Type\", \"application/json;charset=UTF-8\");\n\n if (config.authHeader) {\n headers.set(\"Authorization\", config.authHeader.toString());\n }\n\n fetch(config.url, {\n keepalive: true,\n method: \"POST\",\n headers: headers,\n body: JSON.stringify(logs),\n }).catch((error) => {\n console.error(error);\n });\n }\n logs.splice(0); // clear log queue\n }\n });\n}\n\n/**\n * Sends the provided array of logs to the specified url,\n * retrying the request up to the specified number of retries.\n * @param {Array} logs Array of logs to send.\n * @param {Configuration} config configuration singleton.\n * @param {Number} retries Maximum number of attempts to send the logs.\n */\nexport async function sendLogs(\n logs: Array,\n config: Configuration,\n retries: number,\n): Promise {\n const data = JSON.stringify(logs);\n const url = new URL(config.url);\n\n if (url.protocol === \"ws:\" || url.protocol === \"wss:\") {\n wsock.send(data);\n return;\n }\n\n // Build headers\n const headers = new Headers({\n \"Content-Type\": \"application/json;charset=UTF-8\",\n });\n\n updateAuthHeader(config);\n if (config.authHeader) {\n const authHeaderValue =\n typeof config.authHeader === \"function\"\n ? config.authHeader()\n : config.authHeader;\n headers.set(\"Authorization\", authHeaderValue);\n }\n\n // Update custom headers last to allow them to over-write the defaults. This assumes\n // the user knows what they are doing and may want to over-write the defaults.\n updateCustomHeaders(config);\n if (config.headers) {\n for (const [header, value] of Object.entries(config.headers)) {\n headers.set(header, value);\n }\n }\n\n async function attemptSend(remainingRetries: number): Promise {\n try {\n const response = await fetch(config.url, {\n method: \"POST\",\n headers,\n body: data,\n });\n\n if (!response.ok) {\n if (remainingRetries > 0) {\n return attemptSend(remainingRetries - 1);\n } else {\n throw new Error(`Failed to send logs: ${response.statusText}`);\n }\n }\n } catch (error) {\n if (remainingRetries > 0) {\n return attemptSend(remainingRetries - 1);\n }\n throw error;\n }\n }\n\n return attemptSend(retries);\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { defineCustomDetails } from \"@/attachHandlers\";\nimport { registerAuthCallback } from \"@/utils\";\nimport {\n addCallbacks,\n removeCallbacks,\n packageLog,\n packageCustomLog,\n getSelector,\n buildPath,\n initPackager,\n} from \"@/packageLogs\";\nimport { version as userAleVersion } from \"../package.json\";\nimport { Configuration } from \"@/configure\";\nimport { attachHandlers } from \"@/attachHandlers\";\nimport { initSender } from \"@/sendLogs\";\n\nimport type { Settings, Logging } from \"@/types\";\n\nconst config = Configuration.getInstance();\nconst logs: Array = [];\n\nconst startLoadTimestamp = Date.now();\nlet endLoadTimestamp: number;\nself.onload = function () {\n endLoadTimestamp = Date.now();\n};\n\nexport let started = false;\nexport { defineCustomDetails as details } from \"@/attachHandlers\";\nexport { registerAuthCallback as registerAuthCallback } from \"@/utils\";\nexport {\n addCallbacks as addCallbacks,\n removeCallbacks as removeCallbacks,\n packageLog as packageLog,\n packageCustomLog as packageCustomLog,\n getSelector as getSelector,\n buildPath as buildPath,\n} from \"@/packageLogs\";\nexport type { Logging } from \"@/types\";\n\nconfig.update({\n useraleVersion: userAleVersion,\n});\ninitPackager(logs, config);\nif (config.autostart) {\n setup(config);\n}\n\n/**\n * Hooks the global event listener, and starts up the\n * logging interval.\n * @param {Configuration} config Configuration settings for the logger\n */\nfunction setup(config: Configuration) {\n if (!started) {\n setTimeout(function () {\n let state;\n try {\n state = document.readyState;\n } catch (error) {\n // Assume there is no DOM and this is a web worker context\n state = \"complete\";\n }\n\n if (\n config.autostart &&\n (state === \"interactive\" || state === \"complete\")\n ) {\n attachHandlers(config);\n initSender(logs, config);\n started = config.on = true;\n if (typeof window !== \"undefined\" && typeof document !== \"undefined\") {\n packageCustomLog(\n {\n type: \"load\",\n details: { pageLoadTime: endLoadTimestamp - startLoadTimestamp },\n },\n () => ({}),\n false,\n );\n }\n } else {\n setup(config);\n }\n }, 100);\n }\n}\n\n// Export the Userale API\nexport const version = userAleVersion;\n\n/**\n * Used to start the logging process if the\n * autostart configuration option is set to false.\n */\nexport function start(): void {\n if (!started || config.autostart === false) {\n started = config.on = true;\n config.update({ autostart: true });\n }\n}\n\n/**\n * Halts the logging process. Logs will no longer be sent.\n */\nexport function stop(): void {\n started = config.on = false;\n config.update({ autostart: false });\n}\n\n/**\n * Updates the current configuration\n * object with the provided values.\n * @param {Partial} newConfig The configuration options to use.\n * @return {Settings.Config} Returns the updated configuration.\n */\nexport function options(\n newConfig: Partial | undefined,\n): Settings.Config {\n if (newConfig) {\n config.update(newConfig);\n }\n\n return config;\n}\n\n/**\n * Appends a log to the log queue.\n * @param {Logging.CustomLog} customLog The log to append.\n * @return {boolean} Whether the operation succeeded.\n */\nexport function log(customLog: Logging.CustomLog | undefined) {\n if (customLog) {\n logs.push(customLog);\n return true;\n } else {\n return false;\n }\n}\n\n// Only attach to window in IIFE builds\nif (typeof window !== \"undefined\") {\n (window as any).userale = {\n start,\n stop,\n options,\n log,\n version: userAleVersion,\n details: defineCustomDetails,\n registerAuthCallback,\n addCallbacks,\n removeCallbacks,\n packageLog,\n packageCustomLog,\n getSelector,\n buildPath,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAoBO,MAAI;AACX,MAAI;AAGJ,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AAEG,MAAM,gBAAyC;AAC/C,MAAM,aAAsC;AAC5C,MAAI,aAAoC,CAAC;AAMzC,WAAS,gBACX,cACH;AACA,iBAAa,QAAQ,CAAC,WAAW;AAC/B,UAAI,cAAiD,CAAC;AAEtD,oBAAc,OAAO,KAAK,MAAM,EAAE,OAAO,CAACA,cAAa,QAAQ;AAC7D,QAAAA,aAAY,OAAO,OAAO,yBAAyB,QAAQ,GAAG;AAC9D,eAAOA;AAAA,MACT,GAAG,WAAW;AAEd,aAAO,sBAAsB,MAAM,EAAE,QAAQ,CAAC,QAAQ;AACpD,cAAM,aAAa,OAAO,yBAAyB,QAAQ,GAAG;AAC9D,YAAI,YAAY,YAAY;AAC1B,sBAAY,OAAO;AAAA,QACrB;AAAA,MACF,CAAC;AACD,aAAO,iBAAiB,YAAY,WAAW;AAAA,IACjD,CAAC;AACD,WAAO;AAAA,EACT;AAMO,WAAS,gBAAgB,YAAsB;AACpD,eAAW,QAAQ,CAAC,QAAQ;AAC1B,UAAI,OAAO,UAAU,eAAe,KAAK,YAAY,GAAG,GAAG;AACzD,eAAO,WAAW;AAAA,MACpB;AAAA,IACF,CAAC;AAAA,EACH;AAOO,WAAS,aACd,SACA,WACA;AACA,WAAO;AACP,aAAS;AACT,iBAAa,CAAC;AACd,iBAAa;AACb,mBAAe;AACf,mBAAe;AACf,oBAAgB;AAChB,sBAAkB;AAClB,kBAAc;AAAA,EAChB;AAQO,WAAS,WACd,GACA,WACA;AACA,QAAI,CAAC,OAAO,IAAI;AACd,aAAO;AAAA,IACT;AAEA,QAAI,UAAU;AACd,QAAI,WAAW;AACb,gBAAU,UAAU,CAAC;AAAA,IACvB;AAEA,UAAM,aAAa;AAAA,MACjB,EAAE,aAAa,EAAE,YAAY,IAAI,OAAO,KAAK,EAAE,SAAS,IAAI,KAAK,IAAI;AAAA,IACvE;AAEA,QAAIC,OAAmB;AAAA,MACrB,QAAQ,EAAE,SAAS,YAAY,EAAE,MAAM,IAAI;AAAA,MAC3C,MAAM,UAAU,CAAC;AAAA,MACjB,SAAS,KAAK,SAAS;AAAA,MACvB,WAAW,SAAS;AAAA,MACpB,cAAc,SAAS;AAAA,MACvB,WAAW,KAAK,UAAU;AAAA,MAC1B,YAAY,WAAW;AAAA,MACvB,WAAW,WAAW;AAAA,MACtB,UAAU,YAAY,CAAC;AAAA,MACvB,SAAS,aAAa;AAAA,MACtB,MAAM,EAAE;AAAA,MACR,SAAS;AAAA,MACT,YAAY;AAAA,MACZ;AAAA,MACA,QAAQ,OAAO;AAAA,MACf,aAAa,OAAO;AAAA,MACpB,UAAU,OAAO;AAAA,MACjB,gBAAgB,OAAO;AAAA,MACvB,WAAW,OAAO;AAAA,MAClB,eAAe,OAAO;AAAA,MACtB,kBAAkB,OAAO;AAAA,MACzB,YAAY,WAAW,CAAC;AAAA,MACxB,OAAO,SAAS,CAAC;AAAA,IACnB;AAEA,QAAI,OAAO,kBAAkB,cAAc,CAAC,cAAcA,IAAG,GAAG;AAC9D,aAAO;AAAA,IACT;AAEA,QAAI,OAAO,eAAe,YAAY;AACpC,MAAAA,OAAM,WAAWA,MAAK,CAAC;AAAA,IACzB;AAEA,eAAW,QAAQ,OAAO,OAAO,UAAU,GAAG;AAC5C,UAAI,OAAO,SAAS,YAAY;AAC9B,QAAAA,OAAM,KAAKA,MAAK,CAAC;AACjB,YAAI,CAACA,MAAK;AACR,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAEA,SAAK,KAAKA,IAAG;AACb,WAAO;AAAA,EACT;AASO,WAAS,iBACd,WACA,WACA,YACS;AACT,QAAI,CAAC,OAAO,IAAI;AACd,aAAO;AAAA,IACT;AAEA,QAAI,UAAU;AACd,QAAI,UAAU,WAAW,GAAG;AAM1B,YAAM,kBAAkB;AACxB,gBAAU,gBAAgB;AAAA,IAC5B;AAEA,UAAM,WAAW;AAAA,MACf,SAAS,KAAK,SAAS;AAAA,MACvB,WAAW,SAAS;AAAA,MACpB,cAAc,SAAS;AAAA,MACvB,WAAW,KAAK,UAAU;AAAA,MAC1B,YAAY,KAAK,IAAI;AAAA,MACrB,SAAS,aAAa;AAAA,MACtB,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,QAAQ,OAAO;AAAA,MACf,aAAa,OAAO;AAAA,MACpB,UAAU,OAAO;AAAA,MACjB,gBAAgB,OAAO;AAAA,MACvB,WAAW,OAAO;AAAA,MAClB,eAAe,OAAO;AAAA,MACtB,kBAAkB,OAAO;AAAA,IAC3B;AAEA,QAAIA,OAAM,OAAO,OAAO,UAAU,SAAS;AAE3C,QAAI,OAAO,kBAAkB,cAAc,CAAC,cAAcA,IAAG,GAAG;AAC9D,aAAO;AAAA,IACT;AAEA,QAAI,OAAO,eAAe,YAAY;AACpC,MAAAA,OAAM,WAAWA,IAAG;AAAA,IACtB;AAEA,eAAW,QAAQ,OAAO,OAAO,UAAU,GAAG;AAC5C,UAAI,OAAO,SAAS,YAAY;AAC9B,QAAAA,OAAM,KAAKA,MAAK,IAAI;AACpB,YAAI,CAACA,MAAK;AACR,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAEA,SAAK,KAAKA,IAAG;AAEb,WAAO;AAAA,EACT;AAQO,WAAS,kBAAkB,WAAmB;AACnD,WAAO;AAAA,MACL,OAAO,KAAK,MAAM,SAAS;AAAA,MAC3B,OAAO,QAAQ,YAAY,GAAG,QAAQ,CAAC,CAAC;AAAA,IAC1C;AAAA,EACF;AAOO,WAAS,mBAAmB,GAAU;AAC3C,QAAI;AACF,YAAM,SAAS,EAAE,SAAS,YAAY,EAAE,MAAM,IAAI;AAClD,YAAM,OAAO,UAAU,CAAC;AACxB,YAAM,OAAO,EAAE;AACf,YAAM,YAAY,KAAK;AAAA,QACrB,EAAE,aAAa,EAAE,YAAY,IAAI,OAAO,KAAK,EAAE,SAAS,IAAI,KAAK,IAAI;AAAA,MACvE;AAGA,UAAI,cAAc,MAAM;AACtB,qBAAa;AACb,uBAAe;AACf,uBAAe;AACf,wBAAgB;AAChB,0BAAkB;AAAA,MACpB;AAEA,WAAK,eAAe,UAAU,iBAAiB,SAAS,eAAe;AAIrE,sBAAc;AAAA,UACZ,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,SAAS,KAAK,SAAS;AAAA,UACvB,WAAW,SAAS;AAAA,UACpB,cAAc,SAAS;AAAA,UACvB,WAAW,KAAK,UAAU;AAAA,UAC1B,OAAO;AAAA,UACP,UAAU,YAAY;AAAA,UACtB,WAAW;AAAA,UACX,SAAS;AAAA,UACT,MAAM;AAAA,UACN,SAAS;AAAA,UACT,cAAc,eAAe;AAAA,UAC7B,YAAY,iBAAiB;AAAA,UAC7B,YAAY;AAAA,UACZ,QAAQ,OAAO;AAAA,UACf,aAAa,OAAO;AAAA,UACpB,UAAU,OAAO;AAAA,UACjB,gBAAgB,OAAO;AAAA,UACvB,WAAW,OAAO;AAAA,UAClB,eAAe,OAAO;AAAA,UACtB,kBAAkB,OAAO;AAAA,QAC3B;AAEA,YAAI,OAAO,kBAAkB,cAAc,CAAC,cAAc,WAAW,GAAG;AACtE,iBAAO;AAAA,QACT;AAEA,YAAI,OAAO,eAAe,YAAY;AACpC,wBAAc,WAAW,aAAa,CAAC;AAAA,QACzC;AAEA,mBAAW,QAAQ,OAAO,OAAO,UAAU,GAAG;AAC5C,cAAI,OAAO,SAAS,YAAY;AAC9B,0BAAc,KAAK,aAAa,IAAI;AACpC,gBAAI,CAAC,aAAa;AAChB,qBAAO;AAAA,YACT;AAAA,UACF;AAAA,QACF;AAEA,YAAI;AAAa,eAAK,KAAK,WAAW;AAGtC,qBAAa;AACb,uBAAe;AACf,uBAAe;AACf,wBAAgB;AAChB,0BAAkB;AAAA,MACpB;AAGA,UAAI,cAAc,UAAU,gBAAgB,QAAQ,iBAAiB;AACnE,0BAAkB,kBAAkB;AAAA,MACtC;AAEA,aAAO;AAAA,IACT,QAAE;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAQO,WAAS,YAAY,GAAU;AACpC,QAAI,aAAa,YAAY;AAC3B,UAAI,EAAE,SAAS,MAAM;AACnB,eAAO,EAAE,GAAG,EAAE,OAAO,GAAG,EAAE,MAAM;AAAA,MAClC,WAAW,EAAE,WAAW,MAAM;AAC5B,eAAO;AAAA,UACL,GAAG,SAAS,gBAAgB,aAAa,EAAE;AAAA,UAC3C,GAAG,SAAS,gBAAgB,YAAY,EAAE;AAAA,QAC5C;AAAA,MACF;AAAA,IACF,OAAO;AACL,aAAO,EAAE,GAAG,MAAM,GAAG,KAAK;AAAA,IAC5B;AAAA,EACF;AAMO,WAAS,eAAe;AAC7B,WAAO,EAAE,OAAO,KAAK,YAAY,QAAQ,KAAK,YAAY;AAAA,EAC5D;AAOO,WAAS,YAAY,KAAkB;AAC5C,QAAI,eAAe,eAAe,eAAe,SAAS;AACxD,UAAI,IAAI,WAAW;AACjB,eACE,IAAI,aACH,IAAI,KAAK,MAAM,IAAI,KAAK,OACxB,IAAI,YAAY,MAAM,IAAI,YAAY;AAAA,MAE3C,WAAW,IAAI,UAAU;AACvB,eACE,IAAI,YACH,IAAI,KAAK,MAAM,IAAI,KAAK,OACxB,IAAI,YAAY,MAAM,IAAI,YAAY;AAAA,MAE3C;AAAA,IACF,WAAW,eAAe,UAAU;AAClC,aAAO;AAAA,IACT,WAAW,QAAQ,YAAY;AAC7B,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAOO,WAAS,UAAU,GAAU;AAClC,UAAM,OAAO,EAAE,aAAa;AAC5B,WAAO,gBAAgB,IAAI;AAAA,EAC7B;AAOO,WAAS,gBAAgB,MAAqB;AACnD,QAAI,IAAI;AACR,QAAI;AACJ,UAAM,gBAA0B,CAAC;AACjC,WAAQ,UAAU,KAAK,IAAK;AAC1B,oBAAc,KAAK,YAAY,OAAO,CAAC;AACvC,QAAE;AACF,gBAAU,KAAK;AAAA,IACjB;AACA,WAAO;AAAA,EACT;AAQO,WAAS,WAAW,GAA+B;AACxD,UAAM,aAAkC,CAAC;AACzC,UAAM,qBAAqB,CAAC,OAAO;AAEnC,QAAI,EAAE,UAAU,EAAE,kBAAkB,SAAS;AAC3C,iBAAW,QAAQ,EAAE,OAAO,YAAY;AACtC,YAAI,mBAAmB,SAAS,KAAK,IAAI;AAAG;AAC5C,YAAI,MAAW,KAAK;AACpB,YAAI;AACF,gBAAM,KAAK,MAAM,GAAG;AAAA,QACtB,QAAE;AAAA,QAEF;AACA,mBAAW,KAAK,QAAQ;AAAA,MAC1B;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAOO,WAAS,SAAS,GAAkC;AACzD,UAAM,aAAqC,CAAC;AAC5C,QAAI,EAAE,UAAU,EAAE,kBAAkB,aAAa;AAC/C,YAAM,WAAW,EAAE,OAAO;AAC1B,eAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,cAAM,OAAO,SAAS;AACtB,mBAAW,QAAQ,SAAS,iBAAiB,IAAI;AAAA,MACnD;AAAA,IACF;AACA,WAAO;AAAA,EACT;;;ACvbA,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAM,iBAA+C;AAAA,IACnD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MAAM,eAA2C,CAAC,QAAQ,QAAQ,OAAO;AAMlE,WAAS,oBAAoB,GAAe;AACjD,WAAO;AAAA,MACL,QAAQ,EAAE;AAAA,MACV,MAAM,EAAE;AAAA,MACR,KAAK,EAAE;AAAA,MACP,OAAO,EAAE;AAAA,MACT,MAAM,EAAE;AAAA,IAEV;AAAA,EACF;AAKO,WAAS,uBAAuB,GAAkB;AACvD,WAAO;AAAA,MACL,KAAK,EAAE;AAAA,MACP,MAAM,EAAE;AAAA,MACR,MAAM,EAAE;AAAA,MACR,KAAK,EAAE;AAAA,MACP,OAAO,EAAE;AAAA,MACT,MAAM,EAAE;AAAA,IACV;AAAA,EACF;AAgBO,WAAS,qBAAqB,GAAuB;AAC1D,WAAO;AAAA,MACL,OAAO,EAAE,OAAO;AAAA,IAClB;AAAA,EACF;AAMO,WAAS,oBAAoB,GAAe;AACjD,WAAO;AAAA,MACL,GAAG,EAAE;AAAA,MACL,GAAG,EAAE;AAAA,MACL,GAAG,EAAE;AAAA,IACP;AAAA,EACF;AAKO,WAAS,uBAAuB;AACrC,WAAO;AAAA,MACL,GAAG,OAAO;AAAA,MACV,GAAG,OAAO;AAAA,IACZ;AAAA,EACF;AAKO,WAAS,uBAAuB;AACrC,WAAO;AAAA,MACL,OAAO,OAAO;AAAA,MACd,QAAQ,OAAO;AAAA,IACjB;AAAA,EACF;AAOO,WAAS,cAAcC,SAAsC;AAIlE,aAAS;AAAA,MACP,OAAO;AAAA,MACP,UAAU;AAAA,MACV,WAAW;AAAA,MACX,SAAS;AAAA,MACT,OAAO;AAAA,MACP,MAAM;AAAA,MACN,OAAOA,QAAO,aAAa,yBAAyB;AAAA,MACpD,QAAQA,QAAO,aAAa,uBAAuB;AAAA,MACnD,WAAW;AAAA,MACX,SAAS;AAAA,MACT,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAASA,QAAO,aAAa,yBAAyB;AAAA,MACtD,WAAW;AAAA,IACb;AAEA,kBAAc,CAAC;AACf,qBAAiB;AAAA,MACf,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAEA,oBAAgB;AAAA,MACd,QAAQ;AAAA,IACV;AAAA,EACF;AAQO,WAAS,oBACdC,UACA,MACkD;AAIlD,UAAM,YAA0D;AAAA,MAC9D,OAAO;AAAA,MACP,UAAU;AAAA,MACV,WAAW;AAAA,MACX,SAAS;AAAA,MACT,OAAO;AAAA,MACP,MAAM;AAAA,MACN,MAAM;AAAA,MACN,OAAOA,SAAQ,aAAa,yBAAyB;AAAA,MACrD,QAAQA,SAAQ,aAAa,uBAAuB;AAAA,MACpD,WAAW;AAAA,MACX,SAAS;AAAA,MACT,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAASA,SAAQ,aAAa,yBAAyB;AAAA,MACvD,WAAW;AAAA,MACX,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AACA,WAAO,UAAU;AAAA,EACnB;AAOO,WAAS,eAAeD,SAAgC;AAC7D,QAAI;AACF,oBAAcA,OAAM;AAEpB,MAAC,OAAO,KAAK,MAAM,EAA6B,QAAQ,SAAU,IAAI;AACpE,iBAAS;AAAA,UACP;AAAA,UACA,SAAU,GAAG;AACX,uBAAW,GAAG,OAAO,GAAG;AAAA,UAC1B;AAAA,UACA;AAAA,QACF;AAAA,MACF,CAAC;AAED,qBAAe,QAAQ,SAAU,IAAI;AACnC,iBAAS;AAAA,UACP;AAAA,UACA,SAAU,GAAG;AACX,+BAAmB,CAAC;AAAA,UACtB;AAAA,UACA;AAAA,QACF;AAAA,MACF,CAAC;AAED,MAAC,OAAO,KAAK,cAAc,EAA8B;AAAA,QACvD,SAAU,IAAI;AACZ,sBAAY,MAAM;AAElB,eAAK;AAAA,YACH;AAAA,YACA,SAAU,GAAG;AACX,kBAAI,YAAY,KAAK;AACnB,4BAAY,MAAM;AAClB,2BAAW,GAAG,eAAe,GAAG;AAChC,2BAAW,WAAY;AACrB,8BAAY,MAAM;AAAA,gBACpB,GAAGA,QAAO,UAAU;AAAA,cACtB;AAAA,YACF;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,MAAC,OAAO,KAAK,aAAa,EAA6B;AAAA,QACrD,SAAU,IAAI;AACZ,mBAAS;AAAA,YACP;AAAA,YACA,SAAU,GAAG;AACX,yBAAW,GAAG,OAAO,GAAG;AAAA,YAC1B;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,mBAAa,QAAQ,SAAU,IAAI;AACjC,aAAK;AAAA,UACH;AAAA,UACA,SAAU,GAAG;AACX,uBAAW,GAAG,WAAY;AACxB,qBAAO,EAAE,QAAQ,KAAK;AAAA,YACxB,CAAC;AAAA,UACH;AAAA,UACA;AAAA,QACF;AAAA,MACF,CAAC;AAED,aAAO;AAAA,IACT,QAAE;AACA,aAAO;AAAA,IACT;AAAA,EACF;;;AC1PO,MAAI,eAA8C;AASlD,WAAS,iBAAiBE,SAAuB;AACtD,QAAI,cAAc;AAChB,UAAI;AACF,QAAAA,QAAO,aAAa,aAAa;AAAA,MACnC,SAAS,GAAP;AAIA,gBAAQ,MAAM,oDAAoD,GAAG;AAAA,MACvE;AAAA,IACF;AAAA,EACF;AAOO,WAAS,qBAAqB,UAAkC;AACrE,QAAI;AACF,qBAAe,QAAQ;AACvB,qBAAe;AACf,aAAO;AAAA,IACT,QAAE;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAQO,WAAS,eAAe,UAAkC;AAC/D,QAAI,OAAO,aAAa,YAAY;AAClC,YAAM,IAAI,MAAM,0CAA0C;AAAA,IAC5D;AACA,UAAM,SAAS,SAAS;AACxB,QAAI,OAAO,WAAW,UAAU;AAC9B,YAAM,IAAI,MAAM,4CAA4C;AAAA,IAC9D;AAAA,EACF;;;ACnDO,MAAI,kBAAoD;AASxD,WAAS,oBAAoBC,SAAuB;AACzD,QAAI,iBAAiB;AACnB,UAAI;AACF,QAAAA,QAAO,UAAU,gBAAgB;AAAA,MACnC,SAAS,GAAP;AAIA,gBAAQ,MAAM,gDAAgD,GAAG;AAAA,MACnE;AAAA,IACF;AAAA,EACF;;;;;;ACrBA,MAAI,YAA2B;AAC/B,MAAI,gBAA+B;AAO5B,WAAS,qBAAsC;AACpD,QACE,OAAO,sBAAsB,eAC7B,gBAAgB,mBAChB;AACA,YAAMC,YAA4B;AAAA,QAChC,YAAY;AAAA,QACZ,WAAW;AAAA,QACX,kBAAkB;AAAA,QAClB,WAAW;AAAA,QACX,SAAS;AAAA,QACT,eAAe;AAAA,QACf,mBAAmB;AAAA,QACnB,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ;AAAA,QACA,MAAM,CAAC,OAAiB,OAAO,SAAY,KAAK,KAAK,IAAI;AAAA,QACzD,UAAU;AAAA,QACV,aAAa;AAAA,QACb,kBAAkB;AAAA,QAClB,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,gBAAgB;AAAA,QAChB,QAAQ;AAAA,MACV;AACA,aAAOA;AAAA,IACT;AAEA,QAAI,cAAc,MAAM;AACtB,kBAAY;AAAA,QACV;AAAA,QACA,aAAa,OAAO,KAAK,IAAI,CAAC;AAAA,MAChC;AAAA,IACF;AAEA,QAAI,kBAAkB,MAAM;AAC1B,sBAAgB;AAAA,QACd;AAAA,QACA,sBAAsB;AAAA,MACxB;AAAA,IACF;AAEA,UAAM,SACJ,SAAS,iBACR,WAAY;AACX,YAAM,UAAU,SAAS,qBAAqB,QAAQ;AACtD,aAAO,QAAQ,QAAQ,SAAS;AAAA,IAClC,EAAG;AAEL,UAAM,MAAM,SACR,OAAO,aAAa,KAAK,MAAM,IAC/B,WAAY;AACV,aAAO;AAAA,IACT;AACJ,UAAM,UAAU,IAAI,cAAc;AAClC,UAAM,WAA4B;AAAA,MAChC,YAAY,IAAI,WAAW,KAAK;AAAA,MAChC,WAAW,IAAI,gBAAgB,MAAM,UAAU,QAAQ;AAAA,MACvD,kBAAkB;AAAA,MAClB,WAAW,IAAI,YAAY,KAAK;AAAA,MAChC,SAAS,UAAU,KAAK,MAAM,OAAO,IAAI;AAAA,MACzC;AAAA,MACA,mBAAmB,EAAE,IAAI,gBAAgB,KAAK;AAAA,MAC9C,YAAY,IAAI,kBAAkB,MAAM,SAAS,OAAO;AAAA,MACxD,YAAY,EAAE,IAAI,iBAAiB,KAAK;AAAA,MACxC,WAAW,IAAI,cAAc,KAAK;AAAA,MAClC,MAAM,eAAe,SAAS,YAAY,aAAa,CAAC;AAAA,MACxD,UAAU,IAAI,WAAW,KAAK;AAAA,MAC9B,aAAa,IAAI,cAAc,KAAK;AAAA,MACpC,kBAAkB,EAAE,IAAI,eAAe,KAAK;AAAA,MAC5C,KAAK,IAAI,UAAU,KAAK;AAAA,MACxB,gBAAgB,IAAI,sBAAsB,KAAK;AAAA,MAC/C,gBAAgB,IAAI,uBAAuB,KAAK;AAAA,MAChD,QAAQ,IAAI,WAAW,KAAK;AAAA,IAC9B;AACA,WAAO;AAAA,EACT;AAQO,WAAS,aAAa,YAAoB,OAAY;AAC3D,QAAI,KAAK,eAAe,QAAQ,UAAU,MAAM,MAAM;AACpD,WAAK,eAAe,QAAQ,YAAY,KAAK,UAAU,KAAK,CAAC;AAC7D,aAAO;AAAA,IACT;AAEA,WAAO,KAAK,MAAM,KAAK,eAAe,QAAQ,UAAU,KAAK,EAAE;AAAA,EACjE;AAOO,WAAS,eAAe,GAAiC;AAC9D,QAAI;AACJ,QAAI,EAAE,aAAa,EAAE,YAAY,GAAG;AAClC,YAAM,QAAQ,KAAK,IAAI,IAAI,EAAE;AAO7B,UAAI,QAAQ,GAAG;AACb,mBAAW,WAAY;AACrB,iBAAO,EAAE,YAAY;AAAA,QACvB;AAAA,MACF,WAAW,QAAQ,EAAE,WAAW;AAC9B,cAAM,WAAW,YAAY;AAC7B,mBAAW,SAAU,IAAI;AACvB,iBAAO,KAAK;AAAA,QACd;AAAA,MACF,OAAO;AACL,mBAAW,SAAU,IAAI;AACvB,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,OAAO;AACL,iBAAW,WAAY;AACrB,eAAO,KAAK,IAAI;AAAA,MAClB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAMA,WAAS,wBAAgC;AAEvC,UAAM,MAAM;AACZ,UAAM,MAAM,IAAI,WAAW,MAAM,CAAC;AAClC,WAAO,OAAO,gBAAgB,GAAG;AACjC,WAAO,MAAM,KAAK,KAAK,CAAC,QAAQ;AAC9B,aAAO,IAAI,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AAAA,IACzC,CAAC,EAAE,KAAK,EAAE;AAAA,EACZ;;;ACrJO,MAAM,iBAAN,MAAoB;AAAA,IA6BjB,cAAc;AAvBtB,WAAO,YAAqB;AAC5B,WAAO,aAAkC;AACzC,WAAO,mBAAuC;AAC9C,WAAO,YAAkC;AACzC,WAAO,UAA4B;AACnC,WAAO,gBAAoC;AAC3C,WAAO,oBAA4B;AACnC,WAAO,aAAsB;AAC7B,WAAO,KAAc;AACrB,WAAO,aAAqB;AAC5B,WAAO,YAAgC;AACvC,WAAO,OAA8B,MAAM,KAAK,IAAI;AACpD,WAAO,WAA8B;AACrC,WAAO,cAAgC;AACvC,WAAO,mBAA2B;AAClC,WAAO,MAAc;AACrB,WAAO,iBAA0C;AACjD,WAAO,iBAAmC;AAC1C,WAAO,SAA0B;AACjC,WAAO,UAA4B;AACnC,WAAO,oBAA6B;AAKlC,UAAI,eAAc,aAAa,MAAM;AACnC,aAAK,WAAW;AAAA,MAClB;AAAA,IACF;AAAA,IAGA,OAAc,cAA6B;AACzC,UAAI,eAAc,aAAa,MAAM;AACnC,uBAAc,WAAW,IAAI,eAAc;AAAA,MAC7C;AACA,aAAO,eAAc;AAAA,IACvB;AAAA,IAEQ,aAAmB;AACzB,YAAM,WAAW,mBAAmB;AACpC,WAAK,OAAO,QAAQ;AAAA,IACtB;AAAA,IAKO,QAAc;AACnB,WAAK,WAAW;AAAA,IAClB;AAAA,IAOO,OAAO,WAA2C;AACvD,aAAO,KAAK,SAAS,EAAE,QAAQ,CAAC,WAAW;AACzC,YAAI,WAAW,kBAAkB;AAC/B,gBAAM,kBAAkB,UAAU;AAClC,gBAAM,SAAS,kBACX,eAAc,oBAAoB,eAAe,IACjD;AACJ,cAAI,QAAQ;AACV,iBAAK,YAAY;AAAA,UACnB;AAAA,QACF;AACA,cAAM,uBAAuB,UAAU;AACvC,cAAM,oBACJ,WAAW,YAAY,UAAU,YAAY;AAC/C,YAAI,qBAAqB,sBAAsB;AAC7C;AAAA,QACF;AAEA,cAAM,YAAY,UAAU;AAC5B,YAAI,cAAc,QAAW;AAC3B,eAAK,UAAU;AAAA,QACjB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IAOA,OAAc,oBAAoB,OAAe;AAC/C,YAAM,YAAY;AAClB,YAAM,QAAQ,IAAI,OAAO,SAAS,YAAY,mBAAmB;AACjE,YAAM,UAAU,OAAO,SAAS,KAAK,MAAM,KAAK;AAEhD,UAAI,WAAW,QAAQ,IAAI;AACzB,eAAO,mBAAmB,QAAQ,GAAG,QAAQ,OAAO,GAAG,CAAC;AAAA,MAC1D;AACA,aAAO;AAAA,IACT;AAAA,EACF;AArGO,MAAM,gBAAN;AAGL,EAHW,cAGI,WAAiC;;;ACHlD,MAAI;AACJ,MAAI;AAOG,WAAS,WAAWC,OAA0BC,SAAuB;AAC1E,QAAI,gBAAgB;AAClB,oBAAc,cAAc;AAAA,IAC9B;AAEA,UAAM,MAAM,IAAI,IAAIA,QAAO,GAAG;AAC9B,QAAI,IAAI,aAAa,SAAS,IAAI,aAAa,QAAQ;AACrD,cAAQ,IAAI,UAAUA,QAAO,GAAG;AAAA,IAClC;AAEA,qBAAiB,eAAeD,OAAMC,OAAM;AAC5C,gBAAYD,OAAMC,OAAM;AAAA,EAC1B;AASO,WAAS,eACdD,OACAC,SACgB;AAChB,WAAO,YAAY,WAAY;AAC7B,UAAI,CAACA,QAAO,IAAI;AACd;AAAA,MACF;AAEA,UAAID,MAAK,UAAUC,QAAO,mBAAmB;AAC3C,iBAASD,MAAK,MAAM,CAAC,GAAGC,SAAQ,CAAC;AACjC,QAAAD,MAAK,OAAO,CAAC;AAAA,MACf;AAAA,IACF,GAAGC,QAAO,gBAAgB;AAAA,EAC5B;AAOO,WAAS,YACdD,OACAC,SACM;AACN,SAAK,iBAAiB,YAAY,WAAY;AAC5C,UAAI,CAACA,QAAO,IAAI;AACd;AAAA,MACF;AAEA,UAAID,MAAK,SAAS,GAAG;AACnB,cAAM,MAAM,IAAI,IAAIC,QAAO,GAAG;AAE9B,YAAI,IAAI,aAAa,SAAS,IAAI,aAAa,QAAQ;AACrD,gBAAM,OAAO,KAAK,UAAUD,KAAI;AAChC,gBAAM,KAAK,IAAI;AAAA,QACjB,OAAO;AACL,gBAAM,UAAuB,IAAI,QAAQ;AACzC,kBAAQ,IAAI,gBAAgB,gCAAgC;AAE5D,cAAIC,QAAO,YAAY;AACrB,oBAAQ,IAAI,iBAAiBA,QAAO,WAAW,SAAS,CAAC;AAAA,UAC3D;AAEA,gBAAMA,QAAO,KAAK;AAAA,YAChB,WAAW;AAAA,YACX,QAAQ;AAAA,YACR;AAAA,YACA,MAAM,KAAK,UAAUD,KAAI;AAAA,UAC3B,CAAC,EAAE,MAAM,CAAC,UAAU;AAClB,oBAAQ,MAAM,KAAK;AAAA,UACrB,CAAC;AAAA,QACH;AACA,QAAAA,MAAK,OAAO,CAAC;AAAA,MACf;AAAA,IACF,CAAC;AAAA,EACH;AASA,iBAAsB,SACpBA,OACAC,SACA,SACe;AACf,UAAM,OAAO,KAAK,UAAUD,KAAI;AAChC,UAAM,MAAM,IAAI,IAAIC,QAAO,GAAG;AAE9B,QAAI,IAAI,aAAa,SAAS,IAAI,aAAa,QAAQ;AACrD,YAAM,KAAK,IAAI;AACf;AAAA,IACF;AAGA,UAAM,UAAU,IAAI,QAAQ;AAAA,MAC1B,gBAAgB;AAAA,IAClB,CAAC;AAED,qBAAiBA,OAAM;AACvB,QAAIA,QAAO,YAAY;AACrB,YAAM,kBACJ,OAAOA,QAAO,eAAe,aACzBA,QAAO,WAAW,IAClBA,QAAO;AACb,cAAQ,IAAI,iBAAiB,eAAe;AAAA,IAC9C;AAIA,wBAAoBA,OAAM;AAC1B,QAAIA,QAAO,SAAS;AAClB,iBAAW,CAAC,QAAQ,KAAK,KAAK,OAAO,QAAQA,QAAO,OAAO,GAAG;AAC5D,gBAAQ,IAAI,QAAQ,KAAK;AAAA,MAC3B;AAAA,IACF;AAEA,mBAAe,YAAY,kBAAyC;AAClE,UAAI;AACF,cAAM,WAAW,MAAM,MAAMA,QAAO,KAAK;AAAA,UACvC,QAAQ;AAAA,UACR;AAAA,UACA,MAAM;AAAA,QACR,CAAC;AAED,YAAI,CAAC,SAAS,IAAI;AAChB,cAAI,mBAAmB,GAAG;AACxB,mBAAO,YAAY,mBAAmB,CAAC;AAAA,UACzC,OAAO;AACL,kBAAM,IAAI,MAAM,wBAAwB,SAAS,YAAY;AAAA,UAC/D;AAAA,QACF;AAAA,MACF,SAAS,OAAP;AACA,YAAI,mBAAmB,GAAG;AACxB,iBAAO,YAAY,mBAAmB,CAAC;AAAA,QACzC;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAEA,WAAO,YAAY,OAAO;AAAA,EAC5B;;;AC5IA,MAAMC,UAAS,cAAc,YAAY;AACzC,MAAMC,QAA2B,CAAC;AAElC,MAAM,qBAAqB,KAAK,IAAI;AACpC,MAAI;AACJ,OAAK,SAAS,WAAY;AACxB,uBAAmB,KAAK,IAAI;AAAA,EAC9B;AAEO,MAAI,UAAU;AAarB,EAAAD,QAAO,OAAO;AAAA,IACZ,gBAAgB;AAAA,EAClB,CAAC;AACD,eAAaC,OAAMD,OAAM;AACzB,MAAIA,QAAO,WAAW;AACpB,UAAMA,OAAM;AAAA,EACd;AAOA,WAAS,MAAMA,SAAuB;AACpC,QAAI,CAAC,SAAS;AACZ,iBAAW,WAAY;AACrB,YAAI;AACJ,YAAI;AACF,kBAAQ,SAAS;AAAA,QACnB,SAAS,OAAP;AAEA,kBAAQ;AAAA,QACV;AAEA,YACEA,QAAO,cACN,UAAU,iBAAiB,UAAU,aACtC;AACA,yBAAeA,OAAM;AACrB,qBAAWC,OAAMD,OAAM;AACvB,oBAAUA,QAAO,KAAK;AACtB,cAAI,OAAO,WAAW,eAAe,OAAO,aAAa,aAAa;AACpE;AAAA,cACE;AAAA,gBACE,MAAM;AAAA,gBACN,SAAS,EAAE,cAAc,mBAAmB,mBAAmB;AAAA,cACjE;AAAA,cACA,OAAO,CAAC;AAAA,cACR;AAAA,YACF;AAAA,UACF;AAAA,QACF,OAAO;AACL,gBAAMA,OAAM;AAAA,QACd;AAAA,MACF,GAAG,GAAG;AAAA,IACR;AAAA,EACF;AAGO,MAAME,WAAU;AAMhB,WAAS,QAAc;AAC5B,QAAI,CAAC,WAAWF,QAAO,cAAc,OAAO;AAC1C,gBAAUA,QAAO,KAAK;AACtB,MAAAA,QAAO,OAAO,EAAE,WAAW,KAAK,CAAC;AAAA,IACnC;AAAA,EACF;AAKO,WAAS,OAAa;AAC3B,cAAUA,QAAO,KAAK;AACtB,IAAAA,QAAO,OAAO,EAAE,WAAW,MAAM,CAAC;AAAA,EACpC;AAQO,WAAS,QACd,WACiB;AACjB,QAAI,WAAW;AACb,MAAAA,QAAO,OAAO,SAAS;AAAA,IACzB;AAEA,WAAOA;AAAA,EACT;AAOO,WAAS,IAAI,WAA0C;AAC5D,QAAI,WAAW;AACb,MAAAC,MAAK,KAAK,SAAS;AACnB,aAAO;AAAA,IACT,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF;AAGA,MAAI,OAAO,WAAW,aAAa;AACjC,IAAC,OAAe,UAAU;AAAA,MACxB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;","names":["descriptors","log","config","options","config","config","settings","logs","config","config","logs","version"]} \ No newline at end of file +{"version":3,"sources":["../src/packageLogs.ts","../src/attachHandlers.ts","../src/utils/auth/index.ts","../src/utils/headers/index.ts","../src/getInitialSettings.ts","../src/configure.ts","../src/sendLogs.ts","../src/main.ts"],"sourcesContent":["/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Callbacks, Logging } from \"@/types\";\nimport { Configuration } from \"@/configure\";\n\nexport let logs: Array;\nlet config: Configuration;\n\n// Interval Logging Globals\nlet intervalId: string | null;\nlet intervalType: string | null;\nlet intervalPath: string[] | null;\nlet intervalTimer: number | null;\nlet intervalCounter: number | null;\nlet intervalLog: Logging.Log | null;\n\nexport const filterHandler: CallableFunction | null = null;\nexport const mapHandler: CallableFunction | null = null;\nexport let cbHandlers: Callbacks.CallbackMap = {};\n\n/**\n * Adds named callbacks to be executed when logging.\n * @param {Object } newCallbacks An object containing named callback functions.\n */\nexport function addCallbacks(\n ...newCallbacks: Record[]\n) {\n newCallbacks.forEach((source) => {\n let descriptors: { [key in string | symbol]: any } = {};\n\n descriptors = Object.keys(source).reduce((descriptors, key) => {\n descriptors[key] = Object.getOwnPropertyDescriptor(source, key);\n return descriptors;\n }, descriptors);\n\n Object.getOwnPropertySymbols(source).forEach((sym) => {\n const descriptor = Object.getOwnPropertyDescriptor(source, sym);\n if (descriptor?.enumerable) {\n descriptors[sym] = descriptor;\n }\n });\n Object.defineProperties(cbHandlers, descriptors);\n });\n return cbHandlers;\n}\n\n/**\n * Removes callbacks by name.\n * @param {String[]} targetKeys A list of names of functions to remove.\n */\nexport function removeCallbacks(targetKeys: string[]) {\n targetKeys.forEach((key) => {\n if (Object.prototype.hasOwnProperty.call(cbHandlers, key)) {\n delete cbHandlers[key];\n }\n });\n}\n\n/**\n * Assigns the config and log container to be used by the logging functions.\n * @param {Array} newLogs Log container.\n * @param {Object} newConfig Configuration to use while logging.\n */\nexport function initPackager(\n newLogs: Array,\n newConfig: Configuration,\n) {\n logs = newLogs;\n config = newConfig;\n cbHandlers = {};\n intervalId = null;\n intervalType = null;\n intervalPath = null;\n intervalTimer = null;\n intervalCounter = 0;\n intervalLog = null;\n}\n\n/**\n * Transforms the provided HTML event into a log and appends it to the log queue.\n * @param {Event} e The event to be logged.\n * @param {Function} detailFcn The function to extract additional log parameters from the event.\n * @return {boolean} Whether the event was logged.\n */\nexport function packageLog(\n e: Event,\n detailFcn?: Logging.DynamicDetailFunction | null,\n) {\n if (!config.on) {\n return false;\n }\n\n let details = null;\n if (detailFcn) {\n details = detailFcn(e);\n }\n\n const timeFields = extractTimeFields(\n e.timeStamp && e.timeStamp > 0 ? config.time(e.timeStamp) : Date.now(),\n );\n\n let log: Logging.Log = {\n target: e.target ? getSelector(e.target) : null,\n path: buildPath(e),\n pageUrl: self.location.href,\n pageTitle: document.title,\n pageReferrer: document.referrer,\n userAgent: self.navigator.userAgent,\n clientTime: timeFields.milli,\n microTime: timeFields.micro,\n location: getLocation(e),\n scrnRes: getScreenRes(),\n type: e.type,\n logType: \"raw\",\n userAction: true,\n details: details,\n userId: config.userId,\n toolVersion: config.toolVersion,\n toolName: config.toolName,\n useraleVersion: config.useraleVersion,\n sessionId: config.sessionId,\n httpSessionId: config.httpSessionId,\n browserSessionId: config.browserSessionId,\n attributes: buildAttrs(e),\n style: buildCSS(e),\n };\n\n if (typeof filterHandler === \"function\" && !filterHandler(log)) {\n return false;\n }\n\n if (typeof mapHandler === \"function\") {\n log = mapHandler(log, e);\n }\n\n for (const func of Object.values(cbHandlers)) {\n if (typeof func === \"function\") {\n log = func(log, e);\n if (!log) {\n return false;\n }\n }\n }\n\n logs.push(log);\n return true;\n}\n\n/**\n * Packages the provided customLog to include standard meta data and appends it to the log queue.\n * @param {Logging.CustomLog} customLog The behavior to be logged.\n * @param {Logging.DynamicDetailFunction} detailFcn The function to extract additional log parameters from the event.\n * @param {boolean} userAction Indicates user behavior (true) or system behavior (false)\n * @return {boolean} Whether the event was logged.\n */\nexport function packageCustomLog(\n customLog: Logging.CustomLog,\n detailFcn: Logging.DynamicDetailFunction | Logging.StaticDetailFunction,\n userAction: boolean,\n): boolean {\n if (!config.on) {\n return false;\n }\n\n let details = null;\n if (detailFcn.length === 0) {\n // In the case of a union, the type checker will default to the more stringent\n // type, i.e. the DetailFunction that expects an argument for safety purposes.\n // To avoid this, we must explicitly check the type by asserting it receives\n // no arguments (detailFcn.length === 0) and then cast it to the\n // StaticDetailFunction type.\n const staticDetailFcn = detailFcn as Logging.StaticDetailFunction;\n details = staticDetailFcn();\n }\n\n const metaData = {\n pageUrl: self.location.href,\n pageTitle: document.title,\n pageReferrer: document.referrer,\n userAgent: self.navigator.userAgent,\n clientTime: Date.now(),\n scrnRes: getScreenRes(),\n logType: \"custom\",\n userAction: userAction,\n details: details,\n userId: config.userId,\n toolVersion: config.toolVersion,\n toolName: config.toolName,\n useraleVersion: config.useraleVersion,\n sessionId: config.sessionId,\n httpSessionId: config.httpSessionId,\n browserSessionId: config.browserSessionId,\n };\n\n let log = Object.assign(metaData, customLog);\n\n if (typeof filterHandler === \"function\" && !filterHandler(log)) {\n return false;\n }\n\n if (typeof mapHandler === \"function\") {\n log = mapHandler(log);\n }\n\n for (const func of Object.values(cbHandlers)) {\n if (typeof func === \"function\") {\n log = func(log, null);\n if (!log) {\n return false;\n }\n }\n }\n\n logs.push(log);\n\n return true;\n}\n\n/**\n * Extract the millisecond and microsecond portions of a timestamp.\n * @param {Number} timeStamp The timestamp to split into millisecond and microsecond fields.\n * @return {Object} An object containing the millisecond\n * and microsecond portions of the timestamp.\n */\nexport function extractTimeFields(timeStamp: number) {\n return {\n milli: Math.floor(timeStamp),\n micro: Number((timeStamp % 1).toFixed(3)),\n };\n}\n\n/**\n * Track intervals and gather details about it.\n * @param {Object} e\n * @return boolean\n */\nexport function packageIntervalLog(e: Event) {\n try {\n const target = e.target ? getSelector(e.target) : null;\n const path = buildPath(e);\n const type = e.type;\n const timestamp = Math.floor(\n e.timeStamp && e.timeStamp > 0 ? config.time(e.timeStamp) : Date.now(),\n );\n\n // Init - this should only happen once on initialization\n if (intervalId == null) {\n intervalId = target;\n intervalType = type;\n intervalPath = path;\n intervalTimer = timestamp;\n intervalCounter = 0;\n }\n\n if ((intervalId !== target || intervalType !== type) && intervalTimer) {\n // When to create log? On transition end\n // @todo Possible for intervalLog to not be pushed in the event the interval never ends...\n\n intervalLog = {\n target: intervalId,\n path: intervalPath,\n pageUrl: self.location.href,\n pageTitle: document.title,\n pageReferrer: document.referrer,\n userAgent: self.navigator.userAgent,\n count: intervalCounter,\n duration: timestamp - intervalTimer, // microseconds\n startTime: intervalTimer,\n endTime: timestamp,\n type: intervalType,\n logType: \"interval\",\n targetChange: intervalId !== target,\n typeChange: intervalType !== type,\n userAction: false,\n userId: config.userId,\n toolVersion: config.toolVersion,\n toolName: config.toolName,\n useraleVersion: config.useraleVersion,\n sessionId: config.sessionId,\n httpSessionId: config.httpSessionId,\n browserSessionId: config.browserSessionId,\n };\n\n if (typeof filterHandler === \"function\" && !filterHandler(intervalLog)) {\n return false;\n }\n\n if (typeof mapHandler === \"function\") {\n intervalLog = mapHandler(intervalLog, e);\n }\n\n for (const func of Object.values(cbHandlers)) {\n if (typeof func === \"function\") {\n intervalLog = func(intervalLog, null);\n if (!intervalLog) {\n return false;\n }\n }\n }\n\n if (intervalLog) logs.push(intervalLog);\n\n // Reset\n intervalId = target;\n intervalType = type;\n intervalPath = path;\n intervalTimer = timestamp;\n intervalCounter = 0;\n }\n\n // Interval is still occuring, just update counter\n if (intervalId == target && intervalType == type && intervalCounter) {\n intervalCounter = intervalCounter + 1;\n }\n\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Extracts coordinate information from the event\n * depending on a few browser quirks.\n * @param {Event} e The event to extract coordinate information from.\n * @return {Object} An object containing nullable x and y coordinates for the event.\n */\nexport function getLocation(e: Event) {\n if (e instanceof MouseEvent) {\n if (e.pageX != null) {\n return { x: e.pageX, y: e.pageY };\n } else if (e.clientX != null) {\n return {\n x: document.documentElement.scrollLeft + e.clientX,\n y: document.documentElement.scrollTop + e.clientY,\n };\n }\n } else {\n return { x: null, y: null };\n }\n}\n\n/**\n * Extracts innerWidth and innerHeight to provide estimates of screen resolution\n * @return {Object} An object containing the innerWidth and InnerHeight\n */\nexport function getScreenRes() {\n return { width: self.innerWidth, height: self.innerHeight };\n}\n\n/**\n * Builds a string CSS selector from the provided element\n * @param {EventTarget} ele The element from which the selector is built.\n * @return {string} The CSS selector for the element, or Unknown if it can't be determined.\n */\nexport function getSelector(ele: EventTarget) {\n if (ele instanceof HTMLElement || ele instanceof Element) {\n if (ele.localName) {\n return (\n ele.localName +\n (ele.id ? \"#\" + ele.id : \"\") +\n (ele.className ? \".\" + ele.className : \"\")\n );\n } else if (ele.nodeName) {\n return (\n ele.nodeName +\n (ele.id ? \"#\" + ele.id : \"\") +\n (ele.className ? \".\" + ele.className : \"\")\n );\n }\n } else if (ele instanceof Document) {\n return \"#document\";\n } else if (ele === globalThis) {\n return \"Window\";\n }\n return \"Unknown\";\n}\n\n/**\n * Builds an array of elements from the provided event target, to the root element.\n * @param {Event} e Event from which the path should be built.\n * @return {HTMLElement[]} Array of elements, starting at the event target, ending at the root element.\n */\nexport function buildPath(e: Event) {\n const path = e.composedPath();\n return selectorizePath(path);\n}\n\n/**\n * Builds a CSS selector path from the provided list of elements.\n * @param {EventTarget[]} path Array of HTML Elements from which the path should be built.\n * @return {string[]} Array of string CSS selectors.\n */\nexport function selectorizePath(path: EventTarget[]) {\n let i = 0;\n let pathEle;\n const pathSelectors: string[] = [];\n while ((pathEle = path[i])) {\n pathSelectors.push(getSelector(pathEle));\n ++i;\n pathEle = path[i];\n }\n return pathSelectors;\n}\n\n/**\n * Builds an object containing attributes of an element.\n * Attempts to parse all attribute values as JSON text.\n * @param {Event} e Event from which the target element's attributes should be extracted.\n * @return {Record} Object with element attributes as key-value pairs.\n */\nexport function buildAttrs(e: Event): Record {\n const attributes: Record = {};\n const attributeBlackList = [\"style\"];\n\n if (e.target && e.target instanceof Element) {\n for (const attr of e.target.attributes) {\n if (attributeBlackList.includes(attr.name)) continue;\n let val: any = attr.value;\n try {\n val = JSON.parse(val);\n } catch {\n // Ignore parsing errors, fallback to raw string value\n }\n attributes[attr.name] = val;\n }\n }\n\n return attributes;\n}\n\n/**\n * Builds an object containing all CSS properties of an element.\n * @param {Event} e Event from which the target element's properties should be extracted.\n * @return {Record} Object with all CSS properties as key-value pairs.\n */\nexport function buildCSS(e: Event): Record {\n const properties: Record = {};\n if (e.target && e.target instanceof HTMLElement) {\n const styleObj = e.target.style;\n for (let i = 0; i < styleObj.length; i++) {\n const prop = styleObj[i];\n properties[prop] = styleObj.getPropertyValue(prop);\n }\n }\n return properties;\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { packageLog, packageIntervalLog } from \"@/packageLogs\";\nimport { Events, Logging, Settings } from \"@/types\";\nimport { Configuration } from \"@/configure\";\n\n//@todo: Investigate drag events and their behavior\nlet events: Events.EventDetailsMap;\nlet bufferBools: Events.EventBoolMap;\nlet bufferedEvents: Events.EventDetailsMap;\nlet refreshEvents: Events.EventDetailsMap;\nconst intervalEvents: Array = [\n \"click\",\n \"focus\",\n \"blur\",\n \"input\",\n \"change\",\n \"mouseover\",\n \"submit\",\n];\nconst windowEvents: Array = [\"load\", \"blur\", \"focus\"];\n\n/**\n * Maps a MouseEvent to an object containing useful information.\n * @param {MouseEvent} e Event to extract data from\n */\nexport function extractMouseDetails(e: MouseEvent) {\n return {\n clicks: e.detail,\n ctrl: e.ctrlKey,\n alt: e.altKey,\n shift: e.shiftKey,\n meta: e.metaKey,\n // 'text' : e.target.innerHTML\n };\n}\n\n/** Maps a KeyboardEvent to an object containing useful infromation\n * @param {KeyboardEvent} e Event to extract data from\n */\nexport function extractKeyboardDetails(e: KeyboardEvent) {\n return {\n key: e.key,\n code: e.code,\n ctrl: e.ctrlKey,\n alt: e.altKey,\n shift: e.shiftKey,\n meta: e.metaKey,\n };\n}\n\n/**\n * Maps an InputEvent to an object containing useful information.\n * @param {InputEvent} e Event to extract data from\n */\nexport function extractInputDetails(e: InputEvent) {\n return {\n value: (e.target as HTMLInputElement).value,\n };\n}\n\n/**\n * Maps a ChangeEvent to an object containing useful information.\n * @param {Events.ChangeEvent} e Event to extract data from\n */\nexport function extractChangeDetails(e: Events.ChangeEvent) {\n return {\n value: e.target.value,\n };\n}\n\n/**\n * Maps a WheelEvent to an object containing useful information.\n * @param {WheelEvent} e Event to extract data from\n */\nexport function extractWheelDetails(e: WheelEvent) {\n return {\n x: e.deltaX,\n y: e.deltaY,\n z: e.deltaZ,\n };\n}\n\n/**\n * Maps a ScrollEvent to an object containing useful information.\n */\nexport function extractScrollDetails() {\n return {\n x: window.scrollX,\n y: window.scrollY,\n };\n}\n\n/**\n * Maps a ResizeEvent to an object containing useful information.\n */\nexport function extractResizeDetails() {\n return {\n width: window.outerWidth,\n height: window.outerHeight,\n };\n}\n\n/**\n * Defines the way information is extracted from various events.\n * Also defines which events we will listen to.\n * @param {Settings.Config} config Configuration object to read from.\n */\nexport function defineDetails(config: Settings.DefaultConfig): void {\n // Events list\n // Keys are event types\n // Values are functions that return details object if applicable\n events = {\n click: extractMouseDetails,\n dblclick: extractMouseDetails,\n mousedown: extractMouseDetails,\n mouseup: extractMouseDetails,\n focus: null,\n blur: null,\n input: config.logDetails ? extractKeyboardDetails : null,\n change: config.logDetails ? extractChangeDetails : null,\n dragstart: null,\n dragend: null,\n drag: null,\n drop: null,\n keydown: config.logDetails ? extractKeyboardDetails : null,\n mouseover: null,\n };\n\n bufferBools = {};\n bufferedEvents = {\n wheel: extractWheelDetails,\n scroll: extractScrollDetails,\n resize: extractResizeDetails,\n };\n\n refreshEvents = {\n submit: null,\n };\n}\n\n/**\n * Defines the way information is extracted from various events.\n * Also defines which events we will listen to.\n * @param {Settings.Config} options UserALE Configuration object to read from.\n * @param {Events.AllowedEvents} type of html event (e.g., 'click', 'mouseover', etc.), such as passed to addEventListener methods.\n */\nexport function defineCustomDetails(\n options: Settings.DefaultConfig,\n type: Events.AllowedEvents,\n): Logging.DynamicDetailFunction | null | undefined {\n // Events list\n // Keys are event types\n // Values are functions that return details object if applicable\n const eventType: Events.EventDetailsMap = {\n click: extractMouseDetails,\n dblclick: extractMouseDetails,\n mousedown: extractMouseDetails,\n mouseup: extractMouseDetails,\n focus: null,\n blur: null,\n load: null,\n input: options.logDetails ? extractKeyboardDetails : null,\n change: options.logDetails ? extractChangeDetails : null,\n dragstart: null,\n dragend: null,\n drag: null,\n drop: null,\n keydown: options.logDetails ? extractKeyboardDetails : null,\n mouseover: null,\n wheel: extractWheelDetails,\n scroll: extractScrollDetails,\n resize: extractResizeDetails,\n submit: null,\n };\n return eventType[type];\n}\n\n/**\n * Hooks the event handlers for each event type of interest.\n * @param {Configuration} config Configuration singleton to use.\n * @return {boolean} Whether the operation succeeded\n */\nexport function attachHandlers(config: Configuration): boolean {\n try {\n defineDetails(config);\n\n (Object.keys(events) as Events.AllowedEvents[]).forEach(function (ev) {\n document.addEventListener(\n ev,\n function (e) {\n packageLog(e, events[ev]);\n },\n true,\n );\n });\n\n intervalEvents.forEach(function (ev) {\n document.addEventListener(\n ev,\n function (e) {\n packageIntervalLog(e);\n },\n true,\n );\n });\n\n (Object.keys(bufferedEvents) as Events.BufferedEvents[]).forEach(\n function (ev) {\n bufferBools[ev] = true;\n\n self.addEventListener(\n ev,\n function (e) {\n if (bufferBools[ev]) {\n bufferBools[ev] = false;\n packageLog(e, bufferedEvents[ev]);\n setTimeout(function () {\n bufferBools[ev] = true;\n }, config.resolution);\n }\n },\n true,\n );\n },\n );\n\n (Object.keys(refreshEvents) as Events.RefreshEvents[]).forEach(\n function (ev) {\n document.addEventListener(\n ev,\n function (e) {\n packageLog(e, events[ev]);\n },\n true,\n );\n },\n );\n\n windowEvents.forEach(function (ev) {\n self.addEventListener(\n ev,\n function (e) {\n packageLog(e, function () {\n return { window: true };\n });\n },\n true,\n );\n });\n\n return true;\n } catch {\n return false;\n }\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Configuration } from \"@/configure\";\nimport { Callbacks } from \"@/types\";\n\nexport let authCallback: Callbacks.AuthCallback | null = null;\n\n/**\n * Fetches the most up-to-date auth header string from the auth callback\n * and updates the config object with the new value.\n * @param {Configuration} config Configuration object to be updated.\n * @param {Function} authCallback Callback used to fetch the newest header.\n * @returns {void}\n */\nexport function updateAuthHeader(config: Configuration) {\n if (authCallback) {\n try {\n config.authHeader = authCallback();\n } catch (e) {\n // We should emit the error, but otherwise continue as this could be a temporary issue\n // due to network connectivity or some logic inside the authCallback which is the user's\n // responsibility.\n console.error(`Error encountered while setting the auth header: ${e}`);\n }\n }\n}\n\n/**\n * Registers the provided callback to be used when updating the auth header.\n * @param {Callbacks.AuthCallback} callback Callback used to fetch the newest header. Should return a string.\n * @returns {boolean} Whether the operation succeeded.\n */\nexport function registerAuthCallback(callback: Callbacks.AuthCallback) {\n try {\n verifyCallback(callback);\n authCallback = callback;\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Verify that the provided callback is a function which returns a string\n * @param {Function} callback Callback used to fetch the newest header. Should return a string.\n * @throws {Error} If the callback is not a function or does not return a string.\n * @returns {void}\n */\nexport function verifyCallback(callback: Callbacks.AuthCallback) {\n if (typeof callback !== \"function\") {\n throw new Error(\"Userale auth callback must be a function\");\n }\n const result = callback();\n if (typeof result !== \"string\") {\n throw new Error(\"Userale auth callback must return a string\");\n }\n}\n\n/**\n * Resets the authCallback to null. Used for primarily for testing, but could be used\n * to remove the callback in production.\n * @returns {void}\n */\nexport function resetAuthCallback() {\n authCallback = null;\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Configuration } from \"@/configure\";\nimport { Callbacks } from \"@/types\";\n\nexport let headersCallback: Callbacks.HeadersCallback | null = null;\n\n/**\n * Fetches the most up-to-date custom headers object from the headers callback\n * and updates the config object with the new value.\n * @param {Configuration} config Configuration object to be updated.\n * @param {Callbacks.HeadersCallback} headersCallback Callback used to fetch the newest headers.\n * @returns {void}\n */\nexport function updateCustomHeaders(config: Configuration) {\n if (headersCallback) {\n try {\n config.headers = headersCallback();\n } catch (e) {\n // We should emit the error, but otherwise continue as this could be a temporary issue\n // due to network connectivity or some logic inside the headersCallback which is the user's\n // responsibility.\n console.error(`Error encountered while setting the headers: ${e}`);\n }\n }\n}\n\n/**\n * Registers the provided callback to be used when updating the auth header.\n * @param {Callbacks.HeadersCallback} callback Callback used to fetch the newest headers. Should return an object.\n * @returns {boolean} Whether the operation succeeded.\n */\nexport function registerHeadersCallback(callback: Callbacks.HeadersCallback) {\n try {\n verifyCallback(callback);\n headersCallback = callback;\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Verify that the provided callback is a function which returns a string\n * @param {Callbacks.HeadersCallback} callback Callback used to fetch the newest header. Should return an object.\n * @throws {Error} If the callback is not a function or does not return a string.\n * @returns {void}\n */\nexport function verifyCallback(callback: Callbacks.HeadersCallback) {\n if (typeof callback !== \"function\") {\n throw new Error(\"Userale headers callback must be a function\");\n }\n const result = callback();\n if (typeof result !== \"object\") {\n throw new Error(\"Userale headers callback must return an object\");\n }\n for (const [key, value] of Object.entries(result)) {\n if (typeof key !== \"string\" || typeof value !== \"string\") {\n throw new Error(\n \"Userale header callback must return an object with string keys and values\",\n );\n }\n }\n}\n\n/**\n * Resets the authCallback to null. Used for primarily for testing, but could be used\n * to remove the callback in production.\n * @returns {void}\n */\nexport function resetHeadersCallback() {\n headersCallback = null;\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the 'License'); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an 'AS IS' BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { Settings } from \"./types\";\n\nlet sessionId: string | null = null;\nlet httpSessionId: string | null = null;\n\n/**\n * Extracts the initial configuration settings from the\n * currently executing script tag.\n * @return {Object} The extracted configuration object\n */\nexport function getInitialSettings(): Settings.Config {\n if (\n typeof WorkerGlobalScope !== \"undefined\" &&\n self instanceof WorkerGlobalScope\n ) {\n const settings: Settings.Config = {\n apiKey: null,\n authHeader: null,\n autostart: true,\n browserSessionId: null,\n custIndex: null,\n headers: null,\n httpSessionId: null,\n logCountThreshold: +5,\n logDetails: false,\n resolution: +500,\n sessionId: sessionId,\n time: (ts?: number) => (ts !== undefined ? ts : Date.now()),\n toolName: null,\n toolVersion: null,\n transmitInterval: +5000,\n url: \"http://localhost:8000\",\n useraleVersion: null,\n userFromParams: null,\n userId: null,\n };\n return settings;\n }\n\n if (sessionId === null) {\n sessionId = getsessionId(\n \"userAlesessionId\",\n \"session_\" + String(Date.now()),\n );\n }\n\n if (httpSessionId === null) {\n httpSessionId = getsessionId(\n \"userAleHttpSessionId\",\n generatehttpSessionId(),\n );\n }\n\n const script =\n document.currentScript ||\n (function () {\n const scripts = document.getElementsByTagName(\"script\");\n return scripts[scripts.length - 1];\n })();\n\n const get = script\n ? script.getAttribute.bind(script)\n : function () {\n return null;\n };\n const headers = get(\"data-headers\");\n const settings: Settings.Config = {\n apiKey: get(\"data-api-key\") || null,\n authHeader: get(\"data-auth\") || null,\n autostart: get(\"data-autostart\") === \"false\" ? false : true,\n browserSessionId: null,\n custIndex: get(\"data-index\") || null,\n headers: headers ? JSON.parse(headers) : null,\n httpSessionId: httpSessionId,\n logCountThreshold: +(get(\"data-threshold\") || 5),\n logDetails: get(\"data-log-details\") === \"true\" ? true : false,\n resolution: +(get(\"data-resolution\") || 500),\n sessionId: get(\"data-session\") || sessionId,\n time: timeStampScale(document.createEvent(\"CustomEvent\")),\n toolName: get(\"data-tool\") || null,\n toolVersion: get(\"data-version\") || null,\n transmitInterval: +(get(\"data-interval\") || 5000),\n url: get(\"data-url\") || \"http://localhost:8000\",\n useraleVersion: get(\"data-userale-version\") || null,\n userFromParams: get(\"data-user-from-params\") || null,\n userId: get(\"data-user\") || null,\n };\n return settings;\n}\n\n/**\n * defines sessionId, stores it in sessionStorage, checks to see if there is a sessionId in\n * storage when script is started. This prevents events like 'submit', which refresh page data\n * from refreshing the current user session\n *\n */\nexport function getsessionId(sessionKey: string, value: any) {\n if (self.sessionStorage.getItem(sessionKey) === null) {\n self.sessionStorage.setItem(sessionKey, JSON.stringify(value));\n return value;\n }\n\n return JSON.parse(self.sessionStorage.getItem(sessionKey) || \"\");\n}\n\n/**\n * Creates a function to normalize the timestamp of the provided event.\n * @param {Event} e An event containing a timeStamp property.\n * @return {typeof timeStampScale~tsScaler} The timestamp normalizing function.\n */\nexport function timeStampScale(e: Event): Settings.TimeFunction {\n let tsScaler: Settings.TimeFunction;\n if (e.timeStamp && e.timeStamp > 0) {\n const delta = Date.now() - e.timeStamp;\n /**\n * Returns a timestamp depending on various browser quirks.\n * @param {?Number} ts A timestamp to use for normalization.\n * @return {Number} A normalized timestamp.\n */\n\n if (delta < 0) {\n tsScaler = function () {\n return e.timeStamp / 1000;\n };\n } else if (delta > e.timeStamp) {\n const navStart = performance.timeOrigin;\n tsScaler = function (ts) {\n return ts + navStart;\n };\n } else {\n tsScaler = function (ts) {\n return ts;\n };\n }\n } else {\n tsScaler = function () {\n return Date.now();\n };\n }\n\n return tsScaler;\n}\n\n/**\n * Creates a cryptographiclly random string to represent this http session.\n * @return {String} A random 32 digit hex string\n */\nfunction generatehttpSessionId(): string {\n // 32 digit hex -> 128 bits of info -> 2^64 ~= 10^19 sessions needed for 50% chance of collison\n const len = 32;\n const arr = new Uint8Array(len / 2);\n window.crypto.getRandomValues(arr);\n return Array.from(arr, (dec) => {\n return dec.toString(16).padStart(2, \"0\");\n }).join(\"\");\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getInitialSettings } from \"@/getInitialSettings\";\nimport type { Settings } from \"@/types\";\n\n// Singleton Configuration class\nexport class Configuration {\n [key: string]: Settings.ConfigValueTypes;\n // Private static property to hold the singleton instance\n private static instance: Configuration | null = null;\n\n // Public properties corresponding to fields in the Config interface\n public apiKey: Settings.ApiKey = null;\n public autostart: boolean = false;\n public authHeader: Settings.AuthHeader = null;\n public browserSessionId: Settings.SessionId = null;\n public custIndex: Settings.CustomIndex = null;\n public headers: Settings.Headers = null;\n public httpSessionId: Settings.SessionId = null;\n public logCountThreshold: number = 0;\n public logDetails: boolean = false;\n public on: boolean = false;\n public resolution: number = 0;\n public sessionId: Settings.SessionId = null;\n public time: Settings.TimeFunction = () => Date.now();\n public toolName: Settings.ToolName = null;\n public toolVersion: Settings.Version = null;\n public transmitInterval: number = 0;\n public url: string = \"\";\n public userFromParams: Settings.UserFromParams = null;\n public useraleVersion: Settings.Version = null;\n public userId: Settings.UserId = null;\n public version: Settings.Version = null;\n public websocketsEnabled: boolean = false;\n\n // Private constructor to prevent external instantiation\n private constructor() {\n // Call the initialization method only if it's the first time instantiating\n if (Configuration.instance === null) {\n this.initialize();\n }\n }\n\n // Static method to get the singleton instance\n public static getInstance(): Configuration {\n if (Configuration.instance === null) {\n Configuration.instance = new Configuration();\n }\n return Configuration.instance;\n }\n\n private initialize(): void {\n const settings = getInitialSettings();\n this.update(settings);\n }\n\n /**\n * Resets the configuration to its initial state.\n */\n public reset(): void {\n this.initialize();\n }\n\n /**\n * Shallow merges a newConfig with the configuration class, updating it.\n * Retrieves/updates the userid if userFromParams is provided.\n * @param {Partial} newConfig Configuration object to merge into the current config.\n */\n public update(newConfig: Partial): void {\n Object.keys(newConfig).forEach((option) => {\n if (option === \"userFromParams\") {\n const userParamString = newConfig[option] as Settings.UserFromParams;\n const userId = userParamString\n ? Configuration.getUserIdFromParams(userParamString)\n : null;\n if (userId) {\n this[\"userId\"] = userId;\n }\n }\n const hasNewUserFromParams = newConfig[\"userFromParams\"];\n const willNullifyUserId =\n option === \"userId\" && newConfig[option] === null;\n if (willNullifyUserId && hasNewUserFromParams) {\n return;\n }\n\n const newOption = newConfig[option];\n if (newOption !== undefined) {\n this[option] = newOption;\n }\n });\n }\n\n /**\n * Attempts to extract the userid from the query parameters of the URL.\n * @param {string} param The name of the query parameter containing the userid.\n * @return {string | null} The extracted/decoded userid, or null if none is found.\n */\n public static getUserIdFromParams(param: string) {\n const userField = param;\n const regex = new RegExp(\"[?&]\" + userField + \"(=([^&#]*)|&|#|$)\");\n const results = window.location.href.match(regex);\n\n if (results && results[2]) {\n return decodeURIComponent(results[2].replace(/\\+/g, \" \"));\n }\n return null;\n }\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Configuration } from \"@/configure\";\nimport { Logging } from \"@/types\";\nimport { updateAuthHeader, updateCustomHeaders } from \"@/utils\";\n\nlet sendIntervalId: string | number | NodeJS.Timeout | undefined;\nlet wsock: WebSocket;\n\n/**\n * Initializes the log queue processors.\n * @param {Array} logs Array of logs to append to.\n * @param {Configuration} config Configuration object to use when logging.\n */\nexport function initSender(logs: Array, config: Configuration) {\n if (sendIntervalId) {\n clearInterval(sendIntervalId);\n }\n\n const url = new URL(config.url);\n if (url.protocol === \"ws:\" || url.protocol === \"wss:\") {\n wsock = new WebSocket(config.url);\n }\n\n sendIntervalId = sendOnInterval(logs, config);\n sendOnClose(logs, config);\n}\n\n/**\n * Checks the provided log array on an interval, flushing the logs\n * if the queue has reached the threshold specified by the provided config.\n * @param {Array} logs Array of logs to read from.\n * @param {Configuration} config Configuration singleton to be read from.\n * @return {Number} The newly created interval id.\n */\nexport function sendOnInterval(\n logs: Array,\n config: Configuration,\n): NodeJS.Timeout {\n return setInterval(function () {\n if (!config.on) {\n return;\n }\n\n if (logs.length >= config.logCountThreshold) {\n sendLogs(logs.slice(0), config, 0); // Send a copy\n logs.splice(0); // Clear array reference (no reassignment)\n }\n }, config.transmitInterval);\n}\n\n// /**\n// * Attempts to flush the remaining logs when the window is closed.\n// * @param {Array} logs Array of logs to be flushed.\n// * @param {Configuration} config Configuration singleton to be read from.\n// */\nexport function sendOnClose(\n logs: Array,\n config: Configuration,\n): void {\n self.addEventListener(\"pagehide\", function () {\n if (!config.on) {\n return;\n }\n\n if (logs.length > 0) {\n const url = new URL(config.url);\n\n if (url.protocol === \"ws:\" || url.protocol === \"wss:\") {\n const data = JSON.stringify(logs);\n wsock.send(data);\n } else {\n const headers: HeadersInit = new Headers();\n headers.set(\"Content-Type\", \"application/json;charset=UTF-8\");\n\n if (config.authHeader) {\n headers.set(\"Authorization\", config.authHeader.toString());\n }\n\n if (config.apiKey) {\n headers.set(\"x-api-key\", config.apiKey as string);\n }\n\n fetch(config.url, {\n keepalive: true,\n method: \"POST\",\n headers: headers,\n body: JSON.stringify(logs),\n }).catch((error) => {\n console.error(error);\n });\n }\n logs.splice(0); // clear log queue\n }\n });\n}\n\n/**\n * Sends the provided array of logs to the specified url,\n * retrying the request up to the specified number of retries.\n * @param {Array} logs Array of logs to send.\n * @param {Configuration} config configuration singleton.\n * @param {Number} retries Maximum number of attempts to send the logs.\n */\nexport async function sendLogs(\n logs: Array,\n config: Configuration,\n retries: number,\n): Promise {\n const data = JSON.stringify(logs);\n const url = new URL(config.url);\n\n if (url.protocol === \"ws:\" || url.protocol === \"wss:\") {\n wsock.send(data);\n return;\n }\n\n // Build headers\n const headers = new Headers({\n \"Content-Type\": \"application/json;charset=UTF-8\",\n });\n\n updateAuthHeader(config);\n if (config.authHeader) {\n const authHeaderValue =\n typeof config.authHeader === \"function\"\n ? config.authHeader()\n : config.authHeader;\n headers.set(\"Authorization\", authHeaderValue);\n }\n\n if (config.apiKey) {\n headers.set(\"x-api-key\", config.apiKey as string);\n }\n\n // Update custom headers last to allow them to over-write the defaults. This assumes\n // the user knows what they are doing and may want to over-write the defaults.\n updateCustomHeaders(config);\n if (config.headers) {\n for (const [header, value] of Object.entries(config.headers)) {\n headers.set(header, value);\n }\n }\n\n async function attemptSend(remainingRetries: number): Promise {\n try {\n const response = await fetch(config.url, {\n method: \"POST\",\n headers,\n body: data,\n });\n\n if (!response.ok) {\n if (remainingRetries > 0) {\n return attemptSend(remainingRetries - 1);\n } else {\n throw new Error(`Failed to send logs: ${response.statusText}`);\n }\n }\n } catch (error) {\n if (remainingRetries > 0) {\n return attemptSend(remainingRetries - 1);\n }\n throw error;\n }\n }\n\n return attemptSend(retries);\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { defineCustomDetails } from \"@/attachHandlers\";\nimport { registerAuthCallback } from \"@/utils\";\nimport {\n addCallbacks,\n removeCallbacks,\n packageLog,\n packageCustomLog,\n getSelector,\n buildPath,\n initPackager,\n} from \"@/packageLogs\";\nimport { version as userAleVersion } from \"../package.json\";\nimport { Configuration } from \"@/configure\";\nimport { attachHandlers } from \"@/attachHandlers\";\nimport { initSender } from \"@/sendLogs\";\n\nimport type { Settings, Logging } from \"@/types\";\n\nconst config = Configuration.getInstance();\nconst logs: Array = [];\n\nconst startLoadTimestamp = Date.now();\nlet endLoadTimestamp: number;\nself.onload = function () {\n endLoadTimestamp = Date.now();\n};\n\nexport let started = false;\nexport { defineCustomDetails as details } from \"@/attachHandlers\";\nexport { registerAuthCallback as registerAuthCallback } from \"@/utils\";\nexport {\n addCallbacks as addCallbacks,\n removeCallbacks as removeCallbacks,\n packageLog as packageLog,\n packageCustomLog as packageCustomLog,\n getSelector as getSelector,\n buildPath as buildPath,\n} from \"@/packageLogs\";\nexport type { Logging } from \"@/types\";\n\nconfig.update({\n useraleVersion: userAleVersion,\n});\ninitPackager(logs, config);\nif (config.autostart) {\n setup(config);\n}\n\n/**\n * Hooks the global event listener, and starts up the\n * logging interval.\n * @param {Configuration} config Configuration settings for the logger\n */\nfunction setup(config: Configuration) {\n if (!started) {\n setTimeout(function () {\n let state;\n try {\n state = document.readyState;\n } catch (error) {\n // Assume there is no DOM and this is a web worker context\n state = \"complete\";\n }\n\n if (\n config.autostart &&\n (state === \"interactive\" || state === \"complete\")\n ) {\n attachHandlers(config);\n initSender(logs, config);\n started = config.on = true;\n if (typeof window !== \"undefined\" && typeof document !== \"undefined\") {\n packageCustomLog(\n {\n type: \"load\",\n details: { pageLoadTime: endLoadTimestamp - startLoadTimestamp },\n },\n () => ({}),\n false,\n );\n }\n } else {\n setup(config);\n }\n }, 100);\n }\n}\n\n// Export the Userale API\nexport const version = userAleVersion;\n\n/**\n * Used to start the logging process if the\n * autostart configuration option is set to false.\n */\nexport function start(): void {\n if (!started || config.autostart === false) {\n started = config.on = true;\n config.update({ autostart: true });\n }\n}\n\n/**\n * Halts the logging process. Logs will no longer be sent.\n */\nexport function stop(): void {\n started = config.on = false;\n config.update({ autostart: false });\n}\n\n/**\n * Updates the current configuration\n * object with the provided values.\n * @param {Partial} newConfig The configuration options to use.\n * @return {Settings.Config} Returns the updated configuration.\n */\nexport function options(\n newConfig: Partial | undefined,\n): Settings.Config {\n if (newConfig) {\n config.update(newConfig);\n }\n\n return config;\n}\n\n/**\n * Appends a log to the log queue.\n * @param {Logging.CustomLog} customLog The log to append.\n * @return {boolean} Whether the operation succeeded.\n */\nexport function log(customLog: Logging.CustomLog | undefined) {\n if (customLog) {\n logs.push(customLog);\n return true;\n } else {\n return false;\n }\n}\n\n// Only attach to window in IIFE builds\nif (typeof window !== \"undefined\") {\n (window as any).userale = {\n start,\n stop,\n options,\n log,\n version: userAleVersion,\n details: defineCustomDetails,\n registerAuthCallback,\n addCallbacks,\n removeCallbacks,\n packageLog,\n packageCustomLog,\n getSelector,\n buildPath,\n };\n}\n"],"mappings":"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","names":["descriptors","log","config","options","config","config","settings","logs","config","config","logs","version"]} \ No newline at end of file diff --git a/products/userale/packages/flagon-userale/build/main.mjs b/products/userale/packages/flagon-userale/build/main.mjs index 3fd60b0..8db6eb8 100644 --- a/products/userale/packages/flagon-userale/build/main.mjs +++ b/products/userale/packages/flagon-userale/build/main.mjs @@ -535,6 +535,7 @@ var httpSessionId = null; function getInitialSettings() { if (typeof WorkerGlobalScope !== "undefined" && self instanceof WorkerGlobalScope) { const settings2 = { + apiKey: null, authHeader: null, autostart: true, browserSessionId: null, @@ -577,6 +578,7 @@ function getInitialSettings() { }; const headers = get("data-headers"); const settings = { + apiKey: get("data-api-key") || null, authHeader: get("data-auth") || null, autostart: get("data-autostart") === "false" ? false : true, browserSessionId: null, @@ -642,6 +644,7 @@ function generatehttpSessionId() { // src/configure.ts var _Configuration = class { constructor() { + this.apiKey = null; this.autostart = false; this.authHeader = null; this.browserSessionId = null; @@ -754,6 +757,9 @@ function sendOnClose(logs3, config3) { if (config3.authHeader) { headers.set("Authorization", config3.authHeader.toString()); } + if (config3.apiKey) { + headers.set("x-api-key", config3.apiKey); + } fetch(config3.url, { keepalive: true, method: "POST", @@ -782,6 +788,9 @@ async function sendLogs(logs3, config3, retries) { const authHeaderValue = typeof config3.authHeader === "function" ? config3.authHeader() : config3.authHeader; headers.set("Authorization", authHeaderValue); } + if (config3.apiKey) { + headers.set("x-api-key", config3.apiKey); + } updateCustomHeaders(config3); if (config3.headers) { for (const [header, value] of Object.entries(config3.headers)) { diff --git a/products/userale/packages/flagon-userale/build/main.mjs.map b/products/userale/packages/flagon-userale/build/main.mjs.map index 887b699..3909868 100644 --- a/products/userale/packages/flagon-userale/build/main.mjs.map +++ b/products/userale/packages/flagon-userale/build/main.mjs.map @@ -1 +1 @@ -{"version":3,"sources":["../src/packageLogs.ts","../src/attachHandlers.ts","../src/utils/auth/index.ts","../src/utils/headers/index.ts","../src/getInitialSettings.ts","../src/configure.ts","../src/sendLogs.ts","../src/main.ts"],"sourcesContent":["/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Callbacks, Logging } from \"@/types\";\nimport { Configuration } from \"@/configure\";\n\nexport let logs: Array;\nlet config: Configuration;\n\n// Interval Logging Globals\nlet intervalId: string | null;\nlet intervalType: string | null;\nlet intervalPath: string[] | null;\nlet intervalTimer: number | null;\nlet intervalCounter: number | null;\nlet intervalLog: Logging.Log | null;\n\nexport const filterHandler: CallableFunction | null = null;\nexport const mapHandler: CallableFunction | null = null;\nexport let cbHandlers: Callbacks.CallbackMap = {};\n\n/**\n * Adds named callbacks to be executed when logging.\n * @param {Object } newCallbacks An object containing named callback functions.\n */\nexport function addCallbacks(\n ...newCallbacks: Record[]\n) {\n newCallbacks.forEach((source) => {\n let descriptors: { [key in string | symbol]: any } = {};\n\n descriptors = Object.keys(source).reduce((descriptors, key) => {\n descriptors[key] = Object.getOwnPropertyDescriptor(source, key);\n return descriptors;\n }, descriptors);\n\n Object.getOwnPropertySymbols(source).forEach((sym) => {\n const descriptor = Object.getOwnPropertyDescriptor(source, sym);\n if (descriptor?.enumerable) {\n descriptors[sym] = descriptor;\n }\n });\n Object.defineProperties(cbHandlers, descriptors);\n });\n return cbHandlers;\n}\n\n/**\n * Removes callbacks by name.\n * @param {String[]} targetKeys A list of names of functions to remove.\n */\nexport function removeCallbacks(targetKeys: string[]) {\n targetKeys.forEach((key) => {\n if (Object.prototype.hasOwnProperty.call(cbHandlers, key)) {\n delete cbHandlers[key];\n }\n });\n}\n\n/**\n * Assigns the config and log container to be used by the logging functions.\n * @param {Array} newLogs Log container.\n * @param {Object} newConfig Configuration to use while logging.\n */\nexport function initPackager(\n newLogs: Array,\n newConfig: Configuration,\n) {\n logs = newLogs;\n config = newConfig;\n cbHandlers = {};\n intervalId = null;\n intervalType = null;\n intervalPath = null;\n intervalTimer = null;\n intervalCounter = 0;\n intervalLog = null;\n}\n\n/**\n * Transforms the provided HTML event into a log and appends it to the log queue.\n * @param {Event} e The event to be logged.\n * @param {Function} detailFcn The function to extract additional log parameters from the event.\n * @return {boolean} Whether the event was logged.\n */\nexport function packageLog(\n e: Event,\n detailFcn?: Logging.DynamicDetailFunction | null,\n) {\n if (!config.on) {\n return false;\n }\n\n let details = null;\n if (detailFcn) {\n details = detailFcn(e);\n }\n\n const timeFields = extractTimeFields(\n e.timeStamp && e.timeStamp > 0 ? config.time(e.timeStamp) : Date.now(),\n );\n\n let log: Logging.Log = {\n target: e.target ? getSelector(e.target) : null,\n path: buildPath(e),\n pageUrl: self.location.href,\n pageTitle: document.title,\n pageReferrer: document.referrer,\n userAgent: self.navigator.userAgent,\n clientTime: timeFields.milli,\n microTime: timeFields.micro,\n location: getLocation(e),\n scrnRes: getScreenRes(),\n type: e.type,\n logType: \"raw\",\n userAction: true,\n details: details,\n userId: config.userId,\n toolVersion: config.toolVersion,\n toolName: config.toolName,\n useraleVersion: config.useraleVersion,\n sessionId: config.sessionId,\n httpSessionId: config.httpSessionId,\n browserSessionId: config.browserSessionId,\n attributes: buildAttrs(e),\n style: buildCSS(e),\n };\n\n if (typeof filterHandler === \"function\" && !filterHandler(log)) {\n return false;\n }\n\n if (typeof mapHandler === \"function\") {\n log = mapHandler(log, e);\n }\n\n for (const func of Object.values(cbHandlers)) {\n if (typeof func === \"function\") {\n log = func(log, e);\n if (!log) {\n return false;\n }\n }\n }\n\n logs.push(log);\n return true;\n}\n\n/**\n * Packages the provided customLog to include standard meta data and appends it to the log queue.\n * @param {Logging.CustomLog} customLog The behavior to be logged.\n * @param {Logging.DynamicDetailFunction} detailFcn The function to extract additional log parameters from the event.\n * @param {boolean} userAction Indicates user behavior (true) or system behavior (false)\n * @return {boolean} Whether the event was logged.\n */\nexport function packageCustomLog(\n customLog: Logging.CustomLog,\n detailFcn: Logging.DynamicDetailFunction | Logging.StaticDetailFunction,\n userAction: boolean,\n): boolean {\n if (!config.on) {\n return false;\n }\n\n let details = null;\n if (detailFcn.length === 0) {\n // In the case of a union, the type checker will default to the more stringent\n // type, i.e. the DetailFunction that expects an argument for safety purposes.\n // To avoid this, we must explicitly check the type by asserting it receives\n // no arguments (detailFcn.length === 0) and then cast it to the\n // StaticDetailFunction type.\n const staticDetailFcn = detailFcn as Logging.StaticDetailFunction;\n details = staticDetailFcn();\n }\n\n const metaData = {\n pageUrl: self.location.href,\n pageTitle: document.title,\n pageReferrer: document.referrer,\n userAgent: self.navigator.userAgent,\n clientTime: Date.now(),\n scrnRes: getScreenRes(),\n logType: \"custom\",\n userAction: userAction,\n details: details,\n userId: config.userId,\n toolVersion: config.toolVersion,\n toolName: config.toolName,\n useraleVersion: config.useraleVersion,\n sessionId: config.sessionId,\n httpSessionId: config.httpSessionId,\n browserSessionId: config.browserSessionId,\n };\n\n let log = Object.assign(metaData, customLog);\n\n if (typeof filterHandler === \"function\" && !filterHandler(log)) {\n return false;\n }\n\n if (typeof mapHandler === \"function\") {\n log = mapHandler(log);\n }\n\n for (const func of Object.values(cbHandlers)) {\n if (typeof func === \"function\") {\n log = func(log, null);\n if (!log) {\n return false;\n }\n }\n }\n\n logs.push(log);\n\n return true;\n}\n\n/**\n * Extract the millisecond and microsecond portions of a timestamp.\n * @param {Number} timeStamp The timestamp to split into millisecond and microsecond fields.\n * @return {Object} An object containing the millisecond\n * and microsecond portions of the timestamp.\n */\nexport function extractTimeFields(timeStamp: number) {\n return {\n milli: Math.floor(timeStamp),\n micro: Number((timeStamp % 1).toFixed(3)),\n };\n}\n\n/**\n * Track intervals and gather details about it.\n * @param {Object} e\n * @return boolean\n */\nexport function packageIntervalLog(e: Event) {\n try {\n const target = e.target ? getSelector(e.target) : null;\n const path = buildPath(e);\n const type = e.type;\n const timestamp = Math.floor(\n e.timeStamp && e.timeStamp > 0 ? config.time(e.timeStamp) : Date.now(),\n );\n\n // Init - this should only happen once on initialization\n if (intervalId == null) {\n intervalId = target;\n intervalType = type;\n intervalPath = path;\n intervalTimer = timestamp;\n intervalCounter = 0;\n }\n\n if ((intervalId !== target || intervalType !== type) && intervalTimer) {\n // When to create log? On transition end\n // @todo Possible for intervalLog to not be pushed in the event the interval never ends...\n\n intervalLog = {\n target: intervalId,\n path: intervalPath,\n pageUrl: self.location.href,\n pageTitle: document.title,\n pageReferrer: document.referrer,\n userAgent: self.navigator.userAgent,\n count: intervalCounter,\n duration: timestamp - intervalTimer, // microseconds\n startTime: intervalTimer,\n endTime: timestamp,\n type: intervalType,\n logType: \"interval\",\n targetChange: intervalId !== target,\n typeChange: intervalType !== type,\n userAction: false,\n userId: config.userId,\n toolVersion: config.toolVersion,\n toolName: config.toolName,\n useraleVersion: config.useraleVersion,\n sessionId: config.sessionId,\n httpSessionId: config.httpSessionId,\n browserSessionId: config.browserSessionId,\n };\n\n if (typeof filterHandler === \"function\" && !filterHandler(intervalLog)) {\n return false;\n }\n\n if (typeof mapHandler === \"function\") {\n intervalLog = mapHandler(intervalLog, e);\n }\n\n for (const func of Object.values(cbHandlers)) {\n if (typeof func === \"function\") {\n intervalLog = func(intervalLog, null);\n if (!intervalLog) {\n return false;\n }\n }\n }\n\n if (intervalLog) logs.push(intervalLog);\n\n // Reset\n intervalId = target;\n intervalType = type;\n intervalPath = path;\n intervalTimer = timestamp;\n intervalCounter = 0;\n }\n\n // Interval is still occuring, just update counter\n if (intervalId == target && intervalType == type && intervalCounter) {\n intervalCounter = intervalCounter + 1;\n }\n\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Extracts coordinate information from the event\n * depending on a few browser quirks.\n * @param {Event} e The event to extract coordinate information from.\n * @return {Object} An object containing nullable x and y coordinates for the event.\n */\nexport function getLocation(e: Event) {\n if (e instanceof MouseEvent) {\n if (e.pageX != null) {\n return { x: e.pageX, y: e.pageY };\n } else if (e.clientX != null) {\n return {\n x: document.documentElement.scrollLeft + e.clientX,\n y: document.documentElement.scrollTop + e.clientY,\n };\n }\n } else {\n return { x: null, y: null };\n }\n}\n\n/**\n * Extracts innerWidth and innerHeight to provide estimates of screen resolution\n * @return {Object} An object containing the innerWidth and InnerHeight\n */\nexport function getScreenRes() {\n return { width: self.innerWidth, height: self.innerHeight };\n}\n\n/**\n * Builds a string CSS selector from the provided element\n * @param {EventTarget} ele The element from which the selector is built.\n * @return {string} The CSS selector for the element, or Unknown if it can't be determined.\n */\nexport function getSelector(ele: EventTarget) {\n if (ele instanceof HTMLElement || ele instanceof Element) {\n if (ele.localName) {\n return (\n ele.localName +\n (ele.id ? \"#\" + ele.id : \"\") +\n (ele.className ? \".\" + ele.className : \"\")\n );\n } else if (ele.nodeName) {\n return (\n ele.nodeName +\n (ele.id ? \"#\" + ele.id : \"\") +\n (ele.className ? \".\" + ele.className : \"\")\n );\n }\n } else if (ele instanceof Document) {\n return \"#document\";\n } else if (ele === globalThis) {\n return \"Window\";\n }\n return \"Unknown\";\n}\n\n/**\n * Builds an array of elements from the provided event target, to the root element.\n * @param {Event} e Event from which the path should be built.\n * @return {HTMLElement[]} Array of elements, starting at the event target, ending at the root element.\n */\nexport function buildPath(e: Event) {\n const path = e.composedPath();\n return selectorizePath(path);\n}\n\n/**\n * Builds a CSS selector path from the provided list of elements.\n * @param {EventTarget[]} path Array of HTML Elements from which the path should be built.\n * @return {string[]} Array of string CSS selectors.\n */\nexport function selectorizePath(path: EventTarget[]) {\n let i = 0;\n let pathEle;\n const pathSelectors: string[] = [];\n while ((pathEle = path[i])) {\n pathSelectors.push(getSelector(pathEle));\n ++i;\n pathEle = path[i];\n }\n return pathSelectors;\n}\n\n/**\n * Builds an object containing attributes of an element.\n * Attempts to parse all attribute values as JSON text.\n * @param {Event} e Event from which the target element's attributes should be extracted.\n * @return {Record} Object with element attributes as key-value pairs.\n */\nexport function buildAttrs(e: Event): Record {\n const attributes: Record = {};\n const attributeBlackList = [\"style\"];\n\n if (e.target && e.target instanceof Element) {\n for (const attr of e.target.attributes) {\n if (attributeBlackList.includes(attr.name)) continue;\n let val: any = attr.value;\n try {\n val = JSON.parse(val);\n } catch {\n // Ignore parsing errors, fallback to raw string value\n }\n attributes[attr.name] = val;\n }\n }\n\n return attributes;\n}\n\n/**\n * Builds an object containing all CSS properties of an element.\n * @param {Event} e Event from which the target element's properties should be extracted.\n * @return {Record} Object with all CSS properties as key-value pairs.\n */\nexport function buildCSS(e: Event): Record {\n const properties: Record = {};\n if (e.target && e.target instanceof HTMLElement) {\n const styleObj = e.target.style;\n for (let i = 0; i < styleObj.length; i++) {\n const prop = styleObj[i];\n properties[prop] = styleObj.getPropertyValue(prop);\n }\n }\n return properties;\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { packageLog, packageIntervalLog } from \"@/packageLogs\";\nimport { Events, Logging, Settings } from \"@/types\";\nimport { Configuration } from \"@/configure\";\n\n//@todo: Investigate drag events and their behavior\nlet events: Events.EventDetailsMap;\nlet bufferBools: Events.EventBoolMap;\nlet bufferedEvents: Events.EventDetailsMap;\nlet refreshEvents: Events.EventDetailsMap;\nconst intervalEvents: Array = [\n \"click\",\n \"focus\",\n \"blur\",\n \"input\",\n \"change\",\n \"mouseover\",\n \"submit\",\n];\nconst windowEvents: Array = [\"load\", \"blur\", \"focus\"];\n\n/**\n * Maps a MouseEvent to an object containing useful information.\n * @param {MouseEvent} e Event to extract data from\n */\nexport function extractMouseDetails(e: MouseEvent) {\n return {\n clicks: e.detail,\n ctrl: e.ctrlKey,\n alt: e.altKey,\n shift: e.shiftKey,\n meta: e.metaKey,\n // 'text' : e.target.innerHTML\n };\n}\n\n/** Maps a KeyboardEvent to an object containing useful infromation\n * @param {KeyboardEvent} e Event to extract data from\n */\nexport function extractKeyboardDetails(e: KeyboardEvent) {\n return {\n key: e.key,\n code: e.code,\n ctrl: e.ctrlKey,\n alt: e.altKey,\n shift: e.shiftKey,\n meta: e.metaKey,\n };\n}\n\n/**\n * Maps an InputEvent to an object containing useful information.\n * @param {InputEvent} e Event to extract data from\n */\nexport function extractInputDetails(e: InputEvent) {\n return {\n value: (e.target as HTMLInputElement).value,\n };\n}\n\n/**\n * Maps a ChangeEvent to an object containing useful information.\n * @param {Events.ChangeEvent} e Event to extract data from\n */\nexport function extractChangeDetails(e: Events.ChangeEvent) {\n return {\n value: e.target.value,\n };\n}\n\n/**\n * Maps a WheelEvent to an object containing useful information.\n * @param {WheelEvent} e Event to extract data from\n */\nexport function extractWheelDetails(e: WheelEvent) {\n return {\n x: e.deltaX,\n y: e.deltaY,\n z: e.deltaZ,\n };\n}\n\n/**\n * Maps a ScrollEvent to an object containing useful information.\n */\nexport function extractScrollDetails() {\n return {\n x: window.scrollX,\n y: window.scrollY,\n };\n}\n\n/**\n * Maps a ResizeEvent to an object containing useful information.\n */\nexport function extractResizeDetails() {\n return {\n width: window.outerWidth,\n height: window.outerHeight,\n };\n}\n\n/**\n * Defines the way information is extracted from various events.\n * Also defines which events we will listen to.\n * @param {Settings.Config} config Configuration object to read from.\n */\nexport function defineDetails(config: Settings.DefaultConfig): void {\n // Events list\n // Keys are event types\n // Values are functions that return details object if applicable\n events = {\n click: extractMouseDetails,\n dblclick: extractMouseDetails,\n mousedown: extractMouseDetails,\n mouseup: extractMouseDetails,\n focus: null,\n blur: null,\n input: config.logDetails ? extractKeyboardDetails : null,\n change: config.logDetails ? extractChangeDetails : null,\n dragstart: null,\n dragend: null,\n drag: null,\n drop: null,\n keydown: config.logDetails ? extractKeyboardDetails : null,\n mouseover: null,\n };\n\n bufferBools = {};\n bufferedEvents = {\n wheel: extractWheelDetails,\n scroll: extractScrollDetails,\n resize: extractResizeDetails,\n };\n\n refreshEvents = {\n submit: null,\n };\n}\n\n/**\n * Defines the way information is extracted from various events.\n * Also defines which events we will listen to.\n * @param {Settings.Config} options UserALE Configuration object to read from.\n * @param {Events.AllowedEvents} type of html event (e.g., 'click', 'mouseover', etc.), such as passed to addEventListener methods.\n */\nexport function defineCustomDetails(\n options: Settings.DefaultConfig,\n type: Events.AllowedEvents,\n): Logging.DynamicDetailFunction | null | undefined {\n // Events list\n // Keys are event types\n // Values are functions that return details object if applicable\n const eventType: Events.EventDetailsMap = {\n click: extractMouseDetails,\n dblclick: extractMouseDetails,\n mousedown: extractMouseDetails,\n mouseup: extractMouseDetails,\n focus: null,\n blur: null,\n load: null,\n input: options.logDetails ? extractKeyboardDetails : null,\n change: options.logDetails ? extractChangeDetails : null,\n dragstart: null,\n dragend: null,\n drag: null,\n drop: null,\n keydown: options.logDetails ? extractKeyboardDetails : null,\n mouseover: null,\n wheel: extractWheelDetails,\n scroll: extractScrollDetails,\n resize: extractResizeDetails,\n submit: null,\n };\n return eventType[type];\n}\n\n/**\n * Hooks the event handlers for each event type of interest.\n * @param {Configuration} config Configuration singleton to use.\n * @return {boolean} Whether the operation succeeded\n */\nexport function attachHandlers(config: Configuration): boolean {\n try {\n defineDetails(config);\n\n (Object.keys(events) as Events.AllowedEvents[]).forEach(function (ev) {\n document.addEventListener(\n ev,\n function (e) {\n packageLog(e, events[ev]);\n },\n true,\n );\n });\n\n intervalEvents.forEach(function (ev) {\n document.addEventListener(\n ev,\n function (e) {\n packageIntervalLog(e);\n },\n true,\n );\n });\n\n (Object.keys(bufferedEvents) as Events.BufferedEvents[]).forEach(\n function (ev) {\n bufferBools[ev] = true;\n\n self.addEventListener(\n ev,\n function (e) {\n if (bufferBools[ev]) {\n bufferBools[ev] = false;\n packageLog(e, bufferedEvents[ev]);\n setTimeout(function () {\n bufferBools[ev] = true;\n }, config.resolution);\n }\n },\n true,\n );\n },\n );\n\n (Object.keys(refreshEvents) as Events.RefreshEvents[]).forEach(\n function (ev) {\n document.addEventListener(\n ev,\n function (e) {\n packageLog(e, events[ev]);\n },\n true,\n );\n },\n );\n\n windowEvents.forEach(function (ev) {\n self.addEventListener(\n ev,\n function (e) {\n packageLog(e, function () {\n return { window: true };\n });\n },\n true,\n );\n });\n\n return true;\n } catch {\n return false;\n }\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Configuration } from \"@/configure\";\nimport { Callbacks } from \"@/types\";\n\nexport let authCallback: Callbacks.AuthCallback | null = null;\n\n/**\n * Fetches the most up-to-date auth header string from the auth callback\n * and updates the config object with the new value.\n * @param {Configuration} config Configuration object to be updated.\n * @param {Function} authCallback Callback used to fetch the newest header.\n * @returns {void}\n */\nexport function updateAuthHeader(config: Configuration) {\n if (authCallback) {\n try {\n config.authHeader = authCallback();\n } catch (e) {\n // We should emit the error, but otherwise continue as this could be a temporary issue\n // due to network connectivity or some logic inside the authCallback which is the user's\n // responsibility.\n console.error(`Error encountered while setting the auth header: ${e}`);\n }\n }\n}\n\n/**\n * Registers the provided callback to be used when updating the auth header.\n * @param {Callbacks.AuthCallback} callback Callback used to fetch the newest header. Should return a string.\n * @returns {boolean} Whether the operation succeeded.\n */\nexport function registerAuthCallback(callback: Callbacks.AuthCallback) {\n try {\n verifyCallback(callback);\n authCallback = callback;\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Verify that the provided callback is a function which returns a string\n * @param {Function} callback Callback used to fetch the newest header. Should return a string.\n * @throws {Error} If the callback is not a function or does not return a string.\n * @returns {void}\n */\nexport function verifyCallback(callback: Callbacks.AuthCallback) {\n if (typeof callback !== \"function\") {\n throw new Error(\"Userale auth callback must be a function\");\n }\n const result = callback();\n if (typeof result !== \"string\") {\n throw new Error(\"Userale auth callback must return a string\");\n }\n}\n\n/**\n * Resets the authCallback to null. Used for primarily for testing, but could be used\n * to remove the callback in production.\n * @returns {void}\n */\nexport function resetAuthCallback() {\n authCallback = null;\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Configuration } from \"@/configure\";\nimport { Callbacks } from \"@/types\";\n\nexport let headersCallback: Callbacks.HeadersCallback | null = null;\n\n/**\n * Fetches the most up-to-date custom headers object from the headers callback\n * and updates the config object with the new value.\n * @param {Configuration} config Configuration object to be updated.\n * @param {Callbacks.HeadersCallback} headersCallback Callback used to fetch the newest headers.\n * @returns {void}\n */\nexport function updateCustomHeaders(config: Configuration) {\n if (headersCallback) {\n try {\n config.headers = headersCallback();\n } catch (e) {\n // We should emit the error, but otherwise continue as this could be a temporary issue\n // due to network connectivity or some logic inside the headersCallback which is the user's\n // responsibility.\n console.error(`Error encountered while setting the headers: ${e}`);\n }\n }\n}\n\n/**\n * Registers the provided callback to be used when updating the auth header.\n * @param {Callbacks.HeadersCallback} callback Callback used to fetch the newest headers. Should return an object.\n * @returns {boolean} Whether the operation succeeded.\n */\nexport function registerHeadersCallback(callback: Callbacks.HeadersCallback) {\n try {\n verifyCallback(callback);\n headersCallback = callback;\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Verify that the provided callback is a function which returns a string\n * @param {Callbacks.HeadersCallback} callback Callback used to fetch the newest header. Should return an object.\n * @throws {Error} If the callback is not a function or does not return a string.\n * @returns {void}\n */\nexport function verifyCallback(callback: Callbacks.HeadersCallback) {\n if (typeof callback !== \"function\") {\n throw new Error(\"Userale headers callback must be a function\");\n }\n const result = callback();\n if (typeof result !== \"object\") {\n throw new Error(\"Userale headers callback must return an object\");\n }\n for (const [key, value] of Object.entries(result)) {\n if (typeof key !== \"string\" || typeof value !== \"string\") {\n throw new Error(\n \"Userale header callback must return an object with string keys and values\",\n );\n }\n }\n}\n\n/**\n * Resets the authCallback to null. Used for primarily for testing, but could be used\n * to remove the callback in production.\n * @returns {void}\n */\nexport function resetHeadersCallback() {\n headersCallback = null;\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the 'License'); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an 'AS IS' BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { Settings } from \"./types\";\n\nlet sessionId: string | null = null;\nlet httpSessionId: string | null = null;\n\n/**\n * Extracts the initial configuration settings from the\n * currently executing script tag.\n * @return {Object} The extracted configuration object\n */\nexport function getInitialSettings(): Settings.Config {\n if (\n typeof WorkerGlobalScope !== \"undefined\" &&\n self instanceof WorkerGlobalScope\n ) {\n const settings: Settings.Config = {\n authHeader: null,\n autostart: true,\n browserSessionId: null,\n custIndex: null,\n headers: null,\n httpSessionId: null,\n logCountThreshold: +5,\n logDetails: false,\n resolution: +500,\n sessionId: sessionId,\n time: (ts?: number) => (ts !== undefined ? ts : Date.now()),\n toolName: null,\n toolVersion: null,\n transmitInterval: +5000,\n url: \"http://localhost:8000\",\n useraleVersion: null,\n userFromParams: null,\n userId: null,\n };\n return settings;\n }\n\n if (sessionId === null) {\n sessionId = getsessionId(\n \"userAlesessionId\",\n \"session_\" + String(Date.now()),\n );\n }\n\n if (httpSessionId === null) {\n httpSessionId = getsessionId(\n \"userAleHttpSessionId\",\n generatehttpSessionId(),\n );\n }\n\n const script =\n document.currentScript ||\n (function () {\n const scripts = document.getElementsByTagName(\"script\");\n return scripts[scripts.length - 1];\n })();\n\n const get = script\n ? script.getAttribute.bind(script)\n : function () {\n return null;\n };\n const headers = get(\"data-headers\");\n const settings: Settings.Config = {\n authHeader: get(\"data-auth\") || null,\n autostart: get(\"data-autostart\") === \"false\" ? false : true,\n browserSessionId: null,\n custIndex: get(\"data-index\") || null,\n headers: headers ? JSON.parse(headers) : null,\n httpSessionId: httpSessionId,\n logCountThreshold: +(get(\"data-threshold\") || 5),\n logDetails: get(\"data-log-details\") === \"true\" ? true : false,\n resolution: +(get(\"data-resolution\") || 500),\n sessionId: get(\"data-session\") || sessionId,\n time: timeStampScale(document.createEvent(\"CustomEvent\")),\n toolName: get(\"data-tool\") || null,\n toolVersion: get(\"data-version\") || null,\n transmitInterval: +(get(\"data-interval\") || 5000),\n url: get(\"data-url\") || \"http://localhost:8000\",\n useraleVersion: get(\"data-userale-version\") || null,\n userFromParams: get(\"data-user-from-params\") || null,\n userId: get(\"data-user\") || null,\n };\n return settings;\n}\n\n/**\n * defines sessionId, stores it in sessionStorage, checks to see if there is a sessionId in\n * storage when script is started. This prevents events like 'submit', which refresh page data\n * from refreshing the current user session\n *\n */\nexport function getsessionId(sessionKey: string, value: any) {\n if (self.sessionStorage.getItem(sessionKey) === null) {\n self.sessionStorage.setItem(sessionKey, JSON.stringify(value));\n return value;\n }\n\n return JSON.parse(self.sessionStorage.getItem(sessionKey) || \"\");\n}\n\n/**\n * Creates a function to normalize the timestamp of the provided event.\n * @param {Event} e An event containing a timeStamp property.\n * @return {typeof timeStampScale~tsScaler} The timestamp normalizing function.\n */\nexport function timeStampScale(e: Event): Settings.TimeFunction {\n let tsScaler: Settings.TimeFunction;\n if (e.timeStamp && e.timeStamp > 0) {\n const delta = Date.now() - e.timeStamp;\n /**\n * Returns a timestamp depending on various browser quirks.\n * @param {?Number} ts A timestamp to use for normalization.\n * @return {Number} A normalized timestamp.\n */\n\n if (delta < 0) {\n tsScaler = function () {\n return e.timeStamp / 1000;\n };\n } else if (delta > e.timeStamp) {\n const navStart = performance.timeOrigin;\n tsScaler = function (ts) {\n return ts + navStart;\n };\n } else {\n tsScaler = function (ts) {\n return ts;\n };\n }\n } else {\n tsScaler = function () {\n return Date.now();\n };\n }\n\n return tsScaler;\n}\n\n/**\n * Creates a cryptographiclly random string to represent this http session.\n * @return {String} A random 32 digit hex string\n */\nfunction generatehttpSessionId(): string {\n // 32 digit hex -> 128 bits of info -> 2^64 ~= 10^19 sessions needed for 50% chance of collison\n const len = 32;\n const arr = new Uint8Array(len / 2);\n window.crypto.getRandomValues(arr);\n return Array.from(arr, (dec) => {\n return dec.toString(16).padStart(2, \"0\");\n }).join(\"\");\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getInitialSettings } from \"@/getInitialSettings\";\nimport type { Settings } from \"@/types\";\n\n// Singleton Configuration class\nexport class Configuration {\n [key: string]: Settings.ConfigValueTypes;\n // Private static property to hold the singleton instance\n private static instance: Configuration | null = null;\n\n // Public properties corresponding to fields in the Config interface\n public autostart: boolean = false;\n public authHeader: Settings.AuthHeader = null;\n public browserSessionId: Settings.SessionId = null;\n public custIndex: Settings.CustomIndex = null;\n public headers: Settings.Headers = null;\n public httpSessionId: Settings.SessionId = null;\n public logCountThreshold: number = 0;\n public logDetails: boolean = false;\n public on: boolean = false;\n public resolution: number = 0;\n public sessionId: Settings.SessionId = null;\n public time: Settings.TimeFunction = () => Date.now();\n public toolName: Settings.ToolName = null;\n public toolVersion: Settings.Version = null;\n public transmitInterval: number = 0;\n public url: string = \"\";\n public userFromParams: Settings.UserFromParams = null;\n public useraleVersion: Settings.Version = null;\n public userId: Settings.UserId = null;\n public version: Settings.Version = null;\n public websocketsEnabled: boolean = false;\n\n // Private constructor to prevent external instantiation\n private constructor() {\n // Call the initialization method only if it's the first time instantiating\n if (Configuration.instance === null) {\n this.initialize();\n }\n }\n\n // Static method to get the singleton instance\n public static getInstance(): Configuration {\n if (Configuration.instance === null) {\n Configuration.instance = new Configuration();\n }\n return Configuration.instance;\n }\n\n private initialize(): void {\n const settings = getInitialSettings();\n this.update(settings);\n }\n\n /**\n * Resets the configuration to its initial state.\n */\n public reset(): void {\n this.initialize();\n }\n\n /**\n * Shallow merges a newConfig with the configuration class, updating it.\n * Retrieves/updates the userid if userFromParams is provided.\n * @param {Partial} newConfig Configuration object to merge into the current config.\n */\n public update(newConfig: Partial): void {\n Object.keys(newConfig).forEach((option) => {\n if (option === \"userFromParams\") {\n const userParamString = newConfig[option] as Settings.UserFromParams;\n const userId = userParamString\n ? Configuration.getUserIdFromParams(userParamString)\n : null;\n if (userId) {\n this[\"userId\"] = userId;\n }\n }\n const hasNewUserFromParams = newConfig[\"userFromParams\"];\n const willNullifyUserId =\n option === \"userId\" && newConfig[option] === null;\n if (willNullifyUserId && hasNewUserFromParams) {\n return;\n }\n\n const newOption = newConfig[option];\n if (newOption !== undefined) {\n this[option] = newOption;\n }\n });\n }\n\n /**\n * Attempts to extract the userid from the query parameters of the URL.\n * @param {string} param The name of the query parameter containing the userid.\n * @return {string | null} The extracted/decoded userid, or null if none is found.\n */\n public static getUserIdFromParams(param: string) {\n const userField = param;\n const regex = new RegExp(\"[?&]\" + userField + \"(=([^&#]*)|&|#|$)\");\n const results = window.location.href.match(regex);\n\n if (results && results[2]) {\n return decodeURIComponent(results[2].replace(/\\+/g, \" \"));\n }\n return null;\n }\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Configuration } from \"@/configure\";\nimport { Logging } from \"@/types\";\nimport { updateAuthHeader, updateCustomHeaders } from \"@/utils\";\n\nlet sendIntervalId: string | number | NodeJS.Timeout | undefined;\nlet wsock: WebSocket;\n\n/**\n * Initializes the log queue processors.\n * @param {Array} logs Array of logs to append to.\n * @param {Configuration} config Configuration object to use when logging.\n */\nexport function initSender(logs: Array, config: Configuration) {\n if (sendIntervalId) {\n clearInterval(sendIntervalId);\n }\n\n const url = new URL(config.url);\n if (url.protocol === \"ws:\" || url.protocol === \"wss:\") {\n wsock = new WebSocket(config.url);\n }\n\n sendIntervalId = sendOnInterval(logs, config);\n sendOnClose(logs, config);\n}\n\n/**\n * Checks the provided log array on an interval, flushing the logs\n * if the queue has reached the threshold specified by the provided config.\n * @param {Array} logs Array of logs to read from.\n * @param {Configuration} config Configuration singleton to be read from.\n * @return {Number} The newly created interval id.\n */\nexport function sendOnInterval(\n logs: Array,\n config: Configuration,\n): NodeJS.Timeout {\n return setInterval(function () {\n if (!config.on) {\n return;\n }\n\n if (logs.length >= config.logCountThreshold) {\n sendLogs(logs.slice(0), config, 0); // Send a copy\n logs.splice(0); // Clear array reference (no reassignment)\n }\n }, config.transmitInterval);\n}\n\n// /**\n// * Attempts to flush the remaining logs when the window is closed.\n// * @param {Array} logs Array of logs to be flushed.\n// * @param {Configuration} config Configuration singleton to be read from.\n// */\nexport function sendOnClose(\n logs: Array,\n config: Configuration,\n): void {\n self.addEventListener(\"pagehide\", function () {\n if (!config.on) {\n return;\n }\n\n if (logs.length > 0) {\n const url = new URL(config.url);\n\n if (url.protocol === \"ws:\" || url.protocol === \"wss:\") {\n const data = JSON.stringify(logs);\n wsock.send(data);\n } else {\n const headers: HeadersInit = new Headers();\n headers.set(\"Content-Type\", \"application/json;charset=UTF-8\");\n\n if (config.authHeader) {\n headers.set(\"Authorization\", config.authHeader.toString());\n }\n\n fetch(config.url, {\n keepalive: true,\n method: \"POST\",\n headers: headers,\n body: JSON.stringify(logs),\n }).catch((error) => {\n console.error(error);\n });\n }\n logs.splice(0); // clear log queue\n }\n });\n}\n\n/**\n * Sends the provided array of logs to the specified url,\n * retrying the request up to the specified number of retries.\n * @param {Array} logs Array of logs to send.\n * @param {Configuration} config configuration singleton.\n * @param {Number} retries Maximum number of attempts to send the logs.\n */\nexport async function sendLogs(\n logs: Array,\n config: Configuration,\n retries: number,\n): Promise {\n const data = JSON.stringify(logs);\n const url = new URL(config.url);\n\n if (url.protocol === \"ws:\" || url.protocol === \"wss:\") {\n wsock.send(data);\n return;\n }\n\n // Build headers\n const headers = new Headers({\n \"Content-Type\": \"application/json;charset=UTF-8\",\n });\n\n updateAuthHeader(config);\n if (config.authHeader) {\n const authHeaderValue =\n typeof config.authHeader === \"function\"\n ? config.authHeader()\n : config.authHeader;\n headers.set(\"Authorization\", authHeaderValue);\n }\n\n // Update custom headers last to allow them to over-write the defaults. This assumes\n // the user knows what they are doing and may want to over-write the defaults.\n updateCustomHeaders(config);\n if (config.headers) {\n for (const [header, value] of Object.entries(config.headers)) {\n headers.set(header, value);\n }\n }\n\n async function attemptSend(remainingRetries: number): Promise {\n try {\n const response = await fetch(config.url, {\n method: \"POST\",\n headers,\n body: data,\n });\n\n if (!response.ok) {\n if (remainingRetries > 0) {\n return attemptSend(remainingRetries - 1);\n } else {\n throw new Error(`Failed to send logs: ${response.statusText}`);\n }\n }\n } catch (error) {\n if (remainingRetries > 0) {\n return attemptSend(remainingRetries - 1);\n }\n throw error;\n }\n }\n\n return attemptSend(retries);\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { defineCustomDetails } from \"@/attachHandlers\";\nimport { registerAuthCallback } from \"@/utils\";\nimport {\n addCallbacks,\n removeCallbacks,\n packageLog,\n packageCustomLog,\n getSelector,\n buildPath,\n initPackager,\n} from \"@/packageLogs\";\nimport { version as userAleVersion } from \"../package.json\";\nimport { Configuration } from \"@/configure\";\nimport { attachHandlers } from \"@/attachHandlers\";\nimport { initSender } from \"@/sendLogs\";\n\nimport type { Settings, Logging } from \"@/types\";\n\nconst config = Configuration.getInstance();\nconst logs: Array = [];\n\nconst startLoadTimestamp = Date.now();\nlet endLoadTimestamp: number;\nself.onload = function () {\n endLoadTimestamp = Date.now();\n};\n\nexport let started = false;\nexport { defineCustomDetails as details } from \"@/attachHandlers\";\nexport { registerAuthCallback as registerAuthCallback } from \"@/utils\";\nexport {\n addCallbacks as addCallbacks,\n removeCallbacks as removeCallbacks,\n packageLog as packageLog,\n packageCustomLog as packageCustomLog,\n getSelector as getSelector,\n buildPath as buildPath,\n} from \"@/packageLogs\";\nexport type { Logging } from \"@/types\";\n\nconfig.update({\n useraleVersion: userAleVersion,\n});\ninitPackager(logs, config);\nif (config.autostart) {\n setup(config);\n}\n\n/**\n * Hooks the global event listener, and starts up the\n * logging interval.\n * @param {Configuration} config Configuration settings for the logger\n */\nfunction setup(config: Configuration) {\n if (!started) {\n setTimeout(function () {\n let state;\n try {\n state = document.readyState;\n } catch (error) {\n // Assume there is no DOM and this is a web worker context\n state = \"complete\";\n }\n\n if (\n config.autostart &&\n (state === \"interactive\" || state === \"complete\")\n ) {\n attachHandlers(config);\n initSender(logs, config);\n started = config.on = true;\n if (typeof window !== \"undefined\" && typeof document !== \"undefined\") {\n packageCustomLog(\n {\n type: \"load\",\n details: { pageLoadTime: endLoadTimestamp - startLoadTimestamp },\n },\n () => ({}),\n false,\n );\n }\n } else {\n setup(config);\n }\n }, 100);\n }\n}\n\n// Export the Userale API\nexport const version = userAleVersion;\n\n/**\n * Used to start the logging process if the\n * autostart configuration option is set to false.\n */\nexport function start(): void {\n if (!started || config.autostart === false) {\n started = config.on = true;\n config.update({ autostart: true });\n }\n}\n\n/**\n * Halts the logging process. Logs will no longer be sent.\n */\nexport function stop(): void {\n started = config.on = false;\n config.update({ autostart: false });\n}\n\n/**\n * Updates the current configuration\n * object with the provided values.\n * @param {Partial} newConfig The configuration options to use.\n * @return {Settings.Config} Returns the updated configuration.\n */\nexport function options(\n newConfig: Partial | undefined,\n): Settings.Config {\n if (newConfig) {\n config.update(newConfig);\n }\n\n return config;\n}\n\n/**\n * Appends a log to the log queue.\n * @param {Logging.CustomLog} customLog The log to append.\n * @return {boolean} Whether the operation succeeded.\n */\nexport function log(customLog: Logging.CustomLog | undefined) {\n if (customLog) {\n logs.push(customLog);\n return true;\n } else {\n return false;\n }\n}\n\n// Only attach to window in IIFE builds\nif (typeof window !== \"undefined\") {\n (window as any).userale = {\n start,\n stop,\n options,\n log,\n version: userAleVersion,\n details: defineCustomDetails,\n registerAuthCallback,\n addCallbacks,\n removeCallbacks,\n packageLog,\n packageCustomLog,\n getSelector,\n buildPath,\n };\n}\n"],"mappings":"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","names":["descriptors","log","config","options","config","config","settings","logs","config","config","logs","version"]} \ No newline at end of file +{"version":3,"sources":["../src/packageLogs.ts","../src/attachHandlers.ts","../src/utils/auth/index.ts","../src/utils/headers/index.ts","../src/getInitialSettings.ts","../src/configure.ts","../src/sendLogs.ts","../src/main.ts"],"sourcesContent":["/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Callbacks, Logging } from \"@/types\";\nimport { Configuration } from \"@/configure\";\n\nexport let logs: Array;\nlet config: Configuration;\n\n// Interval Logging Globals\nlet intervalId: string | null;\nlet intervalType: string | null;\nlet intervalPath: string[] | null;\nlet intervalTimer: number | null;\nlet intervalCounter: number | null;\nlet intervalLog: Logging.Log | null;\n\nexport const filterHandler: CallableFunction | null = null;\nexport const mapHandler: CallableFunction | null = null;\nexport let cbHandlers: Callbacks.CallbackMap = {};\n\n/**\n * Adds named callbacks to be executed when logging.\n * @param {Object } newCallbacks An object containing named callback functions.\n */\nexport function addCallbacks(\n ...newCallbacks: Record[]\n) {\n newCallbacks.forEach((source) => {\n let descriptors: { [key in string | symbol]: any } = {};\n\n descriptors = Object.keys(source).reduce((descriptors, key) => {\n descriptors[key] = Object.getOwnPropertyDescriptor(source, key);\n return descriptors;\n }, descriptors);\n\n Object.getOwnPropertySymbols(source).forEach((sym) => {\n const descriptor = Object.getOwnPropertyDescriptor(source, sym);\n if (descriptor?.enumerable) {\n descriptors[sym] = descriptor;\n }\n });\n Object.defineProperties(cbHandlers, descriptors);\n });\n return cbHandlers;\n}\n\n/**\n * Removes callbacks by name.\n * @param {String[]} targetKeys A list of names of functions to remove.\n */\nexport function removeCallbacks(targetKeys: string[]) {\n targetKeys.forEach((key) => {\n if (Object.prototype.hasOwnProperty.call(cbHandlers, key)) {\n delete cbHandlers[key];\n }\n });\n}\n\n/**\n * Assigns the config and log container to be used by the logging functions.\n * @param {Array} newLogs Log container.\n * @param {Object} newConfig Configuration to use while logging.\n */\nexport function initPackager(\n newLogs: Array,\n newConfig: Configuration,\n) {\n logs = newLogs;\n config = newConfig;\n cbHandlers = {};\n intervalId = null;\n intervalType = null;\n intervalPath = null;\n intervalTimer = null;\n intervalCounter = 0;\n intervalLog = null;\n}\n\n/**\n * Transforms the provided HTML event into a log and appends it to the log queue.\n * @param {Event} e The event to be logged.\n * @param {Function} detailFcn The function to extract additional log parameters from the event.\n * @return {boolean} Whether the event was logged.\n */\nexport function packageLog(\n e: Event,\n detailFcn?: Logging.DynamicDetailFunction | null,\n) {\n if (!config.on) {\n return false;\n }\n\n let details = null;\n if (detailFcn) {\n details = detailFcn(e);\n }\n\n const timeFields = extractTimeFields(\n e.timeStamp && e.timeStamp > 0 ? config.time(e.timeStamp) : Date.now(),\n );\n\n let log: Logging.Log = {\n target: e.target ? getSelector(e.target) : null,\n path: buildPath(e),\n pageUrl: self.location.href,\n pageTitle: document.title,\n pageReferrer: document.referrer,\n userAgent: self.navigator.userAgent,\n clientTime: timeFields.milli,\n microTime: timeFields.micro,\n location: getLocation(e),\n scrnRes: getScreenRes(),\n type: e.type,\n logType: \"raw\",\n userAction: true,\n details: details,\n userId: config.userId,\n toolVersion: config.toolVersion,\n toolName: config.toolName,\n useraleVersion: config.useraleVersion,\n sessionId: config.sessionId,\n httpSessionId: config.httpSessionId,\n browserSessionId: config.browserSessionId,\n attributes: buildAttrs(e),\n style: buildCSS(e),\n };\n\n if (typeof filterHandler === \"function\" && !filterHandler(log)) {\n return false;\n }\n\n if (typeof mapHandler === \"function\") {\n log = mapHandler(log, e);\n }\n\n for (const func of Object.values(cbHandlers)) {\n if (typeof func === \"function\") {\n log = func(log, e);\n if (!log) {\n return false;\n }\n }\n }\n\n logs.push(log);\n return true;\n}\n\n/**\n * Packages the provided customLog to include standard meta data and appends it to the log queue.\n * @param {Logging.CustomLog} customLog The behavior to be logged.\n * @param {Logging.DynamicDetailFunction} detailFcn The function to extract additional log parameters from the event.\n * @param {boolean} userAction Indicates user behavior (true) or system behavior (false)\n * @return {boolean} Whether the event was logged.\n */\nexport function packageCustomLog(\n customLog: Logging.CustomLog,\n detailFcn: Logging.DynamicDetailFunction | Logging.StaticDetailFunction,\n userAction: boolean,\n): boolean {\n if (!config.on) {\n return false;\n }\n\n let details = null;\n if (detailFcn.length === 0) {\n // In the case of a union, the type checker will default to the more stringent\n // type, i.e. the DetailFunction that expects an argument for safety purposes.\n // To avoid this, we must explicitly check the type by asserting it receives\n // no arguments (detailFcn.length === 0) and then cast it to the\n // StaticDetailFunction type.\n const staticDetailFcn = detailFcn as Logging.StaticDetailFunction;\n details = staticDetailFcn();\n }\n\n const metaData = {\n pageUrl: self.location.href,\n pageTitle: document.title,\n pageReferrer: document.referrer,\n userAgent: self.navigator.userAgent,\n clientTime: Date.now(),\n scrnRes: getScreenRes(),\n logType: \"custom\",\n userAction: userAction,\n details: details,\n userId: config.userId,\n toolVersion: config.toolVersion,\n toolName: config.toolName,\n useraleVersion: config.useraleVersion,\n sessionId: config.sessionId,\n httpSessionId: config.httpSessionId,\n browserSessionId: config.browserSessionId,\n };\n\n let log = Object.assign(metaData, customLog);\n\n if (typeof filterHandler === \"function\" && !filterHandler(log)) {\n return false;\n }\n\n if (typeof mapHandler === \"function\") {\n log = mapHandler(log);\n }\n\n for (const func of Object.values(cbHandlers)) {\n if (typeof func === \"function\") {\n log = func(log, null);\n if (!log) {\n return false;\n }\n }\n }\n\n logs.push(log);\n\n return true;\n}\n\n/**\n * Extract the millisecond and microsecond portions of a timestamp.\n * @param {Number} timeStamp The timestamp to split into millisecond and microsecond fields.\n * @return {Object} An object containing the millisecond\n * and microsecond portions of the timestamp.\n */\nexport function extractTimeFields(timeStamp: number) {\n return {\n milli: Math.floor(timeStamp),\n micro: Number((timeStamp % 1).toFixed(3)),\n };\n}\n\n/**\n * Track intervals and gather details about it.\n * @param {Object} e\n * @return boolean\n */\nexport function packageIntervalLog(e: Event) {\n try {\n const target = e.target ? getSelector(e.target) : null;\n const path = buildPath(e);\n const type = e.type;\n const timestamp = Math.floor(\n e.timeStamp && e.timeStamp > 0 ? config.time(e.timeStamp) : Date.now(),\n );\n\n // Init - this should only happen once on initialization\n if (intervalId == null) {\n intervalId = target;\n intervalType = type;\n intervalPath = path;\n intervalTimer = timestamp;\n intervalCounter = 0;\n }\n\n if ((intervalId !== target || intervalType !== type) && intervalTimer) {\n // When to create log? On transition end\n // @todo Possible for intervalLog to not be pushed in the event the interval never ends...\n\n intervalLog = {\n target: intervalId,\n path: intervalPath,\n pageUrl: self.location.href,\n pageTitle: document.title,\n pageReferrer: document.referrer,\n userAgent: self.navigator.userAgent,\n count: intervalCounter,\n duration: timestamp - intervalTimer, // microseconds\n startTime: intervalTimer,\n endTime: timestamp,\n type: intervalType,\n logType: \"interval\",\n targetChange: intervalId !== target,\n typeChange: intervalType !== type,\n userAction: false,\n userId: config.userId,\n toolVersion: config.toolVersion,\n toolName: config.toolName,\n useraleVersion: config.useraleVersion,\n sessionId: config.sessionId,\n httpSessionId: config.httpSessionId,\n browserSessionId: config.browserSessionId,\n };\n\n if (typeof filterHandler === \"function\" && !filterHandler(intervalLog)) {\n return false;\n }\n\n if (typeof mapHandler === \"function\") {\n intervalLog = mapHandler(intervalLog, e);\n }\n\n for (const func of Object.values(cbHandlers)) {\n if (typeof func === \"function\") {\n intervalLog = func(intervalLog, null);\n if (!intervalLog) {\n return false;\n }\n }\n }\n\n if (intervalLog) logs.push(intervalLog);\n\n // Reset\n intervalId = target;\n intervalType = type;\n intervalPath = path;\n intervalTimer = timestamp;\n intervalCounter = 0;\n }\n\n // Interval is still occuring, just update counter\n if (intervalId == target && intervalType == type && intervalCounter) {\n intervalCounter = intervalCounter + 1;\n }\n\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Extracts coordinate information from the event\n * depending on a few browser quirks.\n * @param {Event} e The event to extract coordinate information from.\n * @return {Object} An object containing nullable x and y coordinates for the event.\n */\nexport function getLocation(e: Event) {\n if (e instanceof MouseEvent) {\n if (e.pageX != null) {\n return { x: e.pageX, y: e.pageY };\n } else if (e.clientX != null) {\n return {\n x: document.documentElement.scrollLeft + e.clientX,\n y: document.documentElement.scrollTop + e.clientY,\n };\n }\n } else {\n return { x: null, y: null };\n }\n}\n\n/**\n * Extracts innerWidth and innerHeight to provide estimates of screen resolution\n * @return {Object} An object containing the innerWidth and InnerHeight\n */\nexport function getScreenRes() {\n return { width: self.innerWidth, height: self.innerHeight };\n}\n\n/**\n * Builds a string CSS selector from the provided element\n * @param {EventTarget} ele The element from which the selector is built.\n * @return {string} The CSS selector for the element, or Unknown if it can't be determined.\n */\nexport function getSelector(ele: EventTarget) {\n if (ele instanceof HTMLElement || ele instanceof Element) {\n if (ele.localName) {\n return (\n ele.localName +\n (ele.id ? \"#\" + ele.id : \"\") +\n (ele.className ? \".\" + ele.className : \"\")\n );\n } else if (ele.nodeName) {\n return (\n ele.nodeName +\n (ele.id ? \"#\" + ele.id : \"\") +\n (ele.className ? \".\" + ele.className : \"\")\n );\n }\n } else if (ele instanceof Document) {\n return \"#document\";\n } else if (ele === globalThis) {\n return \"Window\";\n }\n return \"Unknown\";\n}\n\n/**\n * Builds an array of elements from the provided event target, to the root element.\n * @param {Event} e Event from which the path should be built.\n * @return {HTMLElement[]} Array of elements, starting at the event target, ending at the root element.\n */\nexport function buildPath(e: Event) {\n const path = e.composedPath();\n return selectorizePath(path);\n}\n\n/**\n * Builds a CSS selector path from the provided list of elements.\n * @param {EventTarget[]} path Array of HTML Elements from which the path should be built.\n * @return {string[]} Array of string CSS selectors.\n */\nexport function selectorizePath(path: EventTarget[]) {\n let i = 0;\n let pathEle;\n const pathSelectors: string[] = [];\n while ((pathEle = path[i])) {\n pathSelectors.push(getSelector(pathEle));\n ++i;\n pathEle = path[i];\n }\n return pathSelectors;\n}\n\n/**\n * Builds an object containing attributes of an element.\n * Attempts to parse all attribute values as JSON text.\n * @param {Event} e Event from which the target element's attributes should be extracted.\n * @return {Record} Object with element attributes as key-value pairs.\n */\nexport function buildAttrs(e: Event): Record {\n const attributes: Record = {};\n const attributeBlackList = [\"style\"];\n\n if (e.target && e.target instanceof Element) {\n for (const attr of e.target.attributes) {\n if (attributeBlackList.includes(attr.name)) continue;\n let val: any = attr.value;\n try {\n val = JSON.parse(val);\n } catch {\n // Ignore parsing errors, fallback to raw string value\n }\n attributes[attr.name] = val;\n }\n }\n\n return attributes;\n}\n\n/**\n * Builds an object containing all CSS properties of an element.\n * @param {Event} e Event from which the target element's properties should be extracted.\n * @return {Record} Object with all CSS properties as key-value pairs.\n */\nexport function buildCSS(e: Event): Record {\n const properties: Record = {};\n if (e.target && e.target instanceof HTMLElement) {\n const styleObj = e.target.style;\n for (let i = 0; i < styleObj.length; i++) {\n const prop = styleObj[i];\n properties[prop] = styleObj.getPropertyValue(prop);\n }\n }\n return properties;\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { packageLog, packageIntervalLog } from \"@/packageLogs\";\nimport { Events, Logging, Settings } from \"@/types\";\nimport { Configuration } from \"@/configure\";\n\n//@todo: Investigate drag events and their behavior\nlet events: Events.EventDetailsMap;\nlet bufferBools: Events.EventBoolMap;\nlet bufferedEvents: Events.EventDetailsMap;\nlet refreshEvents: Events.EventDetailsMap;\nconst intervalEvents: Array = [\n \"click\",\n \"focus\",\n \"blur\",\n \"input\",\n \"change\",\n \"mouseover\",\n \"submit\",\n];\nconst windowEvents: Array = [\"load\", \"blur\", \"focus\"];\n\n/**\n * Maps a MouseEvent to an object containing useful information.\n * @param {MouseEvent} e Event to extract data from\n */\nexport function extractMouseDetails(e: MouseEvent) {\n return {\n clicks: e.detail,\n ctrl: e.ctrlKey,\n alt: e.altKey,\n shift: e.shiftKey,\n meta: e.metaKey,\n // 'text' : e.target.innerHTML\n };\n}\n\n/** Maps a KeyboardEvent to an object containing useful infromation\n * @param {KeyboardEvent} e Event to extract data from\n */\nexport function extractKeyboardDetails(e: KeyboardEvent) {\n return {\n key: e.key,\n code: e.code,\n ctrl: e.ctrlKey,\n alt: e.altKey,\n shift: e.shiftKey,\n meta: e.metaKey,\n };\n}\n\n/**\n * Maps an InputEvent to an object containing useful information.\n * @param {InputEvent} e Event to extract data from\n */\nexport function extractInputDetails(e: InputEvent) {\n return {\n value: (e.target as HTMLInputElement).value,\n };\n}\n\n/**\n * Maps a ChangeEvent to an object containing useful information.\n * @param {Events.ChangeEvent} e Event to extract data from\n */\nexport function extractChangeDetails(e: Events.ChangeEvent) {\n return {\n value: e.target.value,\n };\n}\n\n/**\n * Maps a WheelEvent to an object containing useful information.\n * @param {WheelEvent} e Event to extract data from\n */\nexport function extractWheelDetails(e: WheelEvent) {\n return {\n x: e.deltaX,\n y: e.deltaY,\n z: e.deltaZ,\n };\n}\n\n/**\n * Maps a ScrollEvent to an object containing useful information.\n */\nexport function extractScrollDetails() {\n return {\n x: window.scrollX,\n y: window.scrollY,\n };\n}\n\n/**\n * Maps a ResizeEvent to an object containing useful information.\n */\nexport function extractResizeDetails() {\n return {\n width: window.outerWidth,\n height: window.outerHeight,\n };\n}\n\n/**\n * Defines the way information is extracted from various events.\n * Also defines which events we will listen to.\n * @param {Settings.Config} config Configuration object to read from.\n */\nexport function defineDetails(config: Settings.DefaultConfig): void {\n // Events list\n // Keys are event types\n // Values are functions that return details object if applicable\n events = {\n click: extractMouseDetails,\n dblclick: extractMouseDetails,\n mousedown: extractMouseDetails,\n mouseup: extractMouseDetails,\n focus: null,\n blur: null,\n input: config.logDetails ? extractKeyboardDetails : null,\n change: config.logDetails ? extractChangeDetails : null,\n dragstart: null,\n dragend: null,\n drag: null,\n drop: null,\n keydown: config.logDetails ? extractKeyboardDetails : null,\n mouseover: null,\n };\n\n bufferBools = {};\n bufferedEvents = {\n wheel: extractWheelDetails,\n scroll: extractScrollDetails,\n resize: extractResizeDetails,\n };\n\n refreshEvents = {\n submit: null,\n };\n}\n\n/**\n * Defines the way information is extracted from various events.\n * Also defines which events we will listen to.\n * @param {Settings.Config} options UserALE Configuration object to read from.\n * @param {Events.AllowedEvents} type of html event (e.g., 'click', 'mouseover', etc.), such as passed to addEventListener methods.\n */\nexport function defineCustomDetails(\n options: Settings.DefaultConfig,\n type: Events.AllowedEvents,\n): Logging.DynamicDetailFunction | null | undefined {\n // Events list\n // Keys are event types\n // Values are functions that return details object if applicable\n const eventType: Events.EventDetailsMap = {\n click: extractMouseDetails,\n dblclick: extractMouseDetails,\n mousedown: extractMouseDetails,\n mouseup: extractMouseDetails,\n focus: null,\n blur: null,\n load: null,\n input: options.logDetails ? extractKeyboardDetails : null,\n change: options.logDetails ? extractChangeDetails : null,\n dragstart: null,\n dragend: null,\n drag: null,\n drop: null,\n keydown: options.logDetails ? extractKeyboardDetails : null,\n mouseover: null,\n wheel: extractWheelDetails,\n scroll: extractScrollDetails,\n resize: extractResizeDetails,\n submit: null,\n };\n return eventType[type];\n}\n\n/**\n * Hooks the event handlers for each event type of interest.\n * @param {Configuration} config Configuration singleton to use.\n * @return {boolean} Whether the operation succeeded\n */\nexport function attachHandlers(config: Configuration): boolean {\n try {\n defineDetails(config);\n\n (Object.keys(events) as Events.AllowedEvents[]).forEach(function (ev) {\n document.addEventListener(\n ev,\n function (e) {\n packageLog(e, events[ev]);\n },\n true,\n );\n });\n\n intervalEvents.forEach(function (ev) {\n document.addEventListener(\n ev,\n function (e) {\n packageIntervalLog(e);\n },\n true,\n );\n });\n\n (Object.keys(bufferedEvents) as Events.BufferedEvents[]).forEach(\n function (ev) {\n bufferBools[ev] = true;\n\n self.addEventListener(\n ev,\n function (e) {\n if (bufferBools[ev]) {\n bufferBools[ev] = false;\n packageLog(e, bufferedEvents[ev]);\n setTimeout(function () {\n bufferBools[ev] = true;\n }, config.resolution);\n }\n },\n true,\n );\n },\n );\n\n (Object.keys(refreshEvents) as Events.RefreshEvents[]).forEach(\n function (ev) {\n document.addEventListener(\n ev,\n function (e) {\n packageLog(e, events[ev]);\n },\n true,\n );\n },\n );\n\n windowEvents.forEach(function (ev) {\n self.addEventListener(\n ev,\n function (e) {\n packageLog(e, function () {\n return { window: true };\n });\n },\n true,\n );\n });\n\n return true;\n } catch {\n return false;\n }\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Configuration } from \"@/configure\";\nimport { Callbacks } from \"@/types\";\n\nexport let authCallback: Callbacks.AuthCallback | null = null;\n\n/**\n * Fetches the most up-to-date auth header string from the auth callback\n * and updates the config object with the new value.\n * @param {Configuration} config Configuration object to be updated.\n * @param {Function} authCallback Callback used to fetch the newest header.\n * @returns {void}\n */\nexport function updateAuthHeader(config: Configuration) {\n if (authCallback) {\n try {\n config.authHeader = authCallback();\n } catch (e) {\n // We should emit the error, but otherwise continue as this could be a temporary issue\n // due to network connectivity or some logic inside the authCallback which is the user's\n // responsibility.\n console.error(`Error encountered while setting the auth header: ${e}`);\n }\n }\n}\n\n/**\n * Registers the provided callback to be used when updating the auth header.\n * @param {Callbacks.AuthCallback} callback Callback used to fetch the newest header. Should return a string.\n * @returns {boolean} Whether the operation succeeded.\n */\nexport function registerAuthCallback(callback: Callbacks.AuthCallback) {\n try {\n verifyCallback(callback);\n authCallback = callback;\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Verify that the provided callback is a function which returns a string\n * @param {Function} callback Callback used to fetch the newest header. Should return a string.\n * @throws {Error} If the callback is not a function or does not return a string.\n * @returns {void}\n */\nexport function verifyCallback(callback: Callbacks.AuthCallback) {\n if (typeof callback !== \"function\") {\n throw new Error(\"Userale auth callback must be a function\");\n }\n const result = callback();\n if (typeof result !== \"string\") {\n throw new Error(\"Userale auth callback must return a string\");\n }\n}\n\n/**\n * Resets the authCallback to null. Used for primarily for testing, but could be used\n * to remove the callback in production.\n * @returns {void}\n */\nexport function resetAuthCallback() {\n authCallback = null;\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Configuration } from \"@/configure\";\nimport { Callbacks } from \"@/types\";\n\nexport let headersCallback: Callbacks.HeadersCallback | null = null;\n\n/**\n * Fetches the most up-to-date custom headers object from the headers callback\n * and updates the config object with the new value.\n * @param {Configuration} config Configuration object to be updated.\n * @param {Callbacks.HeadersCallback} headersCallback Callback used to fetch the newest headers.\n * @returns {void}\n */\nexport function updateCustomHeaders(config: Configuration) {\n if (headersCallback) {\n try {\n config.headers = headersCallback();\n } catch (e) {\n // We should emit the error, but otherwise continue as this could be a temporary issue\n // due to network connectivity or some logic inside the headersCallback which is the user's\n // responsibility.\n console.error(`Error encountered while setting the headers: ${e}`);\n }\n }\n}\n\n/**\n * Registers the provided callback to be used when updating the auth header.\n * @param {Callbacks.HeadersCallback} callback Callback used to fetch the newest headers. Should return an object.\n * @returns {boolean} Whether the operation succeeded.\n */\nexport function registerHeadersCallback(callback: Callbacks.HeadersCallback) {\n try {\n verifyCallback(callback);\n headersCallback = callback;\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Verify that the provided callback is a function which returns a string\n * @param {Callbacks.HeadersCallback} callback Callback used to fetch the newest header. Should return an object.\n * @throws {Error} If the callback is not a function or does not return a string.\n * @returns {void}\n */\nexport function verifyCallback(callback: Callbacks.HeadersCallback) {\n if (typeof callback !== \"function\") {\n throw new Error(\"Userale headers callback must be a function\");\n }\n const result = callback();\n if (typeof result !== \"object\") {\n throw new Error(\"Userale headers callback must return an object\");\n }\n for (const [key, value] of Object.entries(result)) {\n if (typeof key !== \"string\" || typeof value !== \"string\") {\n throw new Error(\n \"Userale header callback must return an object with string keys and values\",\n );\n }\n }\n}\n\n/**\n * Resets the authCallback to null. Used for primarily for testing, but could be used\n * to remove the callback in production.\n * @returns {void}\n */\nexport function resetHeadersCallback() {\n headersCallback = null;\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the 'License'); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an 'AS IS' BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { Settings } from \"./types\";\n\nlet sessionId: string | null = null;\nlet httpSessionId: string | null = null;\n\n/**\n * Extracts the initial configuration settings from the\n * currently executing script tag.\n * @return {Object} The extracted configuration object\n */\nexport function getInitialSettings(): Settings.Config {\n if (\n typeof WorkerGlobalScope !== \"undefined\" &&\n self instanceof WorkerGlobalScope\n ) {\n const settings: Settings.Config = {\n apiKey: null,\n authHeader: null,\n autostart: true,\n browserSessionId: null,\n custIndex: null,\n headers: null,\n httpSessionId: null,\n logCountThreshold: +5,\n logDetails: false,\n resolution: +500,\n sessionId: sessionId,\n time: (ts?: number) => (ts !== undefined ? ts : Date.now()),\n toolName: null,\n toolVersion: null,\n transmitInterval: +5000,\n url: \"http://localhost:8000\",\n useraleVersion: null,\n userFromParams: null,\n userId: null,\n };\n return settings;\n }\n\n if (sessionId === null) {\n sessionId = getsessionId(\n \"userAlesessionId\",\n \"session_\" + String(Date.now()),\n );\n }\n\n if (httpSessionId === null) {\n httpSessionId = getsessionId(\n \"userAleHttpSessionId\",\n generatehttpSessionId(),\n );\n }\n\n const script =\n document.currentScript ||\n (function () {\n const scripts = document.getElementsByTagName(\"script\");\n return scripts[scripts.length - 1];\n })();\n\n const get = script\n ? script.getAttribute.bind(script)\n : function () {\n return null;\n };\n const headers = get(\"data-headers\");\n const settings: Settings.Config = {\n apiKey: get(\"data-api-key\") || null,\n authHeader: get(\"data-auth\") || null,\n autostart: get(\"data-autostart\") === \"false\" ? false : true,\n browserSessionId: null,\n custIndex: get(\"data-index\") || null,\n headers: headers ? JSON.parse(headers) : null,\n httpSessionId: httpSessionId,\n logCountThreshold: +(get(\"data-threshold\") || 5),\n logDetails: get(\"data-log-details\") === \"true\" ? true : false,\n resolution: +(get(\"data-resolution\") || 500),\n sessionId: get(\"data-session\") || sessionId,\n time: timeStampScale(document.createEvent(\"CustomEvent\")),\n toolName: get(\"data-tool\") || null,\n toolVersion: get(\"data-version\") || null,\n transmitInterval: +(get(\"data-interval\") || 5000),\n url: get(\"data-url\") || \"http://localhost:8000\",\n useraleVersion: get(\"data-userale-version\") || null,\n userFromParams: get(\"data-user-from-params\") || null,\n userId: get(\"data-user\") || null,\n };\n return settings;\n}\n\n/**\n * defines sessionId, stores it in sessionStorage, checks to see if there is a sessionId in\n * storage when script is started. This prevents events like 'submit', which refresh page data\n * from refreshing the current user session\n *\n */\nexport function getsessionId(sessionKey: string, value: any) {\n if (self.sessionStorage.getItem(sessionKey) === null) {\n self.sessionStorage.setItem(sessionKey, JSON.stringify(value));\n return value;\n }\n\n return JSON.parse(self.sessionStorage.getItem(sessionKey) || \"\");\n}\n\n/**\n * Creates a function to normalize the timestamp of the provided event.\n * @param {Event} e An event containing a timeStamp property.\n * @return {typeof timeStampScale~tsScaler} The timestamp normalizing function.\n */\nexport function timeStampScale(e: Event): Settings.TimeFunction {\n let tsScaler: Settings.TimeFunction;\n if (e.timeStamp && e.timeStamp > 0) {\n const delta = Date.now() - e.timeStamp;\n /**\n * Returns a timestamp depending on various browser quirks.\n * @param {?Number} ts A timestamp to use for normalization.\n * @return {Number} A normalized timestamp.\n */\n\n if (delta < 0) {\n tsScaler = function () {\n return e.timeStamp / 1000;\n };\n } else if (delta > e.timeStamp) {\n const navStart = performance.timeOrigin;\n tsScaler = function (ts) {\n return ts + navStart;\n };\n } else {\n tsScaler = function (ts) {\n return ts;\n };\n }\n } else {\n tsScaler = function () {\n return Date.now();\n };\n }\n\n return tsScaler;\n}\n\n/**\n * Creates a cryptographiclly random string to represent this http session.\n * @return {String} A random 32 digit hex string\n */\nfunction generatehttpSessionId(): string {\n // 32 digit hex -> 128 bits of info -> 2^64 ~= 10^19 sessions needed for 50% chance of collison\n const len = 32;\n const arr = new Uint8Array(len / 2);\n window.crypto.getRandomValues(arr);\n return Array.from(arr, (dec) => {\n return dec.toString(16).padStart(2, \"0\");\n }).join(\"\");\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getInitialSettings } from \"@/getInitialSettings\";\nimport type { Settings } from \"@/types\";\n\n// Singleton Configuration class\nexport class Configuration {\n [key: string]: Settings.ConfigValueTypes;\n // Private static property to hold the singleton instance\n private static instance: Configuration | null = null;\n\n // Public properties corresponding to fields in the Config interface\n public apiKey: Settings.ApiKey = null;\n public autostart: boolean = false;\n public authHeader: Settings.AuthHeader = null;\n public browserSessionId: Settings.SessionId = null;\n public custIndex: Settings.CustomIndex = null;\n public headers: Settings.Headers = null;\n public httpSessionId: Settings.SessionId = null;\n public logCountThreshold: number = 0;\n public logDetails: boolean = false;\n public on: boolean = false;\n public resolution: number = 0;\n public sessionId: Settings.SessionId = null;\n public time: Settings.TimeFunction = () => Date.now();\n public toolName: Settings.ToolName = null;\n public toolVersion: Settings.Version = null;\n public transmitInterval: number = 0;\n public url: string = \"\";\n public userFromParams: Settings.UserFromParams = null;\n public useraleVersion: Settings.Version = null;\n public userId: Settings.UserId = null;\n public version: Settings.Version = null;\n public websocketsEnabled: boolean = false;\n\n // Private constructor to prevent external instantiation\n private constructor() {\n // Call the initialization method only if it's the first time instantiating\n if (Configuration.instance === null) {\n this.initialize();\n }\n }\n\n // Static method to get the singleton instance\n public static getInstance(): Configuration {\n if (Configuration.instance === null) {\n Configuration.instance = new Configuration();\n }\n return Configuration.instance;\n }\n\n private initialize(): void {\n const settings = getInitialSettings();\n this.update(settings);\n }\n\n /**\n * Resets the configuration to its initial state.\n */\n public reset(): void {\n this.initialize();\n }\n\n /**\n * Shallow merges a newConfig with the configuration class, updating it.\n * Retrieves/updates the userid if userFromParams is provided.\n * @param {Partial} newConfig Configuration object to merge into the current config.\n */\n public update(newConfig: Partial): void {\n Object.keys(newConfig).forEach((option) => {\n if (option === \"userFromParams\") {\n const userParamString = newConfig[option] as Settings.UserFromParams;\n const userId = userParamString\n ? Configuration.getUserIdFromParams(userParamString)\n : null;\n if (userId) {\n this[\"userId\"] = userId;\n }\n }\n const hasNewUserFromParams = newConfig[\"userFromParams\"];\n const willNullifyUserId =\n option === \"userId\" && newConfig[option] === null;\n if (willNullifyUserId && hasNewUserFromParams) {\n return;\n }\n\n const newOption = newConfig[option];\n if (newOption !== undefined) {\n this[option] = newOption;\n }\n });\n }\n\n /**\n * Attempts to extract the userid from the query parameters of the URL.\n * @param {string} param The name of the query parameter containing the userid.\n * @return {string | null} The extracted/decoded userid, or null if none is found.\n */\n public static getUserIdFromParams(param: string) {\n const userField = param;\n const regex = new RegExp(\"[?&]\" + userField + \"(=([^&#]*)|&|#|$)\");\n const results = window.location.href.match(regex);\n\n if (results && results[2]) {\n return decodeURIComponent(results[2].replace(/\\+/g, \" \"));\n }\n return null;\n }\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Configuration } from \"@/configure\";\nimport { Logging } from \"@/types\";\nimport { updateAuthHeader, updateCustomHeaders } from \"@/utils\";\n\nlet sendIntervalId: string | number | NodeJS.Timeout | undefined;\nlet wsock: WebSocket;\n\n/**\n * Initializes the log queue processors.\n * @param {Array} logs Array of logs to append to.\n * @param {Configuration} config Configuration object to use when logging.\n */\nexport function initSender(logs: Array, config: Configuration) {\n if (sendIntervalId) {\n clearInterval(sendIntervalId);\n }\n\n const url = new URL(config.url);\n if (url.protocol === \"ws:\" || url.protocol === \"wss:\") {\n wsock = new WebSocket(config.url);\n }\n\n sendIntervalId = sendOnInterval(logs, config);\n sendOnClose(logs, config);\n}\n\n/**\n * Checks the provided log array on an interval, flushing the logs\n * if the queue has reached the threshold specified by the provided config.\n * @param {Array} logs Array of logs to read from.\n * @param {Configuration} config Configuration singleton to be read from.\n * @return {Number} The newly created interval id.\n */\nexport function sendOnInterval(\n logs: Array,\n config: Configuration,\n): NodeJS.Timeout {\n return setInterval(function () {\n if (!config.on) {\n return;\n }\n\n if (logs.length >= config.logCountThreshold) {\n sendLogs(logs.slice(0), config, 0); // Send a copy\n logs.splice(0); // Clear array reference (no reassignment)\n }\n }, config.transmitInterval);\n}\n\n// /**\n// * Attempts to flush the remaining logs when the window is closed.\n// * @param {Array} logs Array of logs to be flushed.\n// * @param {Configuration} config Configuration singleton to be read from.\n// */\nexport function sendOnClose(\n logs: Array,\n config: Configuration,\n): void {\n self.addEventListener(\"pagehide\", function () {\n if (!config.on) {\n return;\n }\n\n if (logs.length > 0) {\n const url = new URL(config.url);\n\n if (url.protocol === \"ws:\" || url.protocol === \"wss:\") {\n const data = JSON.stringify(logs);\n wsock.send(data);\n } else {\n const headers: HeadersInit = new Headers();\n headers.set(\"Content-Type\", \"application/json;charset=UTF-8\");\n\n if (config.authHeader) {\n headers.set(\"Authorization\", config.authHeader.toString());\n }\n\n if (config.apiKey) {\n headers.set(\"x-api-key\", config.apiKey as string);\n }\n\n fetch(config.url, {\n keepalive: true,\n method: \"POST\",\n headers: headers,\n body: JSON.stringify(logs),\n }).catch((error) => {\n console.error(error);\n });\n }\n logs.splice(0); // clear log queue\n }\n });\n}\n\n/**\n * Sends the provided array of logs to the specified url,\n * retrying the request up to the specified number of retries.\n * @param {Array} logs Array of logs to send.\n * @param {Configuration} config configuration singleton.\n * @param {Number} retries Maximum number of attempts to send the logs.\n */\nexport async function sendLogs(\n logs: Array,\n config: Configuration,\n retries: number,\n): Promise {\n const data = JSON.stringify(logs);\n const url = new URL(config.url);\n\n if (url.protocol === \"ws:\" || url.protocol === \"wss:\") {\n wsock.send(data);\n return;\n }\n\n // Build headers\n const headers = new Headers({\n \"Content-Type\": \"application/json;charset=UTF-8\",\n });\n\n updateAuthHeader(config);\n if (config.authHeader) {\n const authHeaderValue =\n typeof config.authHeader === \"function\"\n ? config.authHeader()\n : config.authHeader;\n headers.set(\"Authorization\", authHeaderValue);\n }\n\n if (config.apiKey) {\n headers.set(\"x-api-key\", config.apiKey as string);\n }\n\n // Update custom headers last to allow them to over-write the defaults. This assumes\n // the user knows what they are doing and may want to over-write the defaults.\n updateCustomHeaders(config);\n if (config.headers) {\n for (const [header, value] of Object.entries(config.headers)) {\n headers.set(header, value);\n }\n }\n\n async function attemptSend(remainingRetries: number): Promise {\n try {\n const response = await fetch(config.url, {\n method: \"POST\",\n headers,\n body: data,\n });\n\n if (!response.ok) {\n if (remainingRetries > 0) {\n return attemptSend(remainingRetries - 1);\n } else {\n throw new Error(`Failed to send logs: ${response.statusText}`);\n }\n }\n } catch (error) {\n if (remainingRetries > 0) {\n return attemptSend(remainingRetries - 1);\n }\n throw error;\n }\n }\n\n return attemptSend(retries);\n}\n","/*!\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { defineCustomDetails } from \"@/attachHandlers\";\nimport { registerAuthCallback } from \"@/utils\";\nimport {\n addCallbacks,\n removeCallbacks,\n packageLog,\n packageCustomLog,\n getSelector,\n buildPath,\n initPackager,\n} from \"@/packageLogs\";\nimport { version as userAleVersion } from \"../package.json\";\nimport { Configuration } from \"@/configure\";\nimport { attachHandlers } from \"@/attachHandlers\";\nimport { initSender } from \"@/sendLogs\";\n\nimport type { Settings, Logging } from \"@/types\";\n\nconst config = Configuration.getInstance();\nconst logs: Array = [];\n\nconst startLoadTimestamp = Date.now();\nlet endLoadTimestamp: number;\nself.onload = function () {\n endLoadTimestamp = Date.now();\n};\n\nexport let started = false;\nexport { defineCustomDetails as details } from \"@/attachHandlers\";\nexport { registerAuthCallback as registerAuthCallback } from \"@/utils\";\nexport {\n addCallbacks as addCallbacks,\n removeCallbacks as removeCallbacks,\n packageLog as packageLog,\n packageCustomLog as packageCustomLog,\n getSelector as getSelector,\n buildPath as buildPath,\n} from \"@/packageLogs\";\nexport type { Logging } from \"@/types\";\n\nconfig.update({\n useraleVersion: userAleVersion,\n});\ninitPackager(logs, config);\nif (config.autostart) {\n setup(config);\n}\n\n/**\n * Hooks the global event listener, and starts up the\n * logging interval.\n * @param {Configuration} config Configuration settings for the logger\n */\nfunction setup(config: Configuration) {\n if (!started) {\n setTimeout(function () {\n let state;\n try {\n state = document.readyState;\n } catch (error) {\n // Assume there is no DOM and this is a web worker context\n state = \"complete\";\n }\n\n if (\n config.autostart &&\n (state === \"interactive\" || state === \"complete\")\n ) {\n attachHandlers(config);\n initSender(logs, config);\n started = config.on = true;\n if (typeof window !== \"undefined\" && typeof document !== \"undefined\") {\n packageCustomLog(\n {\n type: \"load\",\n details: { pageLoadTime: endLoadTimestamp - startLoadTimestamp },\n },\n () => ({}),\n false,\n );\n }\n } else {\n setup(config);\n }\n }, 100);\n }\n}\n\n// Export the Userale API\nexport const version = userAleVersion;\n\n/**\n * Used to start the logging process if the\n * autostart configuration option is set to false.\n */\nexport function start(): void {\n if (!started || config.autostart === false) {\n started = config.on = true;\n config.update({ autostart: true });\n }\n}\n\n/**\n * Halts the logging process. Logs will no longer be sent.\n */\nexport function stop(): void {\n started = config.on = false;\n config.update({ autostart: false });\n}\n\n/**\n * Updates the current configuration\n * object with the provided values.\n * @param {Partial} newConfig The configuration options to use.\n * @return {Settings.Config} Returns the updated configuration.\n */\nexport function options(\n newConfig: Partial | undefined,\n): Settings.Config {\n if (newConfig) {\n config.update(newConfig);\n }\n\n return config;\n}\n\n/**\n * Appends a log to the log queue.\n * @param {Logging.CustomLog} customLog The log to append.\n * @return {boolean} Whether the operation succeeded.\n */\nexport function log(customLog: Logging.CustomLog | undefined) {\n if (customLog) {\n logs.push(customLog);\n return true;\n } else {\n return false;\n }\n}\n\n// Only attach to window in IIFE builds\nif (typeof window !== \"undefined\") {\n (window as any).userale = {\n start,\n stop,\n options,\n log,\n version: userAleVersion,\n details: defineCustomDetails,\n registerAuthCallback,\n addCallbacks,\n removeCallbacks,\n packageLog,\n packageCustomLog,\n getSelector,\n buildPath,\n };\n}\n"],"mappings":"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","names":["descriptors","log","config","options","config","config","settings","logs","config","config","logs","version"]} \ No newline at end of file diff --git a/products/userale/packages/flagon-userale/build/packageLogs.d.ts.map b/products/userale/packages/flagon-userale/build/packageLogs.d.ts.map new file mode 100644 index 0000000..5bb4d6c --- /dev/null +++ b/products/userale/packages/flagon-userale/build/packageLogs.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"packageLogs.d.ts","sourceRoot":"","sources":["../src/packageLogs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,eAAO,IAAI,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAWpC,eAAO,MAAM,aAAa,EAAE,gBAAgB,GAAG,IAAW,CAAC;AAC3D,eAAO,MAAM,UAAU,EAAE,gBAAgB,GAAG,IAAW,CAAC;AACxD,eAAO,IAAI,UAAU,EAAE,SAAS,CAAC,WAAgB,CAAC;AAElD;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,GAAG,YAAY,EAAE,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,gBAAgB,CAAC,EAAE,yBAmB7D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,QAMnD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAC3B,SAAS,EAAE,aAAa,QAWzB;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,CAAC,EAAE,KAAK,EACR,SAAS,CAAC,EAAE,OAAO,CAAC,qBAAqB,GAAG,IAAI,WA4DjD;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,OAAO,CAAC,SAAS,EAC5B,SAAS,EAAE,OAAO,CAAC,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,EACvE,UAAU,EAAE,OAAO,GAClB,OAAO,CAyDT;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM;;;EAKlD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,KAAK,WAmF1C;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK;;;;;;cAanC;AAED;;;GAGG;AACH,wBAAgB,YAAY;;;EAE3B;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,WAAW,UAqB3C;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,KAAK,YAGjC;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,WAAW,EAAE,YAUlD;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAkBxD;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUzD"} \ No newline at end of file diff --git a/products/userale/packages/flagon-userale/build/sendLogs.d.ts.map b/products/userale/packages/flagon-userale/build/sendLogs.d.ts.map new file mode 100644 index 0000000..7a5a658 --- /dev/null +++ b/products/userale/packages/flagon-userale/build/sendLogs.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"sendLogs.d.ts","sourceRoot":"","sources":["../src/sendLogs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAMlC;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,aAAa,QAYzE;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EACxB,MAAM,EAAE,aAAa,GACpB,MAAM,CAAC,OAAO,CAWhB;AAOD,wBAAgB,WAAW,CACzB,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EACxB,MAAM,EAAE,aAAa,GACpB,IAAI,CAoCN;AAED;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EACxB,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CA4Df"} \ No newline at end of file diff --git a/products/userale/packages/flagon-userale/build/utils/auth/index.d.ts.map b/products/userale/packages/flagon-userale/build/utils/auth/index.d.ts.map new file mode 100644 index 0000000..fc6f601 --- /dev/null +++ b/products/userale/packages/flagon-userale/build/utils/auth/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/auth/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,eAAO,IAAI,YAAY,EAAE,SAAS,CAAC,YAAY,GAAG,IAAW,CAAC;AAE9D;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,QAWrD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,SAAS,CAAC,YAAY,WAQpE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,CAAC,YAAY,QAQ9D;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,SAEhC"} \ No newline at end of file diff --git a/products/userale/packages/flagon-userale/build/utils/headers/index.d.ts.map b/products/userale/packages/flagon-userale/build/utils/headers/index.d.ts.map new file mode 100644 index 0000000..44c4256 --- /dev/null +++ b/products/userale/packages/flagon-userale/build/utils/headers/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/headers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,eAAO,IAAI,eAAe,EAAE,SAAS,CAAC,eAAe,GAAG,IAAW,CAAC;AAEpE;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,QAWxD;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,SAAS,CAAC,eAAe,WAQ1E;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,CAAC,eAAe,QAejE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,SAEnC"} \ No newline at end of file diff --git a/products/userale/packages/flagon-userale/build/utils/index.d.ts.map b/products/userale/packages/flagon-userale/build/utils/index.d.ts.map new file mode 100644 index 0000000..35bb97a --- /dev/null +++ b/products/userale/packages/flagon-userale/build/utils/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,cAAc,IAAI,kBAAkB,GACrC,MAAM,QAAQ,CAAC;AAChB,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,uBAAuB,EACvB,oBAAoB,EACpB,cAAc,IAAI,qBAAqB,GACxC,MAAM,WAAW,CAAC"} \ No newline at end of file diff --git a/products/userale/packages/flagon-userale/src/configure.ts b/products/userale/packages/flagon-userale/src/configure.ts index a3d08ac..6e42776 100644 --- a/products/userale/packages/flagon-userale/src/configure.ts +++ b/products/userale/packages/flagon-userale/src/configure.ts @@ -25,6 +25,7 @@ export class Configuration { private static instance: Configuration | null = null; // Public properties corresponding to fields in the Config interface + public apiKey: Settings.ApiKey = null; public autostart: boolean = false; public authHeader: Settings.AuthHeader = null; public browserSessionId: Settings.SessionId = null; diff --git a/products/userale/packages/flagon-userale/src/getInitialSettings.ts b/products/userale/packages/flagon-userale/src/getInitialSettings.ts index 324e977..7fc5623 100644 --- a/products/userale/packages/flagon-userale/src/getInitialSettings.ts +++ b/products/userale/packages/flagon-userale/src/getInitialSettings.ts @@ -31,6 +31,7 @@ export function getInitialSettings(): Settings.Config { self instanceof WorkerGlobalScope ) { const settings: Settings.Config = { + apiKey: null, authHeader: null, autostart: true, browserSessionId: null, @@ -81,6 +82,7 @@ export function getInitialSettings(): Settings.Config { }; const headers = get("data-headers"); const settings: Settings.Config = { + apiKey: get("data-api-key") || null, authHeader: get("data-auth") || null, autostart: get("data-autostart") === "false" ? false : true, browserSessionId: null, diff --git a/products/userale/packages/flagon-userale/src/sendLogs.ts b/products/userale/packages/flagon-userale/src/sendLogs.ts index 89ed67f..87e6425 100644 --- a/products/userale/packages/flagon-userale/src/sendLogs.ts +++ b/products/userale/packages/flagon-userale/src/sendLogs.ts @@ -92,6 +92,10 @@ export function sendOnClose( headers.set("Authorization", config.authHeader.toString()); } + if (config.apiKey) { + headers.set("x-api-key", config.apiKey as string); + } + fetch(config.url, { keepalive: true, method: "POST", @@ -140,6 +144,10 @@ export async function sendLogs( headers.set("Authorization", authHeaderValue); } + if (config.apiKey) { + headers.set("x-api-key", config.apiKey as string); + } + // Update custom headers last to allow them to over-write the defaults. This assumes // the user knows what they are doing and may want to over-write the defaults. updateCustomHeaders(config); diff --git a/products/userale/packages/flagon-userale/src/types.d.ts b/products/userale/packages/flagon-userale/src/types.d.ts index ec277ab..c72d830 100644 --- a/products/userale/packages/flagon-userale/src/types.d.ts +++ b/products/userale/packages/flagon-userale/src/types.d.ts @@ -21,6 +21,7 @@ export declare namespace Settings { type UserFromParams = string | null; type ToolName = string | null; type AuthHeader = CallableFunction | string | null; + type ApiKey = string | null; type CustomIndex = string | null; type HeaderObject = { [key: string]: string }; type Headers = HeaderObject | null; @@ -35,6 +36,7 @@ export declare namespace Settings { | UserFromParams | ToolName | AuthHeader + | ApiKey | CustomIndex | Headers; @@ -46,6 +48,7 @@ export declare namespace Settings { export interface Config extends DefaultConfig { autostart: boolean; + apiKey: ApiKey; authHeader: AuthHeader; browserSessionId: SessionId; custIndex: CustomIndex; diff --git a/products/userale/packages/flagon-userale/test/spec/configure.spec.ts b/products/userale/packages/flagon-userale/test/spec/configure.spec.ts index 2dd8d85..5238121 100644 --- a/products/userale/packages/flagon-userale/test/spec/configure.spec.ts +++ b/products/userale/packages/flagon-userale/test/spec/configure.spec.ts @@ -63,6 +63,15 @@ describe("configure", () => { done(); }); + it("allows apiKey to be set via config.update()", (done) => { + config.update({ apiKey: "test-api-key-123" }); + expect(config.apiKey).toBe("test-api-key-123"); + + config.update({ apiKey: null }); + expect(config.apiKey).toBeNull(); + done(); + }); + describe("getUserIdFromParams", () => { it("fetches userId from URL params", (done) => { Object.defineProperty(global.window, "location", { diff --git a/products/userale/packages/flagon-userale/test/spec/sendLogs.spec.ts b/products/userale/packages/flagon-userale/test/spec/sendLogs.spec.ts index f7fc602..8455b95 100644 --- a/products/userale/packages/flagon-userale/test/spec/sendLogs.spec.ts +++ b/products/userale/packages/flagon-userale/test/spec/sendLogs.spec.ts @@ -163,6 +163,65 @@ describe("sendLogs", () => { done(); }); + it("sends x-api-key header when config.apiKey is set", () => { + const fetchSpy = jest.spyOn(global, "fetch").mockResolvedValue(new Response()); + + config.update({ + on: true, + url: "http://test.com", + apiKey: "my-secret-key", + }); + sendOnClose([{ foo: "bar" }], config); + global.window.dispatchEvent(new window.CustomEvent("pagehide")); + + expect(fetchSpy).toHaveBeenCalled(); + const lastCall = fetchSpy.mock.calls[fetchSpy.mock.calls.length - 1]!; + const callHeaders = lastCall[1]!.headers as Headers; + expect(callHeaders.get("x-api-key")).toBe("my-secret-key"); + + fetchSpy.mockRestore(); + }); + + it("does not send x-api-key header when config.apiKey is null", () => { + const fetchSpy = jest.spyOn(global, "fetch").mockResolvedValue(new Response()); + + config.update({ + on: true, + url: "http://test.com", + apiKey: null, + }); + sendOnClose([{ foo: "bar" }], config); + global.window.dispatchEvent(new window.CustomEvent("pagehide")); + + expect(fetchSpy).toHaveBeenCalled(); + const lastCall = fetchSpy.mock.calls[fetchSpy.mock.calls.length - 1]!; + const callHeaders = lastCall[1]!.headers as Headers; + expect(callHeaders.get("x-api-key")).toBeNull(); + + fetchSpy.mockRestore(); + }); + + it("sends both Authorization and x-api-key headers when both are configured", () => { + const fetchSpy = jest.spyOn(global, "fetch").mockResolvedValue(new Response()); + + config.update({ + on: true, + url: "http://test.com", + authHeader: "Bearer some-token", + apiKey: "my-secret-key", + }); + sendOnClose([{ foo: "bar" }], config); + global.window.dispatchEvent(new window.CustomEvent("pagehide")); + + expect(fetchSpy).toHaveBeenCalled(); + const lastCall = fetchSpy.mock.calls[fetchSpy.mock.calls.length - 1]!; + const callHeaders = lastCall[1]!.headers as Headers; + expect(callHeaders.get("Authorization")).toBe("Bearer some-token"); + expect(callHeaders.get("x-api-key")).toBe("my-secret-key"); + + fetchSpy.mockRestore(); + }); + it("sends logs with proper custom headers when using registerHeadersCallback", (done) => { const logs: Array = []; config.update({