@arsel.sa/web-sdk 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +103 -1
- package/dist/arsel.js +1068 -327
- package/dist/arsel.js.map +1 -1
- package/dist/arsel.umd.cjs +107 -1
- package/dist/arsel.umd.cjs.map +1 -1
- package/dist/events.d.ts +7 -0
- package/dist/inapp-view.d.ts +16 -0
- package/dist/inapp.d.ts +83 -0
- package/dist/index.d.ts +20 -9
- package/dist/install.d.ts +10 -0
- package/dist/push.d.ts +16 -0
- package/dist/session.d.ts +5 -1
- package/dist/store.d.ts +31 -4
- package/dist/transport.d.ts +1 -1
- package/dist/types.d.ts +32 -0
- package/dist/version.d.ts +1 -1
- package/package.json +2 -1
- package/sw/arsel-sw.js +27 -2
package/dist/arsel.umd.cjs
CHANGED
|
@@ -1,2 +1,108 @@
|
|
|
1
|
-
(function(u,v){typeof exports=="object"&&typeof module<"u"?v(exports):typeof define=="function"&&define.amd?define(["exports"],v):(u=typeof globalThis<"u"?globalThis:u||self,v(u.Arsel={}))})(this,(function(u){"use strict";const v="arsel",m="events";let N=null;function oe(){return N||(N=new Promise((e,t)=>{const n=indexedDB.open(v,1);n.onupgradeneeded=()=>{const i=n.result;i.objectStoreNames.contains("kv")||i.createObjectStore("kv"),i.objectStoreNames.contains(m)||i.createObjectStore(m,{keyPath:"id",autoIncrement:!0})},n.onsuccess=()=>e(n.result),n.onerror=()=>t(n.error)}),N)}function y(e,t,n){return oe().then(i=>new Promise((s,a)=>{const o=n(i.transaction(e,t).objectStore(e));o.onsuccess=()=>s(o.result),o.onerror=()=>a(o.error)}))}function c(e){return y("kv","readonly",t=>t.get(e)).then(t=>t??null)}function d(e,t){return y("kv","readwrite",n=>n.put(t,e))}function k(e){return y("kv","readwrite",t=>t.delete(e))}function ce(e,t){return y(m,"readwrite",n=>n.add({body:e,idempotencyKey:t,createdAtMs:Date.now()}))}function le(){return y(m,"readonly",e=>e.getAll())}function ue(e){return y(m,"readwrite",t=>t.delete(e))}function de(){return y(m,"readonly",e=>e.count())}const r={clientKey:"client_key",baseUrl:"base_url",anonymousId:"anonymous_id",externalId:"external_id",email:"email",phoneNumber:"phone_number",installationId:"installation_id",deviceSecret:"device_secret",vapidKeyVersion:"vapid_key_version",endpoint:"endpoint",sessionStartedAt:"session_started_at",backgroundedAt:"backgrounded_at",lastResponseCode:"last_response_code",lastResponsePath:"last_response_path",lastResponseAtMs:"last_response_at"};async function T(){const e=await c(r.anonymousId);if(e)return e;const t=crypto.randomUUID();return await d(r.anonymousId,t),t}async function fe(){const e=crypto.randomUUID();return await d(r.anonymousId,e),e}const g="1.0.0",M={"X-Arsel-SDK":`web/${g}`},p={success:"success",retryable:"retryable",permanent:"permanent",reauth:"reauth"},R=-1;function pe(e,t){return e>=200&&e<=299?p.success:e===408||e===429||e>=500&&e<=599?p.retryable:t&&(e===401||e===403||e===404)?p.reauth:e===404?p.retryable:p.permanent}async function P(e,t){try{await Promise.all([d(r.lastResponseCode,t),d(r.lastResponsePath,e),d(r.lastResponseAtMs,Date.now())])}catch{}}async function $(e,t,n,i={},s=!1){let a;try{a=await fetch(e+t,{method:"POST",headers:{"Content-Type":"application/json",...M,...i},body:JSON.stringify(n),credentials:"omit",keepalive:!0})}catch{return await P(t,R),{result:p.retryable,code:R,body:null}}await P(t,a.status);const o=pe(a.status,s);let l=null;try{l=await a.json()}catch{}return{result:o,code:a.status,body:l}}async function j(e,t){try{const n=await fetch(e+t,{credentials:"omit",headers:M});return await P(t,n.status),n.ok?await n.json():null}catch{return await P(t,R),null}}const ye="/v1/events/send",S="arsel.",we=`${S}session_start`,me=`${S}session_end`,be=`${S}identify`,he=80,ve=128,ge=255,x=50,Se=8,W=64*1024;function V(e,t){if(e===null)return null;const n=typeof e;if(n==="string"||n==="boolean")return e;if(n==="number")return Number.isFinite(e)?e:String(e);if(n==="bigint")return String(e);if(e instanceof Date)return Number.isNaN(e.getTime())?void 0:e.toISOString();if(n!=="object"||t>=Se)return;if(Array.isArray(e))return e.map(s=>V(s,t+1)??null);const i={};for(const[s,a]of Object.entries(e)){if(!s)continue;const o=V(a,t+1);o!==void 0&&(i[s]=o)}return i}function Ee(e){const t={};let n=2,i=!1;for(const[s,a]of Object.entries(e??{})){if(!s)continue;const o=V(a,0);if(o===void 0)continue;const l=s.length+JSON.stringify(o).length+6;if(n+l>W){i=!0;continue}n+=l,t[s]=o}return i&&console.warn(`[arsel] event data exceeded ${W} serialized bytes — oversized properties were dropped`),t}async function _e(e,t,n){const[i,s,a,o]=await Promise.all([T(),c(r.externalId),c(r.email),c(r.phoneNumber)]),l={event:e.slice(0,he),anonymous_id:i.slice(0,ve),data:Ee(t),timestamp:new Date(n).toISOString()};return s&&(l.external_id=s.slice(0,ge)),a&&(l.email=a),o&&(l.phone_number=o),JSON.stringify(l)}async function E(e,t,n=Date.now()){await ce(await _e(e,t,n),crypto.randomUUID()),A().catch(()=>{})}let _=null;function A(){return _||(_=Ne().finally(()=>{_=null}),_)}function Ae(e){const t=e[0].idempotencyKey;return e.length===1?t:`${t}:${e[e.length-1].idempotencyKey}:${e.length}`}function Ie(e,t,n){e.some(s=>s.external_id||s.email||s.phone_number)&&console.error(`[arsel] ${e.length} event(s) carrying identifiers were rejected permanently (HTTP ${t}) and dropped. Response: ${JSON.stringify(n)}`)}async function Ne(){const[e,t]=await Promise.all([c(r.clientKey),c(r.baseUrl)]);if(!(!e||!t))for(;;){const n=await le();if(n.length===0)return;for(let i=0;i<n.length;i+=x){const s=n.slice(i,i+x),a=s.map(l=>JSON.parse(l.body)),o=await $(t,ye,s.length===1?a[0]:{events:a},{Authorization:`Bearer ${e}`,"Idempotency-Key":Ae(s)});if(o.result===p.retryable)return;o.result!==p.success&&Ie(a,o.code,o.body);for(const l of s)l.id!==void 0&&await ue(l.id)}}}function B(e){const t=e.replace(/-/g,"+").replace(/_/g,"/"),n=atob(t+"=".repeat((4-t.length%4)%4)),i=new Uint8Array(n.length);for(let s=0;s<n.length;s+=1)i[s]=n.charCodeAt(s);return i.buffer}function b(){return typeof navigator<"u"&&"serviceWorker"in navigator&&typeof PushManager<"u"&&typeof Notification<"u"}function F(e){return`/api/v1/orgs/${e}/push/web/config`}function C(e){return`/api/v1/orgs/${e}/push/subscriptions`}const X=1e4;let h="none",I=null,O=null;function ke(){h="external"}async function Te(e){if(b()){h="managed";try{I=await navigator.serviceWorker.register(e),O=null}catch(t){I=null,O=`service worker registration failed for '${e}': ${String(t)}. Check that the file is deployed and served with a JavaScript content type.`}}}function Pe(e,t){return e.active?Promise.resolve(e):new Promise((n,i)=>{const s=setTimeout(()=>{i(new Error(`service worker did not activate within ${t}ms — check the worker script for load errors in DevTools → Application → Service Workers`))},t),a=l=>{l.addEventListener("statechange",()=>{l.state==="activated"?(clearTimeout(s),n(e)):l.state==="redundant"&&(clearTimeout(s),i(new Error("service worker became redundant before activating — its script likely failed to parse")))})},o=e.installing??e.waiting;o?a(o):e.addEventListener("updatefound",()=>{e.installing&&a(e.installing)})})}function Oe(e,t,n){return Promise.race([e,new Promise((i,s)=>{setTimeout(()=>s(new Error(n)),t)})])}async function U(e=X){if(h==="none")throw new Error("push is not configured — pass serviceWorkerPath to init(), or serviceWorker: 'external' if your own service worker imports arsel-sw.js");if(h==="external")return Oe(navigator.serviceWorker.ready,e,`no service worker became active within ${e}ms — with serviceWorker: 'external', your own worker must be registered and must importScripts arsel-sw.js`);if(O)throw new Error(O);if(!I)throw new Error("service worker registration has not completed");return Pe(I,e)}async function Ke(e=X){try{return await U(e),null}catch(t){return t instanceof Error?t.message:String(t)}}async function De(){const[e,t]=await Promise.all([c(r.clientKey),c(r.baseUrl)]);if(!e||!t||!b())return!1;const n=await j(t,F(e));if(!(n!=null&&n.vapidPublicKey))return!1;let i;try{i=await U()}catch(a){return console.error(`[arsel] ${a instanceof Error?a.message:a}`),!1}const s=await i.pushManager.subscribe({userVisibleOnly:!0,applicationServerKey:B(n.vapidPublicKey)});return H(s,n.keyVersion)}async function H(e,t){var D;const[n,i,s]=await Promise.all([c(r.clientKey),c(r.baseUrl),T()]);if(!n||!i)return!1;let a=await c(r.installationId);a||(a=crypto.randomUUID(),await d(r.installationId,a));const o=e.toJSON(),l=await $(i,C(n),{installationId:a,platform:"web",endpoint:o.endpoint,keys:o.keys,anonymousId:s,enablementStatus:Notification.permission==="granted"?"AUTHORIZED":"DENIED",deviceTimezone:Intl.DateTimeFormat().resolvedOptions().timeZone,deviceLocale:navigator.language});return l.result!==p.success?!1:((D=l.body)!=null&&D.deviceSecret&&await d(r.deviceSecret,l.body.deviceSecret),await d(r.vapidKeyVersion,t),await d(r.endpoint,o.endpoint??null),!0)}async function Re(){const[e,t,n,i]=await Promise.all([c(r.clientKey),c(r.baseUrl),c(r.installationId),c(r.deviceSecret)]);return!e||!t||!n||!i?!1:(await $(t,`${C(e)}/unsubscribe`,{installationId:n},{"X-Arsel-Device-Auth":i},!0)).result===p.success}async function $e(){if(h==="none"||!b()||Notification.permission!=="granted")return;const[e,t]=await Promise.all([c(r.clientKey),c(r.baseUrl)]);if(!e||!t)return;const n=await j(t,F(e));if(!(n!=null&&n.vapidPublicKey))return;let i;try{i=await U()}catch{return}const s=await i.pushManager.getSubscription(),a=await c(r.vapidKeyVersion);if(s&&a===n.keyVersion)return;s&&await s.unsubscribe().catch(()=>!1);const o=await i.pushManager.subscribe({userVisibleOnly:!0,applicationServerKey:B(n.vapidPublicKey)});await H(o,n.keyVersion)}async function Ve(){if(!b())return!1;try{const e=h==="managed"?I:await navigator.serviceWorker.getRegistration();return e?await e.pushManager.getSubscription()!==null:!1}catch{return!1}}const Ue=30*6e4;async function L(e=Date.now()){const t=await c(r.sessionStartedAt)??0,n=await c(r.backgroundedAt)??0;if(t!==0){if(n===0||e-n<Ue)return;await E(me,{duration_seconds:Math.round((n-t)/1e3)},n)}await d(r.sessionStartedAt,e),await d(r.backgroundedAt,0),await E(we,{},e)}async function z(e=Date.now()){(await c(r.sessionStartedAt)??0)!==0&&await d(r.backgroundedAt,e)}function Me(){typeof document>"u"||(document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"?L():z()}),window.addEventListener("pagehide",()=>void z()))}let f=null,J=!1;function w(e){J&&console.info(`[arsel] ${e}`)}const je=/^\+[1-9]\d{6,14}$/,xe=/^[^\s@]+@[^\s@]+\.[^\s@]+$/,q=100;let K=[],Y=!1;function We(){typeof window<"u"&&window.addEventListener("online",()=>void A().catch(()=>{})),typeof document<"u"&&document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&A().catch(()=>{})})}function Z(e){return f||(f=(async()=>{var a;if(!e.clientKey)throw new Error("Arsel: clientKey is required");const t=/^http:\/\/(localhost|127\.0\.0\.1)(:\d+)?(\/|$)/.test(e.baseUrl??"");if(!((a=e.baseUrl)!=null&&a.startsWith("https://"))&&!t)throw new Error("Arsel: baseUrl must be HTTPS (http is allowed for localhost only)");J=e.debug??!1;const n=e.baseUrl.replace(/\/+$/,"");await Promise.all([d(r.clientKey,e.clientKey),d(r.baseUrl,n)]),await T();const i=K;K=[];for(const o of i)await E(o.name,o.properties,o.timestampMs);e.serviceWorker==="external"?ke():e.serviceWorkerPath&&await Te(e.serviceWorkerPath),Me(),We();const s=typeof document<"u"?document:void 0;(s==null?void 0:s.visibilityState)==="visible"&&s.prerendering!==!0&&await L(),A(),$e(),w(`initialized (sdk ${g})`)})(),f)}async function G(e,t={}){const n=e==null?void 0:e.trim();if(!n){w("track() called with a blank event name — ignoring");return}if(n.startsWith(S)){w(`'${S}' is reserved for the SDK — ignoring '${n}'`);return}if(!f){if(K.length>=q){Y||(Y=!0,console.warn(`[arsel] more than ${q} events tracked before init() — dropping the rest. Call init() earlier.`));return}K.push({name:n,properties:t,timestampMs:Date.now()});return}await f,await E(n,t)}async function Q(e){await f;let{email:t,phoneNumber:n}=e??{};const i=e==null?void 0:e.externalId;if(t&&!xe.test(t)&&(console.error(`[arsel] identify(): '${t}' is not a valid email address — ignored`),t=void 0),n&&!je.test(n)&&(console.error(`[arsel] identify(): '${n}' is not E.164 (e.g. +966501234567) — ignored`),n=void 0),!i&&!t&&!n){w("identify() needs at least one of externalId, email or phoneNumber");return}i&&await d(r.externalId,i),t&&await d(r.email,t),n&&await d(r.phoneNumber,n),await E(be,{})}async function ee(){await f,await Promise.all([k(r.externalId),k(r.email),k(r.phoneNumber),k(r.sessionStartedAt)]),await fe(),w("identity reset")}async function te(){await f;const e=await Re();return w(e?"push opt-out recorded":"push opt-out not sent — no registration to revoke"),e}async function ne(){if(await f,!b())return!1;const e=await Ke();if(e)return console.error(`[arsel] promptForPush(): ${e}`),!1;const t=await Notification.requestPermission();return t!=="granted"?(w(`notification permission: ${t}`),!1):De()}async function re(){return await f,T()}async function ie(){const[e,t,n,i,s,a,o,l,D,Be,Fe,Ce]=await Promise.all([c(r.anonymousId),c(r.externalId),c(r.email),c(r.phoneNumber),c(r.installationId),c(r.deviceSecret),c(r.vapidKeyVersion),de(),Ve(),c(r.lastResponseCode),c(r.lastResponsePath),c(r.lastResponseAtMs)]);return{sdkVersion:g,initialized:f!==null,anonymousId:e,hasAssertedIdentity:!!(t||n||i),installationId:s,hasDeviceSecret:!!a,pendingEvents:l,permission:b()?Notification.permission:"unsupported",isSubscribed:D,vapidKeyVersion:o,lastResponseCode:Be,lastResponsePath:Fe,lastResponseAtMs:Ce}}async function se(){await f,await A()}const ae={init:Z,track:G,identify:Q,reset:ee,optOut:te,promptForPush:ne,getAnonymousId:re,diagnostics:ie,flushNow:se,SDK_VERSION:g};u.Arsel=ae,u.SDK_VERSION=g,u.default=ae,u.diagnostics=ie,u.flushNow=se,u.getAnonymousId=re,u.identify=Q,u.init=Z,u.optOut=te,u.promptForPush=ne,u.reset=ee,u.track=G,Object.defineProperties(u,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
|
|
1
|
+
(function(m,K){typeof exports=="object"&&typeof module<"u"?K(exports):typeof define=="function"&&define.amd?define(["exports"],K):(m=typeof globalThis<"u"?globalThis:m||self,K(m.Arsel={}))})(this,(function(m){"use strict";const K="arsel",v={events:"events",inAppBeacons:"inapp_beacons"};let Y=null;function at(){return Y||(Y=new Promise((e,t)=>{const n=indexedDB.open(K,2);n.onupgradeneeded=()=>{const i=n.result;i.objectStoreNames.contains("kv")||i.createObjectStore("kv");for(const r of Object.values(v))i.objectStoreNames.contains(r)||i.createObjectStore(r,{keyPath:"id",autoIncrement:!0})},n.onsuccess=()=>e(n.result),n.onerror=()=>t(n.error)}),Y)}function N(e,t,n){return at().then(i=>new Promise((r,s)=>{const a=n(i.transaction(e,t).objectStore(e));a.onsuccess=()=>r(a.result),a.onerror=()=>s(a.error)}))}function c(e){return N("kv","readonly",t=>t.get(e)).then(t=>t??null)}function u(e,t){return N("kv","readwrite",n=>n.put(t,e))}function L(e){return N("kv","readwrite",t=>t.delete(e))}function ve(e,t,n=""){return N(e,"readwrite",i=>i.add({body:t,idempotencyKey:n,createdAtMs:Date.now()}))}function oe(e){return N(e,"readonly",t=>t.getAll())}function se(e,t){return N(e,"readwrite",n=>n.delete(t))}function Se(e){return N(e,"readonly",t=>t.count())}async function ct(e,t){const n=await oe(e);if(!(n.length<=t))for(const i of n.slice(0,n.length-t))i.id!==void 0&&await se(e,i.id)}const o={clientKey:"client_key",baseUrl:"base_url",anonymousId:"anonymous_id",externalId:"external_id",email:"email",phoneNumber:"phone_number",installationId:"installation_id",deviceSecret:"device_secret",vapidKeyVersion:"vapid_key_version",endpoint:"endpoint",subscriptionStatus:"subscription_status",installReported:"install_reported",sessionStartedAt:"session_started_at",backgroundedAt:"backgrounded_at",lastResponseCode:"last_response_code",lastResponsePath:"last_response_path",lastResponseAtMs:"last_response_at",inAppBundle:"inapp_bundle",inAppState:"inapp_state",inAppSession:"inapp_session"};async function V(){const e=await c(o.anonymousId);if(e)return e;const t=crypto.randomUUID();return await u(o.anonymousId,t),t}async function lt(){const e=crypto.randomUUID();return await u(o.anonymousId,e),e}const D="1.2.0",Ae={"X-Arsel-SDK":`web/${D}`},b={success:"success",retryable:"retryable",permanent:"permanent",reauth:"reauth"},J=-1;function Ee(e,t){return e>=200&&e<=299?b.success:e===408||e===429||e>=500&&e<=599?b.retryable:t&&(e===401||e===403||e===404)?b.reauth:e===404?b.retryable:b.permanent}async function G(e,t){try{await Promise.all([u(o.lastResponseCode,t),u(o.lastResponsePath,e),u(o.lastResponseAtMs,Date.now())])}catch{}}async function F(e,t,n,i={},r=!1){let s;try{s=await fetch(e+t,{method:"POST",headers:{"Content-Type":"application/json",...Ae,...i},body:JSON.stringify(n),credentials:"omit",keepalive:!0})}catch{return await G(t,J),{result:b.retryable,code:J,body:null}}await G(t,s.status);const a=Ee(s.status,r);let l=null;try{l=await s.json()}catch{}return{result:a,code:s.status,body:l}}async function ae(e,t,n={},i=!1,r={}){let s;try{s=await fetch(e+t,{...r,credentials:"omit",headers:{...Ae,...n}})}catch{return await G(t,J),{result:b.retryable,code:J,body:null}}await G(t,s.status);let a=null;try{a=await s.json()}catch{}return{result:Ee(s.status,i),code:s.status,body:a}}const ut="/v1/events/send",k="arsel.",dt=`${k}session_start`,ft=`${k}session_end`,pt=`${k}identify`,mt=`${k}app_installed`,yt=`${k}screen_view`,bt=80,ht=128,gt=255,Ie=50,wt=8,_e=64*1024;function ce(e,t){if(e===null)return null;const n=typeof e;if(n==="string"||n==="boolean")return e;if(n==="number")return Number.isFinite(e)?e:String(e);if(n==="bigint")return String(e);if(e instanceof Date)return Number.isNaN(e.getTime())?void 0:e.toISOString();if(n!=="object"||t>=wt)return;if(Array.isArray(e))return e.map(r=>ce(r,t+1)??null);const i={};for(const[r,s]of Object.entries(e)){if(!r)continue;const a=ce(s,t+1);a!==void 0&&(i[r]=a)}return i}function vt(e){const t={};let n=2,i=!1;for(const[r,s]of Object.entries(e??{})){if(!r)continue;const a=ce(s,0);if(a===void 0)continue;const l=r.length+JSON.stringify(a).length+6;if(n+l>_e){i=!0;continue}n+=l,t[r]=a}return i&&console.warn(`[arsel] event data exceeded ${_e} serialized bytes — oversized properties were dropped`),t}async function St(e,t,n){const[i,r,s,a]=await Promise.all([V(),c(o.externalId),c(o.email),c(o.phoneNumber)]),l={event:e.slice(0,bt),anonymous_id:i.slice(0,ht),data:vt(t),timestamp:new Date(n).toISOString()};return r&&(l.external_id=r.slice(0,gt)),s&&(l.email=s),a&&(l.phone_number=a),JSON.stringify(l)}async function x(e,t,n=Date.now()){await ve(v.events,await St(e,t,n),crypto.randomUUID()),W().catch(()=>{})}let j=null;function W(){return j||(j=It().finally(()=>{j=null}),j)}function At(e){const t=e[0].idempotencyKey;return e.length===1?t:`${t}:${e[e.length-1].idempotencyKey}:${e.length}`}function Et(e,t,n){e.some(r=>r.external_id||r.email||r.phone_number)&&console.error(`[arsel] ${e.length} event(s) carrying identifiers were rejected permanently (HTTP ${t}) and dropped. Response: ${JSON.stringify(n)}`)}async function It(){const[e,t]=await Promise.all([c(o.clientKey),c(o.baseUrl)]);if(!(!e||!t))for(;;){const n=await oe(v.events);if(n.length===0)return;for(let i=0;i<n.length;i+=Ie){const r=n.slice(i,i+Ie),s=r.map(l=>JSON.parse(l.body)),a=await F(t,ut,r.length===1?s[0]:{events:s},{Authorization:`Bearer ${e}`,"Idempotency-Key":At(r)});if(a.result===b.retryable)return;a.result!==b.success&&Et(s,a.code,a.body);for(const l of r)l.id!==void 0&&await se(v.events,l.id)}}}const Z=1e3,_t=720*60*60*Z,Nt=500,Ne=50,kt=86400,xt=900,Q={maxPerSession:1,maxLifetime:3,minSecondsBetween:86400,delaySeconds:0},Pt=["MODAL","BANNER_TOP","BANNER_BOTTOM","IMAGE_ONLY"];let le=!1,d=null,g={},S={startedAt:0,counts:{}},X=null,z=null,ke=!1,ue=null,P=null,xe=!1,Pe=!1;function T(e){xe&&console.info(`[arsel] in-app: ${e}`)}async function Tt(e){le=!0,xe=e;const[t,n,i]=await Promise.all([c(o.inAppBundle),c(o.inAppState),c(o.inAppSession)]);d=t,g=n??{},S=i??{startedAt:0,counts:{}},await Ue(),await ee()}function Dt(e){P=e}function Ot(e){ke=e,e&&fe()}function Mt(){return{messages:(d==null?void 0:d.messages.length)??0,bundleVersion:(d==null?void 0:d.bundleVersion)??null,fetchedAtMs:(d==null?void 0:d.fetchedAtMs)??null}}function Rt(){return Se(v.inAppBeacons)}async function Te(){d=null,await L(o.inAppBundle),le&&await ee(!0)}function Bt(){ee(!0)}function ee(e=!1){return ue??(ue=Ut(e).finally(()=>{ue=null})),ue}async function Ut(e){if(!le)return;const t=Date.now();if(!e&&d&&t-d.fetchedAtMs<d.ttlSeconds*Z)return;const n=await Oe();if(!n)return;const i=Ct(n.clientKey,n.installationId),r={"X-Arsel-Device-Auth":n.deviceSecret},s=!!(d!=null&&d.bundleVersion);s&&(r["If-None-Match"]=`"${(d==null?void 0:d.bundleVersion)??""}"`);let a=await De(n.baseUrl,i,r);if(a.code===Jt&&s&&Pe&&(T("conditional request failed; retrying without If-None-Match"),delete r["If-None-Match"],a=await De(n.baseUrl,i,r)),a.code===Gt){d&&(d={...d,fetchedAtMs:t},await u(o.inAppBundle,d));return}if(a.result!==b.success||!a.body)return;s||(Pe=!0);const l=$t(a.body,t);l&&(d=l,await u(o.inAppBundle,d),await qt(l,t))}function De(e,t,n){return ae(e,t,n,!0,{cache:"no-store"})}function Ct(e,t){const n=encodeURIComponent(e),i=encodeURIComponent(t);return`/api/v1/orgs/${n}/in-app/bundle?installationId=${i}`}async function Oe(){const[e,t,n,i]=await Promise.all([c(o.clientKey),c(o.baseUrl),c(o.installationId),c(o.deviceSecret)]);return!e||!t||!n||!i?null:{clientKey:e,baseUrl:t,installationId:n,deviceSecret:i}}function $t(e,t){if(typeof(e==null?void 0:e.bundleVersion)!="string")return T("response carried no bundleVersion"),null;e.contractVersion!==void 0&&e.contractVersion!==1&&T(`unknown contractVersion ${String(e.contractVersion)}; proceeding`);const n=Array.isArray(e.messages)?e.messages:[],i=[];for(const s of n){const a=Kt(s);a&&i.push(a)}n.length!==i.length&&T(`dropped ${n.length-i.length} unrenderable message(s)`);const r=M(e.ttlSeconds);return{bundleVersion:e.bundleVersion,ttlSeconds:r&&r>0?r:xt,fetchedAtMs:t,messages:i}}function Kt(e){if(!O(e))return null;const t=y(e.campaignId),n=y(e.messageId),i=y(e.layout),r=O(e.content)?e.content:null,s=r?y(r.headline):void 0;if(!t||!n||!i||!r||!s)return T("message missing a required field"),null;if(!Pt.includes(i))return T(`layout ${i} is not renderable on web`),null;const a=O(e.trigger)?e.trigger:{},l=O(e.displayRules)?e.displayRules:{};return{campaignId:t,messageId:n,variantKey:y(e.variantKey)??"default",priority:M(e.priority)??0,expiresAtMs:Yt(e.expiresAt),triggerType:y(a.type)??"APP_OPEN",triggerEventName:y(a.eventName)??null,triggerProperties:O(a.properties)?a.properties:null,displayRules:{maxPerSession:M(l.maxPerSession)??Q.maxPerSession,maxLifetime:M(l.maxLifetime)??Q.maxLifetime,minSecondsBetween:M(l.minSecondsBetween)??Q.minSecondsBetween,delaySeconds:M(l.delaySeconds)??Q.delaySeconds},layout:i,content:{headline:s,body:y(r.body)??"",imageUrl:y(r.imageUrl),backgroundColor:y(r.backgroundColor),textColor:y(r.textColor),showCloseButton:r.showCloseButton!==!1},buttons:Array.isArray(e.buttons)?e.buttons.map(Lt).filter(w=>w!==null):[]}}function Lt(e){if(!O(e))return null;const t=y(e.buttonId),n=y(e.label),i=y(e.action);return!t||!n||!i?null:{buttonId:t,label:n,action:i,value:y(e.value),style:y(e.style)==="SECONDARY"?"SECONDARY":"PRIMARY"}}function Vt(e,t,n,i){if(ke||X!==null||!d)return null;for(const r of d.messages){if(r.triggerType!==t||t!=="APP_OPEN"&&r.triggerEventName!==n||!Ft(r.triggerProperties,i))continue;const s=g[r.messageId];if(r.expiresAtMs!==null&&r.expiresAtMs<=e){Ht(r);continue}if(!(((s==null?void 0:s.shown)??0)>=r.displayRules.maxLifetime)&&!((S.counts[r.messageId]??0)>=r.displayRules.maxPerSession)&&!(s&&e-s.lastShownAtMs<r.displayRules.minSecondsBetween*Z))return r}return null}function Ft(e,t){if(!e)return!0;const n=t;for(const[i,r]of Object.entries(e))if(String(n[i])!==String(r))return!1;return!0}function de(e,t,n={}){try{const i=Vt(Date.now(),e,t,n);if(!i)return;X=i.messageId,Me=t;const r=i.displayRules.delaySeconds*Z;if(r<=0){P==null||P(i);return}z=setTimeout(()=>{z=null,P==null||P(i)},r)}catch(i){T(`observe failed: ${i instanceof Error?i.message:"unknown"}`),X=null}}let Me=null;function jt(){return Me}function Re(){Ue().then(()=>{de("APP_OPEN",null,{})})}function fe(){z!==null&&(clearTimeout(z),z=null,X=null)}function Be(){X=null}async function Wt(e,t){const n=Date.now(),i=g[e.messageId]??{shown:0,lastShownAtMs:0,lastSeenInBundleAtMs:n};g={...g,[e.messageId]:{...i,shown:i.shown+1,lastShownAtMs:n}},S={...S,counts:{...S.counts,[e.messageId]:(S.counts[e.messageId]??0)+1}},await Promise.all([u(o.inAppState,g),u(o.inAppSession,S)]),await te(e,"impression",{triggerEventName:t})}async function Xt(e,t){await te(e,"clicked",{buttonId:t})}async function zt(e,t){await te(e,"dismissed",{visibleSeconds:Math.max(0,Math.min(kt,Math.round(t)))})}function Ht(e){const t=g[e.messageId];t!=null&&t.expiredReported||(g={...g,[e.messageId]:{shown:(t==null?void 0:t.shown)??0,lastShownAtMs:(t==null?void 0:t.lastShownAtMs)??0,lastSeenInBundleAtMs:(t==null?void 0:t.lastSeenInBundleAtMs)??Date.now(),expiredReported:!0}},u(o.inAppState,g),te(e,"expired",{}))}async function te(e,t,n){const i={messageId:e.messageId,campaignId:e.campaignId,eventType:t,timestamp:new Date().toISOString(),variantKey:e.variantKey};n.buttonId&&(i.buttonId=n.buttonId),n.visibleSeconds!==void 0&&(i.visibleSeconds=n.visibleSeconds),n.triggerEventName&&(i.triggerEventName=n.triggerEventName),await ve(v.inAppBeacons,JSON.stringify(i)),await ct(v.inAppBeacons,Nt),ne()}async function ne(){const e=await Oe();if(!e)return;const t=await oe(v.inAppBeacons);if(t.length===0)return;const n=`/api/v1/orgs/${encodeURIComponent(e.clientKey)}/in-app/events`;for(let i=0;i<t.length;i+=Ne){const r=t.slice(i,i+Ne);if((await F(e.baseUrl,n,{installationId:e.installationId,events:r.map(a=>JSON.parse(a.body))},{"X-Arsel-Device-Auth":e.deviceSecret},!0)).result===b.retryable)return;for(const a of r)a.id!==void 0&&await se(v.inAppBeacons,a.id)}}async function qt(e,t){const n=new Set(e.messages.map(r=>r.messageId)),i={};for(const[r,s]of Object.entries(g)){const a=n.has(r)?t:s.lastSeenInBundleAtMs;t-a>_t||(i[r]={...s,lastSeenInBundleAtMs:a})}g=i,await u(o.inAppState,g)}async function Ue(){const e=await c(o.sessionStartedAt)??0;S.startedAt!==e&&(S={startedAt:e,counts:{}},await u(o.inAppSession,S))}function O(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function y(e){return typeof e=="string"&&e.length>0?e:void 0}function M(e){return typeof e=="number"&&Number.isFinite(e)?e:void 0}function Yt(e){if(typeof e!="string")return null;const t=Date.parse(e);return Number.isNaN(t)?null:t}const Jt=-1,Gt=304,Zt=2147483e3,pe=44,Ce=/^#[0-9a-fA-F]{3,8}$/,Qt=.6;let $e=null,en=0;function tn(e,t,n){const i=e.layout==="MODAL",r=Date.now(),s=`arsel-iam-${en+=1}`,a=document.createElement("div");a.setAttribute("data-arsel-inapp","");const l=a.attachShadow({mode:"closed"});pn(l),a.style.setProperty("z-index",String(t.zIndex||Zt)),a.style.setProperty("isolation","isolate"),a.setAttribute("data-layout",e.layout),a.setAttribute("dir",un());const w=document.activeElement instanceof HTMLElement?document.activeElement:null,f=document.createElement("div");f.className="panel",f.tabIndex=-1,i?(f.setAttribute("role","dialog"),f.setAttribute("aria-modal","true"),f.setAttribute("aria-labelledby",`${s}-h`),e.content.body&&f.setAttribute("aria-describedby",`${s}-b`)):(f.setAttribute("role","status"),f.setAttribute("aria-live","polite"));const I=dn(e);I.background&&f.style.setProperty("background",I.background),I.text&&f.style.setProperty("color",I.text);let q=!1;const _=p=>{var A,st;q||(q=!0,document.removeEventListener("keydown",$,!0),a.remove(),w!=null&&w.isConnected?w.focus():i&&((st=(A=document.body).focus)==null||st.call(A)),p==="dismiss"&&n.onDismiss((Date.now()-r)/1e3))},$=p=>{p.key==="Escape"&&(p.stopPropagation(),_("dismiss"))};if(e.layout==="IMAGE_ONLY"&&e.content.imageUrl)f.append(rn(e,()=>$n(e)));else{e.content.imageUrl&&f.append(nn(e.content.imageUrl,e.content.headline));const p=document.createElement("h2");if(p.id=`${s}-h`,p.className="headline",p.textContent=e.content.headline,f.append(p),e.content.body){const A=document.createElement("p");A.id=`${s}-b`,A.className="body",A.textContent=e.content.body,f.append(A)}}if(e.buttons.length>0&&f.append(on(e,n,_)),(e.content.showCloseButton||!e.buttons.some(p=>p.action==="DISMISS"))&&f.append(cn(t.closeLabel,()=>_("dismiss"))),i){const p=document.createElement("div");p.className="backdrop",e.content.showCloseButton&&p.addEventListener("click",()=>_("dismiss")),l.append(p)}l.append(f),document.body.append(a),i?(f.focus({preventScroll:!0}),l.addEventListener("keydown",p=>{p instanceof KeyboardEvent&&ln(p,l)})):(f.textContent,f.setAttribute("aria-busy","true"),requestAnimationFrame(()=>{f.removeAttribute("aria-busy")})),document.addEventListener("keydown",$,!0),requestAnimationFrame(()=>{q||!a.isConnected||document.visibilityState==="visible"&&n.onImpression()});function $n(p){const A=p.buttons[0];if(!A){_("dismiss");return}n.onButton(A),_("button")}return{close:_,root:l}}function nn(e,t){const n=document.createElement("figure");n.className="figure";const i=document.createElement("img");return i.src=e,i.alt=t,i.loading="eager",i.decoding="async",i.referrerPolicy="no-referrer",i.addEventListener("error",()=>n.remove()),n.append(i),n}function rn(e,t){const n=document.createElement("button");n.type="button",n.className="image-only";const i=document.createElement("img");return i.src=e.content.imageUrl??"",i.alt=e.content.headline,i.loading="eager",i.decoding="async",i.referrerPolicy="no-referrer",n.append(i),n.addEventListener("click",t),n}function on(e,t,n){const i=document.createElement("div");i.className="buttons";for(const r of e.buttons){const s=r.action==="URL"&&r.value?sn(r):an(r);s.addEventListener("click",()=>{r.action!=="DISMISS"&&t.onButton(r),n(r.action==="DISMISS"?"dismiss":"button"),r.action==="DEEP_LINK"&&r.value&&location.assign(r.value)}),i.append(s)}return i}function sn(e){const t=document.createElement("a");return t.href=e.value??"#",t.target="_blank",t.rel="noopener noreferrer",t.className=`cta ${e.style.toLowerCase()}`,t.textContent=e.label,t}function an(e){const t=document.createElement("button");return t.type="button",t.className=`cta ${e.style.toLowerCase()}`,t.textContent=e.label,t}function cn(e,t){const n=document.createElement("button");return n.type="button",n.className="close",n.setAttribute("aria-label",e),n.textContent="×",n.addEventListener("click",t),n}function ln(e,t){if(e.key!=="Tab")return;const n=[...t.querySelectorAll("button, a[href]")].filter(a=>!a.hasAttribute("disabled"));if(n.length===0)return;const i=n[0],r=n[n.length-1];if(!i||!r)return;const s=t.activeElement;if(e.shiftKey&&s===i){e.preventDefault(),r.focus();return}!e.shiftKey&&s===r&&(e.preventDefault(),i.focus())}function un(){const e=document.documentElement.getAttribute("dir");if(e)return e;try{return getComputedStyle(document.documentElement).direction||"ltr"}catch{return"ltr"}}function dn(e){const t=Ce.test(e.content.backgroundColor??"")?e.content.backgroundColor:void 0,n=Ce.test(e.content.textColor??"")?e.content.textColor:void 0;return t&&!n?{background:t,text:fn(t)>Qt?"#101010":"#FFFFFF"}:{background:t,text:n}}function fn(e){const t=e.slice(1),n=t.length===3?t.split("").map(a=>a+a).join(""):t.slice(0,6),i=parseInt(n.slice(0,2),16)/255,r=parseInt(n.slice(2,4),16)/255,s=parseInt(n.slice(4,6),16)/255;return .2126*i+.7152*r+.0722*s}function pn(e){if("adoptedStyleSheets"in Document.prototype&&typeof CSSStyleSheet=="function")try{$e??($e=mn()),e.adoptedStyleSheets=[$e];return}catch{}const t=document.createElement("style");t.textContent=Ke,e.append(t)}function mn(){const e=new CSSStyleSheet;return e.replaceSync(Ke),e}const Ke=`
|
|
2
|
+
:host {
|
|
3
|
+
all: initial;
|
|
4
|
+
display: block;
|
|
5
|
+
position: fixed;
|
|
6
|
+
inset: 0;
|
|
7
|
+
pointer-events: none;
|
|
8
|
+
font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
|
9
|
+
line-height: 1.5;
|
|
10
|
+
color: #101010;
|
|
11
|
+
}
|
|
12
|
+
.backdrop {
|
|
13
|
+
position: fixed;
|
|
14
|
+
inset: 0;
|
|
15
|
+
background: rgba(0, 0, 0, 0.45);
|
|
16
|
+
pointer-events: auto;
|
|
17
|
+
}
|
|
18
|
+
.panel {
|
|
19
|
+
position: fixed;
|
|
20
|
+
box-sizing: border-box;
|
|
21
|
+
pointer-events: auto;
|
|
22
|
+
background: #ffffff;
|
|
23
|
+
border-radius: 12px;
|
|
24
|
+
padding: 20px;
|
|
25
|
+
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
|
|
26
|
+
max-height: calc(100vh - 32px);
|
|
27
|
+
overflow-y: auto;
|
|
28
|
+
}
|
|
29
|
+
:host([data-layout="MODAL"]) .panel {
|
|
30
|
+
inset-inline-start: 50%;
|
|
31
|
+
top: 50%;
|
|
32
|
+
transform: translate(-50%, -50%);
|
|
33
|
+
width: min(calc(100vw - 32px), 420px);
|
|
34
|
+
}
|
|
35
|
+
:host([dir="rtl"][data-layout="MODAL"]) .panel {
|
|
36
|
+
transform: translate(50%, -50%);
|
|
37
|
+
}
|
|
38
|
+
:host([data-layout="BANNER_TOP"]) .panel,
|
|
39
|
+
:host([data-layout="BANNER_BOTTOM"]) .panel {
|
|
40
|
+
inset-inline: 16px;
|
|
41
|
+
margin-inline: auto;
|
|
42
|
+
max-width: min(calc(100vw - 32px), 560px);
|
|
43
|
+
}
|
|
44
|
+
:host([data-layout="BANNER_TOP"]) .panel {
|
|
45
|
+
top: 16px;
|
|
46
|
+
padding-top: calc(20px + env(safe-area-inset-top));
|
|
47
|
+
}
|
|
48
|
+
:host([data-layout="BANNER_BOTTOM"]) .panel {
|
|
49
|
+
bottom: 16px;
|
|
50
|
+
padding-bottom: calc(20px + env(safe-area-inset-bottom));
|
|
51
|
+
}
|
|
52
|
+
:host([data-layout="IMAGE_ONLY"]) .panel {
|
|
53
|
+
inset-inline-start: 50%;
|
|
54
|
+
top: 50%;
|
|
55
|
+
transform: translate(-50%, -50%);
|
|
56
|
+
padding: 0;
|
|
57
|
+
background: transparent;
|
|
58
|
+
box-shadow: none;
|
|
59
|
+
}
|
|
60
|
+
.figure { margin: 0 0 12px; }
|
|
61
|
+
.figure img, .image-only img {
|
|
62
|
+
display: block;
|
|
63
|
+
width: 100%;
|
|
64
|
+
height: auto;
|
|
65
|
+
border-radius: 8px;
|
|
66
|
+
}
|
|
67
|
+
.image-only {
|
|
68
|
+
display: block;
|
|
69
|
+
padding: 0;
|
|
70
|
+
border: 0;
|
|
71
|
+
background: none;
|
|
72
|
+
cursor: pointer;
|
|
73
|
+
width: min(calc(100vw - 32px), 420px);
|
|
74
|
+
}
|
|
75
|
+
.headline { margin: 0 0 8px; font-size: 18px; font-weight: 600; }
|
|
76
|
+
.body { margin: 0 0 16px; font-size: 15px; }
|
|
77
|
+
.buttons { display: flex; gap: 8px; flex-wrap: wrap; }
|
|
78
|
+
.cta {
|
|
79
|
+
flex: 1 1 auto;
|
|
80
|
+
min-height: ${pe}px;
|
|
81
|
+
padding: 10px 16px;
|
|
82
|
+
border-radius: 8px;
|
|
83
|
+
border: 1px solid currentColor;
|
|
84
|
+
font: inherit;
|
|
85
|
+
cursor: pointer;
|
|
86
|
+
text-align: center;
|
|
87
|
+
text-decoration: none;
|
|
88
|
+
}
|
|
89
|
+
.cta.primary { background: #101010; color: #ffffff; border-color: #101010; }
|
|
90
|
+
.cta.secondary { background: transparent; color: inherit; }
|
|
91
|
+
.close {
|
|
92
|
+
position: absolute;
|
|
93
|
+
top: 4px;
|
|
94
|
+
inset-inline-end: 4px;
|
|
95
|
+
min-width: ${pe}px;
|
|
96
|
+
min-height: ${pe}px;
|
|
97
|
+
border: 0;
|
|
98
|
+
background: none;
|
|
99
|
+
color: inherit;
|
|
100
|
+
font-size: 22px;
|
|
101
|
+
line-height: 1;
|
|
102
|
+
cursor: pointer;
|
|
103
|
+
}
|
|
104
|
+
@media (prefers-reduced-motion: reduce) {
|
|
105
|
+
.panel { animation: none; transition: none; }
|
|
106
|
+
}
|
|
107
|
+
`;async function yn(e){await c(o.installReported)||(await u(o.installReported,!0),!e&&await x(mt,{sdk_version:D,platform:"web"}))}async function bn(){const[e,t]=await Promise.all([c(o.anonymousId),c(o.installationId)]);return!!e||!!t}const me="REVOKED";function hn(e){const t=e.replace(/-/g,"+").replace(/_/g,"/"),n=atob(t+"=".repeat((4-t.length%4)%4)),i=new Uint8Array(n.length);for(let r=0;r<n.length;r+=1)i[r]=n.charCodeAt(r);return i.buffer}function R(){return typeof navigator<"u"&&"serviceWorker"in navigator&&typeof PushManager<"u"&&typeof Notification<"u"}function Le(e){return`/api/v1/orgs/${e}/push/web/config`}function ye(e){return`/api/v1/orgs/${e}/push/subscriptions`}const Ve=1e4;let B="none",H=null,ie=null;function gn(){B="external"}async function wn(e){if(R()){B="managed";try{H=await navigator.serviceWorker.register(e),ie=null}catch(t){H=null,ie=`service worker registration failed for '${e}': ${String(t)}. Check that the file is deployed and served with a JavaScript content type.`}}}function vn(e,t){return e.active?Promise.resolve(e):new Promise((n,i)=>{const r=setTimeout(()=>{i(new Error(`service worker did not activate within ${t}ms — check the worker script for load errors in DevTools → Application → Service Workers`))},t),s=l=>{l.addEventListener("statechange",()=>{l.state==="activated"?(clearTimeout(r),n(e)):l.state==="redundant"&&(clearTimeout(r),i(new Error("service worker became redundant before activating — its script likely failed to parse")))})},a=e.installing??e.waiting;a?s(a):e.addEventListener("updatefound",()=>{e.installing&&s(e.installing)})})}function Sn(e,t,n){return Promise.race([e,new Promise((i,r)=>{setTimeout(()=>r(new Error(n)),t)})])}async function be(e=Ve){if(B==="none")throw new Error("push is not configured — pass serviceWorkerPath to init(), or serviceWorker: 'external' if your own service worker imports arsel-sw.js");if(B==="external")return Sn(navigator.serviceWorker.ready,e,`no service worker became active within ${e}ms — with serviceWorker: 'external', your own worker must be registered and must importScripts arsel-sw.js`);if(ie)throw new Error(ie);if(!H)throw new Error("service worker registration has not completed");return vn(H,e)}async function An(e=Ve){try{return await be(e),null}catch(t){return t instanceof Error?t.message:String(t)}}async function Fe(e,t){try{return await e.pushManager.subscribe({userVisibleOnly:!0,applicationServerKey:hn(t)})}catch(n){return console.error(`[arsel] push subscribe failed: ${n instanceof Error?n.message:n}`),null}}async function En(){const[e,t]=await Promise.all([c(o.clientKey),c(o.baseUrl)]);if(!e||!t||!R())return!1;const{body:n}=await ae(t,Le(e));if(!(n!=null&&n.vapidPublicKey))return!1;let i;try{i=await be()}catch(s){return console.error(`[arsel] ${s instanceof Error?s.message:s}`),!1}const r=await Fe(i,n.vapidPublicKey);return r?je(r,n.keyVersion):!1}async function je(e,t){var f,I;const[n,i,r]=await Promise.all([c(o.clientKey),c(o.baseUrl),V()]);if(!n||!i)return!1;let s=await c(o.installationId);s||(s=crypto.randomUUID(),await u(o.installationId,s));const a=e.toJSON(),l=await F(i,ye(n),{installationId:s,platform:"web",endpoint:a.endpoint,keys:a.keys,anonymousId:r,enablementStatus:Notification.permission==="granted"?"AUTHORIZED":"DENIED",deviceTimezone:Intl.DateTimeFormat().resolvedOptions().timeZone,deviceLocale:navigator.language});if(l.result!==b.success)return!1;(f=l.body)!=null&&f.deviceSecret&&await u(o.deviceSecret,l.body.deviceSecret),await u(o.vapidKeyVersion,t),await u(o.endpoint,a.endpoint??null);const w=((I=l.body)==null?void 0:I.status)??null;return await u(o.subscriptionStatus,w),w!==me}async function In(){const[e,t,n,i]=await Promise.all([c(o.clientKey),c(o.baseUrl),c(o.installationId),c(o.deviceSecret)]);return!e||!t||!n||!i||(await F(t,`${ye(e)}/unsubscribe`,{installationId:n},{"X-Arsel-Device-Auth":i},!0)).result!==b.success?!1:(await u(o.subscriptionStatus,me),!0)}async function _n(){if(B==="none"||!R()||Notification.permission!=="granted")return;const[e,t]=await Promise.all([c(o.clientKey),c(o.baseUrl)]);if(!e||!t)return;const{body:n}=await ae(t,Le(e));if(!(n!=null&&n.vapidPublicKey))return;let i;try{i=await be()}catch{return}const r=await i.pushManager.getSubscription(),s=await c(o.vapidKeyVersion);if(r&&s===n.keyVersion)return;r&&await r.unsubscribe().catch(()=>!1);const a=await Fe(i,n.vapidPublicKey);a&&await je(a,n.keyVersion)}async function Nn(){if(!R()||await c(o.subscriptionStatus)===me)return!1;try{const e=B==="managed"?H:await navigator.serviceWorker.getRegistration();return e?await e.pushManager.getSubscription()!==null:!1}catch{return!1}}function kn(){return he??(he=xn().finally(()=>{he=null})),he}let he=null;async function xn(){var s;const[e,t,n]=await Promise.all([c(o.clientKey),c(o.baseUrl),V()]);if(!e||!t)return!1;if(await c(o.deviceSecret))return!0;let i=await c(o.installationId);i||(i=crypto.randomUUID(),await u(o.installationId,i));const r=await F(t,ye(e),{installationId:i,platform:"web",anonymousId:n,enablementStatus:"NOT_DETERMINED",deviceTimezone:Intl.DateTimeFormat().resolvedOptions().timeZone,deviceLocale:navigator.language});return r.code===403?(console.error("[arsel] this origin is not on the organization's allowed origins list — in-app messaging is disabled"),!1):r.result!==b.success?!1:((s=r.body)!=null&&s.deviceSecret&&await u(o.deviceSecret,r.body.deviceSecret),!0)}const Pn=30*6e4;async function We(e=Date.now()){const t=await c(o.sessionStartedAt)??0,n=await c(o.backgroundedAt)??0;if(t!==0){if(n===0||e-n<Pn)return;await x(ft,{duration_seconds:Math.round((n-t)/1e3)},n)}await u(o.sessionStartedAt,e),await u(o.backgroundedAt,0),await x(dt,{},e)}async function Xe(e=Date.now()){(await c(o.sessionStartedAt)??0)!==0&&await u(o.backgroundedAt,e)}function Tn(e){typeof document>"u"||(document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"?We().then(()=>e==null?void 0:e()):Xe()}),window.addEventListener("pagehide",()=>void Xe()))}let h=null,ge=!1,U=null;function E(e){ge&&console.info(`[arsel] ${e}`)}const Dn=/^\+[1-9]\d{6,14}$/,On=/^[^\s@]+@[^\s@]+\.[^\s@]+$/,ze=100;let re=[],He=!1;function Mn(){typeof navigator<"u"&&navigator.serviceWorker&&navigator.serviceWorker.addEventListener("message",e=>{const t=e.data;(t==null?void 0:t.type)==="arsel_iam_sync"&&Bt()}),typeof window<"u"&&(window.addEventListener("online",()=>{W().catch(()=>{}),ne().catch(()=>{})}),window.addEventListener("pagehide",()=>{fe(),ne().catch(()=>{})})),typeof document<"u"&&document.addEventListener("visibilitychange",()=>{if(document.visibilityState==="visible"){W().catch(()=>{}),ee().catch(()=>{});return}fe(),ne().catch(()=>{})})}function C(){return U===null}function Rn(e){var n,i;if(!((n=e.clientKey)!=null&&n.trim()))return"clientKey is required (the org's publishable pub_… key)";if(!e.clientKey.startsWith("pub_"))return"clientKey should be the publishable pub_… key — never a secret API key";const t=/^http:\/\/(localhost|127\.0\.0\.1)(:\d+)?(\/|$)/.test(e.baseUrl??"");if(!((i=e.baseUrl)!=null&&i.startsWith("https://"))&&!t)return"baseUrl must be HTTPS (http is allowed for localhost only)";try{new URL(e.baseUrl)}catch{return"baseUrl is not a valid URL"}return null}function qe(e){return h||(h=(async()=>{if(ge=e.debug??!1,U=Rn(e),U){console.error(`[arsel] not started — ${U}`);return}const t=e.baseUrl.replace(/\/+$/,"");await Promise.all([u(o.clientKey,e.clientKey),u(o.baseUrl,t)]);const n=await bn();await V(),await yn(n);const i=re;re=[];for(const l of i)await x(l.name,l.properties,l.timestampMs);e.serviceWorker==="external"?gn():e.serviceWorkerPath&&await wn(e.serviceWorkerPath);const r=Bn(e.inApp);Tn(r?Re:void 0),Mn();const s=typeof document<"u"?document:void 0,a=(s==null?void 0:s.visibilityState)==="visible"&&s.prerendering!==!0;a&&await We(),r&&(Dt(Un(r)),await kn()&&(await Tt(ge),a&&Re())),W().catch(()=>{}),_n().catch(()=>{}),E(`initialized (sdk ${D})`)})(),h)}async function we(e,t={}){const n=e==null?void 0:e.trim();if(!n){E("track() called with a blank event name — ignoring");return}if(n.startsWith(k)){E(`'${k}' is reserved for the SDK — ignoring '${n}'`);return}if(!h){if(re.length>=ze){He||(He=!0,console.warn(`[arsel] more than ${ze} events tracked before init() — dropping the rest. Call init() earlier.`));return}re.push({name:n,properties:t,timestampMs:Date.now()});return}await h,C()&&(await x(n,t),de("CUSTOM_EVENT",n,t))}async function Ye(e,t={}){const n=e==null?void 0:e.trim();if(!n){E("screen() called with a blank name — ignoring");return}await h,await x(yt,{...t,screen_name:n}),de("SCREEN_VIEW",n,t)}function Je(e){Ot(e)}async function Ge(e){if(await h,!C())return;let{email:t,phoneNumber:n}=e??{};const i=e==null?void 0:e.externalId;if(t&&!On.test(t)&&(console.error(`[arsel] identify(): '${t}' is not a valid email address — ignored`),t=void 0),n&&!Dn.test(n)&&(console.error(`[arsel] identify(): '${n}' is not E.164 (e.g. +966501234567) — ignored`),n=void 0),!i&&!t&&!n){E("identify() needs at least one of externalId, email or phoneNumber");return}i&&await u(o.externalId,i),t&&await u(o.email,t),n&&await u(o.phoneNumber,n),await x(pt,{}),await Te()}async function Ze(){await h,C()&&(await Promise.all([L(o.externalId),L(o.email),L(o.phoneNumber),L(o.sessionStartedAt)]),await lt(),await Te(),E("identity reset"))}async function Qe(){if(await h,!C())return!1;const e=await In();return E(e?"push opt-out recorded":"push opt-out not sent — no registration to revoke"),e}async function et(){if(await h,!C()||!R())return!1;const e=await An();if(e)return console.error(`[arsel] promptForPush(): ${e}`),!1;const t=await Notification.requestPermission();return t!=="granted"?(E(`notification permission: ${t}`),!1):En()}async function tt(){return await h,V()}async function nt(){const[e,t,n,i,r,s,a,l,w,f,I,q,_]=await Promise.all([c(o.anonymousId),c(o.externalId),c(o.email),c(o.phoneNumber),c(o.installationId),c(o.deviceSecret),c(o.vapidKeyVersion),Se(v.events),Nn(),c(o.subscriptionStatus),c(o.lastResponseCode),c(o.lastResponsePath),c(o.lastResponseAtMs)]),$=Mt(),ot=await Rt().catch(()=>0);return{sdkVersion:D,initialized:h!==null&&U===null,configError:U,inAppMessages:$.messages,inAppBundleVersion:$.bundleVersion,inAppFetchedAtMs:$.fetchedAtMs,pendingInAppBeacons:ot,anonymousId:e,hasAssertedIdentity:!!(t||n||i),installationId:r,hasDeviceSecret:!!s,pendingEvents:l,permission:R()?Notification.permission:"unsupported",isSubscribed:w,subscriptionStatus:f,vapidKeyVersion:a,lastResponseCode:I,lastResponsePath:q,lastResponseAtMs:_}}async function it(){await h,C()&&await W()}const rt={init:qe,track:we,screen:Ye,suppressInAppMessages:Je,identify:Ge,reset:Ze,optOut:Qe,promptForPush:et,getAnonymousId:tt,diagnostics:nt,flushNow:it,SDK_VERSION:D};function Bn(e){if(e===!1)return;const t=typeof e=="object"&&e!==null?e:{};return{zIndex:t.zIndex??Cn,closeLabel:t.closeLabel??"Close"}}function Un(e){return t=>{const n=jt();try{tn(t,e,{onImpression:()=>void Wt(t,n),onButton:i=>{Xt(t,i.buttonId),i.action==="CUSTOM_EVENT"&&i.value&&we(i.value)},onDismiss:i=>{zt(t,i),Be()}})}catch(i){E(`in-app render failed: ${i instanceof Error?i.message:""}`),Be()}}}const Cn=2147483e3;m.Arsel=rt,m.SDK_VERSION=D,m.default=rt,m.diagnostics=nt,m.flushNow=it,m.getAnonymousId=tt,m.identify=Ge,m.init=qe,m.optOut=Qe,m.promptForPush=et,m.reset=Ze,m.screen=Ye,m.suppressInAppMessages=Je,m.track=we,Object.defineProperties(m,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
|
|
2
108
|
//# sourceMappingURL=arsel.umd.cjs.map
|