@suprsend/web-sdk 4.1.1 → 4.1.2
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/dist/cjs/index.cjs +1 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/es/index.js +137 -134
- package/dist/es/index.js.map +1 -1
- package/dist/types/preferences.d.ts +6 -2
- package/package.json +1 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var z=Object.defineProperty;var B=(a,e,t)=>e in a?z(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t;var f=(a,e,t)=>B(a,typeof e!="symbol"?e+"":e,t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const K=require("mitt"),L=require("jwt-decode"),Q=require("zustand/vanilla"),G=require("socket.io-client");var p=(a=>(a.OPT_IN="opt_in",a.OPT_OUT="opt_out",a))(p||{}),C=(a=>(a.ALL="all",a.REQUIRED="required",a))(C||{}),d=(a=>(a.VALIDATION_ERROR="VALIDATION_ERROR",a.NETWORK_ERROR="NETWORK_ERROR",a.UNKNOWN_ERROR="UNKNOWN_ERROR",a.PERMISSION_DENIED="PERMISSION_DENIED",a.UNSUPPORTED_ACTION="UNSUPPORTED_ACTION",a.NOT_FOUND="NOT_FOUND",a))(d||{}),n=(a=>(a.SUCCESS="success",a.ERROR="error",a))(n||{}),y=(a=>(a.INITIAL="INITIAL",a.LOADING="LOADING",a.SUCCESS="SUCCESS",a.ERROR="ERROR",a.FETCHING_MORE="FETCHING_MORE",a))(y||{});function N(){let a=new Date().getTime();return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(t){const s=(a+Math.random()*16)%16|0;return a=Math.floor(a/16),(t=="x"?s:s&3|8).toString(16)})}function k(){return Math.round(Date.now())}function _(a){return Object.keys(a).length===0}function J(a){return(a==null?void 0:a.length)<=0}function Z(a){const e="=".repeat((4-a.length%4)%4),t=(a+e).replace(/-/g,"+").replace(/_/g,"/"),s=atob(t),r=new Uint8Array(s.length);for(let i=0;i<s.length;++i)r[i]=s.charCodeAt(i);return r}function X(a,e){let t;return(...s)=>(clearTimeout(t),new Promise(r=>{t=setTimeout(()=>r(a(...s)),e)}))}function $(a,e){const t={};return(...s)=>{const[r]=s,i=s.slice(1);return typeof t[r]=="function"?t[r](...i):(t[r]=X(a,e),t[r](...i))}}function o(a){const e={status:a.status};return a.statusCode&&(e.statusCode=a.statusCode),a.body&&(e.body=a.body),a.status===n.ERROR&&(e.error={type:a.errorType,message:a.errorMessage}),e}function A(){return typeof window<"u"}function x(a,e){A()&&(typeof e=="object"&&(e=JSON.stringify(e)),localStorage.setItem(a,e))}function V(a){if(!A())return;const e=localStorage.getItem(a);if(e)try{return JSON.parse(e)}catch{return e}}function Y(a){A()&&localStorage.removeItem(a)}async function q(a){const t=new TextEncoder().encode(a),s=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(s)).map(c=>c.toString(16).padStart(2,"0")).join("")}class U{constructor(e){f(this,"config");this.config=e}getHeaders(){const e={"Content-Type":"application/json",Authorization:this.config.publicApiKey};return this.config.userToken&&(e["x-ss-signature"]=this.config.userToken),e}requestApiInstance(e){switch(e.type){case"get":return this.get(e.url,e.signal);case"post":return this.post(e.url,(e==null?void 0:e.payload)||{},e.signal);case"patch":return this.patch(e.url,(e==null?void 0:e.payload)||{},e.signal);default:return this.get(e.url,e.signal)}}get(e,t){return fetch(e,{method:"GET",headers:this.getHeaders(),signal:t})}post(e,t,s){return fetch(e,{method:"POST",body:JSON.stringify(t),headers:this.getHeaders(),signal:s})}patch(e,t,s){return fetch(e,{method:"PATCH",body:JSON.stringify(t),headers:this.getHeaders(),signal:s})}async request(e){var t,s,r;if(!this.config.distinctId)return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"User isn't authenticated. Call identify method before performing any action"});if((t=this.config.authenticateOptions)!=null&&t.refreshUserToken&&this.config.userToken){const i=L(this.config.userToken),c=(i.exp||0)*1e3,u=Date.now();if(c<=u)try{const h=await this.config.authenticateOptions.refreshUserToken(this.config.userToken,i);h&&typeof h=="string"&&this.config.identify(this.config.distinctId,h,this.config.authenticateOptions)}catch{}}try{const i=await this.requestApiInstance(e),c=await i.json(),u=(c==null?void 0:c.status)||(i.ok?n.SUCCESS:n.ERROR);return o({status:u,body:c,statusCode:i.status,errorMessage:(s=c==null?void 0:c.error)==null?void 0:s.message,errorType:(r=c==null?void 0:c.error)==null?void 0:r.type})}catch(i){return console.error(i),o({status:n.ERROR,statusCode:500,errorMessage:(i==null?void 0:i.message)||"network error",errorType:d.NETWORK_ERROR})}}}class ee{constructor(e){f(this,"config");f(this,"preferenceData");f(this,"preferenceArgs");f(this,"debouncedUpdateCategoryPreferences");f(this,"debouncedUpdateChannelPreferences");f(this,"debounceTime",1e3);this.config=e,this.debouncedUpdateCategoryPreferences=$(this._updateCategoryPreferences.bind(this),this.debounceTime),this.debouncedUpdateChannelPreferences=$(this._updateChannelPreferences.bind(this),this.debounceTime)}validateQueryParams(e={}){const t={};for(const s in e)e[s]&&(typeof e[s]=="object"?t[s]=JSON.stringify(e[s]):t[s]=String(e[s]));return t}set data(e){this.preferenceData=e}get data(){return this.preferenceData}getUrl(e,t){const s=`${this.config.host}/v2/subscriber/${this.config.distinctId}/${e}`,r=this.validateQueryParams(t),i=new URLSearchParams(r).toString();return i?`${s}/?${i}`:s}async getPreferences(e){const t={tenant_id:e==null?void 0:e.tenantId,show_opt_out_channels:(e==null?void 0:e.showOptOutChannels)!==!1,tags:e==null?void 0:e.tags,locale:e==null?void 0:e.locale};this.preferenceArgs={tenantId:t==null?void 0:t.tenant_id,showOptOutChannels:t==null?void 0:t.show_opt_out_channels,tags:t==null?void 0:t.tags,locale:t==null?void 0:t.locale};const s=this.getUrl("full_preference",t),r=await this.config.client().request({type:"get",url:s});return r.error||(this.data=r.body),r}async getCategories(e){const t={tenant_id:e==null?void 0:e.tenantId,show_opt_out_channels:(e==null?void 0:e.showOptOutChannels)!==!1,limit:e==null?void 0:e.limit,offset:e==null?void 0:e.offset,tags:e==null?void 0:e.tags,locale:e==null?void 0:e.locale},s=this.getUrl("category",t);return await this.config.client().request({type:"get",url:s})}async getCategory(e,t){if(!e)return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"Category parameter is missing"});const s={tenant_id:t==null?void 0:t.tenantId,show_opt_out_channels:(t==null?void 0:t.showOptOutChannels)!==!1,locale:t==null?void 0:t.locale},r=this.getUrl(`category/${e}`,s);return await this.config.client().request({type:"get",url:r})}async getOverallChannelPreferences(){const e=this.getUrl("channel_preference");return await this.config.client().request({type:"get",url:e})}async _updateCategoryPreferences(e,t,s,r){const i=this.getUrl(`category/${e}`,r),c=await this.config.client().request({type:"patch",url:i,payload:t});return c!=null&&c.error?this.config.emitter.emit("preferences_error",c):(Object.assign(s,c.body),this.config.emitter.emit("preferences_updated",{status:n.SUCCESS,statusCode:200,body:this.data})),c}async _updateChannelPreferences(e){const t=this.getUrl("channel_preference"),s=await this.config.client().request({type:"patch",url:t,payload:e});return s!=null&&s.error?this.config.emitter.emit("preferences_error",s):(await this.getPreferences(this.preferenceArgs),this.config.emitter.emit("preferences_updated",{status:n.SUCCESS,statusCode:200,body:this.data})),s}async updateCategoryPreference(e,t,s){var h,S,b,T,g;if(!e||![p.OPT_IN,p.OPT_OUT].includes(t))return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:e?"Preference parameter is invalid":"Category parameter is missing"});if(!this.data)return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"Call getPreferences method before performing action"});if(!this.data.sections)return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"Sections doesn't exist"});let r=null,i=!1;for(const R of this.data.sections){let m=!1;if(R.subcategories){for(const O of R.subcategories)if(O.category===e)if(r=O,O.is_editable){if(O.preference!==t){O.preference=t,i=!0,m=!0;break}}else return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"Category preference is not editable"});if(m)break}}if(!r)return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"Category not found"});if(!i)return o({status:n.SUCCESS,body:this.data});const c=[];(h=r==null?void 0:r.channels)==null||h.forEach(R=>{R.preference===p.OPT_OUT&&c.push(R.channel)});let u=!0;typeof(s==null?void 0:s.showOptOutChannels)=="boolean"?u=s==null?void 0:s.showOptOutChannels:typeof((S=this.preferenceArgs)==null?void 0:S.showOptOutChannels)=="boolean"&&(u=this.preferenceArgs.showOptOutChannels);const l={preference:r.preference,opt_out_channels:u&&t===p.OPT_IN?null:c};return this.debouncedUpdateCategoryPreferences(e,e,l,r,{tenant_id:(s==null?void 0:s.tenantId)||((b=this.preferenceArgs)==null?void 0:b.tenantId),show_opt_out_channels:u,tags:(s==null?void 0:s.tags)||((T=this.preferenceArgs)==null?void 0:T.tags),locale:(s==null?void 0:s.locale)||((g=this.preferenceArgs)==null?void 0:g.locale)}),o({status:n.SUCCESS,body:this.data})}async updateChannelPreferenceInCategory(e,t,s,r){var T,g,R,m,O;if(!e||!s)return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:e?"Category parameter is missing":"Channel parameter is missing"});if(![p.OPT_IN,p.OPT_OUT].includes(t))return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"Preference parameter is invalid"});if(!this.data)return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"Call getPreferences method before performing action"});if(!this.data.sections)return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"Sections doesn't exist"});let i=null,c=null,u=!1;for(const I of this.data.sections){let v=!1;if(I.subcategories){for(const E of I.subcategories){if(E.category===s){if(i=E,!E.channels)continue;for(const w of E.channels)if(w.channel===e)if(c=w,w.is_editable){if(w.preference!==t){w.preference=t,t===p.OPT_IN&&(E.preference=p.OPT_IN),u=!0,v=!0;break}}else return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"Channel preference is not editable"})}if(v)break}if(v)break}}if(!i)return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"Category not found"});if(!c)return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"Category's channel not found"});if(!u)return o({status:n.SUCCESS,body:this.data});const l=[];(T=i==null?void 0:i.channels)==null||T.forEach(I=>{I.preference===p.OPT_OUT&&l.push(I.channel)});let h=!0;typeof(r==null?void 0:r.showOptOutChannels)=="boolean"?h=r==null?void 0:r.showOptOutChannels:typeof((g=this.preferenceArgs)==null?void 0:g.showOptOutChannels)=="boolean"&&(h=this.preferenceArgs.showOptOutChannels);const b={preference:h&&i.preference===p.OPT_OUT&&t===p.OPT_IN?p.OPT_IN:i.preference,opt_out_channels:l};return this.debouncedUpdateCategoryPreferences(s,s,b,i,{tenant_id:(r==null?void 0:r.tenantId)||((R=this.preferenceArgs)==null?void 0:R.tenantId),show_opt_out_channels:h,tags:(r==null?void 0:r.tags)||((m=this.preferenceArgs)==null?void 0:m.tags),locale:(r==null?void 0:r.locale)||((O=this.preferenceArgs)==null?void 0:O.locale)}),o({status:n.SUCCESS,body:this.data})}async updateOverallChannelPreference(e,t){if(!e||![C.ALL,C.REQUIRED].includes(t))return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:e?"Preference parameter is invalid":"Channel parameter is missing"});if(!this.data)return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"Call getPreferences method before performing action"});if(!this.data.channel_preferences)return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"Channel preferences doesn't exist"});let s=null,r=!1;const i=t===C.REQUIRED;for(const c of this.data.channel_preferences)if(c.channel===e&&(s=c,c.is_restricted!==i)){c.is_restricted=i,r=!0;break}return s?r?(this.debouncedUpdateChannelPreferences(s.channel,{channel_preferences:[s]}),o({status:n.SUCCESS,body:this.data})):o({status:n.SUCCESS,body:this.data}):o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"Channel data not found"})}}const j="ss_device_id";class te{constructor(e){f(this,"config");f(this,"preferences");this.config=e,this.preferences=new ee(e)}isReservedKey(e){var t;return e.startsWith("$")||((t=e==null?void 0:e.toLowerCase())==null?void 0:t.startsWith("ss_"))}formatParamsToObj(e,t){let s=null;return typeof e=="object"&&t===void 0?s=e:typeof e=="string"&&t!==void 0?s={[e]:t}:console.warn("[SuprSend]: Invalid input parameters"),s}formatParamsToArray(e){if(e)return Array.isArray(e)?e:[e]}validateObjData(e,t){const s={},r=(t==null?void 0:t.allowReservedKeys)||!1,i=(t==null?void 0:t.valueType)||"";for(const c in e){let u=e[c];if(!(c&&u===void 0)){if(!r&&this.isReservedKey(c)){console.warn("[SuprSend]: key cannot start with $ or ss_");continue}i==="number"?u=Number(u):i==="boolean"&&(u=!!u),s[c]=u}}return s}validateArrayData(e){const t=[];for(const s of e)if(s!=null){if(this.isReservedKey(s)){console.warn("[SuprSend]: key cannot start with $ or ss_");continue}t.push(String(s))}return t}async triggerUserEvent(e){return this.config.eventApi({distinct_id:this.config.distinctId,$insert_id:N(),$time:k(),...e})}async set(e,t){const s=this.formatParamsToObj(e,t);if(!s)return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"data provided is empty"});const r=this.validateObjData(s);return _(r)?o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"data provided is empty"}):this.triggerUserEvent({$set:r})}async setOnce(e,t){const s=this.formatParamsToObj(e,t);if(!s)return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"data provided is empty"});const r=this.validateObjData(s);return _(r)?o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"data provided is empty"}):this.triggerUserEvent({$set_once:r})}async increment(e,t){const s=this.formatParamsToObj(e,t);if(!s)return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"data provided is empty"});const r=this.validateObjData(s,{valueType:"number"});return _(r)?o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"data provided is empty"}):this.triggerUserEvent({$add:r})}async append(e,t){const s=this.formatParamsToObj(e,t);if(!s)return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"data provided is empty"});const r=this.validateObjData(s);return _(r)?o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"data provided is empty"}):this.triggerUserEvent({$append:r})}async remove(e,t){const s=this.formatParamsToObj(e,t);if(!s)return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"data provided is empty"});const r=this.validateObjData(s);return _(r)?o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"data provided is empty"}):this.triggerUserEvent({$remove:r})}async unset(e){const t=this.formatParamsToArray(e);if(!t)return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"data provided is empty"});const s=this.validateArrayData(t);return J(s)?o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"data provided is empty"}):this.triggerUserEvent({$unset:s})}appendInternal(e,t){const s=this.formatParamsToObj(e,t);if(!s)return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"data provided is empty"});const r=this.validateObjData(s,{allowReservedKeys:!0});return _(r)?o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"data provided is empty"}):this.triggerUserEvent({$append:r})}removeInternal(e,t){const s=this.formatParamsToObj(e,t);if(!s)return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"data provided is empty"});const r=this.validateObjData(s,{allowReservedKeys:!0});return _(r)?o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"data provided is empty"}):this.triggerUserEvent({$remove:r})}setInternal(e,t){const s=this.formatParamsToObj(e,t);if(!s)return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"data provided is empty"});const r=this.validateObjData(s,{allowReservedKeys:!0});return _(r)?o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"data provided is empty"}):this.triggerUserEvent({$set:r})}validateEmail(e){return/\S+@\S+\.\S+/.test(e)}validateMobile(e){return/^\+[1-9]\d{1,14}$/.test(e)}async addEmail(e){return this.validateEmail(e)?this.appendInternal({$email:e}):o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"provided email is invalid"})}async removeEmail(e){return this.validateEmail(e)?this.removeInternal({$email:e}):o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"provided email is invalid"})}async addSms(e){return this.validateMobile(e)?this.appendInternal({$sms:e}):o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"provided mobile number is invalid, must be as per E.164 standard"})}async removeSms(e){return this.validateMobile(e)?this.removeInternal({$sms:e}):o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"provided mobile number is invalid, must be as per E.164 standard"})}async addWhatsapp(e){return this.validateMobile(e)?this.appendInternal({$whatsapp:e}):o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"provided mobile number is invalid, must be as per E.164 standard"})}async removeWhatsapp(e){return this.validateMobile(e)?this.removeInternal({$whatsapp:e}):o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"provided mobile number is invalid, must be as per E.164 standard"})}getDeviceId(){let e=V(j);return e||(e=N(),x(j,e)),e}async addWebPush(e){if(typeof e!="object")return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"provided push subscription is invalid, must be an object"});const t=this.getDeviceId();return this.appendInternal({$webpush:e,$id_provider:"vapid",$device_id:t})}async removeWebPush(e){if(typeof e!="object")return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"provided push subscription is invalid, must be an object"});const t=this.getDeviceId();return this.removeInternal({$webpush:e,$id_provider:"vapid",$device_id:t})}async addSlack(e){return typeof e!="object"?o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"provided slack data is invalid, must be an object"}):this.appendInternal({$slack:e})}async removeSlack(e){return typeof e!="object"?o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"provided slack data is invalid, must be an object"}):this.removeInternal({$slack:e})}async addMSTeams(e){return typeof e!="object"?o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"provided ms_teams data is invalid, must be object"}):this.appendInternal({$ms_teams:e})}async removeMSTeams(e){return typeof e!="object"?o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"provided ms_teams data is invalid, must be object"}):this.removeInternal({$ms_teams:e})}async setPreferredLanguage(e){return typeof e!="string"?o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"provided language is invalid, must be string"}):this.setInternal({$preferred_language:e})}async setTimezone(e){return typeof e!="string"?o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"provided timezone is invalid, must be string"}):this.setInternal({$timezone:e})}}const M="ss_wp_hash";class se{constructor(e){f(this,"config");this.config=e}async getPushSubscription(){if(!A())return;const e=await navigator.serviceWorker.getRegistration();if(!e)return;const t=e.pushManager.getSubscription();if(t)return t}async checkAndUpdateOnServer(e){const t=e.endpoint;let s=null;try{s=await q(t)}catch{}if(s){if(s===V(M))return o({status:n.SUCCESS});x(M,s)}return await this.config.user.addWebPush(e)}async handleRegisterPush(){try{if(await navigator.serviceWorker.register(`/${this.config.swFileName}`),await Notification.requestPermission()!=="granted")return console.warn("[SuprSend]: Notification permission isnt granted"),o({status:n.ERROR,errorType:d.PERMISSION_DENIED,errorMessage:"Notification permission isn't granted"});const t=await navigator.serviceWorker.ready,s=await t.pushManager.getSubscription();if(s)return this.checkAndUpdateOnServer(s);if(!this.config.vapidKey)return console.warn("[SuprSend]: Vapid key is missing. Add it while creating SuprSend instance"),o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"Vapid key is missing. Add it while creating SuprSend instance"});const r=await t.pushManager.subscribe({userVisibleOnly:!0,applicationServerKey:Z(this.config.vapidKey)});return this.checkAndUpdateOnServer(r)}catch(e){return console.warn("SuprSend: Error getting push subscription",e),o({status:n.ERROR,errorType:d.UNKNOWN_ERROR,errorMessage:(e==null?void 0:e.message)||"Unknown error occured while registering for push"})}}async registerPush(){return A()&&"serviceWorker"in navigator&&"PushManager"in window?this.handleRegisterPush():(console.warn("[SuprSend]: Webpush isn't supported"),o({status:n.ERROR,errorType:d.UNSUPPORTED_ACTION,errorMessage:"Webpush isn't supported"}))}async updatePushSubscription(){const e=await this.getPushSubscription();if(e)return this.checkAndUpdateOnServer(e)}async removePushSubscription(){const e=await this.getPushSubscription();if(e)return this.config.user.removeWebPush(e)}notificationPermission(){return Notification.permission}async pushSubscribed(){return!!await this.getPushSubscription()}}const W=20,re="default",ie=100,D={storeId:"$suprsend_default_store",label:""},ne={tenantId:re,pageSize:W,stores:null,host:{apiHost:"https://inboxs.live",socketHost:"https://betainbox.suprsend.com"}},P={notifications:[],store:D,pageInfo:{total:0,pageSize:W,hasMore:!1},meta:{badge:0},apiStatus:y.INITIAL,isFirstFetch:!0};class ae{constructor(e){f(this,"config");f(this,"feedInstances",[]);this.config=e}initialize(e={}){const t=new H(this.config,e);return this.feedInstances.push(t),t}removeInstance(e){this.feedInstances=this.feedInstances.filter(t=>t!==e)}removeAll(){for(const e of this.feedInstances)e.remove();this.feedInstances=[]}}class H{constructor(e,t){f(this,"feedOptions");f(this,"config");f(this,"store");f(this,"socket");f(this,"expiryTimerId");f(this,"fetchAbortController");f(this,"emitter",K());this.config=e,this.setOptions(t),this.store=this.createFeedStore()}setOptions(e){this.feedOptions={...ne},e!=null&&e.tenantId&&(this.feedOptions.tenantId=e.tenantId),e!=null&&e.host&&(this.feedOptions.host=e.host),typeof(e==null?void 0:e.pageSize)=="number"&&e.pageSize>0&&(this.feedOptions.pageSize=Math.min(e.pageSize,ie)),e!=null&&e.stores&&(this.feedOptions.stores=e.stores),this.validateStore()}validateStore(){const e=this.feedOptions.stores;if(!e)return;if(!Array.isArray(e)||(e==null?void 0:e.length)<=0){console.warn("SuprSend: stores should be an array of objects");return}const t=[];e.forEach(s=>{if(!s.storeId){console.warn("SuprSend: storeId is mandatory for each store. Ignoring store without storeId");return}const r=s==null?void 0:s.query;let i,c,u=[],l=[];typeof(r==null?void 0:r.read)=="boolean"&&(i=r.read),typeof(r==null?void 0:r.archived)=="boolean"&&(c=r.archived),typeof(r==null?void 0:r.tags)=="string"?u=[r.tags]:Array.isArray(r==null?void 0:r.tags)&&(u=r==null?void 0:r.tags.filter(h=>typeof h=="string")),typeof(r==null?void 0:r.categories)=="string"?l=[r.categories]:Array.isArray(r==null?void 0:r.categories)&&(l=r==null?void 0:r.categories.filter(h=>typeof h=="string")),t.push({storeId:s.storeId,label:s.label||s.storeId,query:{archived:c,read:i,tags:u,categories:l}})}),this.feedOptions.stores=t}createFeedStore(){return Q.createStore()(()=>{var e;return{...P,store:((e=this.feedOptions.stores)==null?void 0:e[0])||D}})}initializeSocketEvents(){this.socket.on("connect_error",async e=>{var t;if(e.message==="Authentication Error: wrong auth token"&&((t=this.config.authenticateOptions)!=null&&t.refreshUserToken)&&this.config.userToken){const s=this.socket.auth["x-ss-signature"],r=L(s),i=(r.exp||0)*1e3,c=Date.now();if(i<=c)try{const l=await this.config.authenticateOptions.refreshUserToken(this.config.userToken,r);l&&typeof l=="string"&&(await this.config.identify(this.config.distinctId,l,this.config.authenticateOptions),this.socket.auth["x-ss-signature"]=l,setTimeout(()=>{this.socket.connect()},1e3))}catch{}}}),this.socket.on("new_notification",this.handleNewNotificationSocketEvent.bind(this)),this.socket.on("notification_update",this.handleNoticationUpdateSocketEvent.bind(this)),this.socket.on("bulk_notification_update",this.handleBulkNotificationUpdateSocketEvent.bind(this)),this.socket.on("reset_badge",async()=>{const e=this.store.getState();this.store.setState({meta:{...e.meta,badge:0}}),this.emitter.emit("feed.store_update",this.data)})}async handleNewNotificationSocketEvent(e){var u,l;if(!e.n_id)return;const t=await this.fetchDetails(e.n_id);if(t.status===n.ERROR)return;const s=t.body,r=this.store.getState();let i=!1;const c={...r.meta};this.notificationBelongToStore(s,r.store)&&(i=!0,this.store.setState({notifications:this.orderNotificationsBasedOnPinFlag(s,r.notifications)})),(l=(u=this.feedOptions.stores)==null?void 0:u.map)==null||l.call(u,h=>{this.notificationBelongToStore(s,h)&&(i=!0,c[h.storeId]=(r.meta[h.storeId]||0)+1)}),this.store.setState({meta:{...c,badge:i?c.badge+1:c.badge}}),i&&this.emitter.emit("feed.new_notification",s),this.emitter.emit("feed.store_update",this.data)}async handleNoticationUpdateSocketEvent(e){var l;if(!e.n_id)return;const t=await Promise.allSettled([this.fetchDetails(e.n_id),this.fetchCount()]),s=this.store.getState();if(t[0].status!=="fulfilled")return;const r=t[0].value;if(r.status===n.ERROR)return;const i=r.body,c=(l=s.notifications)==null?void 0:l.some(h=>h.n_id===i.n_id);this.notificationBelongToStore(i,s.store)?c?this.store.setState({notifications:s.notifications.map(h=>h.n_id===i.n_id?i:h)}):this.store.setState({notifications:this.orderNotificationsBasedOnPinFlag(i,s.notifications)}):this.store.setState({notifications:s.notifications.filter(h=>h.n_id!==i.n_id)}),this.emitter.emit("feed.store_update",this.data)}async handleBulkNotificationUpdateSocketEvent(e){const t=this.store.getState();if(e.action==="read"&&e.notification_ids==="all"){for(const s in t.meta)t.meta[s]=0;this.store.setState({notifications:t.notifications.map(s=>(s.read_on||(s.read_on=Date.now()),s)),meta:t.meta})}e.action==="seen"&&Array.isArray(e.notification_ids)&&this.store.setState({notifications:t.notifications.map(s=>(e.notification_ids.includes(s.n_id)&&(s.seen_on=Date.now()),s))}),this.emitter.emit("feed.store_update",this.data)}notificationBelongToStore(e,t){var m,O,I,v;const s=!!e.read_on,r=e.archived,i=e.tags,c=e.n_category,u=(m=t==null?void 0:t.query)==null?void 0:m.read,l=(O=t==null?void 0:t.query)==null?void 0:O.archived,h=(I=t==null?void 0:t.query)==null?void 0:I.tags,S=(v=t==null?void 0:t.query)==null?void 0:v.categories,b=u==null||s===u,T=!!r==!!l;let g=!1,R=!1;return Array.isArray(h)&&h.length>0?h.forEach(E=>{i!=null&&i.includes(E)&&(g=!0)}):g=!0,Array.isArray(S)&&S.length>0?S.includes(c)&&(R=!0):R=!0,b&&g&&R&&T}orderNotificationsBasedOnPinFlag(e,t){if(e.is_pinned)return[e,...t];{let s=!1;const r=[];return t.forEach(i=>{i.is_pinned||s?r.push(i):(r.push(e),r.push(i),s=!0)}),s?r:[...t,e]}}startExpiryTimer(){this.expiryTimerId||(this.expiryTimerId=setInterval(this.removeExpiredFeed.bind(this),3e4))}async removeExpiredFeed(){const e=this.store.getState();let t=!1;const s=e.notifications.filter(r=>(r.expiry?Date.now()>r.expiry:!1)?(t=!0,!1):!0);t&&(this.store.setState({notifications:s}),await this.fetchCount(),this.emitter.emit("feed.store_update",this.data))}getUrl(e,t){var c;const s=`${(c=this.feedOptions.host)==null?void 0:c.apiHost}/v1/feed/${e}`,r=this.validateQueryParams(t),i=new URLSearchParams(r).toString();return i?`${s}?${i}`:s}validateQueryParams(e={}){const t={};for(const s in e){const r=e[s];r==null||r===""||(typeof r=="object"?t[s]=JSON.stringify(r):t[s]=String(r))}return t}requestInprogress(){const e=this.store.getState();return[y.LOADING,y.FETCHING_MORE].includes(e.apiStatus)}storesQueryParamObj(e){return e==null?void 0:e.map(s=>this.storeQueryParamObj(s))}storeQueryParamObj(e){const t=e==null?void 0:e.query,s=(t==null?void 0:t.tags)||[],r=(t==null?void 0:t.categories)||[],i=t==null?void 0:t.read,c=t==null?void 0:t.archived;return{store_id:e.storeId,query:{read:i,archived:c,tags:{or:s},categories:{or:r}}}}async changeActiveStore(e){var r;const t=this.store.getState();if(t.store.storeId===e)return;const s=(r=this.feedOptions.stores)==null?void 0:r.find(i=>i.storeId===e);return s?(this.fetchAbortController&&(this.fetchAbortController.abort(),this.fetchAbortController=void 0),this.store.setState({...P,store:s,meta:t.meta}),await this.fetch()):{status:n.ERROR,error:{type:d.NOT_FOUND,message:`store with storeId ${e} doesnt exist`}}}get data(){const e=this.store.getState();return{notifications:e.notifications,pageInfo:e.pageInfo,meta:e.meta,apiStatus:e.apiStatus,store:e.store}}initializeSocketConnection(){var e;this.socket||(this.socket=G.io((e=this.feedOptions.host)==null?void 0:e.socketHost,{transports:["websocket"],auth:{authorization:this.config.publicApiKey,"x-ss-signature":this.config.userToken,distinct_id:this.config.distinctId,tenant_id:this.feedOptions.tenantId,schema:"1"},reconnectionDelay:1e3,reconnectionDelayMax:1e4}),this.initializeSocketEvents())}async fetch(e={}){const t=this.store.getState();if(this.requestInprogress())return;const s=(e==null?void 0:e.pageSize)||this.feedOptions.pageSize;t.isFirstFetch?(this.store.setState({apiStatus:y.LOADING}),this.fetchCount()):this.store.setState({apiStatus:y.FETCHING_MORE}),this.emitter.emit("feed.store_update",this.data);const r={distinct_id:this.config.distinctId,tenant_id:this.feedOptions.tenantId,page_size:s,store:t.store.storeId!==D.storeId?this.storeQueryParamObj(t.store):null};if(t.notifications.length>0){const l=t.notifications[t.notifications.length-1];r.search_after=[l.is_pinned,l.created_on]}else r.search_after=[];const i=this.getUrl("notifications",r),c=new AbortController;this.fetchAbortController=c;const u=await this.config.client().request({type:"get",url:i,signal:c.signal});if(!c.signal.aborted)return u.status===n.ERROR?(this.store.setState({apiStatus:y.ERROR}),this.emitter.emit("feed.store_update",this.data),u):(this.store.setState({apiStatus:y.SUCCESS,notifications:t.isFirstFetch?u.body.results:[...t.notifications,...u.body.results],pageInfo:{...t.pageInfo,total:u.body.meta.total_count,hasMore:u.body.meta.has_more},isFirstFetch:!1}),this.emitter.emit("feed.store_update",this.data),this.startExpiryTimer(),u)}async fetchNextPage(){return this.store.getState().pageInfo.hasMore===!1?{status:n.ERROR,error:{type:d.VALIDATION_ERROR,message:"No more pages to fetch"}}:this.fetch()}async fetchCount(){const e={distinct_id:this.config.distinctId,tenant_id:this.feedOptions.tenantId,stores:this.feedOptions.stores?this.storesQueryParamObj(this.feedOptions.stores):null},t=this.getUrl("notifications_count",e),s=await this.config.client().request({type:"get",url:t});return s.status===n.SUCCESS&&this.store.setState({meta:s.body}),this.emitter.emit("feed.store_update",this.data),s}async fetchDetails(e){const t=this.getUrl(`notifications/${e}`,{tenant_id:this.feedOptions.tenantId,distinct_id:this.config.distinctId});return await this.config.client().request({type:"get",url:t})}async markAsSeen(e){const t=this.store.getState();let s=!1;if(this.store.setState({notifications:t.notifications.map(i=>(i.n_id===e&&(i.seen_on?s=!0:i.seen_on=Date.now()),i))}),s)return{status:n.SUCCESS};const r=this.getUrl(`notifications/${e}/seen`,{tenant_id:this.feedOptions.tenantId,distinct_id:this.config.distinctId});return this.emitter.emit("feed.store_update",this.data),await this.config.client().request({type:"patch",url:r})}async markAsRead(e){const t=this.store.getState();let s=!1;if(this.store.setState({notifications:t.notifications.map(i=>(i.n_id===e&&(i.read_on?s=!0:(i.read_on=Date.now(),i.seen_on=Date.now())),i))}),s)return{status:n.SUCCESS};const r=this.getUrl(`notifications/${e}/read`,{tenant_id:this.feedOptions.tenantId,distinct_id:this.config.distinctId});return this.emitter.emit("feed.store_update",this.data),await this.config.client().request({type:"patch",url:r})}async markAsUnread(e){const t=this.store.getState();let s=!1;if(this.store.setState({notifications:t.notifications.map(i=>(i.n_id===e&&(i.read_on?i.read_on=null:s=!0),i))}),s)return{status:n.SUCCESS};const r=this.getUrl(`notifications/${e}/unread`,{tenant_id:this.feedOptions.tenantId,distinct_id:this.config.distinctId});return this.emitter.emit("feed.store_update",this.data),await this.config.client().request({type:"patch",url:r})}async markAsInteracted(e){const t=this.store.getState();this.store.setState({notifications:t.notifications.map(r=>(r.n_id===e&&(r.interacted_on||(r.interacted_on=Date.now()),r.read_on||(r.read_on=Date.now())),r))});const s=this.getUrl(`notifications/${e}/interacted`,{tenant_id:this.feedOptions.tenantId,distinct_id:this.config.distinctId});return this.emitter.emit("feed.store_update",this.data),await this.config.client().request({type:"patch",url:s})}async markAsArchived(e){const t=this.store.getState();let s=!1;if(this.store.setState({notifications:t.notifications.filter(i=>i.n_id===e?(s=!!i.archived,!1):!0)}),s)return{status:n.SUCCESS};const r=this.getUrl(`notifications/${e}/archive`,{tenant_id:this.feedOptions.tenantId,distinct_id:this.config.distinctId});return this.emitter.emit("feed.store_update",this.data),await this.config.client().request({type:"patch",url:r})}async markBulkAsSeen(e){const t=this.store.getState();this.store.setState({notifications:t.notifications.map(r=>(e.includes(r.n_id)&&(r.seen_on||(r.seen_on=Date.now())),r))});const s=this.getUrl("bulk/notifications/seen",{tenant_id:this.feedOptions.tenantId,distinct_id:this.config.distinctId});return this.emitter.emit("feed.store_update",this.data),await this.config.client().request({type:"post",url:s,payload:{notification_ids:e}})}async resetBadgeCount(){const e=this.store.getState();this.store.setState({meta:{...e.meta,badge:0}});const t=this.getUrl("reset_bell_count",{tenant_id:this.feedOptions.tenantId,distinct_id:this.config.distinctId});return this.emitter.emit("feed.store_update",this.data),await this.config.client().request({type:"patch",url:t})}async markAllAsRead(){const e=this.store.getState();this.store.setState({meta:{...e.meta,badge:0},notifications:e.notifications.map(s=>(s.read_on=Date.now(),s))});const t=this.getUrl("mark_all_read",{tenant_id:this.feedOptions.tenantId,distinct_id:this.config.distinctId});return this.emitter.emit("feed.store_update",this.data),await this.config.client().request({type:"patch",url:t})}reset(){var e;this.store.setState({...P,store:((e=this.feedOptions.stores)==null?void 0:e[0])||D}),this.emitter.emit("feed.store_update",this.data),this.expiryTimerId&&(clearInterval(this.expiryTimerId),this.expiryTimerId=void 0)}remove(){var e;this.reset(),this.emitter.off("*"),(e=this.socket)==null||e.disconnect(),this.config.feeds.removeInstance(this)}}const oe="https://hub.suprsend.com",ce="serviceworker.js",F="ss_distinct_id";class de{constructor(e,t){f(this,"host");f(this,"publicApiKey");f(this,"distinctId");f(this,"userToken");f(this,"vapidKey");f(this,"swFileName");f(this,"apiClient",null);f(this,"userTokenExpirationTimer",null);f(this,"authenticateOptions");f(this,"user",new te(this));f(this,"webpush",new se(this));f(this,"feeds",new ae(this));f(this,"emitter",K());if(!e)throw new Error("[SuprSend]: publicApiKey is missing");this.publicApiKey=e,this.host=(t==null?void 0:t.host)||oe,this.vapidKey=(t==null?void 0:t.vapidKey)||"",this.swFileName=(t==null?void 0:t.swFileName)||ce}handleRefreshUserToken(e){if(!this.userToken||!A())return;const t=L(this.userToken),s=(t.exp||0)*1e3,r=Date.now(),i=1e3*30;if(s&&s>r){const c=s-r-i;this.userTokenExpirationTimer&&clearTimeout(this.userTokenExpirationTimer),this.userTokenExpirationTimer=setTimeout(async()=>{let u="";try{u=await e(this.userToken,t)}catch{try{u=await e(this.userToken,t)}catch(h){console.warn("[SuprSend]: Couldn't fetch new userToken",h)}}u&&typeof u=="string"&&this.identify(this.distinctId,u,this.authenticateOptions)},c)}}client(){return this.distinctId||console.warn("[SuprSend]: distinctId is missing. User should be authenticated"),this.apiClient||(this.apiClient=new U(this)),this.apiClient}eventApi(e){return this.client().request({url:`${this.host}/v2/event`,payload:e,type:"post"})}async identify(e,t,s){if(!e)return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"distinctId is missing"});if(this.apiClient&&this.distinctId&&this.distinctId!==e)return o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"User already loggedin, reset current user to login new user"});if(this.apiClient&&this.distinctId===e&&this.userToken!==t)return this.userToken=t,this.apiClient=new U(this),s!=null&&s.refreshUserToken&&this.handleRefreshUserToken(s.refreshUserToken),o({status:n.SUCCESS});if(this.distinctId&&this.apiClient)return o({status:n.SUCCESS});this.distinctId=e,this.userToken=t,this.apiClient=new U(this),this.authenticateOptions=s;const r=V(F);if(s!=null&&s.refreshUserToken&&this.handleRefreshUserToken(s.refreshUserToken),r==this.distinctId)return this.webpush.updatePushSubscription(),o({status:n.SUCCESS});const i=await this.eventApi({event:"$identify",$insert_id:N(),$time:k(),properties:{$identified_id:e}});return i.status===n.SUCCESS?(this.webpush.updatePushSubscription(),x(F,this.distinctId)):this.reset({unsubscribePush:!1}),i}isIdentified(e){return e?!!(this.userToken&&this.distinctId):!!this.distinctId}async track(e,t){let s={};return e?(typeof t=="object"&&(s={...s,...t}),this.eventApi({event:String(e),$insert_id:N(),$time:k(),distinct_id:this.distinctId,properties:s})):o({status:n.ERROR,errorType:d.VALIDATION_ERROR,errorMessage:"event name is missing"})}async reset(e){var s,r;return(e==null?void 0:e.unsubscribePush)!==!1&&(await((s=this.webpush)==null?void 0:s.removePushSubscription()),Y(M)),this.apiClient=null,this.distinctId=null,this.userToken="",this.userTokenExpirationTimer&&clearTimeout(this.userTokenExpirationTimer),((r=this.feeds.feedInstances)==null?void 0:r.length)>0&&this.feeds.removeAll(),o({status:n.SUCCESS})}}exports.ApiResponseStatus=y;exports.ChannelLevelPreferenceOptions=C;exports.ERROR_TYPE=d;exports.Feed=H;exports.PreferenceOptions=p;exports.RESPONSE_STATUS=n;exports.SuprSend=de;
|
|
1
|
+
"use strict";var z=Object.defineProperty;var B=(a,e,t)=>e in a?z(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t;var f=(a,e,t)=>B(a,typeof e!="symbol"?e+"":e,t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const K=require("mitt"),L=require("jwt-decode"),Q=require("zustand/vanilla"),G=require("socket.io-client");var p=(a=>(a.OPT_IN="opt_in",a.OPT_OUT="opt_out",a))(p||{}),C=(a=>(a.ALL="all",a.REQUIRED="required",a))(C||{}),c=(a=>(a.VALIDATION_ERROR="VALIDATION_ERROR",a.NETWORK_ERROR="NETWORK_ERROR",a.UNKNOWN_ERROR="UNKNOWN_ERROR",a.PERMISSION_DENIED="PERMISSION_DENIED",a.UNSUPPORTED_ACTION="UNSUPPORTED_ACTION",a.NOT_FOUND="NOT_FOUND",a))(c||{}),n=(a=>(a.SUCCESS="success",a.ERROR="error",a))(n||{}),g=(a=>(a.INITIAL="INITIAL",a.LOADING="LOADING",a.SUCCESS="SUCCESS",a.ERROR="ERROR",a.FETCHING_MORE="FETCHING_MORE",a))(g||{});function N(){let a=new Date().getTime();return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(t){const s=(a+Math.random()*16)%16|0;return a=Math.floor(a/16),(t=="x"?s:s&3|8).toString(16)})}function k(){return Math.round(Date.now())}function _(a){return Object.keys(a).length===0}function J(a){return(a==null?void 0:a.length)<=0}function Z(a){const e="=".repeat((4-a.length%4)%4),t=(a+e).replace(/-/g,"+").replace(/_/g,"/"),s=atob(t),r=new Uint8Array(s.length);for(let i=0;i<s.length;++i)r[i]=s.charCodeAt(i);return r}function X(a,e){let t;return(...s)=>(clearTimeout(t),new Promise(r=>{t=setTimeout(()=>r(a(...s)),e)}))}function $(a,e){const t={};return(...s)=>{const[r]=s,i=s.slice(1);return typeof t[r]=="function"?t[r](...i):(t[r]=X(a,e),t[r](...i))}}function o(a){const e={status:a.status};return a.statusCode&&(e.statusCode=a.statusCode),a.body&&(e.body=a.body),a.status===n.ERROR&&(e.error={type:a.errorType,message:a.errorMessage}),e}function A(){return typeof window<"u"}function x(a,e){A()&&(typeof e=="object"&&(e=JSON.stringify(e)),localStorage.setItem(a,e))}function V(a){if(!A())return;const e=localStorage.getItem(a);if(e)try{return JSON.parse(e)}catch{return e}}function Y(a){A()&&localStorage.removeItem(a)}async function q(a){const t=new TextEncoder().encode(a),s=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(s)).map(d=>d.toString(16).padStart(2,"0")).join("")}class U{constructor(e){f(this,"config");this.config=e}getHeaders(){const e={"Content-Type":"application/json",Authorization:this.config.publicApiKey};return this.config.userToken&&(e["x-ss-signature"]=this.config.userToken),e}requestApiInstance(e){switch(e.type){case"get":return this.get(e.url,e.signal);case"post":return this.post(e.url,(e==null?void 0:e.payload)||{},e.signal);case"patch":return this.patch(e.url,(e==null?void 0:e.payload)||{},e.signal);default:return this.get(e.url,e.signal)}}get(e,t){return fetch(e,{method:"GET",headers:this.getHeaders(),signal:t})}post(e,t,s){return fetch(e,{method:"POST",body:JSON.stringify(t),headers:this.getHeaders(),signal:s})}patch(e,t,s){return fetch(e,{method:"PATCH",body:JSON.stringify(t),headers:this.getHeaders(),signal:s})}async request(e){var t,s,r;if(!this.config.distinctId)return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"User isn't authenticated. Call identify method before performing any action"});if((t=this.config.authenticateOptions)!=null&&t.refreshUserToken&&this.config.userToken){const i=L(this.config.userToken),d=(i.exp||0)*1e3,u=Date.now();if(d<=u)try{const h=await this.config.authenticateOptions.refreshUserToken(this.config.userToken,i);h&&typeof h=="string"&&this.config.identify(this.config.distinctId,h,this.config.authenticateOptions)}catch{}}try{const i=await this.requestApiInstance(e),d=await i.json(),u=(d==null?void 0:d.status)||(i.ok?n.SUCCESS:n.ERROR);return o({status:u,body:d,statusCode:i.status,errorMessage:(s=d==null?void 0:d.error)==null?void 0:s.message,errorType:(r=d==null?void 0:d.error)==null?void 0:r.type})}catch(i){return console.error(i),o({status:n.ERROR,statusCode:500,errorMessage:(i==null?void 0:i.message)||"network error",errorType:c.NETWORK_ERROR})}}}class ee{constructor(e){f(this,"config");f(this,"preferenceData");f(this,"preferenceArgs");f(this,"debouncedUpdateCategoryPreferences");f(this,"debouncedUpdateChannelPreferences");f(this,"debounceTime",1e3);this.config=e,this.debouncedUpdateCategoryPreferences=$(this._updateCategoryPreferences.bind(this),this.debounceTime),this.debouncedUpdateChannelPreferences=$(this._updateChannelPreferences.bind(this),this.debounceTime)}validateQueryParams(e={}){const t={};for(const s in e)e[s]&&(typeof e[s]=="object"?t[s]=JSON.stringify(e[s]):t[s]=String(e[s]));return t}set data(e){this.preferenceData=e}get data(){return this.preferenceData}getUrl(e,t){const s=`${this.config.host}/v2/subscriber/${this.config.distinctId}/${e}`,r=this.validateQueryParams(t),i=new URLSearchParams(r).toString();return i?`${s}/?${i}`:s}async getPreferences(e){const t={tenant_id:e==null?void 0:e.tenantId,show_opt_out_channels:(e==null?void 0:e.showOptOutChannels)!==!1,tags:e==null?void 0:e.tags,locale:e==null?void 0:e.locale};this.preferenceArgs={tenantId:t==null?void 0:t.tenant_id,showOptOutChannels:t==null?void 0:t.show_opt_out_channels,tags:t==null?void 0:t.tags,locale:t==null?void 0:t.locale};const s=this.getUrl("full_preference",t),r=await this.config.client().request({type:"get",url:s});return r.error||(this.data=r.body),r}async getCategories(e){const t={tenant_id:e==null?void 0:e.tenantId,show_opt_out_channels:(e==null?void 0:e.showOptOutChannels)!==!1,limit:e==null?void 0:e.limit,offset:e==null?void 0:e.offset,tags:e==null?void 0:e.tags,locale:e==null?void 0:e.locale},s=this.getUrl("category",t);return await this.config.client().request({type:"get",url:s})}async getCategory(e,t){if(!e)return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"Category parameter is missing"});const s={tenant_id:t==null?void 0:t.tenantId,show_opt_out_channels:(t==null?void 0:t.showOptOutChannels)!==!1,locale:t==null?void 0:t.locale},r=this.getUrl(`category/${e}`,s);return await this.config.client().request({type:"get",url:r})}async getOverallChannelPreferences(e){const t={tenant_id:e==null?void 0:e.tenantId},s=this.getUrl("channel_preference",t);return await this.config.client().request({type:"get",url:s})}async _updateCategoryPreferences(e,t,s,r){const i=this.getUrl(`category/${e}`,r),d=await this.config.client().request({type:"patch",url:i,payload:t});return d!=null&&d.error?this.config.emitter.emit("preferences_error",d):(Object.assign(s,d.body),this.config.emitter.emit("preferences_updated",{status:n.SUCCESS,statusCode:200,body:this.data})),d}async _updateChannelPreferences(e,t){const s=this.getUrl("channel_preference",t),r=await this.config.client().request({type:"patch",url:s,payload:e});return r!=null&&r.error?this.config.emitter.emit("preferences_error",r):(await this.getPreferences(this.preferenceArgs),this.config.emitter.emit("preferences_updated",{status:n.SUCCESS,statusCode:200,body:this.data})),r}async updateCategoryPreference(e,t,s){var h,S,b,T,y;if(!e||![p.OPT_IN,p.OPT_OUT].includes(t))return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:e?"Preference parameter is invalid":"Category parameter is missing"});if(!this.data)return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"Call getPreferences method before performing action"});if(!this.data.sections)return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"Sections doesn't exist"});let r=null,i=!1;for(const R of this.data.sections){let m=!1;if(R.subcategories){for(const O of R.subcategories)if(O.category===e)if(r=O,O.is_editable){if(O.preference!==t){O.preference=t,i=!0,m=!0;break}}else return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"Category preference is not editable"});if(m)break}}if(!r)return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"Category not found"});if(!i)return o({status:n.SUCCESS,body:this.data});const d=[];(h=r==null?void 0:r.channels)==null||h.forEach(R=>{R.preference===p.OPT_OUT&&d.push(R.channel)});let u=!0;typeof(s==null?void 0:s.showOptOutChannels)=="boolean"?u=s==null?void 0:s.showOptOutChannels:typeof((S=this.preferenceArgs)==null?void 0:S.showOptOutChannels)=="boolean"&&(u=this.preferenceArgs.showOptOutChannels);const l={preference:r.preference,opt_out_channels:u&&t===p.OPT_IN?null:d};return this.debouncedUpdateCategoryPreferences(e,e,l,r,{tenant_id:(s==null?void 0:s.tenantId)||((b=this.preferenceArgs)==null?void 0:b.tenantId),show_opt_out_channels:u,tags:(s==null?void 0:s.tags)||((T=this.preferenceArgs)==null?void 0:T.tags),locale:(s==null?void 0:s.locale)||((y=this.preferenceArgs)==null?void 0:y.locale)}),o({status:n.SUCCESS,body:this.data})}async updateChannelPreferenceInCategory(e,t,s,r){var T,y,R,m,O;if(!e||!s)return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:e?"Category parameter is missing":"Channel parameter is missing"});if(![p.OPT_IN,p.OPT_OUT].includes(t))return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"Preference parameter is invalid"});if(!this.data)return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"Call getPreferences method before performing action"});if(!this.data.sections)return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"Sections doesn't exist"});let i=null,d=null,u=!1;for(const I of this.data.sections){let v=!1;if(I.subcategories){for(const E of I.subcategories){if(E.category===s){if(i=E,!E.channels)continue;for(const w of E.channels)if(w.channel===e)if(d=w,w.is_editable){if(w.preference!==t){w.preference=t,t===p.OPT_IN&&(E.preference=p.OPT_IN),u=!0,v=!0;break}}else return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"Channel preference is not editable"})}if(v)break}if(v)break}}if(!i)return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"Category not found"});if(!d)return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"Category's channel not found"});if(!u)return o({status:n.SUCCESS,body:this.data});const l=[];(T=i==null?void 0:i.channels)==null||T.forEach(I=>{I.preference===p.OPT_OUT&&l.push(I.channel)});let h=!0;typeof(r==null?void 0:r.showOptOutChannels)=="boolean"?h=r==null?void 0:r.showOptOutChannels:typeof((y=this.preferenceArgs)==null?void 0:y.showOptOutChannels)=="boolean"&&(h=this.preferenceArgs.showOptOutChannels);const b={preference:h&&i.preference===p.OPT_OUT&&t===p.OPT_IN?p.OPT_IN:i.preference,opt_out_channels:l};return this.debouncedUpdateCategoryPreferences(s,s,b,i,{tenant_id:(r==null?void 0:r.tenantId)||((R=this.preferenceArgs)==null?void 0:R.tenantId),show_opt_out_channels:h,tags:(r==null?void 0:r.tags)||((m=this.preferenceArgs)==null?void 0:m.tags),locale:(r==null?void 0:r.locale)||((O=this.preferenceArgs)==null?void 0:O.locale)}),o({status:n.SUCCESS,body:this.data})}async updateOverallChannelPreference(e,t,s){var u;if(!e||![C.ALL,C.REQUIRED].includes(t))return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:e?"Preference parameter is invalid":"Channel parameter is missing"});if(!this.data)return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"Call getPreferences method before performing action"});if(!this.data.channel_preferences)return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"Channel preferences doesn't exist"});let r=null,i=!1;const d=t===C.REQUIRED;for(const l of this.data.channel_preferences)if(l.channel===e&&(r=l,l.is_restricted!==d)){l.is_restricted=d,i=!0;break}return r?i?(this.debouncedUpdateChannelPreferences(r.channel,{channel_preferences:[r]},{tenant_id:(s==null?void 0:s.tenantId)||((u=this.preferenceArgs)==null?void 0:u.tenantId)}),o({status:n.SUCCESS,body:this.data})):o({status:n.SUCCESS,body:this.data}):o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"Channel data not found"})}}const j="ss_device_id";class te{constructor(e){f(this,"config");f(this,"preferences");this.config=e,this.preferences=new ee(e)}isReservedKey(e){var t;return e.startsWith("$")||((t=e==null?void 0:e.toLowerCase())==null?void 0:t.startsWith("ss_"))}formatParamsToObj(e,t){let s=null;return typeof e=="object"&&t===void 0?s=e:typeof e=="string"&&t!==void 0?s={[e]:t}:console.warn("[SuprSend]: Invalid input parameters"),s}formatParamsToArray(e){if(e)return Array.isArray(e)?e:[e]}validateObjData(e,t){const s={},r=(t==null?void 0:t.allowReservedKeys)||!1,i=(t==null?void 0:t.valueType)||"";for(const d in e){let u=e[d];if(!(d&&u===void 0)){if(!r&&this.isReservedKey(d)){console.warn("[SuprSend]: key cannot start with $ or ss_");continue}i==="number"?u=Number(u):i==="boolean"&&(u=!!u),s[d]=u}}return s}validateArrayData(e){const t=[];for(const s of e)if(s!=null){if(this.isReservedKey(s)){console.warn("[SuprSend]: key cannot start with $ or ss_");continue}t.push(String(s))}return t}async triggerUserEvent(e){return this.config.eventApi({distinct_id:this.config.distinctId,$insert_id:N(),$time:k(),...e})}async set(e,t){const s=this.formatParamsToObj(e,t);if(!s)return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"data provided is empty"});const r=this.validateObjData(s);return _(r)?o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"data provided is empty"}):this.triggerUserEvent({$set:r})}async setOnce(e,t){const s=this.formatParamsToObj(e,t);if(!s)return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"data provided is empty"});const r=this.validateObjData(s);return _(r)?o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"data provided is empty"}):this.triggerUserEvent({$set_once:r})}async increment(e,t){const s=this.formatParamsToObj(e,t);if(!s)return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"data provided is empty"});const r=this.validateObjData(s,{valueType:"number"});return _(r)?o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"data provided is empty"}):this.triggerUserEvent({$add:r})}async append(e,t){const s=this.formatParamsToObj(e,t);if(!s)return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"data provided is empty"});const r=this.validateObjData(s);return _(r)?o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"data provided is empty"}):this.triggerUserEvent({$append:r})}async remove(e,t){const s=this.formatParamsToObj(e,t);if(!s)return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"data provided is empty"});const r=this.validateObjData(s);return _(r)?o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"data provided is empty"}):this.triggerUserEvent({$remove:r})}async unset(e){const t=this.formatParamsToArray(e);if(!t)return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"data provided is empty"});const s=this.validateArrayData(t);return J(s)?o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"data provided is empty"}):this.triggerUserEvent({$unset:s})}appendInternal(e,t){const s=this.formatParamsToObj(e,t);if(!s)return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"data provided is empty"});const r=this.validateObjData(s,{allowReservedKeys:!0});return _(r)?o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"data provided is empty"}):this.triggerUserEvent({$append:r})}removeInternal(e,t){const s=this.formatParamsToObj(e,t);if(!s)return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"data provided is empty"});const r=this.validateObjData(s,{allowReservedKeys:!0});return _(r)?o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"data provided is empty"}):this.triggerUserEvent({$remove:r})}setInternal(e,t){const s=this.formatParamsToObj(e,t);if(!s)return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"data provided is empty"});const r=this.validateObjData(s,{allowReservedKeys:!0});return _(r)?o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"data provided is empty"}):this.triggerUserEvent({$set:r})}validateEmail(e){return/\S+@\S+\.\S+/.test(e)}validateMobile(e){return/^\+[1-9]\d{1,14}$/.test(e)}async addEmail(e){return this.validateEmail(e)?this.appendInternal({$email:e}):o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"provided email is invalid"})}async removeEmail(e){return this.validateEmail(e)?this.removeInternal({$email:e}):o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"provided email is invalid"})}async addSms(e){return this.validateMobile(e)?this.appendInternal({$sms:e}):o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"provided mobile number is invalid, must be as per E.164 standard"})}async removeSms(e){return this.validateMobile(e)?this.removeInternal({$sms:e}):o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"provided mobile number is invalid, must be as per E.164 standard"})}async addWhatsapp(e){return this.validateMobile(e)?this.appendInternal({$whatsapp:e}):o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"provided mobile number is invalid, must be as per E.164 standard"})}async removeWhatsapp(e){return this.validateMobile(e)?this.removeInternal({$whatsapp:e}):o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"provided mobile number is invalid, must be as per E.164 standard"})}getDeviceId(){let e=V(j);return e||(e=N(),x(j,e)),e}async addWebPush(e){if(typeof e!="object")return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"provided push subscription is invalid, must be an object"});const t=this.getDeviceId();return this.appendInternal({$webpush:e,$id_provider:"vapid",$device_id:t})}async removeWebPush(e){if(typeof e!="object")return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"provided push subscription is invalid, must be an object"});const t=this.getDeviceId();return this.removeInternal({$webpush:e,$id_provider:"vapid",$device_id:t})}async addSlack(e){return typeof e!="object"?o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"provided slack data is invalid, must be an object"}):this.appendInternal({$slack:e})}async removeSlack(e){return typeof e!="object"?o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"provided slack data is invalid, must be an object"}):this.removeInternal({$slack:e})}async addMSTeams(e){return typeof e!="object"?o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"provided ms_teams data is invalid, must be object"}):this.appendInternal({$ms_teams:e})}async removeMSTeams(e){return typeof e!="object"?o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"provided ms_teams data is invalid, must be object"}):this.removeInternal({$ms_teams:e})}async setPreferredLanguage(e){return typeof e!="string"?o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"provided language is invalid, must be string"}):this.setInternal({$preferred_language:e})}async setTimezone(e){return typeof e!="string"?o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"provided timezone is invalid, must be string"}):this.setInternal({$timezone:e})}}const M="ss_wp_hash";class se{constructor(e){f(this,"config");this.config=e}async getPushSubscription(){if(!A())return;const e=await navigator.serviceWorker.getRegistration();if(!e)return;const t=e.pushManager.getSubscription();if(t)return t}async checkAndUpdateOnServer(e){const t=e.endpoint;let s=null;try{s=await q(t)}catch{}if(s){if(s===V(M))return o({status:n.SUCCESS});x(M,s)}return await this.config.user.addWebPush(e)}async handleRegisterPush(){try{if(await navigator.serviceWorker.register(`/${this.config.swFileName}`),await Notification.requestPermission()!=="granted")return console.warn("[SuprSend]: Notification permission isnt granted"),o({status:n.ERROR,errorType:c.PERMISSION_DENIED,errorMessage:"Notification permission isn't granted"});const t=await navigator.serviceWorker.ready,s=await t.pushManager.getSubscription();if(s)return this.checkAndUpdateOnServer(s);if(!this.config.vapidKey)return console.warn("[SuprSend]: Vapid key is missing. Add it while creating SuprSend instance"),o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"Vapid key is missing. Add it while creating SuprSend instance"});const r=await t.pushManager.subscribe({userVisibleOnly:!0,applicationServerKey:Z(this.config.vapidKey)});return this.checkAndUpdateOnServer(r)}catch(e){return console.warn("SuprSend: Error getting push subscription",e),o({status:n.ERROR,errorType:c.UNKNOWN_ERROR,errorMessage:(e==null?void 0:e.message)||"Unknown error occured while registering for push"})}}async registerPush(){return A()&&"serviceWorker"in navigator&&"PushManager"in window?this.handleRegisterPush():(console.warn("[SuprSend]: Webpush isn't supported"),o({status:n.ERROR,errorType:c.UNSUPPORTED_ACTION,errorMessage:"Webpush isn't supported"}))}async updatePushSubscription(){const e=await this.getPushSubscription();if(e)return this.checkAndUpdateOnServer(e)}async removePushSubscription(){const e=await this.getPushSubscription();if(e)return this.config.user.removeWebPush(e)}notificationPermission(){return Notification.permission}async pushSubscribed(){return!!await this.getPushSubscription()}}const W=20,re="default",ie=100,D={storeId:"$suprsend_default_store",label:""},ne={tenantId:re,pageSize:W,stores:null,host:{apiHost:"https://inboxs.live",socketHost:"https://betainbox.suprsend.com"}},P={notifications:[],store:D,pageInfo:{total:0,pageSize:W,hasMore:!1},meta:{badge:0},apiStatus:g.INITIAL,isFirstFetch:!0};class ae{constructor(e){f(this,"config");f(this,"feedInstances",[]);this.config=e}initialize(e={}){const t=new H(this.config,e);return this.feedInstances.push(t),t}removeInstance(e){this.feedInstances=this.feedInstances.filter(t=>t!==e)}removeAll(){for(const e of this.feedInstances)e.remove();this.feedInstances=[]}}class H{constructor(e,t){f(this,"feedOptions");f(this,"config");f(this,"store");f(this,"socket");f(this,"expiryTimerId");f(this,"fetchAbortController");f(this,"emitter",K());this.config=e,this.setOptions(t),this.store=this.createFeedStore()}setOptions(e){this.feedOptions={...ne},e!=null&&e.tenantId&&(this.feedOptions.tenantId=e.tenantId),e!=null&&e.host&&(this.feedOptions.host=e.host),typeof(e==null?void 0:e.pageSize)=="number"&&e.pageSize>0&&(this.feedOptions.pageSize=Math.min(e.pageSize,ie)),e!=null&&e.stores&&(this.feedOptions.stores=e.stores),this.validateStore()}validateStore(){const e=this.feedOptions.stores;if(!e)return;if(!Array.isArray(e)||(e==null?void 0:e.length)<=0){console.warn("SuprSend: stores should be an array of objects");return}const t=[];e.forEach(s=>{if(!s.storeId){console.warn("SuprSend: storeId is mandatory for each store. Ignoring store without storeId");return}const r=s==null?void 0:s.query;let i,d,u=[],l=[];typeof(r==null?void 0:r.read)=="boolean"&&(i=r.read),typeof(r==null?void 0:r.archived)=="boolean"&&(d=r.archived),typeof(r==null?void 0:r.tags)=="string"?u=[r.tags]:Array.isArray(r==null?void 0:r.tags)&&(u=r==null?void 0:r.tags.filter(h=>typeof h=="string")),typeof(r==null?void 0:r.categories)=="string"?l=[r.categories]:Array.isArray(r==null?void 0:r.categories)&&(l=r==null?void 0:r.categories.filter(h=>typeof h=="string")),t.push({storeId:s.storeId,label:s.label||s.storeId,query:{archived:d,read:i,tags:u,categories:l}})}),this.feedOptions.stores=t}createFeedStore(){return Q.createStore()(()=>{var e;return{...P,store:((e=this.feedOptions.stores)==null?void 0:e[0])||D}})}initializeSocketEvents(){this.socket.on("connect_error",async e=>{var t;if(e.message==="Authentication Error: wrong auth token"&&((t=this.config.authenticateOptions)!=null&&t.refreshUserToken)&&this.config.userToken){const s=this.socket.auth["x-ss-signature"],r=L(s),i=(r.exp||0)*1e3,d=Date.now();if(i<=d)try{const l=await this.config.authenticateOptions.refreshUserToken(this.config.userToken,r);l&&typeof l=="string"&&(await this.config.identify(this.config.distinctId,l,this.config.authenticateOptions),this.socket.auth["x-ss-signature"]=l,setTimeout(()=>{this.socket.connect()},1e3))}catch{}}}),this.socket.on("new_notification",this.handleNewNotificationSocketEvent.bind(this)),this.socket.on("notification_update",this.handleNoticationUpdateSocketEvent.bind(this)),this.socket.on("bulk_notification_update",this.handleBulkNotificationUpdateSocketEvent.bind(this)),this.socket.on("reset_badge",async()=>{const e=this.store.getState();this.store.setState({meta:{...e.meta,badge:0}}),this.emitter.emit("feed.store_update",this.data)})}async handleNewNotificationSocketEvent(e){var u,l;if(!e.n_id)return;const t=await this.fetchDetails(e.n_id);if(t.status===n.ERROR)return;const s=t.body,r=this.store.getState();let i=!1;const d={...r.meta};this.notificationBelongToStore(s,r.store)&&(i=!0,this.store.setState({notifications:this.orderNotificationsBasedOnPinFlag(s,r.notifications)})),(l=(u=this.feedOptions.stores)==null?void 0:u.map)==null||l.call(u,h=>{this.notificationBelongToStore(s,h)&&(i=!0,d[h.storeId]=(r.meta[h.storeId]||0)+1)}),this.store.setState({meta:{...d,badge:i?d.badge+1:d.badge}}),i&&this.emitter.emit("feed.new_notification",s),this.emitter.emit("feed.store_update",this.data)}async handleNoticationUpdateSocketEvent(e){var l;if(!e.n_id)return;const t=await Promise.allSettled([this.fetchDetails(e.n_id),this.fetchCount()]),s=this.store.getState();if(t[0].status!=="fulfilled")return;const r=t[0].value;if(r.status===n.ERROR)return;const i=r.body,d=(l=s.notifications)==null?void 0:l.some(h=>h.n_id===i.n_id);this.notificationBelongToStore(i,s.store)?d?this.store.setState({notifications:s.notifications.map(h=>h.n_id===i.n_id?i:h)}):this.store.setState({notifications:this.orderNotificationsBasedOnPinFlag(i,s.notifications)}):this.store.setState({notifications:s.notifications.filter(h=>h.n_id!==i.n_id)}),this.emitter.emit("feed.store_update",this.data)}async handleBulkNotificationUpdateSocketEvent(e){const t=this.store.getState();if(e.action==="read"&&e.notification_ids==="all"){for(const s in t.meta)t.meta[s]=0;this.store.setState({notifications:t.notifications.map(s=>(s.read_on||(s.read_on=Date.now()),s)),meta:t.meta})}e.action==="seen"&&Array.isArray(e.notification_ids)&&this.store.setState({notifications:t.notifications.map(s=>(e.notification_ids.includes(s.n_id)&&(s.seen_on=Date.now()),s))}),this.emitter.emit("feed.store_update",this.data)}notificationBelongToStore(e,t){var m,O,I,v;const s=!!e.read_on,r=e.archived,i=e.tags,d=e.n_category,u=(m=t==null?void 0:t.query)==null?void 0:m.read,l=(O=t==null?void 0:t.query)==null?void 0:O.archived,h=(I=t==null?void 0:t.query)==null?void 0:I.tags,S=(v=t==null?void 0:t.query)==null?void 0:v.categories,b=u==null||s===u,T=!!r==!!l;let y=!1,R=!1;return Array.isArray(h)&&h.length>0?h.forEach(E=>{i!=null&&i.includes(E)&&(y=!0)}):y=!0,Array.isArray(S)&&S.length>0?S.includes(d)&&(R=!0):R=!0,b&&y&&R&&T}orderNotificationsBasedOnPinFlag(e,t){if(e.is_pinned)return[e,...t];{let s=!1;const r=[];return t.forEach(i=>{i.is_pinned||s?r.push(i):(r.push(e),r.push(i),s=!0)}),s?r:[...t,e]}}startExpiryTimer(){this.expiryTimerId||(this.expiryTimerId=setInterval(this.removeExpiredFeed.bind(this),3e4))}async removeExpiredFeed(){const e=this.store.getState();let t=!1;const s=e.notifications.filter(r=>(r.expiry?Date.now()>r.expiry:!1)?(t=!0,!1):!0);t&&(this.store.setState({notifications:s}),await this.fetchCount(),this.emitter.emit("feed.store_update",this.data))}getUrl(e,t){var d;const s=`${(d=this.feedOptions.host)==null?void 0:d.apiHost}/v1/feed/${e}`,r=this.validateQueryParams(t),i=new URLSearchParams(r).toString();return i?`${s}?${i}`:s}validateQueryParams(e={}){const t={};for(const s in e){const r=e[s];r==null||r===""||(typeof r=="object"?t[s]=JSON.stringify(r):t[s]=String(r))}return t}requestInprogress(){const e=this.store.getState();return[g.LOADING,g.FETCHING_MORE].includes(e.apiStatus)}storesQueryParamObj(e){return e==null?void 0:e.map(s=>this.storeQueryParamObj(s))}storeQueryParamObj(e){const t=e==null?void 0:e.query,s=(t==null?void 0:t.tags)||[],r=(t==null?void 0:t.categories)||[],i=t==null?void 0:t.read,d=t==null?void 0:t.archived;return{store_id:e.storeId,query:{read:i,archived:d,tags:{or:s},categories:{or:r}}}}async changeActiveStore(e){var r;const t=this.store.getState();if(t.store.storeId===e)return;const s=(r=this.feedOptions.stores)==null?void 0:r.find(i=>i.storeId===e);return s?(this.fetchAbortController&&(this.fetchAbortController.abort(),this.fetchAbortController=void 0),this.store.setState({...P,store:s,meta:t.meta}),await this.fetch()):{status:n.ERROR,error:{type:c.NOT_FOUND,message:`store with storeId ${e} doesnt exist`}}}get data(){const e=this.store.getState();return{notifications:e.notifications,pageInfo:e.pageInfo,meta:e.meta,apiStatus:e.apiStatus,store:e.store}}initializeSocketConnection(){var e;this.socket||(this.socket=G.io((e=this.feedOptions.host)==null?void 0:e.socketHost,{transports:["websocket"],auth:{authorization:this.config.publicApiKey,"x-ss-signature":this.config.userToken,distinct_id:this.config.distinctId,tenant_id:this.feedOptions.tenantId,schema:"1"},reconnectionDelay:1e3,reconnectionDelayMax:1e4}),this.initializeSocketEvents())}async fetch(e={}){const t=this.store.getState();if(this.requestInprogress())return;const s=(e==null?void 0:e.pageSize)||this.feedOptions.pageSize;t.isFirstFetch?(this.store.setState({apiStatus:g.LOADING}),this.fetchCount()):this.store.setState({apiStatus:g.FETCHING_MORE}),this.emitter.emit("feed.store_update",this.data);const r={distinct_id:this.config.distinctId,tenant_id:this.feedOptions.tenantId,page_size:s,store:t.store.storeId!==D.storeId?this.storeQueryParamObj(t.store):null};if(t.notifications.length>0){const l=t.notifications[t.notifications.length-1];r.search_after=[l.is_pinned,l.created_on]}else r.search_after=[];const i=this.getUrl("notifications",r),d=new AbortController;this.fetchAbortController=d;const u=await this.config.client().request({type:"get",url:i,signal:d.signal});if(!d.signal.aborted)return u.status===n.ERROR?(this.store.setState({apiStatus:g.ERROR}),this.emitter.emit("feed.store_update",this.data),u):(this.store.setState({apiStatus:g.SUCCESS,notifications:t.isFirstFetch?u.body.results:[...t.notifications,...u.body.results],pageInfo:{...t.pageInfo,total:u.body.meta.total_count,hasMore:u.body.meta.has_more},isFirstFetch:!1}),this.emitter.emit("feed.store_update",this.data),this.startExpiryTimer(),u)}async fetchNextPage(){return this.store.getState().pageInfo.hasMore===!1?{status:n.ERROR,error:{type:c.VALIDATION_ERROR,message:"No more pages to fetch"}}:this.fetch()}async fetchCount(){const e={distinct_id:this.config.distinctId,tenant_id:this.feedOptions.tenantId,stores:this.feedOptions.stores?this.storesQueryParamObj(this.feedOptions.stores):null},t=this.getUrl("notifications_count",e),s=await this.config.client().request({type:"get",url:t});return s.status===n.SUCCESS&&this.store.setState({meta:s.body}),this.emitter.emit("feed.store_update",this.data),s}async fetchDetails(e){const t=this.getUrl(`notifications/${e}`,{tenant_id:this.feedOptions.tenantId,distinct_id:this.config.distinctId});return await this.config.client().request({type:"get",url:t})}async markAsSeen(e){const t=this.store.getState();let s=!1;if(this.store.setState({notifications:t.notifications.map(i=>(i.n_id===e&&(i.seen_on?s=!0:i.seen_on=Date.now()),i))}),s)return{status:n.SUCCESS};const r=this.getUrl(`notifications/${e}/seen`,{tenant_id:this.feedOptions.tenantId,distinct_id:this.config.distinctId});return this.emitter.emit("feed.store_update",this.data),await this.config.client().request({type:"patch",url:r})}async markAsRead(e){const t=this.store.getState();let s=!1;if(this.store.setState({notifications:t.notifications.map(i=>(i.n_id===e&&(i.read_on?s=!0:(i.read_on=Date.now(),i.seen_on=Date.now())),i))}),s)return{status:n.SUCCESS};const r=this.getUrl(`notifications/${e}/read`,{tenant_id:this.feedOptions.tenantId,distinct_id:this.config.distinctId});return this.emitter.emit("feed.store_update",this.data),await this.config.client().request({type:"patch",url:r})}async markAsUnread(e){const t=this.store.getState();let s=!1;if(this.store.setState({notifications:t.notifications.map(i=>(i.n_id===e&&(i.read_on?i.read_on=null:s=!0),i))}),s)return{status:n.SUCCESS};const r=this.getUrl(`notifications/${e}/unread`,{tenant_id:this.feedOptions.tenantId,distinct_id:this.config.distinctId});return this.emitter.emit("feed.store_update",this.data),await this.config.client().request({type:"patch",url:r})}async markAsInteracted(e){const t=this.store.getState();this.store.setState({notifications:t.notifications.map(r=>(r.n_id===e&&(r.interacted_on||(r.interacted_on=Date.now()),r.read_on||(r.read_on=Date.now())),r))});const s=this.getUrl(`notifications/${e}/interacted`,{tenant_id:this.feedOptions.tenantId,distinct_id:this.config.distinctId});return this.emitter.emit("feed.store_update",this.data),await this.config.client().request({type:"patch",url:s})}async markAsArchived(e){const t=this.store.getState();let s=!1;if(this.store.setState({notifications:t.notifications.filter(i=>i.n_id===e?(s=!!i.archived,!1):!0)}),s)return{status:n.SUCCESS};const r=this.getUrl(`notifications/${e}/archive`,{tenant_id:this.feedOptions.tenantId,distinct_id:this.config.distinctId});return this.emitter.emit("feed.store_update",this.data),await this.config.client().request({type:"patch",url:r})}async markBulkAsSeen(e){const t=this.store.getState();this.store.setState({notifications:t.notifications.map(r=>(e.includes(r.n_id)&&(r.seen_on||(r.seen_on=Date.now())),r))});const s=this.getUrl("bulk/notifications/seen",{tenant_id:this.feedOptions.tenantId,distinct_id:this.config.distinctId});return this.emitter.emit("feed.store_update",this.data),await this.config.client().request({type:"post",url:s,payload:{notification_ids:e}})}async resetBadgeCount(){const e=this.store.getState();this.store.setState({meta:{...e.meta,badge:0}});const t=this.getUrl("reset_bell_count",{tenant_id:this.feedOptions.tenantId,distinct_id:this.config.distinctId});return this.emitter.emit("feed.store_update",this.data),await this.config.client().request({type:"patch",url:t})}async markAllAsRead(){const e=this.store.getState();this.store.setState({meta:{...e.meta,badge:0},notifications:e.notifications.map(s=>(s.read_on=Date.now(),s))});const t=this.getUrl("mark_all_read",{tenant_id:this.feedOptions.tenantId,distinct_id:this.config.distinctId});return this.emitter.emit("feed.store_update",this.data),await this.config.client().request({type:"patch",url:t})}reset(){var e;this.store.setState({...P,store:((e=this.feedOptions.stores)==null?void 0:e[0])||D}),this.emitter.emit("feed.store_update",this.data),this.expiryTimerId&&(clearInterval(this.expiryTimerId),this.expiryTimerId=void 0)}remove(){var e;this.reset(),this.emitter.off("*"),(e=this.socket)==null||e.disconnect(),this.config.feeds.removeInstance(this)}}const oe="https://hub.suprsend.com",ce="serviceworker.js",F="ss_distinct_id";class de{constructor(e,t){f(this,"host");f(this,"publicApiKey");f(this,"distinctId");f(this,"userToken");f(this,"vapidKey");f(this,"swFileName");f(this,"apiClient",null);f(this,"userTokenExpirationTimer",null);f(this,"authenticateOptions");f(this,"user",new te(this));f(this,"webpush",new se(this));f(this,"feeds",new ae(this));f(this,"emitter",K());if(!e)throw new Error("[SuprSend]: publicApiKey is missing");this.publicApiKey=e,this.host=(t==null?void 0:t.host)||oe,this.vapidKey=(t==null?void 0:t.vapidKey)||"",this.swFileName=(t==null?void 0:t.swFileName)||ce}handleRefreshUserToken(e){if(!this.userToken||!A())return;const t=L(this.userToken),s=(t.exp||0)*1e3,r=Date.now(),i=1e3*30;if(s&&s>r){const d=s-r-i;this.userTokenExpirationTimer&&clearTimeout(this.userTokenExpirationTimer),this.userTokenExpirationTimer=setTimeout(async()=>{let u="";try{u=await e(this.userToken,t)}catch{try{u=await e(this.userToken,t)}catch(h){console.warn("[SuprSend]: Couldn't fetch new userToken",h)}}u&&typeof u=="string"&&this.identify(this.distinctId,u,this.authenticateOptions)},d)}}client(){return this.distinctId||console.warn("[SuprSend]: distinctId is missing. User should be authenticated"),this.apiClient||(this.apiClient=new U(this)),this.apiClient}eventApi(e){return this.client().request({url:`${this.host}/v2/event`,payload:e,type:"post"})}async identify(e,t,s){if(!e)return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"distinctId is missing"});if(this.apiClient&&this.distinctId&&this.distinctId!==e)return o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"User already loggedin, reset current user to login new user"});if(this.apiClient&&this.distinctId===e&&this.userToken!==t)return this.userToken=t,this.apiClient=new U(this),s!=null&&s.refreshUserToken&&this.handleRefreshUserToken(s.refreshUserToken),o({status:n.SUCCESS});if(this.distinctId&&this.apiClient)return o({status:n.SUCCESS});this.distinctId=e,this.userToken=t,this.apiClient=new U(this),this.authenticateOptions=s;const r=V(F);if(s!=null&&s.refreshUserToken&&this.handleRefreshUserToken(s.refreshUserToken),r==this.distinctId)return this.webpush.updatePushSubscription(),o({status:n.SUCCESS});const i=await this.eventApi({event:"$identify",$insert_id:N(),$time:k(),properties:{$identified_id:e}});return i.status===n.SUCCESS?(this.webpush.updatePushSubscription(),x(F,this.distinctId)):this.reset({unsubscribePush:!1}),i}isIdentified(e){return e?!!(this.userToken&&this.distinctId):!!this.distinctId}async track(e,t){let s={};return e?(typeof t=="object"&&(s={...s,...t}),this.eventApi({event:String(e),$insert_id:N(),$time:k(),distinct_id:this.distinctId,properties:s})):o({status:n.ERROR,errorType:c.VALIDATION_ERROR,errorMessage:"event name is missing"})}async reset(e){var s,r;return(e==null?void 0:e.unsubscribePush)!==!1&&(await((s=this.webpush)==null?void 0:s.removePushSubscription()),Y(M)),this.apiClient=null,this.distinctId=null,this.userToken="",this.userTokenExpirationTimer&&clearTimeout(this.userTokenExpirationTimer),((r=this.feeds.feedInstances)==null?void 0:r.length)>0&&this.feeds.removeAll(),o({status:n.SUCCESS})}}exports.ApiResponseStatus=g;exports.ChannelLevelPreferenceOptions=C;exports.ERROR_TYPE=c;exports.Feed=H;exports.PreferenceOptions=p;exports.RESPONSE_STATUS=n;exports.SuprSend=de;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|