@elbwalker/utils
Version:
Shared utils for walkerOS packages
1 lines • 42 kB
Source Map (JSON)
{"version":3,"sources":["../src/web/browser.ts","../src/web/elb.ts","../src/web/getAttribute.ts","../src/core/constants.ts","../src/core/is.ts","../src/web/getHashWeb.ts","../src/web/isVisible.ts","../src/core/assign.ts","../src/core/send.ts","../src/core/tryCatch.ts","../src/web/sendWeb.ts","../src/core/castValue.ts","../src/core/getId.ts","../src/core/consent.ts","../src/core/getMarketingParameters.ts","../src/web/session/sessionStart.ts","../src/web/storage.ts","../src/web/session/sessionStorage.ts","../src/web/session/sessionWindow.ts"],"sourcesContent":["export function getLanguage(navigatorRef: Navigator): string | undefined {\n return navigatorRef.language;\n}\n\nexport function getTimezone(): string | undefined {\n return Intl.DateTimeFormat().resolvedOptions().timeZone;\n}\n\nexport function getScreenSize(windowRef: Window): string {\n return `${windowRef.screen.width}x${windowRef.screen.height}`;\n}\n","import type { Elb } from '@elbwalker/types';\n\nexport const elb: Elb.Fn = function () {\n const w = window as unknown as Record<string, unknown[]>;\n (w.elbLayer = w.elbLayer || []).push(arguments);\n};\n","export function getAttribute(element: Element, name: string): string {\n return (element.getAttribute(name) || '').trim();\n}\n","import type { WalkerOS } from '@elbwalker/types';\n\nexport type CommandTypes =\n | 'Action'\n | 'Config'\n | 'Consent'\n | 'Context'\n | 'Custom'\n | 'Destination'\n | 'Elb'\n | 'Globals'\n | 'Hook'\n | 'Init'\n | 'Link'\n | 'On'\n | 'Prefix'\n | 'Ready'\n | 'Run'\n | 'Session'\n | 'User'\n | 'Walker';\n\n// Define Commands with keys as CommandTypes\nexport const Commands: Record<CommandTypes, WalkerOS.Commands> = {\n Action: 'action',\n Config: 'config',\n Consent: 'consent',\n Context: 'context',\n Custom: 'custom',\n Destination: 'destination',\n Elb: 'elb',\n Globals: 'globals',\n Hook: 'hook',\n Init: 'init',\n Link: 'link',\n On: 'on',\n Prefix: 'data-elb',\n Ready: 'ready',\n Run: 'run',\n Session: 'session',\n User: 'user',\n Walker: 'walker',\n} as const;\n\nexport type StorageType = 'cookie' | 'local' | 'session';\n\nconst UtilsStorage: { [key: string]: StorageType } = {\n Cookie: 'cookie',\n Local: 'local',\n Session: 'session',\n} as const;\n\nconst Utils = {\n Storage: UtilsStorage,\n};\n\nexport const Const = {\n Commands,\n Utils,\n};\n\nexport default Const;\n","import type { WalkerOS } from '@elbwalker/types';\nimport { Const } from './constants';\n\nexport function isArguments(value: unknown): value is IArguments {\n return Object.prototype.toString.call(value) === '[object Arguments]';\n}\n\nexport function isArray<T>(value: unknown): value is T[] {\n return Array.isArray(value);\n}\n\nexport function isBoolean(value: unknown): value is boolean {\n return typeof value === 'boolean';\n}\n\nexport function isCommand(entity: string) {\n return entity === Const.Commands.Walker;\n}\n\nexport function isDefined<T>(val: T | undefined): val is T {\n return typeof val !== 'undefined';\n}\n\nexport function isElementOrDocument(elem: unknown): elem is Element {\n return elem === document || elem instanceof Element;\n}\n\nexport function isNumber(value: unknown): value is number {\n return typeof value === 'number' && !Number.isNaN(value);\n}\n\nexport function isObject(value: unknown): value is WalkerOS.AnyObject {\n return (\n typeof value === 'object' &&\n value !== null &&\n !isArray(value) &&\n Object.prototype.toString.call(value) === '[object Object]'\n );\n}\n\nexport function isSameType<T>(\n variable: unknown,\n type: T,\n): variable is typeof type {\n return typeof variable === typeof type;\n}\n\nexport function isString(value: unknown): value is string {\n return typeof value === 'string';\n}\n","import { isDefined } from '../core/is';\n\nasync function sha256(message: string): Promise<string | undefined> {\n const crypto: Crypto | undefined =\n isDefined(window) && window.crypto ? window.crypto : undefined;\n\n // Crypto API not available\n if (!crypto || !crypto.subtle || !TextEncoder) return;\n\n const msgBuffer = new TextEncoder().encode(message);\n const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashHex = hashArray\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n return hashHex;\n}\n\nexport async function getHashWeb(\n str: string,\n length?: number,\n): Promise<string> {\n return ((await sha256(str)) || '').slice(0, length);\n}\n","export function isVisible(element: HTMLElement): boolean {\n // Check for hiding styles\n const style = getComputedStyle(element);\n if (style.display === 'none') return false;\n if (style.visibility !== 'visible') return false;\n if (style.opacity && Number(style.opacity) < 0.1) return false;\n\n // Window positions\n let pointContainer;\n const windowHeight = window.innerHeight; // Height of the viewport\n\n // Element positions\n const elemRectRel = element.getBoundingClientRect(); // Get the elements relative to the viewport\n const elementHeight = elemRectRel.height; // Height of the element\n const elementTopRel = elemRectRel.y; // Relative distance from window top to element top\n const elementBottomRel = elementTopRel + elementHeight; // Relative distance from window to to element bottom\n const elemCenterRel = {\n // Relative position on viewport of the elements center\n x: elemRectRel.x + element.offsetWidth / 2,\n y: elemRectRel.y + element.offsetHeight / 2,\n };\n\n // Differentiate between small and large elements\n if (elementHeight <= windowHeight) {\n // Smaller than the viewport\n\n // Must have a width and height\n if (\n element.offsetWidth + elemRectRel.width === 0 ||\n element.offsetHeight + elemRectRel.height === 0\n )\n return false;\n\n if (elemCenterRel.x < 0) return false;\n if (\n elemCenterRel.x >\n (document.documentElement.clientWidth || window.innerWidth)\n )\n return false;\n if (elemCenterRel.y < 0) return false;\n if (\n elemCenterRel.y >\n (document.documentElement.clientHeight || window.innerHeight)\n )\n return false;\n\n // Select the element that is at the center of the target\n pointContainer = document.elementFromPoint(\n elemCenterRel.x,\n elemCenterRel.y,\n );\n } else {\n // Bigger than the viewport\n\n // that are considered visible if they fill half of the screen\n const viewportCenter = windowHeight / 2;\n\n // Check if upper part is above the viewports center\n if (elementTopRel < 0 && elementBottomRel < viewportCenter) return false;\n\n // Check if lower part is below the viewports center\n if (elementBottomRel > windowHeight && elementTopRel > viewportCenter)\n return false;\n\n // Select the element that is in the middle of the screen\n pointContainer = document.elementFromPoint(\n elemCenterRel.x,\n windowHeight / 2,\n );\n }\n\n // Check for potential overlays\n if (pointContainer) {\n do {\n if (pointContainer === element) return true; // should be visible\n } while ((pointContainer = pointContainer.parentElement));\n }\n\n return false;\n}\n","interface Assign {\n merge?: boolean; // Merge array properties (default) instead of overriding them\n shallow?: boolean; // Create a shallow copy (default) instead of updating the target object\n extend?: boolean; // Extend the target with new properties (default) instead of only updating existing ones\n}\n\nconst defaultOptions: Assign = {\n merge: true,\n shallow: true,\n extend: true,\n};\n\nexport function assign<T extends object, U extends object>(\n target: T,\n obj: U = {} as U,\n options: Assign = {},\n): T & U {\n options = { ...defaultOptions, ...options };\n\n const finalObj = Object.entries(obj).reduce((acc, [key, sourceProp]) => {\n const targetProp = target[key as keyof typeof target];\n\n // Only merge arrays\n if (\n options.merge &&\n Array.isArray(targetProp) &&\n Array.isArray(sourceProp)\n ) {\n acc[key as keyof typeof acc] = sourceProp.reduce(\n (acc, item) => {\n // Remove duplicates\n return acc.includes(item) ? acc : [...acc, item];\n },\n [...targetProp],\n );\n } else if (options.extend || key in target) {\n // Extend the target with new properties or update existing ones\n acc[key as keyof typeof acc] = sourceProp;\n }\n\n return acc;\n }, {} as U);\n\n // Handle shallow or deep copy based on options\n if (options.shallow) {\n return { ...target, ...finalObj };\n } else {\n Object.assign(target, finalObj);\n return target as T & U;\n }\n}\n","import type { WalkerOS } from '@elbwalker/types';\nimport { isSameType } from './is';\nimport { assign } from './assign';\n\nexport type SendDataValue = WalkerOS.Property | WalkerOS.Properties;\nexport type SendHeaders = { [key: string]: string };\n\nexport interface SendResponse {\n ok: boolean;\n data?: unknown;\n error?: string;\n}\n\nexport function transformData(data?: SendDataValue): string | undefined {\n if (data === undefined) return data;\n\n return isSameType(data, '' as string) ? data : JSON.stringify(data);\n}\n\nexport function getHeaders(headers: SendHeaders = {}): SendHeaders {\n return assign(\n {\n 'Content-Type': 'application/json; charset=utf-8',\n },\n headers,\n );\n}\n","// Use function overload to support different return type depending on onError\n// Types\nexport function tryCatch<P extends unknown[], R, S>(\n fn: (...args: P) => R | undefined,\n onError: (err: unknown) => S,\n onFinally?: () => void,\n): (...args: P) => R | S;\nexport function tryCatch<P extends unknown[], R>(\n fn: (...args: P) => R | undefined,\n onError?: undefined,\n onFinally?: () => void,\n): (...args: P) => R | undefined;\n// Implementation\nexport function tryCatch<P extends unknown[], R, S>(\n fn: (...args: P) => R | undefined,\n onError?: (err: unknown) => S,\n onFinally?: () => void,\n): (...args: P) => R | S | undefined {\n return function (...args: P): R | S | undefined {\n try {\n return fn(...args);\n } catch (err) {\n if (!onError) return;\n return onError(err);\n } finally {\n onFinally?.();\n }\n };\n}\n\n// Use function overload to support different return type depending on onError\n// Types\nexport function tryCatchAsync<P extends unknown[], R, S>(\n fn: (...args: P) => R,\n onError: (err: unknown) => S,\n onFinally?: () => void | Promise<void>,\n): (...args: P) => Promise<R | S>;\nexport function tryCatchAsync<P extends unknown[], R>(\n fn: (...args: P) => R,\n onError?: undefined,\n onFinally?: () => void | Promise<void>,\n): (...args: P) => Promise<R | undefined>;\n// Implementation\nexport function tryCatchAsync<P extends unknown[], R, S>(\n fn: (...args: P) => R,\n onError?: (err: unknown) => S,\n onFinally?: () => void | Promise<void>,\n): (...args: P) => Promise<R | S | undefined> {\n return async function (...args: P): Promise<R | S | undefined> {\n try {\n return await fn(...args);\n } catch (err) {\n if (!onError) return;\n return await onError(err);\n } finally {\n await onFinally?.();\n }\n };\n}\n","import type { SendDataValue, SendHeaders, SendResponse } from '../core/send';\nimport { getHeaders, transformData } from '../core/send';\nimport { tryCatch, tryCatchAsync } from '../core/tryCatch';\n\nexport type SendWebTransport = 'fetch' | 'beacon' | 'xhr';\n\nexport interface SendWebOptions {\n headers?: SendHeaders;\n transport?: SendWebTransport;\n method?: string;\n}\n\nexport interface SendWebOptionsFetch extends SendWebOptions {\n credentials?: 'omit' | 'same-origin' | 'include'; // Add credentials option\n noCors?: boolean; // Add noCors option for fetch transport\n}\n\ntype SendWebOptionsDynamic<T extends SendWebTransport> = T extends 'fetch'\n ? SendWebOptionsFetch\n : SendWebOptions;\n\nexport type SendWebReturn<T extends SendWebTransport> = T extends 'fetch'\n ? Promise<SendResponse>\n : SendResponse;\n\nexport function sendWeb<T extends SendWebTransport>(\n url: string,\n data?: SendDataValue,\n options: SendWebOptionsDynamic<T> & { transport?: T } = {\n transport: 'fetch' as T,\n },\n): SendWebReturn<T> {\n const transport = options.transport || 'fetch';\n\n switch (transport) {\n case 'beacon':\n return sendWebAsBeacon(url, data) as SendWebReturn<T>;\n case 'xhr':\n return sendWebAsXhr(url, data, options) as SendWebReturn<T>;\n case 'fetch':\n default:\n return sendWebAsFetch(url, data, options) as SendWebReturn<T>;\n }\n}\n\nexport async function sendWebAsFetch(\n url: string,\n data?: SendDataValue,\n options: SendWebOptionsFetch = {},\n): Promise<SendResponse> {\n const headers = getHeaders(options.headers);\n const body = transformData(data);\n\n return tryCatchAsync(\n async () => {\n const response = await fetch(url, {\n method: options.method || 'POST',\n headers,\n keepalive: true,\n credentials: options.credentials || 'same-origin',\n mode: options.noCors ? 'no-cors' : 'cors',\n body,\n });\n\n const responseData = options.noCors ? '' : await response.text();\n\n return {\n ok: response.ok,\n data: responseData,\n error: response.ok ? undefined : response.statusText,\n };\n },\n (error) => {\n return {\n ok: false,\n error: (error as Error).message,\n };\n },\n )();\n}\n\nexport function sendWebAsBeacon(\n url: string,\n data?: SendDataValue,\n): SendResponse {\n const body = transformData(data);\n const ok = navigator.sendBeacon(url, body);\n\n return {\n ok,\n error: ok ? undefined : 'Failed to send beacon',\n };\n}\n\nexport function sendWebAsXhr(\n url: string,\n data?: SendDataValue,\n options: SendWebOptions = {},\n): SendResponse {\n const headers = getHeaders(options.headers);\n const method = options.method || 'POST';\n const body = transformData(data);\n\n return tryCatch(\n () => {\n const xhr = new XMLHttpRequest();\n xhr.open(method, url, false); // Synchronous request\n for (const header in headers) {\n xhr.setRequestHeader(header, headers[header]);\n }\n xhr.send(body);\n\n const ok = xhr.status >= 200 && xhr.status < 300;\n\n const parsedData = tryCatch(JSON.parse, () => xhr.response)(xhr.response);\n\n return {\n ok,\n data: parsedData,\n error: ok ? undefined : `${xhr.status} ${xhr.statusText}`,\n };\n },\n (error) => {\n return {\n ok: false,\n error: (error as Error).message,\n };\n },\n )();\n}\n","import type { WalkerOS } from '@elbwalker/types';\n\nexport function castValue(value: unknown): WalkerOS.PropertyType {\n if (value === 'true') return true;\n if (value === 'false') return false;\n\n const number = Number(value); // Converts \"\" to 0\n if (value == number && value !== '') return number;\n\n return String(value);\n}\n","export function getId(length = 6): string {\n let str = '';\n for (let l = 36; str.length < length; )\n str += ((Math.random() * l) | 0).toString(l);\n return str;\n}\n","import type { WalkerOS, Elb } from '@elbwalker/types';\nimport { assign } from './assign';\nimport { pushToDestinations, createPushResult } from './destination';\nimport { onApply } from './on';\n\nexport function getGrantedConsent(\n required: WalkerOS.Consent | undefined,\n state: WalkerOS.Consent = {},\n individual: WalkerOS.Consent = {},\n): false | WalkerOS.Consent {\n // Merge state and individual, prioritizing individual states\n const states: WalkerOS.Consent = { ...state, ...individual };\n\n const grantedStates: WalkerOS.Consent = {};\n let hasRequiredConsent = required === undefined;\n\n Object.keys(states).forEach((name) => {\n if (states[name]) {\n // consent granted\n grantedStates[name] = true;\n\n // Check if it's required and granted consent\n if (required && required[name]) hasRequiredConsent = true;\n }\n });\n\n return hasRequiredConsent ? grantedStates : false;\n}\n\nexport async function setConsent(\n instance: WalkerOS.Instance,\n data: WalkerOS.Consent,\n): Promise<Elb.PushResult> {\n const { consent } = instance;\n\n let runQueue = false;\n const update: WalkerOS.Consent = {};\n Object.entries(data).forEach(([name, granted]) => {\n const state = !!granted;\n\n update[name] = state;\n\n // Only run queue if state was set to true\n runQueue = runQueue || state;\n });\n\n // Update consent state\n instance.consent = assign(consent, update);\n\n // Run on consent events\n onApply(instance, 'consent', undefined, update);\n\n // Process previous events if not disabled\n return runQueue\n ? pushToDestinations(instance)\n : createPushResult({ ok: true });\n}\n","import type { WalkerOS } from '@elbwalker/types';\nimport { assign } from './assign';\n\nexport interface MarketingParameters {\n [key: string]: string;\n}\n\nexport function getMarketingParameters(\n url: URL,\n custom: MarketingParameters = {},\n): WalkerOS.Properties {\n const clickId = 'clickId';\n const data: WalkerOS.Properties = {};\n const parameters: MarketingParameters = {\n utm_campaign: 'campaign',\n utm_content: 'content',\n utm_medium: 'medium',\n utm_source: 'source',\n utm_term: 'term',\n dclid: clickId,\n fbclid: clickId,\n gclid: clickId,\n msclkid: clickId,\n ttclid: clickId,\n twclid: clickId,\n igshid: clickId,\n sclid: clickId,\n };\n\n Object.entries(assign(parameters, custom)).forEach(([key, name]) => {\n const param = url.searchParams.get(key); // Search for the parameter in the URL\n if (param) {\n if (name === clickId) {\n name = key;\n data[clickId] = key; // Reference the clickId parameter\n }\n\n data[name] = param;\n }\n });\n\n return data;\n}\n","import type { WalkerOS } from '@elbwalker/types';\nimport type { SessionStorageConfig } from './';\nimport { sessionStorage, sessionWindow } from './';\nimport { elb as elbOrg } from '../elb';\nimport { isArray, isDefined, isString } from '../../core/is';\nimport { getGrantedConsent } from '../../core';\n\nexport interface SessionConfig extends SessionStorageConfig {\n consent?: string | string[];\n storage?: boolean;\n cb?: SessionCallback | false;\n instance?: WalkerOS.Instance;\n}\n\nexport type SessionFunction = typeof sessionStorage | typeof sessionWindow;\nexport type SessionCallback = (\n session: WalkerOS.SessionData,\n instance: WalkerOS.Instance | undefined,\n defaultCb: SessionCallback,\n) => void;\n\nexport function sessionStart(\n config: SessionConfig = {},\n): WalkerOS.SessionData | void {\n const { cb, consent, instance, storage } = config;\n const elb = instance?.push || elbOrg;\n const sessionFn: SessionFunction = storage ? sessionStorage : sessionWindow;\n\n // Consent\n if (consent) {\n const consentHandler = onConsentFn(config, cb);\n\n const consentConfig = (\n isArray(consent) ? consent : [consent]\n ).reduce<WalkerOS.AnyObject>(\n (acc, key) => ({ ...acc, [key]: consentHandler }),\n {},\n );\n elb('walker on', 'consent', consentConfig);\n } else {\n // just do it\n return callFuncAndCb(sessionFn(config), instance, cb);\n }\n}\n\nfunction callFuncAndCb(\n session: WalkerOS.SessionData,\n instance?: WalkerOS.Instance,\n cb?: SessionCallback | false,\n) {\n if (cb === false) return session; // Callback is disabled\n if (!cb) cb = defaultCb; // Default callback if none is provided\n return cb(session, instance, defaultCb);\n}\n\nfunction onConsentFn(config: SessionConfig, cb?: SessionCallback | false) {\n // Track the last processed group to prevent duplicate processing\n let lastProcessedGroup: string | undefined;\n\n const func = (instance: WalkerOS.Instance, consent: WalkerOS.Consent) => {\n // Skip if we've already processed this group\n if (isDefined(lastProcessedGroup) && lastProcessedGroup === instance?.group)\n return;\n\n // Remember this group has been processed\n lastProcessedGroup = instance?.group;\n\n let sessionFn: SessionFunction = () => sessionWindow(config); // Window by default\n\n if (config.consent) {\n const consentKeys = (\n isArray(config.consent) ? config.consent : [config.consent]\n ).reduce<WalkerOS.Consent>((acc, key) => ({ ...acc, [key]: true }), {});\n\n if (getGrantedConsent(consentKeys, consent))\n // Use storage if consent is granted\n sessionFn = () => sessionStorage(config);\n }\n\n return callFuncAndCb(sessionFn(), instance, cb);\n };\n\n return func;\n}\n\nconst defaultCb: SessionCallback = (\n session,\n instance,\n): WalkerOS.SessionData => {\n const elb = instance?.push || elbOrg;\n const user: WalkerOS.User = {};\n\n // User.session is the session ID\n if (session.id) user.session = session.id;\n\n // Set device ID only in storage mode\n if (session.storage && session.device) user.device = session.device;\n\n // Set user IDs\n elb('walker user', user);\n\n if (session.isStart) elb('session start', session);\n\n return session;\n};\n","import type { WalkerOS } from '@elbwalker/types';\nimport type { StorageType } from '../core/constants';\nimport Const from '../core/constants';\nimport { castValue } from '../core/castValue';\n\nexport interface StorageValue {\n e: number; // Expiration timestamp\n v: string; // Value\n}\n\nexport function storageDelete(\n key: string,\n storage: StorageType = Const.Utils.Storage.Session,\n) {\n switch (storage) {\n case Const.Utils.Storage.Cookie:\n storageWrite(key, '', 0, storage);\n break;\n case Const.Utils.Storage.Local:\n window.localStorage.removeItem(key);\n break;\n case Const.Utils.Storage.Session:\n window.sessionStorage.removeItem(key);\n break;\n }\n}\n\nexport function storageRead(\n key: string,\n storage: StorageType = Const.Utils.Storage.Session,\n): WalkerOS.PropertyType {\n // Helper function for local and session storage to support expiration\n function parseItem(string: string | null): StorageValue {\n try {\n return JSON.parse(string || '');\n } catch (err) {\n let e = 1,\n v = '';\n\n // Remove expiration date\n if (string) {\n e = 0;\n v = string;\n }\n\n return { e, v };\n }\n }\n let value, item;\n\n switch (storage) {\n case Const.Utils.Storage.Cookie:\n value = decodeURIComponent(\n document.cookie\n .split('; ')\n .find((row) => row.startsWith(key + '='))\n ?.split('=')[1] || '',\n );\n break;\n case Const.Utils.Storage.Local:\n item = parseItem(window.localStorage.getItem(key));\n break;\n case Const.Utils.Storage.Session:\n item = parseItem(window.sessionStorage.getItem(key));\n break;\n }\n\n // Check if item is expired\n if (item) {\n value = item.v;\n\n if (item.e != 0 && item.e < Date.now()) {\n storageDelete(key, storage); // Remove item\n value = ''; // Conceal the outdated value\n }\n }\n\n return castValue(value || '');\n}\n\nexport function storageWrite(\n key: string,\n value: WalkerOS.PropertyType,\n maxAgeInMinutes = 30,\n storage: StorageType = Const.Utils.Storage.Session,\n domain?: string,\n): WalkerOS.PropertyType {\n const e = Date.now() + 1000 * 60 * maxAgeInMinutes;\n const item: StorageValue = { e, v: String(value) };\n const stringifiedItem = JSON.stringify(item);\n\n switch (storage) {\n case Const.Utils.Storage.Cookie: {\n value = typeof value === 'object' ? JSON.stringify(value) : value;\n let cookie = `${key}=${encodeURIComponent(value)}; max-age=${\n maxAgeInMinutes * 60\n }; path=/; SameSite=Lax; secure`;\n\n if (domain) cookie += '; domain=' + domain;\n\n document.cookie = cookie;\n break;\n }\n case Const.Utils.Storage.Local:\n window.localStorage.setItem(key, stringifiedItem);\n break;\n case Const.Utils.Storage.Session:\n window.sessionStorage.setItem(key, stringifiedItem);\n break;\n }\n\n return storageRead(key, storage);\n}\n","import type { WalkerOS } from '@elbwalker/types';\nimport type { SessionWindowConfig } from '.';\nimport type { StorageType } from '../../core/constants';\nimport { storageRead, storageWrite } from '../storage';\nimport { sessionWindow } from '.';\nimport { tryCatch } from '../../core/tryCatch';\nimport { getId } from '../../core/getId';\n\nexport interface SessionStorageConfig extends SessionWindowConfig {\n deviceKey?: string;\n deviceStorage?: StorageType;\n deviceAge?: number;\n sessionKey?: string;\n sessionStorage?: StorageType;\n length?: number; // Minutes after last update to consider session as expired (default: 30)\n pulse?: boolean;\n}\n\nexport function sessionStorage(\n config: SessionStorageConfig = {},\n): WalkerOS.SessionData {\n const now = Date.now();\n const {\n length = 30, // Session length in minutes\n deviceKey = 'elbDeviceId',\n deviceStorage = 'local',\n deviceAge = 30, // Device ID age in days\n sessionKey = 'elbSessionId',\n sessionStorage = 'local',\n pulse = false, // Handle the counting\n } = config;\n const windowSession = sessionWindow(config); // Status based on window only\n let isStart = false;\n\n // Retrieve or create device ID\n const device = tryCatch((key: string, age: number, storage: StorageType) => {\n let id = storageRead(key, storage);\n if (!id) {\n id = getId(8); // Create a new device ID\n storageWrite(key, id, age * 1440, storage); // Write device ID to storage\n }\n return String(id);\n })(deviceKey, deviceAge, deviceStorage);\n\n // Retrieve or initialize session data\n const existingSession: WalkerOS.SessionData =\n tryCatch(\n (key: string, storage?: StorageType) => {\n const session = JSON.parse(String(storageRead(key, storage)));\n\n // Only update session if it's not a pulse check\n if (pulse) return session;\n\n // Mark session as not new by default\n session.isNew = false;\n\n // Handle new marketing entry\n if (windowSession.marketing) {\n Object.assign(session, windowSession); // Overwrite existing session with marketing data\n isStart = true; // This is a session start\n }\n\n // Check if session is still active\n if (isStart || session.updated + length * 60000 < now) {\n // Session has expired\n delete session.id; // Unset session ID\n delete session.referrer; // Unset referrer\n session.start = now; // Set new session start\n session.count++; // Increase session count\n session.runs = 1; // Reset runs\n isStart = true; // It's a new session\n } else {\n // Session is still active\n session.runs++; // Increase number of runs\n }\n\n return session;\n },\n () => {\n // No existing session or something went wrong\n isStart = true; // Start a new session\n },\n )(sessionKey, sessionStorage) || {};\n\n // Default session data\n const defaultSession: Partial<WalkerOS.SessionData> = {\n id: getId(12),\n start: now,\n isNew: true,\n count: 1,\n runs: 1,\n };\n\n // Merge session data\n const session = Object.assign(\n defaultSession, // Default session values\n windowSession, // Basic session data based on window\n existingSession, // (Updated) existing session\n { device }, // Device ID\n { isStart, storage: true, updated: now }, // Status of the session\n config.data, // Given data has the highest priority\n );\n\n // Write (updated) session to storage\n storageWrite(sessionKey, JSON.stringify(session), length * 2, sessionStorage);\n\n return session;\n}\n","import type { WalkerOS } from '@elbwalker/types';\nimport type { MarketingParameters } from '../../core/getMarketingParameters';\nimport { getMarketingParameters } from '../../core/getMarketingParameters';\nimport { getId } from '../../core/getId';\n\nexport interface SessionWindowConfig {\n data?: WalkerOS.Properties;\n domains?: string[];\n isStart?: boolean;\n parameters?: MarketingParameters;\n referrer?: string;\n url?: string;\n}\n\nexport function sessionWindow(\n config: SessionWindowConfig = {},\n): WalkerOS.SessionData {\n let isStart = config.isStart || false;\n const known = { isStart, storage: false };\n\n // If session has explicitly started, return known\n if (config.isStart === false) return known;\n\n // Entry type\n if (!isStart) {\n // Only focus on linked or direct navigation types\n // and ignore reloads and all others\n const [perf] = performance.getEntriesByType(\n 'navigation',\n ) as PerformanceNavigationTiming[];\n if (perf.type !== 'navigate') return known;\n }\n\n const url = new URL(config.url || window.location.href);\n const ref = config.referrer || document.referrer;\n const referrer = ref && new URL(ref).hostname;\n\n // Marketing\n const marketing = getMarketingParameters(url, config.parameters);\n if (Object.keys(marketing).length) {\n // Check for marketing parameters like UTM and add existing\n if (!marketing.marketing)\n // Flag as a marketing session without overwriting\n marketing.marketing = true;\n\n isStart = true;\n }\n\n // Referrer\n if (!isStart) {\n // Small chance of multiple unintended events for same users\n // https://en.wikipedia.org/wiki/HTTP_referer#Referrer_hiding\n // Use domains: [''] to disable direct or hidden referrer\n\n const domains = config.domains || [];\n domains.push(url.hostname);\n isStart = !domains.includes(referrer);\n }\n\n return isStart\n ? // It's a session start, moin\n Object.assign(\n {\n isStart,\n storage: false,\n start: Date.now(),\n id: getId(12),\n referrer,\n },\n marketing,\n config.data,\n )\n : // No session start\n known;\n}\n"],"mappings":";AAAO,SAAS,YAAY,cAA6C;AACvE,SAAO,aAAa;AACtB;AAEO,SAAS,cAAkC;AAChD,SAAO,KAAK,eAAe,EAAE,gBAAgB,EAAE;AACjD;AAEO,SAAS,cAAc,WAA2B;AACvD,SAAO,GAAG,UAAU,OAAO,KAAK,IAAI,UAAU,OAAO,MAAM;AAC7D;;;ACRO,IAAM,MAAc,WAAY;AACrC,QAAM,IAAI;AACV,GAAC,EAAE,WAAW,EAAE,YAAY,CAAC,GAAG,KAAK,SAAS;AAChD;;;ACLO,SAAS,aAAa,SAAkB,MAAsB;AACnE,UAAQ,QAAQ,aAAa,IAAI,KAAK,IAAI,KAAK;AACjD;;;ACqBO,IAAM,WAAoD;AAAA,EAC/D,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,KAAK;AAAA,EACL,SAAS;AAAA,EACT,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,IAAI;AAAA,EACJ,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,KAAK;AAAA,EACL,SAAS;AAAA,EACT,MAAM;AAAA,EACN,QAAQ;AACV;AAIA,IAAM,eAA+C;AAAA,EACnD,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,SAAS;AACX;AAEA,IAAM,QAAQ;AAAA,EACZ,SAAS;AACX;AAEO,IAAM,QAAQ;AAAA,EACnB;AAAA,EACA;AACF;AAEA,IAAO,oBAAQ;;;ACtDR,SAAS,QAAW,OAA8B;AACvD,SAAO,MAAM,QAAQ,KAAK;AAC5B;AAUO,SAAS,UAAa,KAA8B;AACzD,SAAO,OAAO,QAAQ;AACxB;AAmBO,SAAS,WACd,UACA,MACyB;AACzB,SAAO,OAAO,aAAa,OAAO;AACpC;;;AC3CA,eAAe,OAAO,SAA8C;AAClE,QAAM,SACJ,UAAU,MAAM,KAAK,OAAO,SAAS,OAAO,SAAS;AAGvD,MAAI,CAAC,UAAU,CAAC,OAAO,UAAU,CAAC,YAAa;AAE/C,QAAM,YAAY,IAAI,YAAY,EAAE,OAAO,OAAO;AAClD,QAAM,aAAa,MAAM,OAAO,OAAO,OAAO,WAAW,SAAS;AAClE,QAAM,YAAY,MAAM,KAAK,IAAI,WAAW,UAAU,CAAC;AACvD,QAAM,UAAU,UACb,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAC1C,KAAK,EAAE;AACV,SAAO;AACT;AAEA,eAAsB,WACpB,KACA,QACiB;AACjB,UAAS,MAAM,OAAO,GAAG,KAAM,IAAI,MAAM,GAAG,MAAM;AACpD;;;ACvBO,SAAS,UAAU,SAA+B;AAEvD,QAAM,QAAQ,iBAAiB,OAAO;AACtC,MAAI,MAAM,YAAY,OAAQ,QAAO;AACrC,MAAI,MAAM,eAAe,UAAW,QAAO;AAC3C,MAAI,MAAM,WAAW,OAAO,MAAM,OAAO,IAAI,IAAK,QAAO;AAGzD,MAAI;AACJ,QAAM,eAAe,OAAO;AAG5B,QAAM,cAAc,QAAQ,sBAAsB;AAClD,QAAM,gBAAgB,YAAY;AAClC,QAAM,gBAAgB,YAAY;AAClC,QAAM,mBAAmB,gBAAgB;AACzC,QAAM,gBAAgB;AAAA;AAAA,IAEpB,GAAG,YAAY,IAAI,QAAQ,cAAc;AAAA,IACzC,GAAG,YAAY,IAAI,QAAQ,eAAe;AAAA,EAC5C;AAGA,MAAI,iBAAiB,cAAc;AAIjC,QACE,QAAQ,cAAc,YAAY,UAAU,KAC5C,QAAQ,eAAe,YAAY,WAAW;AAE9C,aAAO;AAET,QAAI,cAAc,IAAI,EAAG,QAAO;AAChC,QACE,cAAc,KACb,SAAS,gBAAgB,eAAe,OAAO;AAEhD,aAAO;AACT,QAAI,cAAc,IAAI,EAAG,QAAO;AAChC,QACE,cAAc,KACb,SAAS,gBAAgB,gBAAgB,OAAO;AAEjD,aAAO;AAGT,qBAAiB,SAAS;AAAA,MACxB,cAAc;AAAA,MACd,cAAc;AAAA,IAChB;AAAA,EACF,OAAO;AAIL,UAAM,iBAAiB,eAAe;AAGtC,QAAI,gBAAgB,KAAK,mBAAmB,eAAgB,QAAO;AAGnE,QAAI,mBAAmB,gBAAgB,gBAAgB;AACrD,aAAO;AAGT,qBAAiB,SAAS;AAAA,MACxB,cAAc;AAAA,MACd,eAAe;AAAA,IACjB;AAAA,EACF;AAGA,MAAI,gBAAgB;AAClB,OAAG;AACD,UAAI,mBAAmB,QAAS,QAAO;AAAA,IACzC,SAAU,iBAAiB,eAAe;AAAA,EAC5C;AAEA,SAAO;AACT;;;ACzEA,IAAM,iBAAyB;AAAA,EAC7B,OAAO;AAAA,EACP,SAAS;AAAA,EACT,QAAQ;AACV;AAEO,SAAS,OACd,QACA,MAAS,CAAC,GACV,UAAkB,CAAC,GACZ;AACP,YAAU,EAAE,GAAG,gBAAgB,GAAG,QAAQ;AAE1C,QAAM,WAAW,OAAO,QAAQ,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,UAAU,MAAM;AACtE,UAAM,aAAa,OAAO,GAA0B;AAGpD,QACE,QAAQ,SACR,MAAM,QAAQ,UAAU,KACxB,MAAM,QAAQ,UAAU,GACxB;AACA,UAAI,GAAuB,IAAI,WAAW;AAAA,QACxC,CAACA,MAAK,SAAS;AAEb,iBAAOA,KAAI,SAAS,IAAI,IAAIA,OAAM,CAAC,GAAGA,MAAK,IAAI;AAAA,QACjD;AAAA,QACA,CAAC,GAAG,UAAU;AAAA,MAChB;AAAA,IACF,WAAW,QAAQ,UAAU,OAAO,QAAQ;AAE1C,UAAI,GAAuB,IAAI;AAAA,IACjC;AAEA,WAAO;AAAA,EACT,GAAG,CAAC,CAAM;AAGV,MAAI,QAAQ,SAAS;AACnB,WAAO,EAAE,GAAG,QAAQ,GAAG,SAAS;AAAA,EAClC,OAAO;AACL,WAAO,OAAO,QAAQ,QAAQ;AAC9B,WAAO;AAAA,EACT;AACF;;;ACrCO,SAAS,cAAc,MAA0C;AACtE,MAAI,SAAS,OAAW,QAAO;AAE/B,SAAO,WAAW,MAAM,EAAY,IAAI,OAAO,KAAK,UAAU,IAAI;AACpE;AAEO,SAAS,WAAW,UAAuB,CAAC,GAAgB;AACjE,SAAO;AAAA,IACL;AAAA,MACE,gBAAgB;AAAA,IAClB;AAAA,IACA;AAAA,EACF;AACF;;;ACbO,SAAS,SACd,IACA,SACA,WACmC;AACnC,SAAO,YAAa,MAA4B;AAC9C,QAAI;AACF,aAAO,GAAG,GAAG,IAAI;AAAA,IACnB,SAAS,KAAK;AACZ,UAAI,CAAC,QAAS;AACd,aAAO,QAAQ,GAAG;AAAA,IACpB,UAAE;AACA,kBAAY;AAAA,IACd;AAAA,EACF;AACF;AAeO,SAAS,cACd,IACA,SACA,WAC4C;AAC5C,SAAO,kBAAmB,MAAqC;AAC7D,QAAI;AACF,aAAO,MAAM,GAAG,GAAG,IAAI;AAAA,IACzB,SAAS,KAAK;AACZ,UAAI,CAAC,QAAS;AACd,aAAO,MAAM,QAAQ,GAAG;AAAA,IAC1B,UAAE;AACA,YAAM,YAAY;AAAA,IACpB;AAAA,EACF;AACF;;;ACjCO,SAAS,QACd,KACA,MACA,UAAwD;AAAA,EACtD,WAAW;AACb,GACkB;AAClB,QAAM,YAAY,QAAQ,aAAa;AAEvC,UAAQ,WAAW;AAAA,IACjB,KAAK;AACH,aAAO,gBAAgB,KAAK,IAAI;AAAA,IAClC,KAAK;AACH,aAAO,aAAa,KAAK,MAAM,OAAO;AAAA,IACxC,KAAK;AAAA,IACL;AACE,aAAO,eAAe,KAAK,MAAM,OAAO;AAAA,EAC5C;AACF;AAEA,eAAsB,eACpB,KACA,MACA,UAA+B,CAAC,GACT;AACvB,QAAM,UAAU,WAAW,QAAQ,OAAO;AAC1C,QAAM,OAAO,cAAc,IAAI;AAE/B,SAAO;AAAA,IACL,YAAY;AACV,YAAM,WAAW,MAAM,MAAM,KAAK;AAAA,QAChC,QAAQ,QAAQ,UAAU;AAAA,QAC1B;AAAA,QACA,WAAW;AAAA,QACX,aAAa,QAAQ,eAAe;AAAA,QACpC,MAAM,QAAQ,SAAS,YAAY;AAAA,QACnC;AAAA,MACF,CAAC;AAED,YAAM,eAAe,QAAQ,SAAS,KAAK,MAAM,SAAS,KAAK;AAE/D,aAAO;AAAA,QACL,IAAI,SAAS;AAAA,QACb,MAAM;AAAA,QACN,OAAO,SAAS,KAAK,SAAY,SAAS;AAAA,MAC5C;AAAA,IACF;AAAA,IACA,CAAC,UAAU;AACT,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,OAAQ,MAAgB;AAAA,MAC1B;AAAA,IACF;AAAA,EACF,EAAE;AACJ;AAEO,SAAS,gBACd,KACA,MACc;AACd,QAAM,OAAO,cAAc,IAAI;AAC/B,QAAM,KAAK,UAAU,WAAW,KAAK,IAAI;AAEzC,SAAO;AAAA,IACL;AAAA,IACA,OAAO,KAAK,SAAY;AAAA,EAC1B;AACF;AAEO,SAAS,aACd,KACA,MACA,UAA0B,CAAC,GACb;AACd,QAAM,UAAU,WAAW,QAAQ,OAAO;AAC1C,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,OAAO,cAAc,IAAI;AAE/B,SAAO;AAAA,IACL,MAAM;AACJ,YAAM,MAAM,IAAI,eAAe;AAC/B,UAAI,KAAK,QAAQ,KAAK,KAAK;AAC3B,iBAAW,UAAU,SAAS;AAC5B,YAAI,iBAAiB,QAAQ,QAAQ,MAAM,CAAC;AAAA,MAC9C;AACA,UAAI,KAAK,IAAI;AAEb,YAAM,KAAK,IAAI,UAAU,OAAO,IAAI,SAAS;AAE7C,YAAM,aAAa,SAAS,KAAK,OAAO,MAAM,IAAI,QAAQ,EAAE,IAAI,QAAQ;AAExE,aAAO;AAAA,QACL;AAAA,QACA,MAAM;AAAA,QACN,OAAO,KAAK,SAAY,GAAG,IAAI,MAAM,IAAI,IAAI,UAAU;AAAA,MACzD;AAAA,IACF;AAAA,IACA,CAAC,UAAU;AACT,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,OAAQ,MAAgB;AAAA,MAC1B;AAAA,IACF;AAAA,EACF,EAAE;AACJ;;;AC/HO,SAAS,UAAU,OAAuC;AAC/D,MAAI,UAAU,OAAQ,QAAO;AAC7B,MAAI,UAAU,QAAS,QAAO;AAE9B,QAAM,SAAS,OAAO,KAAK;AAC3B,MAAI,SAAS,UAAU,UAAU,GAAI,QAAO;AAE5C,SAAO,OAAO,KAAK;AACrB;;;ACVO,SAAS,MAAM,SAAS,GAAW;AACxC,MAAI,MAAM;AACV,WAAS,IAAI,IAAI,IAAI,SAAS;AAC5B,YAAS,KAAK,OAAO,IAAI,IAAK,GAAG,SAAS,CAAC;AAC7C,SAAO;AACT;;;ACAO,SAAS,kBACd,UACA,QAA0B,CAAC,GAC3B,aAA+B,CAAC,GACN;AAE1B,QAAM,SAA2B,EAAE,GAAG,OAAO,GAAG,WAAW;AAE3D,QAAM,gBAAkC,CAAC;AACzC,MAAI,qBAAqB,aAAa;AAEtC,SAAO,KAAK,MAAM,EAAE,QAAQ,CAAC,SAAS;AACpC,QAAI,OAAO,IAAI,GAAG;AAEhB,oBAAc,IAAI,IAAI;AAGtB,UAAI,YAAY,SAAS,IAAI,EAAG,sBAAqB;AAAA,IACvD;AAAA,EACF,CAAC;AAED,SAAO,qBAAqB,gBAAgB;AAC9C;;;ACpBO,SAAS,uBACd,KACA,SAA8B,CAAC,GACV;AACrB,QAAM,UAAU;AAChB,QAAM,OAA4B,CAAC;AACnC,QAAM,aAAkC;AAAA,IACtC,cAAc;AAAA,IACd,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,OAAO;AAAA,EACT;AAEA,SAAO,QAAQ,OAAO,YAAY,MAAM,CAAC,EAAE,QAAQ,CAAC,CAAC,KAAK,IAAI,MAAM;AAClE,UAAM,QAAQ,IAAI,aAAa,IAAI,GAAG;AACtC,QAAI,OAAO;AACT,UAAI,SAAS,SAAS;AACpB,eAAO;AACP,aAAK,OAAO,IAAI;AAAA,MAClB;AAEA,WAAK,IAAI,IAAI;AAAA,IACf;AAAA,EACF,CAAC;AAED,SAAO;AACT;;;ACrBO,SAAS,aACd,SAAwB,CAAC,GACI;AAC7B,QAAM,EAAE,IAAI,SAAS,UAAU,QAAQ,IAAI;AAC3C,QAAMC,OAAM,UAAU,QAAQ;AAC9B,QAAM,YAA6B,UAAU,iBAAiB;AAG9D,MAAI,SAAS;AACX,UAAM,iBAAiB,YAAY,QAAQ,EAAE;AAE7C,UAAM,iBACJ,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO,GACrC;AAAA,MACA,CAAC,KAAK,SAAS,EAAE,GAAG,KAAK,CAAC,GAAG,GAAG,eAAe;AAAA,MAC/C,CAAC;AAAA,IACH;AACA,IAAAA,KAAI,aAAa,WAAW,aAAa;AAAA,EAC3C,OAAO;AAEL,WAAO,cAAc,UAAU,MAAM,GAAG,UAAU,EAAE;AAAA,EACtD;AACF;AAEA,SAAS,cACP,SACA,UACA,IACA;AACA,MAAI,OAAO,MAAO,QAAO;AACzB,MAAI,CAAC,GAAI,MAAK;AACd,SAAO,GAAG,SAAS,UAAU,SAAS;AACxC;AAEA,SAAS,YAAY,QAAuB,IAA8B;AAExE,MAAI;AAEJ,QAAM,OAAO,CAAC,UAA6B,YAA8B;AAEvE,QAAI,UAAU,kBAAkB,KAAK,uBAAuB,UAAU;AACpE;AAGF,yBAAqB,UAAU;AAE/B,QAAI,YAA6B,MAAM,cAAc,MAAM;AAE3D,QAAI,OAAO,SAAS;AAClB,YAAM,eACJ,QAAQ,OAAO,OAAO,IAAI,OAAO,UAAU,CAAC,OAAO,OAAO,GAC1D,OAAyB,CAAC,KAAK,SAAS,EAAE,GAAG,KAAK,CAAC,GAAG,GAAG,KAAK,IAAI,CAAC,CAAC;AAEtE,UAAI,kBAAkB,aAAa,OAAO;AAExC,oBAAY,MAAM,eAAe,MAAM;AAAA,IAC3C;AAEA,WAAO,cAAc,UAAU,GAAG,UAAU,EAAE;AAAA,EAChD;AAEA,SAAO;AACT;AAEA,IAAM,YAA6B,CACjC,SACA,aACyB;AACzB,QAAMA,OAAM,UAAU,QAAQ;AAC9B,QAAM,OAAsB,CAAC;AAG7B,MAAI,QAAQ,GAAI,MAAK,UAAU,QAAQ;AAGvC,MAAI,QAAQ,WAAW,QAAQ,OAAQ,MAAK,SAAS,QAAQ;AAG7D,EAAAA,KAAI,eAAe,IAAI;AAEvB,MAAI,QAAQ,QAAS,CAAAA,KAAI,iBAAiB,OAAO;AAEjD,SAAO;AACT;;;AC9FO,SAAS,cACd,KACA,UAAuB,kBAAM,MAAM,QAAQ,SAC3C;AACA,UAAQ,SAAS;AAAA,IACf,KAAK,kBAAM,MAAM,QAAQ;AACvB,mBAAa,KAAK,IAAI,GAAG,OAAO;AAChC;AAAA,IACF,KAAK,kBAAM,MAAM,QAAQ;AACvB,aAAO,aAAa,WAAW,GAAG;AAClC;AAAA,IACF,KAAK,kBAAM,MAAM,QAAQ;AACvB,aAAO,eAAe,WAAW,GAAG;AACpC;AAAA,EACJ;AACF;AAEO,SAAS,YACd,KACA,UAAuB,kBAAM,MAAM,QAAQ,SACpB;AAEvB,WAAS,UAAU,QAAqC;AACtD,QAAI;AACF,aAAO,KAAK,MAAM,UAAU,EAAE;AAAA,IAChC,SAAS,KAAK;AACZ,UAAI,IAAI,GACN,IAAI;AAGN,UAAI,QAAQ;AACV,YAAI;AACJ,YAAI;AAAA,MACN;AAEA,aAAO,EAAE,GAAG,EAAE;AAAA,IAChB;AAAA,EACF;AACA,MAAI,OAAO;AAEX,UAAQ,SAAS;AAAA,IACf,KAAK,kBAAM,MAAM,QAAQ;AACvB,cAAQ;AAAA,QACN,SAAS,OACN,MAAM,IAAI,EACV,KAAK,CAAC,QAAQ,IAAI,WAAW,MAAM,GAAG,CAAC,GACtC,MAAM,GAAG,EAAE,CAAC,KAAK;AAAA,MACvB;AACA;AAAA,IACF,KAAK,kBAAM,MAAM,QAAQ;AACvB,aAAO,UAAU,OAAO,aAAa,QAAQ,GAAG,CAAC;AACjD;AAAA,IACF,KAAK,kBAAM,MAAM,QAAQ;AACvB,aAAO,UAAU,OAAO,eAAe,QAAQ,GAAG,CAAC;AACnD;AAAA,EACJ;AAGA,MAAI,MAAM;AACR,YAAQ,KAAK;AAEb,QAAI,KAAK,KAAK,KAAK,KAAK,IAAI,KAAK,IAAI,GAAG;AACtC,oBAAc,KAAK,OAAO;AAC1B,cAAQ;AAAA,IACV;AAAA,EACF;AAEA,SAAO,UAAU,SAAS,EAAE;AAC9B;AAEO,SAAS,aACd,KACA,OACA,kBAAkB,IAClB,UAAuB,kBAAM,MAAM,QAAQ,SAC3C,QACuB;AACvB,QAAM,IAAI,KAAK,IAAI,IAAI,MAAO,KAAK;AACnC,QAAM,OAAqB,EAAE,GAAG,GAAG,OAAO,KAAK,EAAE;AACjD,QAAM,kBAAkB,KAAK,UAAU,IAAI;AAE3C,UAAQ,SAAS;AAAA,IACf,KAAK,kBAAM,MAAM,QAAQ,QAAQ;AAC/B,cAAQ,OAAO,UAAU,WAAW,KAAK,UAAU,KAAK,IAAI;AAC5D,UAAI,SAAS,GAAG,GAAG,IAAI,mBAAmB,KAAK,CAAC,aAC9C,kBAAkB,EACpB;AAEA,UAAI,OAAQ,WAAU,cAAc;AAEpC,eAAS,SAAS;AAClB;AAAA,IACF;AAAA,IACA,KAAK,kBAAM,MAAM,QAAQ;AACvB,aAAO,aAAa,QAAQ,KAAK,eAAe;AAChD;AAAA,IACF,KAAK,kBAAM,MAAM,QAAQ;AACvB,aAAO,eAAe,QAAQ,KAAK,eAAe;AAClD;AAAA,EACJ;AAEA,SAAO,YAAY,KAAK,OAAO;AACjC;;;AC9FO,SAAS,eACd,SAA+B,CAAC,GACV;AACtB,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM;AAAA,IACJ,SAAS;AAAA;AAAA,IACT,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,YAAY;AAAA;AAAA,IACZ,aAAa;AAAA,IACb,gBAAAC,kBAAiB;AAAA,IACjB,QAAQ;AAAA;AAAA,EACV,IAAI;AACJ,QAAM,gBAAgB,cAAc,MAAM;AAC1C,MAAI,UAAU;AAGd,QAAM,SAAS,SAAS,CAAC,KAAa,KAAa,YAAyB;AAC1E,QAAI,KAAK,YAAY,KAAK,OAAO;AACjC,QAAI,CAAC,IAAI;AACP,WAAK,MAAM,CAAC;AACZ,mBAAa,KAAK,IAAI,MAAM,MAAM,OAAO;AAAA,IAC3C;AACA,WAAO,OAAO,EAAE;AAAA,EAClB,CAAC,EAAE,WAAW,WAAW,aAAa;AAGtC,QAAM,kBACJ;AAAA,IACE,CAAC,KAAa,YAA0B;AACtC,YAAMC,WAAU,KAAK,MAAM,OAAO,YAAY,KAAK,OAAO,CAAC,CAAC;AAG5D,UAAI,MAAO,QAAOA;AAGlB,MAAAA,SAAQ,QAAQ;AAGhB,UAAI,cAAc,WAAW;AAC3B,eAAO,OAAOA,UAAS,aAAa;AACpC,kBAAU;AAAA,MACZ;AAGA,UAAI,WAAWA,SAAQ,UAAU,SAAS,MAAQ,KAAK;AAErD,eAAOA,SAAQ;AACf,eAAOA,SAAQ;AACf,QAAAA,SAAQ,QAAQ;AAChB,QAAAA,SAAQ;AACR,QAAAA,SAAQ,OAAO;AACf,kBAAU;AAAA,MACZ,OAAO;AAEL,QAAAA,SAAQ;AAAA,MACV;AAEA,aAAOA;AAAA,IACT;AAAA,IACA,MAAM;AAEJ,gBAAU;AAAA,IACZ;AAAA,EACF,EAAE,YAAYD,eAAc,KAAK,CAAC;AAGpC,QAAM,iBAAgD;AAAA,IACpD,IAAI,MAAM,EAAE;AAAA,IACZ,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AAGA,QAAM,UAAU,OAAO;AAAA,IACrB;AAAA;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,IACA,EAAE,OAAO;AAAA;AAAA,IACT,EAAE,SAAS,SAAS,MAAM,SAAS,IAAI;AAAA;AAAA,IACvC,OAAO;AAAA;AAAA,EACT;AAGA,eAAa,YAAY,KAAK,UAAU,OAAO,GAAG,SAAS,GAAGA,eAAc;AAE5E,SAAO;AACT;;;AC7FO,SAAS,cACd,SAA8B,CAAC,GACT;AACtB,MAAI,UAAU,OAAO,WAAW;AAChC,QAAM,QAAQ,EAAE,SAAS,SAAS,MAAM;AAGxC,MAAI,OAAO,YAAY,MAAO,QAAO;AAGrC,MAAI,CAAC,SAAS;AAGZ,UAAM,CAAC,IAAI,IAAI,YAAY;AAAA,MACzB;AAAA,IACF;AACA,QAAI,KAAK,SAAS,WAAY,QAAO;AAAA,EACvC;AAEA,QAAM,MAAM,IAAI,IAAI,OAAO,OAAO,OAAO,SAAS,IAAI;AACtD,QAAM,MAAM,OAAO,YAAY,SAAS;AACxC,QAAM,WAAW,OAAO,IAAI,IAAI,GAAG,EAAE;AAGrC,QAAM,YAAY,uBAAuB,KAAK,OAAO,UAAU;AAC/D,MAAI,OAAO,KAAK,SAAS,EAAE,QAAQ;AAEjC,QAAI,CAAC,UAAU;AAEb,gBAAU,YAAY;AAExB,cAAU;AAAA,EACZ;AAGA,MAAI,CAAC,SAAS;AAKZ,UAAM,UAAU,OAAO,WAAW,CAAC;AACnC,YAAQ,KAAK,IAAI,QAAQ;AACzB,cAAU,CAAC,QAAQ,SAAS,QAAQ;AAAA,EACtC;AAEA,SAAO;AAAA;AAAA,IAEH,OAAO;AAAA,MACL;AAAA,QACE;AAAA,QACA,SAAS;AAAA,QACT,OAAO,KAAK,IAAI;AAAA,QAChB,IAAI,MAAM,EAAE;AAAA,QACZ;AAAA,MACF;AAAA,MACA;AAAA,MACA,OAAO;AAAA,IACT;AAAA;AAAA;AAAA,IAEA;AAAA;AACN;","names":["acc","elb","sessionStorage","session"]}