diff --git a/CHANGELOG.md b/CHANGELOG.md index fe4dd95b..07025f4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +### Version 5.3.0 (25th March 2021) +#### Added +- Added `getWebUUID` method to access SDK generated ID `web_uuid`. +- Added `getAttribution` method to access user's current attribution information. + +#### Fixed +- Fixed issue with URL strategy retrying to send requests after SDK was disabled. + +--- + ### Version 5.2.1 (16th September 2021) #### Fixed - Fixed top-level Typescript declarations. diff --git a/README.md b/README.md index 05a8cab5..1e7719f0 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ To lazy load the Adjust Web SDK through CDN paste th The Adjust Web SDK should be loaded only once per page and it should be initiated once per page load. -When loading the sdk through CDN we suggest using minified version. You can target specific version like `https://cdn.adjust.com/adjust-5.2.1.min.js`, or you can target latest version `https://cdn.adjust.com/adjust-latest.min.js` if you want automatic updates without need to change the target file. The sdk files are cached so they are served as fast as possible, and the cache is refreshed every half an hour. If you want updates immediately make sure to target specific version. +When loading the sdk through CDN we suggest using minified version. You can target specific version like `https://cdn.adjust.com/adjust-5.3.0.min.js`, or you can target latest version `https://cdn.adjust.com/adjust-latest.min.js` if you want automatic updates without need to change the target file. The sdk files are cached so they are served as fast as possible, and the cache is refreshed every half an hour. If you want updates immediately make sure to target specific version. It's also possible to install our sdk through NPM: @@ -385,6 +385,36 @@ Example: Adjust.disableThirdPartySharing(); ``` +## Get `web_uuid` + +To identify unique web users in Adjust, Web SDK generates an ID known as `web_uuid` whenever it tracks first session. The ID is created per subdomain and per browser. +The identifier follows the Universally Unique Identifier (UUID) format. + +To get `web_uuid` use the following method: + +**getWebUUID** + +Example: + +```js +const webUUID = Adjust.getWebUUID(); +``` + +## User attribution + +You can access your user's current attribution information by using the following method: + +**getAttribution** + +Example: + +```js +const attribution = Adjust.getAttribution(); +``` + +> **Note** Current attribution information is only available after our backend tracks the app install and triggers the attribution callback. +It is not possible to access a user's attribution value before the SDK has been initialized and the attribution callback has been triggered. + ## License The Adjust SDK is licensed under the MIT License. diff --git a/VERSION b/VERSION index 26d99a28..03f488b0 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -5.2.1 +5.3.0 diff --git a/dist/adjust-latest.d.ts b/dist/adjust-latest.d.ts index 173b65f2..04216c53 100644 --- a/dist/adjust-latest.d.ts +++ b/dist/adjust-latest.d.ts @@ -68,6 +68,36 @@ declare namespace Adjust { } type LogLevel = 'none' | 'error' | 'warning' | 'info' | 'verbose' + + interface Attribution { + + /** Adjust device identifier */ + adid: string, + + /** Tracker token */ + tracker_token: string, + + /** Tracker name */ + tracker_name: string, + + /** Network grouping level */ + network?: string, + + /** Campaign grouping level */ + campaign?: string, + + /** Ad group grouping level */ + adgroup?: string, + + /** Creative grouping level */ + creative?: string, + + /** Click label */ + click_label?: string, + + /** Attribution state, for example 'installed' or 'reattributed' */ + state: string + } interface InitOptions { @@ -121,7 +151,7 @@ declare namespace Adjust { * // attribution: details about the changed attribution * } * }); */ - attributionCallback?: (e: string, attribution: Object) => any; + attributionCallback?: (e: string, attribution: Attribution) => any; /** Optional. Logging level used by SDK instance. By default this param is set to `error`. We highly recommend that * you use `verbose` when testing in order to see precise logs and to make sure integration is done properly. @@ -160,6 +190,30 @@ declare namespace Adjust { */ function initSdk({ logLevel, logOutput, ...options }: InitOptions): void + /** + * Get user's current attribution information + * + * Current attribution information is only available after our backend tracks the app install and triggers the + * attribution callback. It is not possible to access a user's attribution value before the SDK has been initialized + * and the attribution callback has been triggered. + * + * @returns current attribution information if available or `undefined` otherwise + * + * @example + * const attribution = Adjust.getAttribution(); + */ + function getAttribution (): Attribution | undefined + + /** + * Get web_uuid - a unique ID of user generated per subdomain and per browser + * + * @returns `web_uuid` if available or `undefined` otherwise + * + * @example + * const webUuid = Adjust.getWebUUID(); + */ + function getWebUUID (): string | undefined + /** * Track event with already initiated Adjust SDK instance * diff --git a/dist/adjust-latest.js b/dist/adjust-latest.js index 39da33d4..473275b7 100644 --- a/dist/adjust-latest.js +++ b/dist/adjust-latest.js @@ -2774,7 +2774,7 @@ function isEmptyEntry(value |}*/ var Globals = { namespace: "adjust-sdk" || false, - version: "5.2.1" || false, + version: "5.3.0" || false, env: "production" }; /* harmony default export */ var globals = (Globals); @@ -4044,7 +4044,7 @@ function timePassed(d1 /*:: // -import { type UrlT, type ActivityStateMapT, type CommonRequestParams } from './types';*/ +import { type UrlT, type ActivityStateMapT, type AttributionMapT, type CommonRequestParams } from './types';*/ @@ -4439,6 +4439,31 @@ function activity_state_destroy() _active = false; } +function getAttribution() +/*: AttributionMapT | null*/ +{ + if (!_started) { + return null; + } + + if (!_activityState.attribution) { + logger.log('No attribution data yet'); + return null; + } + + return _activityState.attribution; +} + +function getWebUUID() +/*: string*/ +{ + if (!_started) { + return null; + } + + return _activityState.uuid; +} + var ActivityState = { get current() { return currentGetter(); @@ -4460,7 +4485,9 @@ var ActivityState = { updateSessionLength: updateSessionLength, resetSessionOffset: resetSessionOffset, updateLastActive: updateLastActive, - destroy: activity_state_destroy + destroy: activity_state_destroy, + getAttribution: getAttribution, + getWebUUID: getWebUUID }; /* harmony default export */ var activity_state = (ActivityState); // CONCATENATED MODULE: ./src/sdk/pub-sub.js @@ -11532,25 +11559,7 @@ var _excluded = ["logLevel", "logOutput"]; var main_Promise = typeof Promise === 'undefined' ? __webpack_require__(3).Promise : Promise; /*:: // -import { type InitOptionsT, type LogOptionsT, type EventParamsT, type GlobalParamsT, type CustomErrorT, type ActivityStateMapT, type SmartBannerOptionsT } from './types';*/ - - - - - - - - - - - - - - - - - - +import { type InitOptionsT, type LogOptionsT, type EventParamsT, type GlobalParamsT, type CustomErrorT, type ActivityStateMapT, type SmartBannerOptionsT, type AttributionMapT } from './types';*/ @@ -11635,6 +11644,34 @@ function initSdk() _start(options); }); } +/** + * Get user's current attribution information + * + * @returns {AttributionMapT|undefined} current attribution information if available or `undefined` otherwise + */ + + +function main_getAttribution() +/*: ?AttributionMapT*/ +{ + return _preCheck('get attribution', function () { + return activity_state.getAttribution(); + }); +} +/** + * Get `web_uuid` - a unique ID of user generated per subdomain and per browser + * + * @returns {string|undefined} `web_uuid` if available or `undefined` otherwise + */ + + +function main_getWebUUID() +/*: ?string*/ +{ + return _preCheck('get web_uuid', function () { + return activity_state.getWebUUID(); + }); +} /** * Track event with already initiated instance * @@ -12108,7 +12145,9 @@ function _preCheck(description /*: string*/ , callback /*: () => mixed*/ -) { +) +/*: mixed*/ +{ var _ref3 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, schedule = _ref3.schedule, stopBeforeInit = _ref3.stopBeforeInit; @@ -12133,7 +12172,7 @@ function _preCheck(description scheduler_delay(callback, description); logger.log("Running ".concat(description, " is delayed until Adjust SDK is up")); } else { - callback(); + return callback(); } } } @@ -12144,6 +12183,8 @@ function _clearDatabase() { var Adjust = { initSdk: initSdk, + getAttribution: main_getAttribution, + getWebUUID: main_getWebUUID, trackEvent: trackEvent, addGlobalCallbackParameters: addGlobalCallbackParameters, addGlobalPartnerParameters: addGlobalPartnerParameters, diff --git a/dist/adjust-latest.min.js b/dist/adjust-latest.min.js index 9494dc6a..88bb25c3 100644 --- a/dist/adjust-latest.min.js +++ b/dist/adjust-latest.min.js @@ -5,4 +5,4 @@ * @license Licensed under MIT license * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE * @version v4.2.8+1e68dce6 - */var r;r=function(){"use strict";function e(e){return"function"==typeof e}var r=Array.isArray?Array.isArray:function(e){return"[object Array]"===Object.prototype.toString.call(e)},o=0,i=void 0,a=void 0,s=function(e,t){m[o]=e,m[o+1]=t,2===(o+=2)&&(a?a(h):w())},u="undefined"!=typeof window?window:void 0,c=u||{},l=c.MutationObserver||c.WebKitMutationObserver,d="undefined"==typeof self&&void 0!==t&&"[object process]"==={}.toString.call(t),f="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel;function p(){var e=setTimeout;return function(){return e(h,1)}}var m=new Array(1e3);function h(){for(var e=0;ee.length)&&(t=e.length);for(var n=0,r=new Array(t);n=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){function n(t){return"function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?(e.exports=n=function(e){return typeof e},e.exports.default=e.exports,e.exports.__esModule=!0):(e.exports=n=function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e.exports.default=e.exports,e.exports.__esModule=!0),n(t)}e.exports=n,e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){e.exports=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){var n,r,o=e.exports={};function i(){throw new Error("setTimeout has not been defined")}function a(){throw new Error("clearTimeout has not been defined")}function s(e){if(n===setTimeout)return setTimeout(e,0);if((n===i||!n)&&setTimeout)return n=setTimeout,setTimeout(e,0);try{return n(e,0)}catch(t){try{return n.call(null,e,0)}catch(t){return n.call(this,e,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:i}catch(e){n=i}try{r="function"==typeof clearTimeout?clearTimeout:a}catch(e){r=a}}();var u,c=[],l=!1,d=-1;function f(){l&&u&&(l=!1,u.length?c=u.concat(c):d=-1,c.length&&p())}function p(){if(!l){var e=s(f);l=!0;for(var t=c.length;t;){for(u=c,c=[];++d1)for(var n=1;n \");background-repeat:no-repeat;background-position:center center;background-size:8px 8px, auto;cursor:pointer}.adjust-smart-banner__Dw5N6VeDUP14gIEdMH7SH .adjust-smart-banner__YV2trFakzl9_mm1H-9Ht5 .adjust-smart-banner__31MvUOHjvsAEpS_14bUpGT .adjust-smart-banner__L_BSzs7rJajVPX4zdt2R6{width:56px;height:56px;overflow:hidden;background-color:#6e7492;border-radius:8px}.adjust-smart-banner__Dw5N6VeDUP14gIEdMH7SH .adjust-smart-banner__YV2trFakzl9_mm1H-9Ht5 .adjust-smart-banner__31MvUOHjvsAEpS_14bUpGT .adjust-smart-banner__L_BSzs7rJajVPX4zdt2R6 .adjust-smart-banner__3Yj45mdOZKIOH2d6Z2UXXa{display:flex;align-items:center;justify-content:center;width:100%;height:100%;color:#353a52;font-weight:bold;font-size:23px;font-family:ArialMt,Arial,sans-serif;line-height:32px;background-color:#e0e2ec}.adjust-smart-banner__Dw5N6VeDUP14gIEdMH7SH .adjust-smart-banner__YV2trFakzl9_mm1H-9Ht5 .adjust-smart-banner__31MvUOHjvsAEpS_14bUpGT .adjust-smart-banner__L_BSzs7rJajVPX4zdt2R6 .adjust-smart-banner__4hg0kzTWzWiGjzCDqbktp{width:100%}.adjust-smart-banner__Dw5N6VeDUP14gIEdMH7SH .adjust-smart-banner__YV2trFakzl9_mm1H-9Ht5 .adjust-smart-banner__31MvUOHjvsAEpS_14bUpGT .adjust-smart-banner__3mbKdOA0SmqrfOLvHomXyc{flex:1 1 0%;min-height:0;min-width:0;margin:0 12px}.adjust-smart-banner__Dw5N6VeDUP14gIEdMH7SH .adjust-smart-banner__YV2trFakzl9_mm1H-9Ht5 .adjust-smart-banner__31MvUOHjvsAEpS_14bUpGT .adjust-smart-banner__3DSKm9idx4dze89DWsCMXr{overflow:hidden;text-overflow:ellipsis}.adjust-smart-banner__Dw5N6VeDUP14gIEdMH7SH .adjust-smart-banner__YV2trFakzl9_mm1H-9Ht5 .adjust-smart-banner__31MvUOHjvsAEpS_14bUpGT h4{margin:5px 0 8px;color:#353a52;font-family:Arial-BoldMT,ArialMt,Arial,sans-serif;font-size:12px;font-weight:bold;line-height:16px;white-space:nowrap}.adjust-smart-banner__Dw5N6VeDUP14gIEdMH7SH .adjust-smart-banner__YV2trFakzl9_mm1H-9Ht5 .adjust-smart-banner__31MvUOHjvsAEpS_14bUpGT p{margin:8px 0 7px;color:#353a52;font-family:ArialMt,Arial,sans-serif;font-size:9px;line-height:11px;max-height:22px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}.adjust-smart-banner__Dw5N6VeDUP14gIEdMH7SH .adjust-smart-banner__YV2trFakzl9_mm1H-9Ht5 .adjust-smart-banner__31MvUOHjvsAEpS_14bUpGT .adjust-smart-banner__3_w6WNex3gOuKV8gztVNoI{color:#6e7492;background:#f9fafc;border:1px solid #cdd0e0;border-radius:4px;border-color:#6e7492;box-shadow:inset 0px -1px 0px 0px #e0e2ec;padding:4px 6.5px;display:inline-block;vertical-align:middle;text-align:center;font-family:ArialMt,Arial,sans-serif;font-size:12px;font-weight:500;line-height:16px;cursor:pointer;text-decoration:none}\n",""]),t.locals={bannerContainer:"adjust-smart-banner__1Xb2YvQsm_ZuqGpC3GYV1K",banner:"adjust-smart-banner__Dw5N6VeDUP14gIEdMH7SH",stickyToTop:"adjust-smart-banner__1gDv13AgIJ63OmoMUWN6vd",stickyToBottom:"adjust-smart-banner__2Xpm01sHnZNYOOkNk05cAc",bannerBody:"adjust-smart-banner__YV2trFakzl9_mm1H-9Ht5",content:"adjust-smart-banner__31MvUOHjvsAEpS_14bUpGT",dismiss:"adjust-smart-banner__3PQ7z78EskytjOkrU199hE",appIcon:"adjust-smart-banner__L_BSzs7rJajVPX4zdt2R6",placeholder:"adjust-smart-banner__3Yj45mdOZKIOH2d6Z2UXXa",image:"adjust-smart-banner__4hg0kzTWzWiGjzCDqbktp",textContainer:"adjust-smart-banner__3mbKdOA0SmqrfOLvHomXyc",bannerText:"adjust-smart-banner__3DSKm9idx4dze89DWsCMXr",action:"adjust-smart-banner__3_w6WNex3gOuKV8gztVNoI"}},function(e,t){e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n=function(e,t){var n=e[1]||"",r=e[3];if(!r)return n;if(t&&"function"==typeof btoa){var o=(a=r,"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(a))))+" */"),i=r.sources.map((function(e){return"/*# sourceURL="+r.sourceRoot+e+" */"}));return[n].concat(i).concat([o]).join("\n")}var a;return[n].join("\n")}(t,e);return t[2]?"@media "+t[2]+"{"+n+"}":n})).join("")},t.i=function(e,n){"string"==typeof e&&(e=[[null,e,""]]);for(var r={},o=0;o=0&&d.splice(t,1)}function g(e){var t=document.createElement("style");if(void 0===e.attrs.type&&(e.attrs.type="text/css"),void 0===e.attrs.nonce){var r=function(){0;return n.nc}();r&&(e.attrs.nonce=r)}return y(t,e.attrs),h(e,t),t}function y(e,t){Object.keys(t).forEach((function(n){e.setAttribute(n,t[n])}))}function b(e,t){var n,r,o,i;if(t.transform&&e.css){if(!(i="function"==typeof t.transform?t.transform(e.css):t.transform.default(e.css)))return function(){};e.css=i}if(t.singleton){var a=l++;n=c||(c=g(t)),r=_.bind(null,n,a,!1),o=_.bind(null,n,a,!0)}else e.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=function(e){var t=document.createElement("link");return void 0===e.attrs.type&&(e.attrs.type="text/css"),e.attrs.rel="stylesheet",y(t,e.attrs),h(e,t),t}(t),r=S.bind(null,n,t),o=function(){v(n),n.href&&URL.revokeObjectURL(n.href)}):(n=g(t),r=x.bind(null,n),o=function(){v(n)});return r(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;r(e=t)}else o()}}e.exports=function(e,t){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");(t=t||{}).attrs="object"==typeof t.attrs?t.attrs:{},t.singleton||"boolean"==typeof t.singleton||(t.singleton=a()),t.insertInto||(t.insertInto="head"),t.insertAt||(t.insertAt="bottom");var n=m(e,t);return p(n,t),function(e){for(var r=[],o=0;o0&&void 0!==arguments[0]?arguments[0]:[];return e.reduce((function(e,t){return o()(o()({},e),{},v()({},t.key,t.value))}),{})}function S(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[];return e.filter((function(e){return-1!==t.indexOf(e)}))}function P(e,t){return new RegExp("\\/".concat(t,"(\\/.*|\\?.*){0,1}$")).test(e)}function j(e,t){var n=u()(t,2),r=n[0],i=n[1];return o()(o()({},e),{},v()({},r,i))}function D(e){return Object.keys(e).map((function(t){return[t,e[t]]}))}function I(e){return Object.keys(e).map((function(t){return e[t]}))}function T(e){return w(e)?!b(e):!!e||0===e}var N,O={namespace:"adjust-sdk",version:"5.2.1",env:"production"},E=(N={},v()(N,"none",-1),v()(N,"error",0),v()(N,"warning",1),v()(N,"info",2),v()(N,"verbose",3),N),A={log:" ",info:" ",warn:" ",error:""},C={development:"verbose",production:"error",test:"verbose"},R=B(),M="";function B(){return C[O.env]||"error"}function U(e,t){var n;if(!(E[R]2?s-2:0),c=2;c2&&void 0!==arguments[2]?arguments[2]:[];return n.map((function(n){return we(e,t,n)}))}function _e(e,t,n){var r=ge[t][Se(e,fe.right)],o=r.fields[r.keyPath],i=n instanceof Array?n.slice():[n],a=(re(o)?o.composite:[r.keyPath]).map((function(e,t){var n=r.fields[e];return be(te(n)?n.values:null,i[t])}));return 1===a.length?a[0]:a}function xe(e){return ge.values[e]||e}function Se(e,t){return(ge.storeNames[t][e]||{}).name||e}function Pe(e,t){return{name:t.name,message:t.message.replace('"'.concat(e,'"'),Se(e,fe.right))}}!function(e){e.LowerBound="lowerBound",e.UpperBound="upperBound"}(de||(de={})),function(e){e.right="right",e.left="left"}(fe||(fe={}));var je=n(5),De=n.n(je),Ie=n(6),Te=n.n(Ie);function Ne(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1,n=e+"",r=1;r<=t;r+=1)e0?"-":"+")+Ne(Math.floor(Math.abs(t)/60))+Ne(Math.abs(t)%60)}(t);return"".concat(n,"T").concat(r,"Z").concat(o)}function Ee(e,t){return isNaN(e)||isNaN(t)?0:Math.abs(t-e)}var Ae={},Ce=!1,Re=!1;function Me(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};Ae=Ce?o()({},e):{}}function Be(){Ce&&(Ae.lastInterval=function(){var e=Ae.lastActive;if(e)return Math.round(Ee(e,Date.now())/1e3);return-1}(),Ae.lastActive=Date.now())}function Ue(e){Ae=o()(o()({},Ae),e)}function Le(){Re=!0}function He(){var e=Ae.lastActive;return Math.round(Ee(e,Date.now())/1e3)}function qe(){return(Ae.timeSpent||0)+(Re?He():0)}function Ke(){var e=Ee(Ae.lastActive,Date.now())<$.sessionWindow,t=Re||!Re&&e;return(Ae.sessionLength||0)+(t?He():0)}function Fe(){Ce&&(Ue({timeSpent:qe(),sessionLength:Ke()}),Be())}var Ve={get current(){return Ce?o()({},Ae):{}},set current(e){Me(e)},init:function(e){Ce=!0,Me(e)},isStarted:function(){return Ce},toForeground:Le,toBackground:function(){Re=!1},initParams:function(){Fe(),Le()},getParams:function(e){if(!Ce)return null;var t=Ae.lastInterval>=0?Ae.lastInterval:0,n={timeSpent:Ae.timeSpent||0,sessionLength:Ae.sessionLength||0,sessionCount:Ae.sessionCount||1,lastInterval:t||0};return e&&P(e,"event")&&(n.eventCount=Ae.eventCount),n},updateParams:function(e,t){if(Ce){var n={};n.timeSpent=qe(),n.sessionLength=Ke(),P(e,"session")&&(n.sessionCount=(Ae.sessionCount||0)+1),P(e,"event")&&(n.eventCount=(Ae.eventCount||0)+1),Ue(n),t||Be()}},updateInstalled:function(){Ce&&(Ae.installed||Ue({installed:!0}))},updateSessionOffset:Fe,updateSessionLength:function(){Ce&&(Ue({sessionLength:Ke()}),Be())},resetSessionOffset:function(){Ce&&Ue({timeSpent:0,sessionLength:0})},updateLastActive:Be,destroy:function(){Ae={},Ce=!1,Re=!1}},ze={},Ge=[];function Ye(e,t){var n="id"+Math.random().toString(36).substr(2,16),r={id:n,cb:t};return ze[e]||(ze[e]=[]),ze[e].push(r),n}function We(e,t){ze[e]&&ze[e].forEach((function(n){"function"==typeof n.cb&&Ge.push(setTimeout((function(){return n.cb(e,t)})))}))}var Je=new(function(){function e(){var t=this;De()(this,e),v()(this,"defaultName",O.namespace),v()(this,"storageName",this.defaultName),v()(this,"storeNames",ge.storeNames.left),v()(this,"storesMap",void 0),this.storesMap={};var n=this.read.bind(this),r=this.write.bind(this);I(this.storeNames).forEach((function(e){var o=e.name;Object.defineProperty(t.storesMap,o,{get:function(){return n(o)},set:function(e){r(o,e)}})})),Object.freeze(this.storesMap)}return Te()(e,[{key:"read",value:function(e){var t=localStorage.getItem("".concat(this.storageName,".").concat(e)),n=t?JSON.parse(t):null;return e===Z.Preferences&&n?we(Z.Preferences,fe.right,n):n}},{key:"write",value:function(e,t){t?localStorage.setItem("".concat(this.storageName,".").concat(e),JSON.stringify(t instanceof Array?t:we(Z.Preferences,fe.left,t))):localStorage.removeItem("".concat(this.storageName,".").concat(e))}},{key:"clear",value:function(){this.deleteData()}},{key:"deleteData",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];I(this.storeNames).forEach((function(n){!t&&n.permanent||localStorage.removeItem("".concat(e.storageName,".").concat(n.name))}))}},{key:"setCustomName",value:function(e){var t=this;if(e&&e.length){var n="".concat(O.namespace,"-").concat(e);I(this.storeNames).forEach((function(e){var r=e.name,o=localStorage.getItem("".concat(t.storageName,".").concat(r));o&&localStorage.setItem("".concat(n,".").concat(r),o)})),this.deleteData(!0),this.storageName=n}}},{key:"stores",get:function(){return this.storesMap}}]),e}()),Xe=ie.preferences.name,Qe=Ze();function Ze(){return Qe||$e(),Qe?o()({},Qe):null}function $e(){Qe=Je.stores[Xe]}function et(){var e=Ze();return e?e.sdkDisabled:null}function tt(e){var t=e?o()({},e):null;Je.stores[Xe]=o()(o()({},Ze()),{},{sdkDisabled:t}),$e()}function nt(){var e=Ze();return e?e.thirdPartySharingDisabled:null}function rt(){var e=Je.stores[Xe]||{},t=(Qe||{}).sdkDisabled||null;e.sdkDisabled&&!t&&We("sdk:shutdown"),$e()}function ot(){Je.stores[Xe]||(Je.stores[Xe]=o()({},Qe))}var it,at,st="undefined"==typeof Promise?n(3).Promise:Promise;!function(e){e.add="add",e.put="put",e.get="get",e.list="list",e.clear="clear",e.delete="delete"}(it||(it={})),function(e){e.readonly="readonly",e.readwrite="readwrite"}(at||(at={}));var ut=function(){function e(){De()(this,e),v()(this,"dbDefaultName",O.namespace),v()(this,"dbName",this.dbDefaultName),v()(this,"dbVersion",1),v()(this,"idbFactory",void 0),v()(this,"indexedDbConnection",null),v()(this,"notSupportedError",{name:"IDBNotSupported",message:"IndexedDB is not supported"}),v()(this,"databaseOpenError",{name:"CannotOpenDatabaseError",message:"Cannot open a database"}),v()(this,"noConnectionError",{name:"NoDatabaseConnection",message:"Cannot open a transaction"});var t=e.getIndexedDB();if(!t)throw this.notSupportedError;this.idbFactory=t}return Te()(e,[{key:"setCustomName",value:function(e){return e&&e.length>0?(this.dbName="".concat(O.namespace,"-").concat(e),this.migrateDb(this.dbDefaultName,this.dbName)):st.resolve()}},{key:"openDatabase",value:function(t,n,r){var o=this;return e.isSupported().then((function(e){return e?new st((function(e,i){var a=o.idbFactory.open(t,r);n&&(a.onupgradeneeded=function(e){return n(e,i)}),a.onsuccess=function(t){var n=t.target.result;n?e(n):i(o.databaseOpenError)},a.onerror=i})):st.reject(o.notSupportedError)}))}},{key:"databaseExists",value:function(e){var t=this;return new st((function(n){var r=!0;t.openDatabase(e,(function(){r=!1})).then((function(n){if(n.close(),!r)return t.deleteDatabaseByName(e)})).then((function(){return n(r)}))}))}},{key:"cloneData",value:function(e,t){var n=this;return I(ge.storeNames.left).map((function(e){return e.name})).filter((function(e){return"p"!==e})).map((function(r){return function(){return o=r,i=n.indexedDbConnection,n.indexedDbConnection=e,n.getAll(o).then((function(e){if(n.indexedDbConnection=t,!(e.length<1))return n.addBulk(o,e,!0)})).then((function(){n.indexedDbConnection=i}));var o,i}})).reduce((function(e,t){return e.then(t)}),st.resolve())}},{key:"migrateDb",value:function(e,t){var n=this;return this.databaseExists(e).then((function(r){return r?st.all([n.openDatabase(e,n.handleUpgradeNeeded,n.dbVersion),n.openDatabase(t,n.handleUpgradeNeeded,n.dbVersion)]).then((function(t){var r=u()(t,2),o=r[0],i=r[1];return n.cloneData(o,i).then((function(){return n.indexedDbConnection=i,o.close(),n.deleteDatabaseByName(e)}))})).then((function(){return H.info("Database migration finished")})):n.openDatabase(t,n.handleUpgradeNeeded,n.dbVersion).then((function(e){n.indexedDbConnection=e}))}))}},{key:"handleUpgradeNeeded",value:function(e,t){var n=e.target.result;e.target.transaction.onerror=t,e.target.transaction.onabort=t;var r=ge.storeNames.left,o=Ve.current||{},i=o&&!b(o);D(r).filter((function(e){return!u()(e,2)[1].permanent})).forEach((function(e){var t=u()(e,2),r=t[0],a=t[1].name,s=ge.right[r],c=n.createObjectStore(a,{keyPath:s.keyPath,autoIncrement:s.autoIncrement||!1});if(s.index&&c.createIndex("".concat(s.index,"Index"),s.index),a===Q.ActivityState&&i)return c.add(we(r,fe.left,o)),void H.info("Activity state has been recovered");var l=Je.stores[a];l&&(l.forEach((function(e){return c.add(e)})),H.info("Migration from localStorage done for ".concat(r," store")))})),ot(),Je.clear()}},{key:"open",value:function(){var e=this;return this.indexedDbConnection?st.resolve({success:!0}):this.openDatabase(this.dbName,this.handleUpgradeNeeded,this.dbVersion).then((function(t){return e.indexedDbConnection=t,e.indexedDbConnection.onclose=function(){return e.destroy},{success:!0}}))}},{key:"getTransactionStore",value:function(e,t,n){var r,o=e.storeName,i=e.mode,a=n.transaction([o],i),s=a.objectStore(o),u=ge.right[Se(o,fe.right)];return u.index&&(r=s.index("".concat(u.index,"Index"))),a.onerror=t,a.onabort=t,{transaction:a,store:s,index:r,options:u}}},{key:"overrideError",value:function(e,t){var n=t.target.error;return e({name:n.name,message:n.message})}},{key:"getCompositeKeys",value:function(e){var t=e.fields[e.keyPath];return re(t)?t.composite:null}},{key:"targetIsObject",value:function(e){return w(e)}},{key:"prepareTarget",value:function(e,t,n){if(n===it.clear||!t)return null;var r=this.getCompositeKeys(e);return-1!==[it.add,it.put].indexOf(n)?this.targetIsObject(t)?r?o()(v()({},e.keyPath,r.map((function(e){return t[e]})).join("")),t):t:null:t instanceof Array?t.join(""):t}},{key:"prepareResult",value:function(e,t){var n=this.getCompositeKeys(e);return n&&this.targetIsObject(t)?n.map((function(e){return t[e]})):null}},{key:"initRequest",value:function(e){var t=this,n=e.storeName,r=e.target,o=void 0===r?null:r,i=e.action,a=e.mode,s=void 0===a?at.readonly:a;return this.open().then((function(){return new st((function(e,r){if(t.indexedDbConnection){var a=t.getTransactionStore({storeName:n,mode:s},r,t.indexedDbConnection),u=a.store,c=a.options,l=u[i](t.prepareTarget(c,o,i)),d=t.prepareResult(c,o);l.onsuccess=function(){i!==it.get||l.result?e(d||l.result||o):r({name:"NotRecordFoundError",message:'Requested record not found in "'.concat(n,'" store')})},l.onerror=function(e){return t.overrideError(r,e)}}else r(t.noConnectionError)}))}))}},{key:"initBulkRequest",value:function(e){var t=this,n=e.storeName,r=e.target,o=e.action,i=e.mode,a=void 0===i?at.readwrite:i;return!r||r&&!r.length?st.reject({name:"NoTargetDefined",message:"No array provided to perform ".concat(o,' bulk operation into "').concat(n,'" store')}):this.open().then((function(){return new st((function(e,i){if(t.indexedDbConnection){var s=t.getTransactionStore({storeName:n,mode:a},i,t.indexedDbConnection),u=s.transaction,c=s.store,l=s.options,d=new Array,f=r[0];u.oncomplete=function(){return e(d)};!function e(n){n.onerror=function(e){return t.overrideError(i,e)},n.onsuccess=function(){d.push(t.prepareResult(l,f)||n.result),f=r[d.length],d.length1&&void 0!==arguments[1]&&arguments[1];return this.openCursor({storeName:e,action:it.list,firstOnly:t})}},{key:"getFirst",value:function(e){return this.getAll(e,!0).then((function(e){return e.length?e[0]:void 0}))}},{key:"getItem",value:function(e,t){return this.initRequest({storeName:e,target:t,action:it.get})}},{key:"filterBy",value:function(e,t){var n=IDBKeyRange.only(t);return this.openCursor({storeName:e,action:it.list,range:n})}},{key:"addItem",value:function(e,t){return this.initRequest({storeName:e,target:t,action:it.add,mode:at.readwrite})}},{key:"addBulk",value:function(e,t,n){return this.initBulkRequest({storeName:e,target:t,action:n?it.put:it.add,mode:at.readwrite})}},{key:"updateItem",value:function(e,t){return this.initRequest({storeName:e,target:t,action:it.put,mode:at.readwrite})}},{key:"deleteItem",value:function(e,t){return this.initRequest({storeName:e,target:t,action:it.delete,mode:at.readwrite})}},{key:"deleteBulk",value:function(e,t,n){var r=n?IDBKeyRange[n](t):IDBKeyRange.only(t);return this.openCursor({storeName:e,action:it.delete,range:r,mode:at.readwrite})}},{key:"trimItems",value:function(e,t){var n=this,r=ge.right[Se(e,fe.right)];return this.getAll(e).then((function(e){return e.length?e[t-1]:null})).then((function(t){return t?n.deleteBulk(e,t[r.keyPath],de.UpperBound):[]}))}},{key:"count",value:function(e){var t=this;return this.open().then((function(){return new st((function(n,r){if(t.indexedDbConnection){var o=t.getTransactionStore({storeName:e,mode:at.readonly},r,t.indexedDbConnection).store.count();o.onsuccess=function(){return n(o.result)},o.onerror=function(e){return t.overrideError(r,e)}}else r(t.noConnectionError)}))}))}},{key:"clear",value:function(e){return this.initRequest({storeName:e,action:it.clear,mode:at.readwrite})}},{key:"destroy",value:function(){this.indexedDbConnection&&this.indexedDbConnection.close(),this.indexedDbConnection=null}},{key:"deleteDatabase",value:function(){return this.destroy(),this.deleteDatabaseByName(this.dbName)}}],[{key:"tryOpen",value:function(t){return new st((function(n){try{var r=t.open(e.dbValidationName);r.onsuccess=function(){r.result.close(),t.deleteDatabase(e.dbValidationName),n(!0)},r.onerror=function(){return n(!1)}}catch(e){n(!1)}}))}},{key:"isSupported",value:function(){return e.isSupportedPromise||(e.isSupportedPromise=new st((function(t){var n=e.getIndexedDB(),r=!!navigator.platform&&/iPad|iPhone|iPod/.test(navigator.platform);!n||r?(H.warn("IndexedDB is not supported in this browser"),t(!1)):t(e.tryOpen(n).then((function(e){return e||H.warn("IndexedDB is not supported in this browser"),e})))}))),e.isSupportedPromise}},{key:"getIndexedDB",value:function(){return window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB}}]),e}();v()(ut,"dbValidationName","validate-db-openable"),v()(ut,"isSupportedPromise",null);var ct="undefined"==typeof Promise?n(3).Promise:Promise,lt=function(){function e(){De()(this,e)}return Te()(e,[{key:"open",value:function(){return e.isSupported().then((function(e){if(!e)return{status:"error",error:{name:"LSNotSupported",message:"LocalStorage is not supported"}};var t=ge.storeNames.left,n=Ve.current||{},r=n&&!b(n);return D(t).filter((function(e){return!u()(e,2)[1].permanent})).forEach((function(e){var t=u()(e,2),o=t[0],i=t[1].name;i!==Q.ActivityState||Je.stores[i]?Je.stores[i]||(Je.stores[i]=[]):Je.stores[i]=r?[we(o,fe.left,n)]:[]})),ot(),{status:"success"}}))}},{key:"getCompositeKeys",value:function(e){var t=e.fields[e.keyPath];return re(t)?t.composite:null}},{key:"getKeys",value:function(e){var t=Se(e,fe.right),n=ge.right[t];return this.getCompositeKeys(n)||[n.keyPath]}},{key:"nextIndex",value:function(e){return"number"==typeof e?e+1:void 0}},{key:"initRequest",value:function(e,t){var n=this,r=e.storeName,i=e.id,a=e.item,s=ge.right[Se(r,fe.right)];return this.open().then((function(e){return"error"===e.status?ct.reject(e.error):new ct((function(e,u){var c,l=Je.stores[r],d=n.getKeys(r),f=(l[l.length-1]||{})[s.keyPath]||0;if(i){var p=Array.isArray(i)?i.slice():[i];c=d.map((function(e,t){return[e,p[t]]})).reduce(j,{})}else c=o()({},a);var m=c?_(l,d,c):0;return t(e,u,{keys:d,items:l,index:m,options:s,lastId:f})}))}))}},{key:"sort",value:function(e,t,n){var r=l()(e),o=t.slice().reverse();return r.sort((function(e,t){return o.reduce((function(r,o){return r||function(e,t,r){var o=n?n===e[r]:e[r]e[r]:e[r]>t[r];return o?-1:i?1:0}(e,t,o)}),0)}))}},{key:"prepareTarget",value:function(e,t,n){var r=this.getCompositeKeys(e);return r?o()(v()({},e.keyPath,r.map((function(e){return t[e]})).join("")),t):e.autoIncrement&&n?o()(v()({},e.keyPath,n),t):o()({},t)}},{key:"prepareResult",value:function(e,t){var n=this.getCompositeKeys(e);return n?n.map((function(e){return t[e]})).filter((function(e){return!ye(e)})):t[e.keyPath]}},{key:"getAll",value:function(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return this.open().then((function(r){return"error"===r.status?ct.reject(r.error):new ct((function(r,o){var i=Je.stores[e];i instanceof Array?r(n?[i[0]]:t.sort(i,t.getKeys(e))):o({name:"NotFoundError",message:"No objectStore named ".concat(e," in this database")})}))}))}},{key:"getFirst",value:function(e){return this.getAll(e,!0).then((function(e){return e.length?e[0]:void 0}))}},{key:"getItem",value:function(e,t){var n=this;return this.initRequest({storeName:e,id:t},(function(t,r,o){var i=o.items,a=o.index,s=o.options;-1===a?r({name:"NotRecordFoundError",message:'Requested record not found in "'.concat(e,'" store')}):t(n.prepareTarget(s,i[a]))}))}},{key:"filterBy",value:function(e,t){return this.getAll(e).then((function(n){return n.filter((function(n){var r=ge.right[Se(e,fe.right)];return(r.index&&n[r.index])===t}))}))}},{key:"addItem",value:function(e,t){var n=this;return this.initRequest({storeName:e,item:t},(function(r,o,i){var a=i.items,s=i.index,u=i.options,c=i.lastId;-1!==s?o({name:"ConstraintError",message:'Constraint was not satisfied, trying to add existing item into "'.concat(e,'" store')}):(a.push(n.prepareTarget(u,t,n.nextIndex(c))),Je.stores[e]=a,r(n.prepareResult(u,t)))}))}},{key:"addBulk",value:function(e,t,n){var r=this;return this.initRequest({storeName:e},(function(o,i,a){var s=a.keys,u=a.items,c=a.options,d=a.lastId;if(!t||t&&!t.length)i({name:"NoTargetDefined",message:'No array provided to perform add bulk operation into "'.concat(e,'" store')});else{var f=d,p=t.map((function(e){return r.prepareTarget(c,e,f=r.nextIndex(f))})),m=p.filter((function(e){return-1!==_(u,s,e)})).map((function(e){return e[c.keyPath]})),h=n?u.filter((function(e){return-1===m.indexOf(e[c.keyPath])})):l()(u);if(m.length&&!n)i({name:"ConstraintError",message:'Constraint was not satisfied, trying to add existing items into "'.concat(e,'" store')});else Je.stores[e]=r.sort([].concat(l()(h),l()(p)),s),o(t.map((function(e){return r.prepareResult(c,e)})))}}))}},{key:"updateItem",value:function(e,t){var n=this;return this.initRequest({storeName:e,item:t},(function(r,o,i){var a=i.items,s=i.index,u=i.options,c=i.lastId,l=-1===s?n.nextIndex(c):void 0,d=n.prepareTarget(u,t,l);-1===s?a.push(d):a.splice(s,1,d),Je.stores[e]=a,r(n.prepareResult(u,t))}))}},{key:"deleteItem",value:function(e,t){return this.initRequest({storeName:e,id:t},(function(n,r,o){var i=o.items,a=o.index;-1!==a&&(i.splice(a,1),Je.stores[e]=i),n(t)}))}},{key:"findMax",value:function(e,t,n){if(!e.length)return-1;for(var r={index:-1,value:"string"==typeof n?"":0},o=0;o=r.value&&(r={value:e[o][t],index:o})}return r.index}},{key:"deleteBulk",value:function(e,t,n){var r=this;return this.getAll(e).then((function(o){var i=r.getKeys(e),a=ge.right[Se(e,fe.right)].index||i[0],s=n?null:t,u=r.sort(o,i,s),c=r.findMax(u,a,t);if(-1===c)return[];var l=n===de.LowerBound?c:0,d=n&&n!==de.UpperBound?u.length:c+1,f=u.splice(l,d).map((function(e){return 1===i.length?e[a]:i.map((function(t){return e[t]}))}));return Je.stores[e]=u,f}))}},{key:"trimItems",value:function(e,t){var n=this,r=Se(e,fe.right),o=ge.right[r];return this.getAll(e).then((function(e){return e.length?e[t-1]:null})).then((function(t){return t?n.deleteBulk(e,t[o.keyPath],de.UpperBound):[]}))}},{key:"count",value:function(e){return this.open().then((function(t){if("error"===t.status)return ct.reject(t.error);var n=Je.stores[e];return ct.resolve(n instanceof Array?n.length:1)}))}},{key:"clear",value:function(e){return this.open().then((function(t){return"error"===t.status?ct.reject(t.error):new ct((function(t){Je.stores[e]=[],t()}))}))}},{key:"destroy",value:function(){}},{key:"deleteDatabase",value:function(){}}],[{key:"isSupported",value:function(){if(e.isSupportedPromise)return e.isSupportedPromise;var t=(new Date).toString(),n=window.localStorage;return e.isSupportedPromise=new ct((function(e){n.setItem(t,t);var r=n.getItem(t)===t;n.removeItem(t),e(!(!r||!n))})).catch((function(){return H.warn("LocalStorage is not supported in this browser"),ct.resolve(!1)})),e.isSupportedPromise}}]),e}();v()(lt,"isSupportedPromise",null);var dt,ft,pt="undefined"==typeof Promise?n(3).Promise:Promise;(ft=dt||(dt={}))[ft.noStorage=f]="noStorage",ft[ft.indexedDB=p]="indexedDB",ft[ft.localStorage=m]="localStorage";var mt,ht={getAll:function(e,t,n){return e.getAll(t,n).then((function(e){return ke(t,fe.right,e)}))},getFirst:function(e,t){return e.getFirst(t).then((function(e){return we(t,fe.right,e)}))},getItem:function(e,t,n){return e.getItem(t,_e(t,fe.left,n)).then((function(e){return we(t,fe.right,e)})).catch((function(e){return pt.reject(Pe(t,e))}))},filterBy:function(e,t,n){return e.filterBy(t,xe(n)).then((function(e){return ke(t,fe.right,e)}))},addItem:function(e,t,n){var r=we(t,fe.left,n);return e.addItem(t,r).then((function(e){return _e(t,fe.right,e)})).catch((function(e){return pt.reject(Pe(t,e))}))},addBulk:function(e,t,n,r){var o=ke(t,fe.left,n);return e.addBulk(t,o,r).then((function(e){return e.map((function(e){return _e(t,fe.right,e)}))})).catch((function(e){return pt.reject(Pe(t,e))}))},updateItem:function(e,t,n){var r=we(t,fe.left,n);return e.updateItem(t,r).then((function(e){return _e(t,fe.right,e)}))},deleteItem:function(e,t,n){return e.deleteItem(t,_e(t,fe.left,n)).then((function(e){return _e(t,fe.right,e)}))},deleteBulk:function(e,t,n,r){return e.deleteBulk(t,xe(n),r).then((function(e){return e.map((function(e){return _e(t,fe.right,e)}))}))},trimItems:function(e,t,n){return e.trimItems(t,n)},count:function(e,t){return e.count(t)},clear:function(e,t){return e.clear(t)},destroy:function(e){return e.destroy()},deleteDatabase:function(e){return e.deleteDatabase()}};var vt=null;function gt(e){var t=null;return null!==vt?vt:vt=pt.all([ut.isSupported(),lt.isSupported()]).then((function(n){var r=u()(n,2),o=r[0],i=r[1];if(Je.setCustomName(e),o){mt=dt.indexedDB;var a=new ut;return a.setCustomName(e).then((function(){return t=a}))}return i?(mt=dt.localStorage,t=new lt,pt.resolve(t)):(H.error("There is no storage available, app will run with minimum set of features"),mt=dt.noStorage,t=null,pt.resolve(t))})).then((function(){return{type:mt,storage:t}}))}var yt,bt,wt=o()({init:gt,getType:function(){return mt}},D(ht).map((function(e){var t=u()(e,2),n=t[0],r=t[1];return[n,function(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),o=1;o1&&void 0!==arguments[1]?arguments[1]:St,n=xt();if(Array.isArray(n)){var r=0,o=function o(){var i=n[r++],a=t[i];return e(a).catch((function(e){if("NO_CONNECTION"===e.code&&(H.log("Failed to connect ".concat(Pt[i]," endpoint")),r2&&void 0!==arguments[2]&&arguments[2];return{status:"error",action:n?"CONTINUE":"RETRY",response:k(e.responseText)?JSON.parse(e.responseText):e.responseText,message:d[t],code:t}}function Tt(e,t){var n=e.slice(0,e.length-t.length-1).split("").reduce((function(e){return e.concat(" ")}),"");return"".concat(t).concat(n,":")}function Nt(e,t){var n=function(e){return e.replace(/([A-Z])/g,(function(e){return"_".concat(e.toLowerCase())}))},r=D(o()(o()(o()({},$.getBaseParams()),t),e)).map((function(e){var t=u()(e,2),r=t[0],o=t[1];return[n(r),o]}));return H.log("REQUEST PARAMETERS:"),r.filter((function(e){return T(u()(e,2)[1])})).map((function(e){var t=u()(e,2),n=t[0],r=t[1];return H.log(Tt("REQUEST PARAMETERS:",n),r),function(e){var t=u()(e,2),n=t[0],r=t[1],o=encodeURIComponent(n),i=r;return"string"==typeof r&&(i=encodeURIComponent(r)),w(r)&&(i=encodeURIComponent(JSON.stringify(r)||"")),[o,i].join("=")}([n,r])})).join("&")}function Ot(e,t,n){var r=n.xhr,o=n.url;if(4===r.readyState){var i=r.status>=200&&r.status<300,a=k(r.responseText);if(0!==r.status)return a?t(i?function(e,t){var n=JSON.parse(e.responseText),r={status:"success",adid:n.adid,timestamp:n.timestamp,ask_in:n.ask_in,retry_in:n.retry_in,continue_in:n.continue_in,tracking_state:n.tracking_state,attribution:void 0,message:void 0};return P(t,"attribution")&&(r.attribution=n.attribution,r.message=n.message),D(r).filter((function(e){return!!u()(e,2)[1]})).reduce(j,{})}(r,o):It(r,"SERVER_CANNOT_PROCESS",!0)):e(It(r,i?"SERVER_MALFORMED_RESPONSE":"SERVER_INTERNAL_ERROR"));e(It(r,"NO_CONNECTION"))}}function Et(e,t,n){var r=e.url,o=e.method,i=void 0===o?"GET":o,a=e.params,s=function(e,t,n){var r=e.url,o=e.method,i=Nt(e.params,t);return{fullUrl:n["/gdpr_forget_device"===r?"gdpr":"app"]+r+("GET"===o?"?".concat(i):""),encodedParams:i}}({url:r,method:i,params:void 0===a?{}:a},t,n),c=s.fullUrl,l=s.encodedParams;return new Dt((function(e,t){var n=new XMLHttpRequest;n.open(i,c,!0),function(e,t){var n=[["Client-SDK","js".concat(O.version)],["Content-Type","POST"===t?"application/x-www-form-urlencoded":"application/json"]];H.log("REQUEST HEADERS:"),n.forEach((function(t){var n=u()(t,2),r=n[0],o=n[1];e.setRequestHeader(r,o),H.log(Tt("REQUEST HEADERS:",r),o)}))}(n,i),n.onreadystatechange=function(){return Ot(t,e,{xhr:n,url:r})},n.onerror=function(){return t(It(n,"TRANSACTION_ERROR"))},n.send("GET"===i?void 0:l)}))}function At(e,t){return"success"===e.status?function(e,t){var n=P(t,"gdpr_forget_device"),r=P(t,"attribution"),o=P(t,"session"),i=P(t,"disable_third_party_sharing"),a="opted_out"===e.tracking_state;if(!n&&a)return We("sdk:gdpr-forget-me"),e;r||n||a||!e.ask_in||We("attribution:check",e);o&&We("session:finished",e);if(i)return We("sdk:third-party-sharing-opt-out"),e;return e}(e,t):e}function Ct(e){return kt().then((function(t){return function(e,t){return jt((function(n){return Et(e,t,n)}))}(e,t)})).then((function(t){return At(t,e.url)}))}var Rt={long:{delay:12e4,maxDelay:864e5,minRange:.5,maxRange:1},short:{delay:200,maxDelay:36e5,minRange:.5,maxRange:1},test:{delay:100,maxDelay:300}};function Mt(e,t){var n,r,o=Rt[t=t||"long"],i=o.delay*Math.pow(2,e-1);return i=Math.min(i,o.maxDelay),o.minRange&&o.maxRange&&(i*=(n=o.minRange,r=o.maxRange,Math.random()*(r-n)+n)),Math.round(i)}var Bt=navigator.onLine;function Ut(){Bt=!0}function Lt(){Bt=!1}function Ht(e,t,n){e.addEventListener&&e.addEventListener(t,n,!1)}function qt(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}function Kt(){return Bt}var Ft="undefined"==typeof Promise?n(3).Promise:Promise,Vt=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.url,n=e.method,r=void 0===n?"GET":n,i=e.params,a=void 0===i?{}:i,s=e.continueCb,c=e.strategy,l=e.wait,f={url:t,method:r,params:a,continueCb:s},p=t,m=r,h=o()({},a),v=s,g=c,y=null,w={request:0,connection:0},k=x(l),_=null;function x(e){return(e=e||150)>2147483647?2147483647:e}function S(e){var t=e.url,n=e.method,r=e.params,i=e.continueCb;t&&(p=t),n&&(m=n),b(r)||(h=o()({},r)),h=o()({createdAt:Oe()},h),"function"==typeof i&&(v=i)}function P(e){if(!_)return!1;if(y){var t=k-(Date.now()-_);if(e&&t0&&void 0!==arguments[0]?arguments[0]:{},t=e.url,n=e.method,r=e.params,o=void 0===r?{}:r,i=e.continueCb,a=e.wait;return S({url:t,method:n,params:o,continueCb:i}),I({wait:a})}function U(){return!!y}function L(){y&&clearTimeout(y),y=null}function q(){var e=!!_;L(),_=null,e&&(k=150,w.request=0,w.connection=0,H.log("Previous ".concat(p||"unknown"," request attempt canceled")),E())}return{send:B,isRunning:U,clear:q}},zt=function(e){return"gdpr"===e?"GDPR disable":"disable"},Gt=function(e){return{start:{inProgress:"Adjust SDK ".concat(zt(e)," process has already started"),done:"Adjust SDK ".concat(zt(e)," process is now started")},finish:{inProgress:"Adjust SDK ".concat(zt(e)," process has already finished"),done:"Adjust SDK ".concat(zt(e)," process is now finished")}}};function Yt(e,t){var n=e.reason,r=e.pending,o=et()||{},i="start"===t&&o.pending?"start":"finish",a="start"===t&&o.reason,s="finish"===t&&o.reason&&!o.pending;return a||s?(H.log(Gt(o.reason)[i].inProgress),!1):(H.log(Gt(n)[i].done),tt({reason:n||"general",pending:r}),!0)}function Wt(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return Yt({reason:e,pending:t||!1},"start")}function Jt(){var e=et()||{};return"general"===e.reason||"gdpr"===e.reason&&!e.pending?"off":"gdpr"===e.reason&&e.pending?"paused":"on"}var Xt="undefined"==typeof Promise?n(3).Promise:Promise,Qt=!1;function Zt(e){return e?"unknown"===e.uuid?(Wt({reason:"gdpr"}),Ve.destroy(),{exists:!0,stored:null}):(Ve.init(e),{exists:!0,stored:e}):{exists:!1}}function $t(){return"off"!==Jt()&&Ve.isStarted()}function en(){if(!$t())return Xt.resolve(null);var e=o()(o()({},Ve.current),{},{lastActive:Date.now()});return wt.updateItem("activityState",e).then((function(){return Ve.current=e}))}var tn="undefined"==typeof Promise?n(3).Promise:Promise,nn=Vt({strategy:"long",continueCb:function(e,t){var n=e&&e.continue_in||null;return on.pause=n?{timestamp:Date.now(),wait:n}:null,wt.getFirst("queue").then((function(e){return e?wt.deleteItem("queue",e.timestamp):null})).then((function(){return t(),on.running=!1,dn({wait:n})}))}}),rn=!1,on={running:!1,timestamp:null,pause:null};function an(){var e=Date.now();return on.timestamp&&e<=on.timestamp&&(e=on.timestamp+1),on.timestamp=e,e}function sn(e){return P(e,"session")&&Ve.resetSessionOffset(),Ve.updateLastActive(),en()}function un(e){var t=e.url,n=e.method,r=e.params,i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},a=i.auto,s=i.timestamp;Ve.updateParams(t,a);var c=D(r||{}).filter((function(e){return T(u()(e,2)[1])})).reduce(j,{}),l={timestamp:an(),url:t,method:n,params:o()(o()({},Ve.getParams(t)),c)};return s&&(l.createdAt=s),wt.addItem("queue",l).then((function(){return sn(t)})).then((function(){return on.running?{}:dn()}))}function cn(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.timestamp,n=e.createdAt,r=e.url,i=e.method,a=e.params,s=arguments.length>1?arguments[1]:void 0,u=Ve.current||{},c="/session"===r&&!u.installed,l=!r&&!i&&!a;return rn&&!c||l?(on.running=!1,tn.resolve({})):nn.send({url:r,method:i,params:o()(o()({},a),{},{createdAt:Oe(n||t)}),wait:s||ln()})}function ln(){var e=on.pause||{},t=e.timestamp,n=e.wait,r=Date.now()-(t||0);return r0&&void 0!==arguments[0]?arguments[0]:{},t=e.cleanUp,n=e.wait;if(on.running)return tn.resolve({});on.running=!0;var r=tn.resolve({});return t&&(r=r.then(pn)),r.then((function(){return wt.getFirst("queue")})).then((function(e){return cn(e,n)}))}function fn(e){if(void 0!==e)if(e!==rn){var t=rn;rn=e,!e&&t&&dn(),H.info("The app is now in ".concat(e?"offline":"online"," mode"))}else H.error("The app is already in ".concat(e?"offline":"online"," mode"));else H.error("State not provided, true or false has to be defined")}function pn(){var e=Date.now()-$.requestValidityWindow;return wt.deleteBulk("queue",e,"upperBound")}var mn="undefined"==typeof Promise?n(3).Promise:Promise,hn="No type provided",vn="Global parameter type not provided, `callback` or `partner` types are available";function gn(e){return(e||[]).map((function(e){return{key:e.key,value:e.value}}))}function yn(){return mn.all([wt.filterBy("globalParams","callback"),wt.filterBy("globalParams","partner")]).then((function(e){var t=u()(e,2),n=t[0],r=t[1];return{callbackParams:gn(n),partnerParams:gn(r)}}))}function bn(e,t){if(void 0===t)return H.error(vn),mn.reject({message:hn});var n=x(e),r=Object.keys(n).map((function(e){return{key:e,value:n[e],type:t}}));return mn.all([wt.filterBy("globalParams",t),wt.addBulk("globalParams",r,!0)]).then((function(e){var n=u()(e,2),o=n[0],i=n[1],a=S(o.map((function(e){return e.key})),i.map((function(e){return e[0]})));return H.log("Following ".concat(t," parameters have been saved: ").concat(r.map((function(e){return"".concat(e.key,":").concat(e.value)})).join(", "))),a.length&&H.log("Keys: ".concat(a.join(", ")," already existed so their values have been updated")),i}))}function wn(e,t){return void 0===t?(H.error(vn),mn.reject({message:hn})):wt.deleteItem("globalParams",[e,t]).then((function(n){return H.log("".concat(e," ").concat(t," parameter has been deleted")),n}))}function kn(e){return void 0===e?(H.error(vn),mn.reject({message:hn})):wt.deleteBulk("globalParams",e).then((function(t){return H.log("All ".concat(e," parameters have been deleted")),t}))}var _n,xn,Sn,Pn="undefined"==typeof Promise?n(3).Promise:Promise,jn=!1,Dn=document;function In(){return Sn=function(){var e=document;if(void 0!==e.hidden)return{hidden:"hidden",visibilityChange:"visibilitychange"};for(var t=D({mozHidden:"mozvisibilitychange",msHidden:"msvisibilitychange",oHidden:"ovisibilitychange",webkitHidden:"webkitvisibilitychange"}),n=0;n0;return!n||n&&1e3*t>=$.sessionWindow?yn().then((function(e){var t,n,r;un({url:"/session",method:"POST",params:(t=e,n=t.callbackParams,r=t.partnerParams,{callbackParams:n.length?x(n):null,partnerParams:r.length?x(r):null})},{auto:!0})})):(We("attribution:check"),en())}var Rn="undefined"==typeof Promise?n(3).Promise:Promise,Mn=Vt({url:"/attribution",strategy:"short",continueCb:function(e,t,n){if(!e||e&&"error"===e.status)return t(),Rn.resolve({state:"unknown"});if(!e.ask_in)return t(),function(e){if(b(e)||!function(e){var t=e.adid,n=void 0===t?"":t,r=e.attribution,o=void 0===r?{}:r;return!!n&&!!S(Bn,Object.keys(o)).length}(e)||function(e){var t=e.adid,n=e.attribution,r=Ve.current.attribution||{};return!(n&&Bn.some((function(e){return r[e]!==n[e]})))&&t===r.adid}(e))return Rn.resolve({state:"same"});var t=D(e.attribution).filter((function(e){var t=u()(e,1)[0];return-1!==Bn.indexOf(t)})).reduce(j,{adid:e.adid});return Ve.current=o()(o()({},Ve.current),{},{attribution:t}),en().then((function(){return We("attribution:change",t),H.info("Attribution has been updated"),{state:"changed"}}))}(e);return n(e.ask_in)}}),Bn=["tracker_token","tracker_name","network","campaign","adgroup","creative","click_label","state"];var Un=Vt({url:"/gdpr_forget_device",method:"POST",strategy:"short"}),Ln={running:"Adjust SDK is running pending GDPR Forget Me request",pending:"Adjust SDK will run GDPR Forget Me request after initialisation",paused:"Adjust SDK is already prepared to send GDPR Forget Me request",off:"Adjust SDK is already disabled"};function Hn(e){var t=Jt();return e||"on"===t?$.isInitialised()?(Un.send({params:o()({},Ve.getParams())}).then((function(){We("sdk:gdpr-forget-me")})),!0):(H.log(Ln.pending),!0):(H.log(Ln[t]),!1)}function qn(){return Yt({reason:"gdpr",pending:!1},"finish")}var Kn={running:"Adjust SDK is running pending third-party sharing opt-out request",delayed:"Adjust SDK will run third-party sharing opt-out request after initialisation",pending:"Adjust SDK already queued third-party sharing opt-out request",off:"Third-party sharing opt-out is already done",start:{inProgress:"Third-party sharing opt-out has already started",done:"Third-party sharing opt-out is now started"},finish:{inProgress:"Third-party sharing opt-out has already finished",done:"Third-party sharing opt-out is now finished"}};function Fn(){var e=nt()||{};return e.reason?e.pending?"pending":"off":"on"}function Vn(e){var t=Fn();return e||"on"===t?$.isInitialised()?(un({url:"/disable_third_party_sharing",method:"POST"}),!0):(H.log(Kn.delayed),!0):(H.log(Kn[t]),!1)}function zn(e,t){var n,r,i=nt()||{},a="start"===t&&e?"start":"finish",s="start"===t&&i.reason,u="finish"===t&&i.reason&&!i.pending;return s||u?(H.log(Kn[a].inProgress),!1):(H.log(Kn[a].done),r=(n={reason:"general",pending:e})?o()({},n):null,Je.stores[Xe]=o()(o()({},Ze()),{},{thirdPartySharingDisabled:r}),$e(),!0)}function Gn(){return zn(!1,"finish")}function Yn(){"pending"===Fn()&&(H.log(Kn.running),Vn(!0))}var Wn=[];function Jn(e,t){Wn.push({method:e,description:t,timestamp:Date.now()})}var Xn,Qn="undefined"==typeof Promise?n(3).Promise:Promise;function Zn(e,t){var n,r,i=t.callbackParams,a=t.partnerParams,s={},u=o()({eventToken:e.eventToken},(n=e.revenue,r=e.currency,isNaN(n)||(n=parseFloat(n))<0||!r?{}:{revenue:n.toFixed(5),currency:r})),c=o()(o()({},x(i)),x(e.callbackParams)),l=o()(o()({},x(a)),x(e.partnerParams));return b(c)||(s.callbackParams=c),b(l)||(s.partnerParams=l),o()(o()({},u),s)}function $n(e){return e?wt.getAll("eventDeduplication").then((function(e){return e.map((function(e){return e.id}))})).then((function(t){return-1===t.indexOf(e)?function(e){var t=$.getCustomConfig().eventDeduplicationListLimit,n=t>0?t:10;return wt.count("eventDeduplication").then((function(e){var t=Qn.resolve();if(e>=n){var r=e-n+1;H.log("Event deduplication list limit has been reached. Oldest ids are about to be removed (".concat(r," of them)")),t=wt.trimItems("eventDeduplication",r)}return t})).then((function(){return H.info("New event deduplication id is added to the list: ".concat(e)),wt.addItem("eventDeduplication",{id:e})}))}(e):Qn.reject({message:"Event won't be tracked, since it was previously tracked with the same deduplication id ".concat(e)})})):Qn.resolve()}function er(e){return{clickTime:Oe(),source:"web_referrer",referrer:decodeURIComponent(e)}}function tr(){var e=window.location.search.substring(1).split("&").map((function(e){return e.split("=")})).reduce(j,{}).adjust_referrer;e&&un({url:"/sdk_click",method:"POST",params:er(e)})}function nr(){var e,t,n=null===(e=navigator)||void 0===e||null===(t=e.userAgent)||void 0===t?void 0:t.toLowerCase();if(n&&!(n.length<1))return/ipad|iphone|ipod/.test(n)?Xn.iOS:n.includes("windows")?/phone|mobile/.test(n)?Xn.WindowsPhone:Xn.WindowsPC:n.includes("android")?Xn.Android:void 0}function rr(e){if(!e)return null;try{return JSON.parse(e)}catch(e){return null}}!function(e){e.Android="android",e.iOS="ios",e.WindowsPC="windows",e.WindowsPhone="windows-phone"}(Xn||(Xn={}));var or={getItem:function(e){return rr(localStorage.getItem("".concat("adjust-smart-banner",".").concat(e)))},setItem:function(e,t){t?localStorage.setItem("".concat("adjust-smart-banner",".").concat(e),JSON.stringify(t)):localStorage.removeItem("".concat("adjust-smart-banner",".").concat(e))}},ir={status:0,code:"NO_CONNECTION",message:"No internet connectivity"},ar="undefined"==typeof Promise?n(3).Promise:Promise,sr=function(){function e(){De()(this,e)}return Te()(e,null,[{key:"xhr",value:function(e){return new ar((function(t,n){var r=new XMLHttpRequest;r.open("GET",e),[["Client-SDK","js".concat(O.version)],["Content-Type","application/json"]].forEach((function(e){var t=u()(e,2),n=t[0],o=t[1];r.setRequestHeader(n,o)})),r.onerror=function(){return n(ir)},r.onreadystatechange=function(){if(4===r.readyState){var e=r.status>=200&&r.status<300,o=rr(r.responseText);0===r.status?n(ir):e?t(o):n({status:r.status,message:o||r.responseText||""})}},r.send()}))}},{key:"encodeParams",value:function(e){return Object.keys(e).map((function(t){return[encodeURIComponent(t),encodeURIComponent(e[t])].join("=")})).join("&")}},{key:"getEndpoint",value:function(){return e.lastSuccessfulEndpoint||e.defaultEndpoint}},{key:"request",value:function(t,n){return jt((function(r){var o=r.app,i=n?"?".concat(e.encodeParams(n)):"";return e.xhr("".concat(o).concat(t).concat(i)).then((function(t){return e.lastSuccessfulEndpoint=r.app,t})).catch((function(t){throw e.lastSuccessfulEndpoint=void 0,t}))}))}}]),e}();v()(sr,"defaultEndpoint","https://app.adjust.com"),v()(sr,"lastSuccessfulEndpoint",void 0);var ur;"undefined"==typeof Promise&&n(3).Promise;function cr(e,t){return sr.request("/smart_banner",{app_web_token:e}).then((function(e){var n,r,o,i,a,s,u,c=e.find((function(e){return e.platform===t}));return c?(i=(n=c).title,a=n.description,s=n.button_label,u=n.tracker_token,i&&a&&s&&u?{appId:(null===(r=n.app)||void 0===r?void 0:r.default_store_app_id)||"",appName:(null===(o=n.app)||void 0===o?void 0:o.name)||"",position:n.position||ur.Bottom,imageUrl:n.image_url,header:i,description:a,buttonText:s,trackerToken:u,deeplinkPath:n.deeplink_path,dismissInterval:864e5}:null):null})).catch((function(e){return H.error("Network error occurred during loading Smart Banner: "+JSON.stringify(e)),null}))}!function(e){e.Top="top",e.Bottom="bottom"}(ur||(ur={}));var lr=n(4),dr=n.n(lr),fr="undefined"==typeof Promise?n(3).Promise:Promise,pr=function(){function e(t,n,r){De()(this,e),v()(this,"appTraceUrl",(function(e){return"https://www.apptrace.com/api/app/".concat(e,"/artwork_url_small")})),v()(this,"appName",void 0),v()(this,"image",void 0),v()(this,"placeholder",void 0),this.image=n,this.placeholder=r,this.appName=t.appName;var o=this.getSources(t);this.showImage(o)}return Te()(e,[{key:"getSources",value:function(e){var t=[];return e.imageUrl&&t.push(e.imageUrl),t.push(this.appTraceUrl(e.appId)),t}},{key:"showImage",value:function(e){var t=this;return e.reduce((function(e,n){return e.catch((function(){return t.loadImage(n,t.image)}))}),fr.reject()).then((function(){t.placeholder.remove()})).catch((function(){t.image.remove(),t.placeholder.innerText=t.appName.length?t.appName[0].toUpperCase():""}))}},{key:"loadImage",value:function(e,t){return new fr((function(n,r){t.onload=n,t.onerror=r,t.src=e}))}}]),e}(),mr=function(){function e(t,n,r){De()(this,e),v()(this,"parent",document.body),v()(this,"banner",void 0),v()(this,"dismissButton",null),v()(this,"onDismiss",void 0),this.onDismiss=n,this.render(t,r)}return Te()(e,[{key:"render",value:function(e,t){this.banner=document.createElement("div"),this.banner.setAttribute("class",dr.a.bannerContainer);var n=e.position===ur.Top?dr.a.stickyToTop:dr.a.stickyToBottom,r=e.deeplinkPath?"?deeplink=".concat(encodeURIComponent(e.deeplinkPath)):"",o="".concat(t,"/").concat(e.trackerToken).concat(r);this.banner.innerHTML=function(e,t,n,r,o){return'\n
\n
\n
\n \n
\n
\n ').concat(t,'\n
\n
\n

').concat(t,'

\n

').concat(n,'

\n
\n e.length)&&(t=e.length);for(var n=0,r=new Array(t);n=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){function n(t){return"function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?(e.exports=n=function(e){return typeof e},e.exports.default=e.exports,e.exports.__esModule=!0):(e.exports=n=function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e.exports.default=e.exports,e.exports.__esModule=!0),n(t)}e.exports=n,e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){e.exports=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){var n,r,o=e.exports={};function i(){throw new Error("setTimeout has not been defined")}function a(){throw new Error("clearTimeout has not been defined")}function s(e){if(n===setTimeout)return setTimeout(e,0);if((n===i||!n)&&setTimeout)return n=setTimeout,setTimeout(e,0);try{return n(e,0)}catch(t){try{return n.call(null,e,0)}catch(t){return n.call(this,e,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:i}catch(e){n=i}try{r="function"==typeof clearTimeout?clearTimeout:a}catch(e){r=a}}();var u,c=[],l=!1,d=-1;function f(){l&&u&&(l=!1,u.length?c=u.concat(c):d=-1,c.length&&p())}function p(){if(!l){var e=s(f);l=!0;for(var t=c.length;t;){for(u=c,c=[];++d1)for(var n=1;n \");background-repeat:no-repeat;background-position:center center;background-size:8px 8px, auto;cursor:pointer}.adjust-smart-banner__Dw5N6VeDUP14gIEdMH7SH .adjust-smart-banner__YV2trFakzl9_mm1H-9Ht5 .adjust-smart-banner__31MvUOHjvsAEpS_14bUpGT .adjust-smart-banner__L_BSzs7rJajVPX4zdt2R6{width:56px;height:56px;overflow:hidden;background-color:#6e7492;border-radius:8px}.adjust-smart-banner__Dw5N6VeDUP14gIEdMH7SH .adjust-smart-banner__YV2trFakzl9_mm1H-9Ht5 .adjust-smart-banner__31MvUOHjvsAEpS_14bUpGT .adjust-smart-banner__L_BSzs7rJajVPX4zdt2R6 .adjust-smart-banner__3Yj45mdOZKIOH2d6Z2UXXa{display:flex;align-items:center;justify-content:center;width:100%;height:100%;color:#353a52;font-weight:bold;font-size:23px;font-family:ArialMt,Arial,sans-serif;line-height:32px;background-color:#e0e2ec}.adjust-smart-banner__Dw5N6VeDUP14gIEdMH7SH .adjust-smart-banner__YV2trFakzl9_mm1H-9Ht5 .adjust-smart-banner__31MvUOHjvsAEpS_14bUpGT .adjust-smart-banner__L_BSzs7rJajVPX4zdt2R6 .adjust-smart-banner__4hg0kzTWzWiGjzCDqbktp{width:100%}.adjust-smart-banner__Dw5N6VeDUP14gIEdMH7SH .adjust-smart-banner__YV2trFakzl9_mm1H-9Ht5 .adjust-smart-banner__31MvUOHjvsAEpS_14bUpGT .adjust-smart-banner__3mbKdOA0SmqrfOLvHomXyc{flex:1 1 0%;min-height:0;min-width:0;margin:0 12px}.adjust-smart-banner__Dw5N6VeDUP14gIEdMH7SH .adjust-smart-banner__YV2trFakzl9_mm1H-9Ht5 .adjust-smart-banner__31MvUOHjvsAEpS_14bUpGT .adjust-smart-banner__3DSKm9idx4dze89DWsCMXr{overflow:hidden;text-overflow:ellipsis}.adjust-smart-banner__Dw5N6VeDUP14gIEdMH7SH .adjust-smart-banner__YV2trFakzl9_mm1H-9Ht5 .adjust-smart-banner__31MvUOHjvsAEpS_14bUpGT h4{margin:5px 0 8px;color:#353a52;font-family:Arial-BoldMT,ArialMt,Arial,sans-serif;font-size:12px;font-weight:bold;line-height:16px;white-space:nowrap}.adjust-smart-banner__Dw5N6VeDUP14gIEdMH7SH .adjust-smart-banner__YV2trFakzl9_mm1H-9Ht5 .adjust-smart-banner__31MvUOHjvsAEpS_14bUpGT p{margin:8px 0 7px;color:#353a52;font-family:ArialMt,Arial,sans-serif;font-size:9px;line-height:11px;max-height:22px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}.adjust-smart-banner__Dw5N6VeDUP14gIEdMH7SH .adjust-smart-banner__YV2trFakzl9_mm1H-9Ht5 .adjust-smart-banner__31MvUOHjvsAEpS_14bUpGT .adjust-smart-banner__3_w6WNex3gOuKV8gztVNoI{color:#6e7492;background:#f9fafc;border:1px solid #cdd0e0;border-radius:4px;border-color:#6e7492;box-shadow:inset 0px -1px 0px 0px #e0e2ec;padding:4px 6.5px;display:inline-block;vertical-align:middle;text-align:center;font-family:ArialMt,Arial,sans-serif;font-size:12px;font-weight:500;line-height:16px;cursor:pointer;text-decoration:none}\n",""]),t.locals={bannerContainer:"adjust-smart-banner__1Xb2YvQsm_ZuqGpC3GYV1K",banner:"adjust-smart-banner__Dw5N6VeDUP14gIEdMH7SH",stickyToTop:"adjust-smart-banner__1gDv13AgIJ63OmoMUWN6vd",stickyToBottom:"adjust-smart-banner__2Xpm01sHnZNYOOkNk05cAc",bannerBody:"adjust-smart-banner__YV2trFakzl9_mm1H-9Ht5",content:"adjust-smart-banner__31MvUOHjvsAEpS_14bUpGT",dismiss:"adjust-smart-banner__3PQ7z78EskytjOkrU199hE",appIcon:"adjust-smart-banner__L_BSzs7rJajVPX4zdt2R6",placeholder:"adjust-smart-banner__3Yj45mdOZKIOH2d6Z2UXXa",image:"adjust-smart-banner__4hg0kzTWzWiGjzCDqbktp",textContainer:"adjust-smart-banner__3mbKdOA0SmqrfOLvHomXyc",bannerText:"adjust-smart-banner__3DSKm9idx4dze89DWsCMXr",action:"adjust-smart-banner__3_w6WNex3gOuKV8gztVNoI"}},function(e,t){e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n=function(e,t){var n=e[1]||"",r=e[3];if(!r)return n;if(t&&"function"==typeof btoa){var o=(a=r,"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(a))))+" */"),i=r.sources.map((function(e){return"/*# sourceURL="+r.sourceRoot+e+" */"}));return[n].concat(i).concat([o]).join("\n")}var a;return[n].join("\n")}(t,e);return t[2]?"@media "+t[2]+"{"+n+"}":n})).join("")},t.i=function(e,n){"string"==typeof e&&(e=[[null,e,""]]);for(var r={},o=0;o=0&&d.splice(t,1)}function g(e){var t=document.createElement("style");if(void 0===e.attrs.type&&(e.attrs.type="text/css"),void 0===e.attrs.nonce){var r=function(){0;return n.nc}();r&&(e.attrs.nonce=r)}return y(t,e.attrs),h(e,t),t}function y(e,t){Object.keys(t).forEach((function(n){e.setAttribute(n,t[n])}))}function b(e,t){var n,r,o,i;if(t.transform&&e.css){if(!(i="function"==typeof t.transform?t.transform(e.css):t.transform.default(e.css)))return function(){};e.css=i}if(t.singleton){var a=l++;n=c||(c=g(t)),r=_.bind(null,n,a,!1),o=_.bind(null,n,a,!0)}else e.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=function(e){var t=document.createElement("link");return void 0===e.attrs.type&&(e.attrs.type="text/css"),e.attrs.rel="stylesheet",y(t,e.attrs),h(e,t),t}(t),r=S.bind(null,n,t),o=function(){v(n),n.href&&URL.revokeObjectURL(n.href)}):(n=g(t),r=x.bind(null,n),o=function(){v(n)});return r(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;r(e=t)}else o()}}e.exports=function(e,t){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");(t=t||{}).attrs="object"==typeof t.attrs?t.attrs:{},t.singleton||"boolean"==typeof t.singleton||(t.singleton=a()),t.insertInto||(t.insertInto="head"),t.insertAt||(t.insertAt="bottom");var n=m(e,t);return p(n,t),function(e){for(var r=[],o=0;o0&&void 0!==arguments[0]?arguments[0]:[];return e.reduce((function(e,t){return o()(o()({},e),{},v()({},t.key,t.value))}),{})}function S(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[];return e.filter((function(e){return-1!==t.indexOf(e)}))}function P(e,t){return new RegExp("\\/".concat(t,"(\\/.*|\\?.*){0,1}$")).test(e)}function j(e,t){var n=u()(t,2),r=n[0],i=n[1];return o()(o()({},e),{},v()({},r,i))}function D(e){return Object.keys(e).map((function(t){return[t,e[t]]}))}function I(e){return Object.keys(e).map((function(t){return e[t]}))}function N(e){return w(e)?!b(e):!!e||0===e}var T,O={namespace:"adjust-sdk",version:"5.3.0",env:"production"},E=(T={},v()(T,"none",-1),v()(T,"error",0),v()(T,"warning",1),v()(T,"info",2),v()(T,"verbose",3),T),A={log:" ",info:" ",warn:" ",error:""},C={development:"verbose",production:"error",test:"verbose"},R=B(),M="";function B(){return C[O.env]||"error"}function U(e,t){var n;if(!(E[R]2?s-2:0),c=2;c2&&void 0!==arguments[2]?arguments[2]:[];return n.map((function(n){return we(e,t,n)}))}function _e(e,t,n){var r=ge[t][Se(e,fe.right)],o=r.fields[r.keyPath],i=n instanceof Array?n.slice():[n],a=(re(o)?o.composite:[r.keyPath]).map((function(e,t){var n=r.fields[e];return be(te(n)?n.values:null,i[t])}));return 1===a.length?a[0]:a}function xe(e){return ge.values[e]||e}function Se(e,t){return(ge.storeNames[t][e]||{}).name||e}function Pe(e,t){return{name:t.name,message:t.message.replace('"'.concat(e,'"'),Se(e,fe.right))}}!function(e){e.LowerBound="lowerBound",e.UpperBound="upperBound"}(de||(de={})),function(e){e.right="right",e.left="left"}(fe||(fe={}));var je=n(5),De=n.n(je),Ie=n(6),Ne=n.n(Ie);function Te(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1,n=e+"",r=1;r<=t;r+=1)e0?"-":"+")+Te(Math.floor(Math.abs(t)/60))+Te(Math.abs(t)%60)}(t);return"".concat(n,"T").concat(r,"Z").concat(o)}function Ee(e,t){return isNaN(e)||isNaN(t)?0:Math.abs(t-e)}var Ae={},Ce=!1,Re=!1;function Me(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};Ae=Ce?o()({},e):{}}function Be(){Ce&&(Ae.lastInterval=function(){var e=Ae.lastActive;if(e)return Math.round(Ee(e,Date.now())/1e3);return-1}(),Ae.lastActive=Date.now())}function Ue(e){Ae=o()(o()({},Ae),e)}function Le(){Re=!0}function He(){var e=Ae.lastActive;return Math.round(Ee(e,Date.now())/1e3)}function qe(){return(Ae.timeSpent||0)+(Re?He():0)}function Ke(){var e=Ee(Ae.lastActive,Date.now())<$.sessionWindow,t=Re||!Re&&e;return(Ae.sessionLength||0)+(t?He():0)}function Fe(){Ce&&(Ue({timeSpent:qe(),sessionLength:Ke()}),Be())}var Ve={get current(){return Ce?o()({},Ae):{}},set current(e){Me(e)},init:function(e){Ce=!0,Me(e)},isStarted:function(){return Ce},toForeground:Le,toBackground:function(){Re=!1},initParams:function(){Fe(),Le()},getParams:function(e){if(!Ce)return null;var t=Ae.lastInterval>=0?Ae.lastInterval:0,n={timeSpent:Ae.timeSpent||0,sessionLength:Ae.sessionLength||0,sessionCount:Ae.sessionCount||1,lastInterval:t||0};return e&&P(e,"event")&&(n.eventCount=Ae.eventCount),n},updateParams:function(e,t){if(Ce){var n={};n.timeSpent=qe(),n.sessionLength=Ke(),P(e,"session")&&(n.sessionCount=(Ae.sessionCount||0)+1),P(e,"event")&&(n.eventCount=(Ae.eventCount||0)+1),Ue(n),t||Be()}},updateInstalled:function(){Ce&&(Ae.installed||Ue({installed:!0}))},updateSessionOffset:Fe,updateSessionLength:function(){Ce&&(Ue({sessionLength:Ke()}),Be())},resetSessionOffset:function(){Ce&&Ue({timeSpent:0,sessionLength:0})},updateLastActive:Be,destroy:function(){Ae={},Ce=!1,Re=!1},getAttribution:function(){return Ce?Ae.attribution?Ae.attribution:(H.log("No attribution data yet"),null):null},getWebUUID:function(){return Ce?Ae.uuid:null}},ze={},Ge=[];function Ye(e,t){var n="id"+Math.random().toString(36).substr(2,16),r={id:n,cb:t};return ze[e]||(ze[e]=[]),ze[e].push(r),n}function We(e,t){ze[e]&&ze[e].forEach((function(n){"function"==typeof n.cb&&Ge.push(setTimeout((function(){return n.cb(e,t)})))}))}var Je=new(function(){function e(){var t=this;De()(this,e),v()(this,"defaultName",O.namespace),v()(this,"storageName",this.defaultName),v()(this,"storeNames",ge.storeNames.left),v()(this,"storesMap",void 0),this.storesMap={};var n=this.read.bind(this),r=this.write.bind(this);I(this.storeNames).forEach((function(e){var o=e.name;Object.defineProperty(t.storesMap,o,{get:function(){return n(o)},set:function(e){r(o,e)}})})),Object.freeze(this.storesMap)}return Ne()(e,[{key:"read",value:function(e){var t=localStorage.getItem("".concat(this.storageName,".").concat(e)),n=t?JSON.parse(t):null;return e===Z.Preferences&&n?we(Z.Preferences,fe.right,n):n}},{key:"write",value:function(e,t){t?localStorage.setItem("".concat(this.storageName,".").concat(e),JSON.stringify(t instanceof Array?t:we(Z.Preferences,fe.left,t))):localStorage.removeItem("".concat(this.storageName,".").concat(e))}},{key:"clear",value:function(){this.deleteData()}},{key:"deleteData",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];I(this.storeNames).forEach((function(n){!t&&n.permanent||localStorage.removeItem("".concat(e.storageName,".").concat(n.name))}))}},{key:"setCustomName",value:function(e){var t=this;if(e&&e.length){var n="".concat(O.namespace,"-").concat(e);I(this.storeNames).forEach((function(e){var r=e.name,o=localStorage.getItem("".concat(t.storageName,".").concat(r));o&&localStorage.setItem("".concat(n,".").concat(r),o)})),this.deleteData(!0),this.storageName=n}}},{key:"stores",get:function(){return this.storesMap}}]),e}()),Xe=ie.preferences.name,Qe=Ze();function Ze(){return Qe||$e(),Qe?o()({},Qe):null}function $e(){Qe=Je.stores[Xe]}function et(){var e=Ze();return e?e.sdkDisabled:null}function tt(e){var t=e?o()({},e):null;Je.stores[Xe]=o()(o()({},Ze()),{},{sdkDisabled:t}),$e()}function nt(){var e=Ze();return e?e.thirdPartySharingDisabled:null}function rt(){var e=Je.stores[Xe]||{},t=(Qe||{}).sdkDisabled||null;e.sdkDisabled&&!t&&We("sdk:shutdown"),$e()}function ot(){Je.stores[Xe]||(Je.stores[Xe]=o()({},Qe))}var it,at,st="undefined"==typeof Promise?n(3).Promise:Promise;!function(e){e.add="add",e.put="put",e.get="get",e.list="list",e.clear="clear",e.delete="delete"}(it||(it={})),function(e){e.readonly="readonly",e.readwrite="readwrite"}(at||(at={}));var ut=function(){function e(){De()(this,e),v()(this,"dbDefaultName",O.namespace),v()(this,"dbName",this.dbDefaultName),v()(this,"dbVersion",1),v()(this,"idbFactory",void 0),v()(this,"indexedDbConnection",null),v()(this,"notSupportedError",{name:"IDBNotSupported",message:"IndexedDB is not supported"}),v()(this,"databaseOpenError",{name:"CannotOpenDatabaseError",message:"Cannot open a database"}),v()(this,"noConnectionError",{name:"NoDatabaseConnection",message:"Cannot open a transaction"});var t=e.getIndexedDB();if(!t)throw this.notSupportedError;this.idbFactory=t}return Ne()(e,[{key:"setCustomName",value:function(e){return e&&e.length>0?(this.dbName="".concat(O.namespace,"-").concat(e),this.migrateDb(this.dbDefaultName,this.dbName)):st.resolve()}},{key:"openDatabase",value:function(t,n,r){var o=this;return e.isSupported().then((function(e){return e?new st((function(e,i){var a=o.idbFactory.open(t,r);n&&(a.onupgradeneeded=function(e){return n(e,i)}),a.onsuccess=function(t){var n=t.target.result;n?e(n):i(o.databaseOpenError)},a.onerror=i})):st.reject(o.notSupportedError)}))}},{key:"databaseExists",value:function(e){var t=this;return new st((function(n){var r=!0;t.openDatabase(e,(function(){r=!1})).then((function(n){if(n.close(),!r)return t.deleteDatabaseByName(e)})).then((function(){return n(r)}))}))}},{key:"cloneData",value:function(e,t){var n=this;return I(ge.storeNames.left).map((function(e){return e.name})).filter((function(e){return"p"!==e})).map((function(r){return function(){return o=r,i=n.indexedDbConnection,n.indexedDbConnection=e,n.getAll(o).then((function(e){if(n.indexedDbConnection=t,!(e.length<1))return n.addBulk(o,e,!0)})).then((function(){n.indexedDbConnection=i}));var o,i}})).reduce((function(e,t){return e.then(t)}),st.resolve())}},{key:"migrateDb",value:function(e,t){var n=this;return this.databaseExists(e).then((function(r){return r?st.all([n.openDatabase(e,n.handleUpgradeNeeded,n.dbVersion),n.openDatabase(t,n.handleUpgradeNeeded,n.dbVersion)]).then((function(t){var r=u()(t,2),o=r[0],i=r[1];return n.cloneData(o,i).then((function(){return n.indexedDbConnection=i,o.close(),n.deleteDatabaseByName(e)}))})).then((function(){return H.info("Database migration finished")})):n.openDatabase(t,n.handleUpgradeNeeded,n.dbVersion).then((function(e){n.indexedDbConnection=e}))}))}},{key:"handleUpgradeNeeded",value:function(e,t){var n=e.target.result;e.target.transaction.onerror=t,e.target.transaction.onabort=t;var r=ge.storeNames.left,o=Ve.current||{},i=o&&!b(o);D(r).filter((function(e){return!u()(e,2)[1].permanent})).forEach((function(e){var t=u()(e,2),r=t[0],a=t[1].name,s=ge.right[r],c=n.createObjectStore(a,{keyPath:s.keyPath,autoIncrement:s.autoIncrement||!1});if(s.index&&c.createIndex("".concat(s.index,"Index"),s.index),a===Q.ActivityState&&i)return c.add(we(r,fe.left,o)),void H.info("Activity state has been recovered");var l=Je.stores[a];l&&(l.forEach((function(e){return c.add(e)})),H.info("Migration from localStorage done for ".concat(r," store")))})),ot(),Je.clear()}},{key:"open",value:function(){var e=this;return this.indexedDbConnection?st.resolve({success:!0}):this.openDatabase(this.dbName,this.handleUpgradeNeeded,this.dbVersion).then((function(t){return e.indexedDbConnection=t,e.indexedDbConnection.onclose=function(){return e.destroy},{success:!0}}))}},{key:"getTransactionStore",value:function(e,t,n){var r,o=e.storeName,i=e.mode,a=n.transaction([o],i),s=a.objectStore(o),u=ge.right[Se(o,fe.right)];return u.index&&(r=s.index("".concat(u.index,"Index"))),a.onerror=t,a.onabort=t,{transaction:a,store:s,index:r,options:u}}},{key:"overrideError",value:function(e,t){var n=t.target.error;return e({name:n.name,message:n.message})}},{key:"getCompositeKeys",value:function(e){var t=e.fields[e.keyPath];return re(t)?t.composite:null}},{key:"targetIsObject",value:function(e){return w(e)}},{key:"prepareTarget",value:function(e,t,n){if(n===it.clear||!t)return null;var r=this.getCompositeKeys(e);return-1!==[it.add,it.put].indexOf(n)?this.targetIsObject(t)?r?o()(v()({},e.keyPath,r.map((function(e){return t[e]})).join("")),t):t:null:t instanceof Array?t.join(""):t}},{key:"prepareResult",value:function(e,t){var n=this.getCompositeKeys(e);return n&&this.targetIsObject(t)?n.map((function(e){return t[e]})):null}},{key:"initRequest",value:function(e){var t=this,n=e.storeName,r=e.target,o=void 0===r?null:r,i=e.action,a=e.mode,s=void 0===a?at.readonly:a;return this.open().then((function(){return new st((function(e,r){if(t.indexedDbConnection){var a=t.getTransactionStore({storeName:n,mode:s},r,t.indexedDbConnection),u=a.store,c=a.options,l=u[i](t.prepareTarget(c,o,i)),d=t.prepareResult(c,o);l.onsuccess=function(){i!==it.get||l.result?e(d||l.result||o):r({name:"NotRecordFoundError",message:'Requested record not found in "'.concat(n,'" store')})},l.onerror=function(e){return t.overrideError(r,e)}}else r(t.noConnectionError)}))}))}},{key:"initBulkRequest",value:function(e){var t=this,n=e.storeName,r=e.target,o=e.action,i=e.mode,a=void 0===i?at.readwrite:i;return!r||r&&!r.length?st.reject({name:"NoTargetDefined",message:"No array provided to perform ".concat(o,' bulk operation into "').concat(n,'" store')}):this.open().then((function(){return new st((function(e,i){if(t.indexedDbConnection){var s=t.getTransactionStore({storeName:n,mode:a},i,t.indexedDbConnection),u=s.transaction,c=s.store,l=s.options,d=new Array,f=r[0];u.oncomplete=function(){return e(d)};!function e(n){n.onerror=function(e){return t.overrideError(i,e)},n.onsuccess=function(){d.push(t.prepareResult(l,f)||n.result),f=r[d.length],d.length1&&void 0!==arguments[1]&&arguments[1];return this.openCursor({storeName:e,action:it.list,firstOnly:t})}},{key:"getFirst",value:function(e){return this.getAll(e,!0).then((function(e){return e.length?e[0]:void 0}))}},{key:"getItem",value:function(e,t){return this.initRequest({storeName:e,target:t,action:it.get})}},{key:"filterBy",value:function(e,t){var n=IDBKeyRange.only(t);return this.openCursor({storeName:e,action:it.list,range:n})}},{key:"addItem",value:function(e,t){return this.initRequest({storeName:e,target:t,action:it.add,mode:at.readwrite})}},{key:"addBulk",value:function(e,t,n){return this.initBulkRequest({storeName:e,target:t,action:n?it.put:it.add,mode:at.readwrite})}},{key:"updateItem",value:function(e,t){return this.initRequest({storeName:e,target:t,action:it.put,mode:at.readwrite})}},{key:"deleteItem",value:function(e,t){return this.initRequest({storeName:e,target:t,action:it.delete,mode:at.readwrite})}},{key:"deleteBulk",value:function(e,t,n){var r=n?IDBKeyRange[n](t):IDBKeyRange.only(t);return this.openCursor({storeName:e,action:it.delete,range:r,mode:at.readwrite})}},{key:"trimItems",value:function(e,t){var n=this,r=ge.right[Se(e,fe.right)];return this.getAll(e).then((function(e){return e.length?e[t-1]:null})).then((function(t){return t?n.deleteBulk(e,t[r.keyPath],de.UpperBound):[]}))}},{key:"count",value:function(e){var t=this;return this.open().then((function(){return new st((function(n,r){if(t.indexedDbConnection){var o=t.getTransactionStore({storeName:e,mode:at.readonly},r,t.indexedDbConnection).store.count();o.onsuccess=function(){return n(o.result)},o.onerror=function(e){return t.overrideError(r,e)}}else r(t.noConnectionError)}))}))}},{key:"clear",value:function(e){return this.initRequest({storeName:e,action:it.clear,mode:at.readwrite})}},{key:"destroy",value:function(){this.indexedDbConnection&&this.indexedDbConnection.close(),this.indexedDbConnection=null}},{key:"deleteDatabase",value:function(){return this.destroy(),this.deleteDatabaseByName(this.dbName)}}],[{key:"tryOpen",value:function(t){return new st((function(n){try{var r=t.open(e.dbValidationName);r.onsuccess=function(){r.result.close(),t.deleteDatabase(e.dbValidationName),n(!0)},r.onerror=function(){return n(!1)}}catch(e){n(!1)}}))}},{key:"isSupported",value:function(){return e.isSupportedPromise||(e.isSupportedPromise=new st((function(t){var n=e.getIndexedDB(),r=!!navigator.platform&&/iPad|iPhone|iPod/.test(navigator.platform);!n||r?(H.warn("IndexedDB is not supported in this browser"),t(!1)):t(e.tryOpen(n).then((function(e){return e||H.warn("IndexedDB is not supported in this browser"),e})))}))),e.isSupportedPromise}},{key:"getIndexedDB",value:function(){return window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB}}]),e}();v()(ut,"dbValidationName","validate-db-openable"),v()(ut,"isSupportedPromise",null);var ct="undefined"==typeof Promise?n(3).Promise:Promise,lt=function(){function e(){De()(this,e)}return Ne()(e,[{key:"open",value:function(){return e.isSupported().then((function(e){if(!e)return{status:"error",error:{name:"LSNotSupported",message:"LocalStorage is not supported"}};var t=ge.storeNames.left,n=Ve.current||{},r=n&&!b(n);return D(t).filter((function(e){return!u()(e,2)[1].permanent})).forEach((function(e){var t=u()(e,2),o=t[0],i=t[1].name;i!==Q.ActivityState||Je.stores[i]?Je.stores[i]||(Je.stores[i]=[]):Je.stores[i]=r?[we(o,fe.left,n)]:[]})),ot(),{status:"success"}}))}},{key:"getCompositeKeys",value:function(e){var t=e.fields[e.keyPath];return re(t)?t.composite:null}},{key:"getKeys",value:function(e){var t=Se(e,fe.right),n=ge.right[t];return this.getCompositeKeys(n)||[n.keyPath]}},{key:"nextIndex",value:function(e){return"number"==typeof e?e+1:void 0}},{key:"initRequest",value:function(e,t){var n=this,r=e.storeName,i=e.id,a=e.item,s=ge.right[Se(r,fe.right)];return this.open().then((function(e){return"error"===e.status?ct.reject(e.error):new ct((function(e,u){var c,l=Je.stores[r],d=n.getKeys(r),f=(l[l.length-1]||{})[s.keyPath]||0;if(i){var p=Array.isArray(i)?i.slice():[i];c=d.map((function(e,t){return[e,p[t]]})).reduce(j,{})}else c=o()({},a);var m=c?_(l,d,c):0;return t(e,u,{keys:d,items:l,index:m,options:s,lastId:f})}))}))}},{key:"sort",value:function(e,t,n){var r=l()(e),o=t.slice().reverse();return r.sort((function(e,t){return o.reduce((function(r,o){return r||function(e,t,r){var o=n?n===e[r]:e[r]e[r]:e[r]>t[r];return o?-1:i?1:0}(e,t,o)}),0)}))}},{key:"prepareTarget",value:function(e,t,n){var r=this.getCompositeKeys(e);return r?o()(v()({},e.keyPath,r.map((function(e){return t[e]})).join("")),t):e.autoIncrement&&n?o()(v()({},e.keyPath,n),t):o()({},t)}},{key:"prepareResult",value:function(e,t){var n=this.getCompositeKeys(e);return n?n.map((function(e){return t[e]})).filter((function(e){return!ye(e)})):t[e.keyPath]}},{key:"getAll",value:function(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return this.open().then((function(r){return"error"===r.status?ct.reject(r.error):new ct((function(r,o){var i=Je.stores[e];i instanceof Array?r(n?[i[0]]:t.sort(i,t.getKeys(e))):o({name:"NotFoundError",message:"No objectStore named ".concat(e," in this database")})}))}))}},{key:"getFirst",value:function(e){return this.getAll(e,!0).then((function(e){return e.length?e[0]:void 0}))}},{key:"getItem",value:function(e,t){var n=this;return this.initRequest({storeName:e,id:t},(function(t,r,o){var i=o.items,a=o.index,s=o.options;-1===a?r({name:"NotRecordFoundError",message:'Requested record not found in "'.concat(e,'" store')}):t(n.prepareTarget(s,i[a]))}))}},{key:"filterBy",value:function(e,t){return this.getAll(e).then((function(n){return n.filter((function(n){var r=ge.right[Se(e,fe.right)];return(r.index&&n[r.index])===t}))}))}},{key:"addItem",value:function(e,t){var n=this;return this.initRequest({storeName:e,item:t},(function(r,o,i){var a=i.items,s=i.index,u=i.options,c=i.lastId;-1!==s?o({name:"ConstraintError",message:'Constraint was not satisfied, trying to add existing item into "'.concat(e,'" store')}):(a.push(n.prepareTarget(u,t,n.nextIndex(c))),Je.stores[e]=a,r(n.prepareResult(u,t)))}))}},{key:"addBulk",value:function(e,t,n){var r=this;return this.initRequest({storeName:e},(function(o,i,a){var s=a.keys,u=a.items,c=a.options,d=a.lastId;if(!t||t&&!t.length)i({name:"NoTargetDefined",message:'No array provided to perform add bulk operation into "'.concat(e,'" store')});else{var f=d,p=t.map((function(e){return r.prepareTarget(c,e,f=r.nextIndex(f))})),m=p.filter((function(e){return-1!==_(u,s,e)})).map((function(e){return e[c.keyPath]})),h=n?u.filter((function(e){return-1===m.indexOf(e[c.keyPath])})):l()(u);if(m.length&&!n)i({name:"ConstraintError",message:'Constraint was not satisfied, trying to add existing items into "'.concat(e,'" store')});else Je.stores[e]=r.sort([].concat(l()(h),l()(p)),s),o(t.map((function(e){return r.prepareResult(c,e)})))}}))}},{key:"updateItem",value:function(e,t){var n=this;return this.initRequest({storeName:e,item:t},(function(r,o,i){var a=i.items,s=i.index,u=i.options,c=i.lastId,l=-1===s?n.nextIndex(c):void 0,d=n.prepareTarget(u,t,l);-1===s?a.push(d):a.splice(s,1,d),Je.stores[e]=a,r(n.prepareResult(u,t))}))}},{key:"deleteItem",value:function(e,t){return this.initRequest({storeName:e,id:t},(function(n,r,o){var i=o.items,a=o.index;-1!==a&&(i.splice(a,1),Je.stores[e]=i),n(t)}))}},{key:"findMax",value:function(e,t,n){if(!e.length)return-1;for(var r={index:-1,value:"string"==typeof n?"":0},o=0;o=r.value&&(r={value:e[o][t],index:o})}return r.index}},{key:"deleteBulk",value:function(e,t,n){var r=this;return this.getAll(e).then((function(o){var i=r.getKeys(e),a=ge.right[Se(e,fe.right)].index||i[0],s=n?null:t,u=r.sort(o,i,s),c=r.findMax(u,a,t);if(-1===c)return[];var l=n===de.LowerBound?c:0,d=n&&n!==de.UpperBound?u.length:c+1,f=u.splice(l,d).map((function(e){return 1===i.length?e[a]:i.map((function(t){return e[t]}))}));return Je.stores[e]=u,f}))}},{key:"trimItems",value:function(e,t){var n=this,r=Se(e,fe.right),o=ge.right[r];return this.getAll(e).then((function(e){return e.length?e[t-1]:null})).then((function(t){return t?n.deleteBulk(e,t[o.keyPath],de.UpperBound):[]}))}},{key:"count",value:function(e){return this.open().then((function(t){if("error"===t.status)return ct.reject(t.error);var n=Je.stores[e];return ct.resolve(n instanceof Array?n.length:1)}))}},{key:"clear",value:function(e){return this.open().then((function(t){return"error"===t.status?ct.reject(t.error):new ct((function(t){Je.stores[e]=[],t()}))}))}},{key:"destroy",value:function(){}},{key:"deleteDatabase",value:function(){}}],[{key:"isSupported",value:function(){if(e.isSupportedPromise)return e.isSupportedPromise;var t=(new Date).toString(),n=window.localStorage;return e.isSupportedPromise=new ct((function(e){n.setItem(t,t);var r=n.getItem(t)===t;n.removeItem(t),e(!(!r||!n))})).catch((function(){return H.warn("LocalStorage is not supported in this browser"),ct.resolve(!1)})),e.isSupportedPromise}}]),e}();v()(lt,"isSupportedPromise",null);var dt,ft,pt="undefined"==typeof Promise?n(3).Promise:Promise;(ft=dt||(dt={}))[ft.noStorage=f]="noStorage",ft[ft.indexedDB=p]="indexedDB",ft[ft.localStorage=m]="localStorage";var mt,ht={getAll:function(e,t,n){return e.getAll(t,n).then((function(e){return ke(t,fe.right,e)}))},getFirst:function(e,t){return e.getFirst(t).then((function(e){return we(t,fe.right,e)}))},getItem:function(e,t,n){return e.getItem(t,_e(t,fe.left,n)).then((function(e){return we(t,fe.right,e)})).catch((function(e){return pt.reject(Pe(t,e))}))},filterBy:function(e,t,n){return e.filterBy(t,xe(n)).then((function(e){return ke(t,fe.right,e)}))},addItem:function(e,t,n){var r=we(t,fe.left,n);return e.addItem(t,r).then((function(e){return _e(t,fe.right,e)})).catch((function(e){return pt.reject(Pe(t,e))}))},addBulk:function(e,t,n,r){var o=ke(t,fe.left,n);return e.addBulk(t,o,r).then((function(e){return e.map((function(e){return _e(t,fe.right,e)}))})).catch((function(e){return pt.reject(Pe(t,e))}))},updateItem:function(e,t,n){var r=we(t,fe.left,n);return e.updateItem(t,r).then((function(e){return _e(t,fe.right,e)}))},deleteItem:function(e,t,n){return e.deleteItem(t,_e(t,fe.left,n)).then((function(e){return _e(t,fe.right,e)}))},deleteBulk:function(e,t,n,r){return e.deleteBulk(t,xe(n),r).then((function(e){return e.map((function(e){return _e(t,fe.right,e)}))}))},trimItems:function(e,t,n){return e.trimItems(t,n)},count:function(e,t){return e.count(t)},clear:function(e,t){return e.clear(t)},destroy:function(e){return e.destroy()},deleteDatabase:function(e){return e.deleteDatabase()}};var vt=null;function gt(e){var t=null;return null!==vt?vt:vt=pt.all([ut.isSupported(),lt.isSupported()]).then((function(n){var r=u()(n,2),o=r[0],i=r[1];if(Je.setCustomName(e),o){mt=dt.indexedDB;var a=new ut;return a.setCustomName(e).then((function(){return t=a}))}return i?(mt=dt.localStorage,t=new lt,pt.resolve(t)):(H.error("There is no storage available, app will run with minimum set of features"),mt=dt.noStorage,t=null,pt.resolve(t))})).then((function(){return{type:mt,storage:t}}))}var yt,bt,wt=o()({init:gt,getType:function(){return mt}},D(ht).map((function(e){var t=u()(e,2),n=t[0],r=t[1];return[n,function(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),o=1;o1&&void 0!==arguments[1]?arguments[1]:St,n=xt();if(Array.isArray(n)){var r=0,o=function o(){var i=n[r++],a=t[i];return e(a).catch((function(e){if("NO_CONNECTION"===e.code&&(H.log("Failed to connect ".concat(Pt[i]," endpoint")),r2&&void 0!==arguments[2]&&arguments[2];return{status:"error",action:n?"CONTINUE":"RETRY",response:k(e.responseText)?JSON.parse(e.responseText):e.responseText,message:d[t],code:t}}function Nt(e,t){var n=e.slice(0,e.length-t.length-1).split("").reduce((function(e){return e.concat(" ")}),"");return"".concat(t).concat(n,":")}function Tt(e,t){var n=function(e){return e.replace(/([A-Z])/g,(function(e){return"_".concat(e.toLowerCase())}))},r=D(o()(o()(o()({},$.getBaseParams()),t),e)).map((function(e){var t=u()(e,2),r=t[0],o=t[1];return[n(r),o]}));return H.log("REQUEST PARAMETERS:"),r.filter((function(e){return N(u()(e,2)[1])})).map((function(e){var t=u()(e,2),n=t[0],r=t[1];return H.log(Nt("REQUEST PARAMETERS:",n),r),function(e){var t=u()(e,2),n=t[0],r=t[1],o=encodeURIComponent(n),i=r;return"string"==typeof r&&(i=encodeURIComponent(r)),w(r)&&(i=encodeURIComponent(JSON.stringify(r)||"")),[o,i].join("=")}([n,r])})).join("&")}function Ot(e,t,n){var r=n.xhr,o=n.url;if(4===r.readyState){var i=r.status>=200&&r.status<300,a=k(r.responseText);if(0!==r.status)return a?t(i?function(e,t){var n=JSON.parse(e.responseText),r={status:"success",adid:n.adid,timestamp:n.timestamp,ask_in:n.ask_in,retry_in:n.retry_in,continue_in:n.continue_in,tracking_state:n.tracking_state,attribution:void 0,message:void 0};return P(t,"attribution")&&(r.attribution=n.attribution,r.message=n.message),D(r).filter((function(e){return!!u()(e,2)[1]})).reduce(j,{})}(r,o):It(r,"SERVER_CANNOT_PROCESS",!0)):e(It(r,i?"SERVER_MALFORMED_RESPONSE":"SERVER_INTERNAL_ERROR"));e(It(r,"NO_CONNECTION"))}}function Et(e,t,n){var r=e.url,o=e.method,i=void 0===o?"GET":o,a=e.params,s=function(e,t,n){var r=e.url,o=e.method,i=Tt(e.params,t);return{fullUrl:n["/gdpr_forget_device"===r?"gdpr":"app"]+r+("GET"===o?"?".concat(i):""),encodedParams:i}}({url:r,method:i,params:void 0===a?{}:a},t,n),c=s.fullUrl,l=s.encodedParams;return new Dt((function(e,t){var n=new XMLHttpRequest;n.open(i,c,!0),function(e,t){var n=[["Client-SDK","js".concat(O.version)],["Content-Type","POST"===t?"application/x-www-form-urlencoded":"application/json"]];H.log("REQUEST HEADERS:"),n.forEach((function(t){var n=u()(t,2),r=n[0],o=n[1];e.setRequestHeader(r,o),H.log(Nt("REQUEST HEADERS:",r),o)}))}(n,i),n.onreadystatechange=function(){return Ot(t,e,{xhr:n,url:r})},n.onerror=function(){return t(It(n,"TRANSACTION_ERROR"))},n.send("GET"===i?void 0:l)}))}function At(e,t){return"success"===e.status?function(e,t){var n=P(t,"gdpr_forget_device"),r=P(t,"attribution"),o=P(t,"session"),i=P(t,"disable_third_party_sharing"),a="opted_out"===e.tracking_state;if(!n&&a)return We("sdk:gdpr-forget-me"),e;r||n||a||!e.ask_in||We("attribution:check",e);o&&We("session:finished",e);if(i)return We("sdk:third-party-sharing-opt-out"),e;return e}(e,t):e}function Ct(e){return kt().then((function(t){return function(e,t){return jt((function(n){return Et(e,t,n)}))}(e,t)})).then((function(t){return At(t,e.url)}))}var Rt={long:{delay:12e4,maxDelay:864e5,minRange:.5,maxRange:1},short:{delay:200,maxDelay:36e5,minRange:.5,maxRange:1},test:{delay:100,maxDelay:300}};function Mt(e,t){var n,r,o=Rt[t=t||"long"],i=o.delay*Math.pow(2,e-1);return i=Math.min(i,o.maxDelay),o.minRange&&o.maxRange&&(i*=(n=o.minRange,r=o.maxRange,Math.random()*(r-n)+n)),Math.round(i)}var Bt=navigator.onLine;function Ut(){Bt=!0}function Lt(){Bt=!1}function Ht(e,t,n){e.addEventListener&&e.addEventListener(t,n,!1)}function qt(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}function Kt(){return Bt}var Ft="undefined"==typeof Promise?n(3).Promise:Promise,Vt=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.url,n=e.method,r=void 0===n?"GET":n,i=e.params,a=void 0===i?{}:i,s=e.continueCb,c=e.strategy,l=e.wait,f={url:t,method:r,params:a,continueCb:s},p=t,m=r,h=o()({},a),v=s,g=c,y=null,w={request:0,connection:0},k=x(l),_=null;function x(e){return(e=e||150)>2147483647?2147483647:e}function S(e){var t=e.url,n=e.method,r=e.params,i=e.continueCb;t&&(p=t),n&&(m=n),b(r)||(h=o()({},r)),h=o()({createdAt:Oe()},h),"function"==typeof i&&(v=i)}function P(e){if(!_)return!1;if(y){var t=k-(Date.now()-_);if(e&&t0&&void 0!==arguments[0]?arguments[0]:{},t=e.url,n=e.method,r=e.params,o=void 0===r?{}:r,i=e.continueCb,a=e.wait;return S({url:t,method:n,params:o,continueCb:i}),I({wait:a})}function U(){return!!y}function L(){y&&clearTimeout(y),y=null}function q(){var e=!!_;L(),_=null,e&&(k=150,w.request=0,w.connection=0,H.log("Previous ".concat(p||"unknown"," request attempt canceled")),E())}return{send:B,isRunning:U,clear:q}},zt=function(e){return"gdpr"===e?"GDPR disable":"disable"},Gt=function(e){return{start:{inProgress:"Adjust SDK ".concat(zt(e)," process has already started"),done:"Adjust SDK ".concat(zt(e)," process is now started")},finish:{inProgress:"Adjust SDK ".concat(zt(e)," process has already finished"),done:"Adjust SDK ".concat(zt(e)," process is now finished")}}};function Yt(e,t){var n=e.reason,r=e.pending,o=et()||{},i="start"===t&&o.pending?"start":"finish",a="start"===t&&o.reason,s="finish"===t&&o.reason&&!o.pending;return a||s?(H.log(Gt(o.reason)[i].inProgress),!1):(H.log(Gt(n)[i].done),tt({reason:n||"general",pending:r}),!0)}function Wt(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return Yt({reason:e,pending:t||!1},"start")}function Jt(){var e=et()||{};return"general"===e.reason||"gdpr"===e.reason&&!e.pending?"off":"gdpr"===e.reason&&e.pending?"paused":"on"}var Xt="undefined"==typeof Promise?n(3).Promise:Promise,Qt=!1;function Zt(e){return e?"unknown"===e.uuid?(Wt({reason:"gdpr"}),Ve.destroy(),{exists:!0,stored:null}):(Ve.init(e),{exists:!0,stored:e}):{exists:!1}}function $t(){return"off"!==Jt()&&Ve.isStarted()}function en(){if(!$t())return Xt.resolve(null);var e=o()(o()({},Ve.current),{},{lastActive:Date.now()});return wt.updateItem("activityState",e).then((function(){return Ve.current=e}))}var tn="undefined"==typeof Promise?n(3).Promise:Promise,nn=Vt({strategy:"long",continueCb:function(e,t){var n=e&&e.continue_in||null;return on.pause=n?{timestamp:Date.now(),wait:n}:null,wt.getFirst("queue").then((function(e){return e?wt.deleteItem("queue",e.timestamp):null})).then((function(){return t(),on.running=!1,dn({wait:n})}))}}),rn=!1,on={running:!1,timestamp:null,pause:null};function an(){var e=Date.now();return on.timestamp&&e<=on.timestamp&&(e=on.timestamp+1),on.timestamp=e,e}function sn(e){return P(e,"session")&&Ve.resetSessionOffset(),Ve.updateLastActive(),en()}function un(e){var t=e.url,n=e.method,r=e.params,i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},a=i.auto,s=i.timestamp;Ve.updateParams(t,a);var c=D(r||{}).filter((function(e){return N(u()(e,2)[1])})).reduce(j,{}),l={timestamp:an(),url:t,method:n,params:o()(o()({},Ve.getParams(t)),c)};return s&&(l.createdAt=s),wt.addItem("queue",l).then((function(){return sn(t)})).then((function(){return on.running?{}:dn()}))}function cn(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.timestamp,n=e.createdAt,r=e.url,i=e.method,a=e.params,s=arguments.length>1?arguments[1]:void 0,u=Ve.current||{},c="/session"===r&&!u.installed,l=!r&&!i&&!a;return rn&&!c||l?(on.running=!1,tn.resolve({})):nn.send({url:r,method:i,params:o()(o()({},a),{},{createdAt:Oe(n||t)}),wait:s||ln()})}function ln(){var e=on.pause||{},t=e.timestamp,n=e.wait,r=Date.now()-(t||0);return r0&&void 0!==arguments[0]?arguments[0]:{},t=e.cleanUp,n=e.wait;if(on.running)return tn.resolve({});on.running=!0;var r=tn.resolve({});return t&&(r=r.then(pn)),r.then((function(){return wt.getFirst("queue")})).then((function(e){return cn(e,n)}))}function fn(e){if(void 0!==e)if(e!==rn){var t=rn;rn=e,!e&&t&&dn(),H.info("The app is now in ".concat(e?"offline":"online"," mode"))}else H.error("The app is already in ".concat(e?"offline":"online"," mode"));else H.error("State not provided, true or false has to be defined")}function pn(){var e=Date.now()-$.requestValidityWindow;return wt.deleteBulk("queue",e,"upperBound")}var mn="undefined"==typeof Promise?n(3).Promise:Promise,hn="No type provided",vn="Global parameter type not provided, `callback` or `partner` types are available";function gn(e){return(e||[]).map((function(e){return{key:e.key,value:e.value}}))}function yn(){return mn.all([wt.filterBy("globalParams","callback"),wt.filterBy("globalParams","partner")]).then((function(e){var t=u()(e,2),n=t[0],r=t[1];return{callbackParams:gn(n),partnerParams:gn(r)}}))}function bn(e,t){if(void 0===t)return H.error(vn),mn.reject({message:hn});var n=x(e),r=Object.keys(n).map((function(e){return{key:e,value:n[e],type:t}}));return mn.all([wt.filterBy("globalParams",t),wt.addBulk("globalParams",r,!0)]).then((function(e){var n=u()(e,2),o=n[0],i=n[1],a=S(o.map((function(e){return e.key})),i.map((function(e){return e[0]})));return H.log("Following ".concat(t," parameters have been saved: ").concat(r.map((function(e){return"".concat(e.key,":").concat(e.value)})).join(", "))),a.length&&H.log("Keys: ".concat(a.join(", ")," already existed so their values have been updated")),i}))}function wn(e,t){return void 0===t?(H.error(vn),mn.reject({message:hn})):wt.deleteItem("globalParams",[e,t]).then((function(n){return H.log("".concat(e," ").concat(t," parameter has been deleted")),n}))}function kn(e){return void 0===e?(H.error(vn),mn.reject({message:hn})):wt.deleteBulk("globalParams",e).then((function(t){return H.log("All ".concat(e," parameters have been deleted")),t}))}var _n,xn,Sn,Pn="undefined"==typeof Promise?n(3).Promise:Promise,jn=!1,Dn=document;function In(){return Sn=function(){var e=document;if(void 0!==e.hidden)return{hidden:"hidden",visibilityChange:"visibilitychange"};for(var t=D({mozHidden:"mozvisibilitychange",msHidden:"msvisibilitychange",oHidden:"ovisibilitychange",webkitHidden:"webkitvisibilitychange"}),n=0;n0;return!n||n&&1e3*t>=$.sessionWindow?yn().then((function(e){var t,n,r;un({url:"/session",method:"POST",params:(t=e,n=t.callbackParams,r=t.partnerParams,{callbackParams:n.length?x(n):null,partnerParams:r.length?x(r):null})},{auto:!0})})):(We("attribution:check"),en())}var Rn="undefined"==typeof Promise?n(3).Promise:Promise,Mn=Vt({url:"/attribution",strategy:"short",continueCb:function(e,t,n){if(!e||e&&"error"===e.status)return t(),Rn.resolve({state:"unknown"});if(!e.ask_in)return t(),function(e){if(b(e)||!function(e){var t=e.adid,n=void 0===t?"":t,r=e.attribution,o=void 0===r?{}:r;return!!n&&!!S(Bn,Object.keys(o)).length}(e)||function(e){var t=e.adid,n=e.attribution,r=Ve.current.attribution||{};return!(n&&Bn.some((function(e){return r[e]!==n[e]})))&&t===r.adid}(e))return Rn.resolve({state:"same"});var t=D(e.attribution).filter((function(e){var t=u()(e,1)[0];return-1!==Bn.indexOf(t)})).reduce(j,{adid:e.adid});return Ve.current=o()(o()({},Ve.current),{},{attribution:t}),en().then((function(){return We("attribution:change",t),H.info("Attribution has been updated"),{state:"changed"}}))}(e);return n(e.ask_in)}}),Bn=["tracker_token","tracker_name","network","campaign","adgroup","creative","click_label","state"];var Un=Vt({url:"/gdpr_forget_device",method:"POST",strategy:"short"}),Ln={running:"Adjust SDK is running pending GDPR Forget Me request",pending:"Adjust SDK will run GDPR Forget Me request after initialisation",paused:"Adjust SDK is already prepared to send GDPR Forget Me request",off:"Adjust SDK is already disabled"};function Hn(e){var t=Jt();return e||"on"===t?$.isInitialised()?(Un.send({params:o()({},Ve.getParams())}).then((function(){We("sdk:gdpr-forget-me")})),!0):(H.log(Ln.pending),!0):(H.log(Ln[t]),!1)}function qn(){return Yt({reason:"gdpr",pending:!1},"finish")}var Kn={running:"Adjust SDK is running pending third-party sharing opt-out request",delayed:"Adjust SDK will run third-party sharing opt-out request after initialisation",pending:"Adjust SDK already queued third-party sharing opt-out request",off:"Third-party sharing opt-out is already done",start:{inProgress:"Third-party sharing opt-out has already started",done:"Third-party sharing opt-out is now started"},finish:{inProgress:"Third-party sharing opt-out has already finished",done:"Third-party sharing opt-out is now finished"}};function Fn(){var e=nt()||{};return e.reason?e.pending?"pending":"off":"on"}function Vn(e){var t=Fn();return e||"on"===t?$.isInitialised()?(un({url:"/disable_third_party_sharing",method:"POST"}),!0):(H.log(Kn.delayed),!0):(H.log(Kn[t]),!1)}function zn(e,t){var n,r,i=nt()||{},a="start"===t&&e?"start":"finish",s="start"===t&&i.reason,u="finish"===t&&i.reason&&!i.pending;return s||u?(H.log(Kn[a].inProgress),!1):(H.log(Kn[a].done),r=(n={reason:"general",pending:e})?o()({},n):null,Je.stores[Xe]=o()(o()({},Ze()),{},{thirdPartySharingDisabled:r}),$e(),!0)}function Gn(){return zn(!1,"finish")}function Yn(){"pending"===Fn()&&(H.log(Kn.running),Vn(!0))}var Wn=[];function Jn(e,t){Wn.push({method:e,description:t,timestamp:Date.now()})}var Xn,Qn="undefined"==typeof Promise?n(3).Promise:Promise;function Zn(e,t){var n,r,i=t.callbackParams,a=t.partnerParams,s={},u=o()({eventToken:e.eventToken},(n=e.revenue,r=e.currency,isNaN(n)||(n=parseFloat(n))<0||!r?{}:{revenue:n.toFixed(5),currency:r})),c=o()(o()({},x(i)),x(e.callbackParams)),l=o()(o()({},x(a)),x(e.partnerParams));return b(c)||(s.callbackParams=c),b(l)||(s.partnerParams=l),o()(o()({},u),s)}function $n(e){return e?wt.getAll("eventDeduplication").then((function(e){return e.map((function(e){return e.id}))})).then((function(t){return-1===t.indexOf(e)?function(e){var t=$.getCustomConfig().eventDeduplicationListLimit,n=t>0?t:10;return wt.count("eventDeduplication").then((function(e){var t=Qn.resolve();if(e>=n){var r=e-n+1;H.log("Event deduplication list limit has been reached. Oldest ids are about to be removed (".concat(r," of them)")),t=wt.trimItems("eventDeduplication",r)}return t})).then((function(){return H.info("New event deduplication id is added to the list: ".concat(e)),wt.addItem("eventDeduplication",{id:e})}))}(e):Qn.reject({message:"Event won't be tracked, since it was previously tracked with the same deduplication id ".concat(e)})})):Qn.resolve()}function er(e){return{clickTime:Oe(),source:"web_referrer",referrer:decodeURIComponent(e)}}function tr(){var e=window.location.search.substring(1).split("&").map((function(e){return e.split("=")})).reduce(j,{}).adjust_referrer;e&&un({url:"/sdk_click",method:"POST",params:er(e)})}function nr(){var e,t,n=null===(e=navigator)||void 0===e||null===(t=e.userAgent)||void 0===t?void 0:t.toLowerCase();if(n&&!(n.length<1))return/ipad|iphone|ipod/.test(n)?Xn.iOS:n.includes("windows")?/phone|mobile/.test(n)?Xn.WindowsPhone:Xn.WindowsPC:n.includes("android")?Xn.Android:void 0}function rr(e){if(!e)return null;try{return JSON.parse(e)}catch(e){return null}}!function(e){e.Android="android",e.iOS="ios",e.WindowsPC="windows",e.WindowsPhone="windows-phone"}(Xn||(Xn={}));var or={getItem:function(e){return rr(localStorage.getItem("".concat("adjust-smart-banner",".").concat(e)))},setItem:function(e,t){t?localStorage.setItem("".concat("adjust-smart-banner",".").concat(e),JSON.stringify(t)):localStorage.removeItem("".concat("adjust-smart-banner",".").concat(e))}},ir={status:0,code:"NO_CONNECTION",message:"No internet connectivity"},ar="undefined"==typeof Promise?n(3).Promise:Promise,sr=function(){function e(){De()(this,e)}return Ne()(e,null,[{key:"xhr",value:function(e){return new ar((function(t,n){var r=new XMLHttpRequest;r.open("GET",e),[["Client-SDK","js".concat(O.version)],["Content-Type","application/json"]].forEach((function(e){var t=u()(e,2),n=t[0],o=t[1];r.setRequestHeader(n,o)})),r.onerror=function(){return n(ir)},r.onreadystatechange=function(){if(4===r.readyState){var e=r.status>=200&&r.status<300,o=rr(r.responseText);0===r.status?n(ir):e?t(o):n({status:r.status,message:o||r.responseText||""})}},r.send()}))}},{key:"encodeParams",value:function(e){return Object.keys(e).map((function(t){return[encodeURIComponent(t),encodeURIComponent(e[t])].join("=")})).join("&")}},{key:"getEndpoint",value:function(){return e.lastSuccessfulEndpoint||e.defaultEndpoint}},{key:"request",value:function(t,n){return jt((function(r){var o=r.app,i=n?"?".concat(e.encodeParams(n)):"";return e.xhr("".concat(o).concat(t).concat(i)).then((function(t){return e.lastSuccessfulEndpoint=r.app,t})).catch((function(t){throw e.lastSuccessfulEndpoint=void 0,t}))}))}}]),e}();v()(sr,"defaultEndpoint","https://app.adjust.com"),v()(sr,"lastSuccessfulEndpoint",void 0);var ur;"undefined"==typeof Promise&&n(3).Promise;function cr(e,t){return sr.request("/smart_banner",{app_web_token:e}).then((function(e){var n,r,o,i,a,s,u,c=e.find((function(e){return e.platform===t}));return c?(i=(n=c).title,a=n.description,s=n.button_label,u=n.tracker_token,i&&a&&s&&u?{appId:(null===(r=n.app)||void 0===r?void 0:r.default_store_app_id)||"",appName:(null===(o=n.app)||void 0===o?void 0:o.name)||"",position:n.position||ur.Bottom,imageUrl:n.image_url,header:i,description:a,buttonText:s,trackerToken:u,deeplinkPath:n.deeplink_path,dismissInterval:864e5}:null):null})).catch((function(e){return H.error("Network error occurred during loading Smart Banner: "+JSON.stringify(e)),null}))}!function(e){e.Top="top",e.Bottom="bottom"}(ur||(ur={}));var lr=n(4),dr=n.n(lr),fr="undefined"==typeof Promise?n(3).Promise:Promise,pr=function(){function e(t,n,r){De()(this,e),v()(this,"appTraceUrl",(function(e){return"https://www.apptrace.com/api/app/".concat(e,"/artwork_url_small")})),v()(this,"appName",void 0),v()(this,"image",void 0),v()(this,"placeholder",void 0),this.image=n,this.placeholder=r,this.appName=t.appName;var o=this.getSources(t);this.showImage(o)}return Ne()(e,[{key:"getSources",value:function(e){var t=[];return e.imageUrl&&t.push(e.imageUrl),t.push(this.appTraceUrl(e.appId)),t}},{key:"showImage",value:function(e){var t=this;return e.reduce((function(e,n){return e.catch((function(){return t.loadImage(n,t.image)}))}),fr.reject()).then((function(){t.placeholder.remove()})).catch((function(){t.image.remove(),t.placeholder.innerText=t.appName.length?t.appName[0].toUpperCase():""}))}},{key:"loadImage",value:function(e,t){return new fr((function(n,r){t.onload=n,t.onerror=r,t.src=e}))}}]),e}(),mr=function(){function e(t,n,r){De()(this,e),v()(this,"parent",document.body),v()(this,"banner",void 0),v()(this,"dismissButton",null),v()(this,"onDismiss",void 0),this.onDismiss=n,this.render(t,r)}return Ne()(e,[{key:"render",value:function(e,t){this.banner=document.createElement("div"),this.banner.setAttribute("class",dr.a.bannerContainer);var n=e.position===ur.Top?dr.a.stickyToTop:dr.a.stickyToBottom,r=e.deeplinkPath?"?deeplink=".concat(encodeURIComponent(e.deeplinkPath)):"",o="".concat(t,"/").concat(e.trackerToken).concat(r);this.banner.innerHTML=function(e,t,n,r,o){return'\n
\n
\n
\n \n
\n
\n ').concat(t,'\n
\n
\n

').concat(t,'

\n

').concat(n,'

\n
\n
{ + const attr = Adjust.getAttribution() + + if (attr) { + write('Attribution:') + write(JSON.stringify(attr, undefined, 2)) + } + })() +} + +export default init diff --git a/src/demo/get-web-uuid/get-web-uuid.html b/src/demo/get-web-uuid/get-web-uuid.html new file mode 100644 index 00000000..598c7a89 --- /dev/null +++ b/src/demo/get-web-uuid/get-web-uuid.html @@ -0,0 +1,10 @@ +
+
+ + +
+ +
+
Adjust.getWebUUID()
+
+
diff --git a/src/demo/get-web-uuid/get-web-uuid.js b/src/demo/get-web-uuid/get-web-uuid.js new file mode 100644 index 00000000..6a913ffc --- /dev/null +++ b/src/demo/get-web-uuid/get-web-uuid.js @@ -0,0 +1,16 @@ +import Adjust from '../../sdk/main' +import SimpleAction from '../simple-action' +import { write } from '../log' + +function init () { + SimpleAction('get-web-uuid', () => { + const web_uuid = Adjust.getWebUUID() + + if (web_uuid) { + write('Web UUID:') + write(web_uuid) + } + })() +} + +export default init diff --git a/src/demo/main.js b/src/demo/main.js index 7ba97e69..25e22afa 100644 --- a/src/demo/main.js +++ b/src/demo/main.js @@ -13,6 +13,8 @@ import stopInit from './stop/stop' import restartInit from './restart/restart' import gdprForgetMeInit from './gdpr-forget-me/gdpr-forget-me' import disableThirdPartySharingInit from './disable-third-party-sharing/disable-third-party-sharing' +import getWebUUID from './get-web-uuid/get-web-uuid' +import getAttribution from './get-attribution/get-attribution' function init (defaultAppConfig, defaultEventConfig) { logInit() @@ -30,6 +32,8 @@ function init (defaultAppConfig, defaultEventConfig) { restartInit() gdprForgetMeInit() disableThirdPartySharingInit() + getWebUUID() + getAttribution() } export default init diff --git a/src/index.html b/src/index.html index dad9c0b3..90d5c103 100644 --- a/src/index.html +++ b/src/index.html @@ -27,6 +27,8 @@

Web SDK Demo

${require('./demo/restart/restart.html')} ${require('./demo/gdpr-forget-me/gdpr-forget-me.html')} ${require('./demo/disable-third-party-sharing/disable-third-party-sharing.html')} + ${require('./demo/get-web-uuid/get-web-uuid.html')} + ${require('./demo/get-attribution/get-attribution.html')}
diff --git a/src/sdk/__mocks__/url-strategy.ts b/src/sdk/__mocks__/url-strategy.ts new file mode 100644 index 00000000..255fd626 --- /dev/null +++ b/src/sdk/__mocks__/url-strategy.ts @@ -0,0 +1,27 @@ +import type { BaseUrlsMap, UrlStrategy } from '../url-strategy' + +const module = jest.requireActual('../url-strategy') + +const testEndpoints = { + default: { app: 'app.default', gdpr: '' }, + india: { app: 'app.india', gdpr: '' }, + china: { app: 'app.china', gdpr: '' } +} + +const singleEndpoint = { default: { app: 'app', gdpr: 'gdpr' } } + +export const mockEndpoints = { + endpoints: testEndpoints, + singleEndpoint +} + +export function urlStrategyRetries( + sendRequest: (urls: BaseUrlsMap) => Promise, + endpoints: Partial> = mockEndpoints.endpoints +) { + return module.urlStrategyRetries(sendRequest, endpoints) +} + +export function getBaseUrlsIterator(endpoints: Partial> = mockEndpoints.singleEndpoint) { + return module.getBaseUrlsIterator(endpoints) +} diff --git a/src/sdk/__tests__/activity-state.spec.js b/src/sdk/__tests__/activity-state.spec.js index 4931fa1e..3aed37ed 100644 --- a/src/sdk/__tests__/activity-state.spec.js +++ b/src/sdk/__tests__/activity-state.spec.js @@ -1,6 +1,8 @@ import * as ActivityState from '../activity-state' import {MINUTE, SECOND} from '../constants' +jest.mock('../logger') + describe('activity state functionality', () => { const now = Date.now() @@ -315,4 +317,39 @@ describe('activity state functionality', () => { }) + describe('getting web-uuid', () => { + + it('returns actual uuid', () => { + expect(ActivityState.default.getWebUUID()).toEqual('some-uuid') + }) + + it('returns null when ActivityState is not initialised', () => { + ActivityState.default.destroy() + localStorage.clear() + + expect(ActivityState.default.getWebUUID()).toBeNull() + }) + + }) + + describe('getting attribution', () => { + + it('returns null when ActivityState is not initialised', () => { + ActivityState.default.destroy() + localStorage.clear() + + expect(ActivityState.default.getAttribution()).toBeNull() + }) + + it('returns null when not attributed', () => { + expect(ActivityState.default.getAttribution()).toBeNull() + }) + + it('returns actual attribution', () => { + ActivityState.default.current = { ...ActivityState.default.current, attribution: { adid: 'dummy-adid' } } + + expect(ActivityState.default.getAttribution()).toEqual({ adid: 'dummy-adid' }) + }) + }) + }) diff --git a/src/sdk/__tests__/event.spec.js b/src/sdk/__tests__/event.spec.js index 123fb52a..04ac74ae 100644 --- a/src/sdk/__tests__/event.spec.js +++ b/src/sdk/__tests__/event.spec.js @@ -10,6 +10,7 @@ import * as Storage from '../storage/storage' jest.mock('../http') jest.mock('../logger') +jest.mock('../url-strategy') jest.useFakeTimers() const appOptions = { @@ -20,6 +21,7 @@ const appOptions = { function expectRequest (requestConfig, timestamp) { const fullConfig = { + endpoint: 'app', ...requestConfig, params: { attempts: 1, diff --git a/src/sdk/__tests__/gdpr-forget-device.spec.js b/src/sdk/__tests__/gdpr-forget-device.spec.js index f500040b..f46b064c 100644 --- a/src/sdk/__tests__/gdpr-forget-device.spec.js +++ b/src/sdk/__tests__/gdpr-forget-device.spec.js @@ -9,6 +9,7 @@ import * as PubSub from '../pub-sub' jest.mock('../http') jest.mock('../logger') +jest.mock('../url-strategy') jest.useFakeTimers() const appOptions = { @@ -23,6 +24,7 @@ function expectRequest () { } const fullConfig = { + endpoint: 'gdpr', ...requestConfig, params: { attempts: 1, diff --git a/src/sdk/__tests__/http.spec.js b/src/sdk/__tests__/http.spec.js index fa27bc1b..9382b080 100644 --- a/src/sdk/__tests__/http.spec.js +++ b/src/sdk/__tests__/http.spec.js @@ -4,9 +4,9 @@ import * as Time from '../time' import * as ActivityState from '../activity-state' import * as PubSub from '../pub-sub' import * as Config from '../config' -import * as UrlStrategy from '../url-strategy' jest.mock('../logger') +jest.mock('../url-strategy') jest.useFakeTimers() describe('perform api requests', () => { @@ -30,9 +30,6 @@ describe('perform api requests', () => { 'queue_size=0' ].join('&') - const urlStrategyRetriesMock = sendRequestCb => sendRequestCb({ app: 'app', gdpr: 'gdpr' }) - const urlStrategyRetriesActual = UrlStrategy.urlStrategyRetries - const oldXMLHttpRequest = global.XMLHttpRequest const oldLocale = global.navigator.language const oldPlatform = global.navigator.platform @@ -47,9 +44,6 @@ describe('perform api requests', () => { Utils.setGlobalProp(global.navigator, 'platform') Utils.setGlobalProp(global.navigator, 'doNotTrack') - - jest.spyOn(UrlStrategy, 'urlStrategyRetries').mockImplementation(urlStrategyRetriesMock) - jest.spyOn(Time, 'getTimestamp').mockReturnValue('some-time') ActivityState.default.init({uuid: 'some-uuid'}) @@ -78,6 +72,7 @@ describe('perform api requests', () => { expect.assertions(1) expect(http.default({ + endpoint: 'app', url: '/some-url', params: {} })).rejects.toEqual({ @@ -102,6 +97,7 @@ describe('perform api requests', () => { expect.assertions(1) expect(http.default({ + endpoint: 'app', url: '/some-url', params: {} })).rejects.toEqual({ @@ -126,6 +122,7 @@ describe('perform api requests', () => { expect.assertions(1) expect(http.default({ + endpoint: 'app', url: '/some-url', params: {} })).resolves.toEqual({ @@ -150,6 +147,7 @@ describe('perform api requests', () => { expect.assertions(1) expect(http.default({ + endpoint: 'app', url: '/some-url', params: {} })).rejects.toEqual({ @@ -174,6 +172,7 @@ describe('perform api requests', () => { expect.assertions(1) expect(http.default({ + endpoint: 'app', url: '/some-url', params: {} })).rejects.toEqual({ @@ -198,6 +197,7 @@ describe('perform api requests', () => { expect.assertions(0) expect(http.default({ + endpoint: 'app', url: '/not-resolved-request' })).resolves.toEqual({}) @@ -228,6 +228,7 @@ describe('perform api requests', () => { expect.assertions(4) expect(http.default({ + endpoint: 'app', url: '/some-url', params: { eventToken: '567abc', @@ -263,6 +264,7 @@ describe('perform api requests', () => { expect.assertions(4) expect(http.default({ + endpoint: 'app', url: '/some-url', params: { eventToken: '567abc' @@ -305,6 +307,7 @@ describe('perform api requests', () => { expect.assertions(4) expect(http.default({ + endpoint: 'app', url: '/some-other-url', params: { bla: 'truc' @@ -349,6 +352,7 @@ describe('perform api requests', () => { expect.assertions(4) expect(http.default({ + endpoint: 'app', url: '/some-other-url', params: { bla: 'truc' @@ -375,6 +379,7 @@ describe('perform api requests', () => { expect.assertions(4) expect(http.default({ + endpoint: 'gdpr', url: '/gdpr_forget_device', method: 'POST' })).resolves.toEqual({ @@ -399,6 +404,7 @@ describe('perform api requests', () => { expect.assertions(4) expect(http.default({ + endpoint: 'app', url: '/sweet-url', params: { some: 'thing' @@ -421,46 +427,12 @@ describe('perform api requests', () => { }) }) - describe('custom url', () => { - beforeAll(() => { - jest.spyOn(UrlStrategy, 'urlStrategyRetries').mockImplementation(urlStrategyRetriesActual) - }) - - afterAll(() => { - jest.spyOn(UrlStrategy, 'urlStrategyRetries').mockImplementation(urlStrategyRetriesMock) - }) - - it('overrides base and gdpr url with custom one', () => { - Config.default.set({ customUrl: 'custom-base', ...appParams }) - - expect.assertions(4) - - expect(http.default({ - url: '/some-url' - })).resolves.toEqual({ - status: 'success', - ...response - }) - - return Utils.flushPromises() - .then(() => { - - expect(mockXHR.open).toHaveBeenCalledWith('GET', `custom-base/some-url?${defaultParamsString}`, true) - expect(mockXHR.setRequestHeader).toHaveBeenCalledWith('Client-SDK', 'jsTEST') - expect(mockXHR.send).toHaveBeenCalledWith(undefined) - - mockXHR.onreadystatechange() - - Config.default.set(appParams) - }) - }) - }) - it('excludes empty values from the request params', () => { expect.assertions(4) expect(http.default({ + endpoint: 'app', url: '/some-url', params: { some: 'thing', @@ -493,6 +465,7 @@ describe('perform api requests', () => { expect.assertions(5) expect(http.default({ + endpoint: 'app', url: '/some-url', method: 'POST', params: { @@ -535,6 +508,7 @@ describe('perform api requests', () => { }) expect(http.default({ + endpoint: 'app', url: '/session', params: { some: 'thing', @@ -564,6 +538,7 @@ describe('perform api requests', () => { }) expect(http.default({ + endpoint: 'app', url: '/attribution', params: { some: 'thing', @@ -617,6 +592,7 @@ describe('perform api requests', () => { expect.assertions(4) http.default({ + endpoint: 'app', url: '/session' }).then(result => { expect(result).toEqual({ @@ -678,6 +654,7 @@ describe('perform api requests', () => { expect.assertions(3) http.default({ + endpoint: 'app', url: '/event', params: { eventToken: 'token1' @@ -708,6 +685,7 @@ describe('perform api requests', () => { expect.assertions(3) http.default({ + endpoint: 'app', url: '/anything', params: { bla: 'truc' @@ -734,6 +712,7 @@ describe('perform api requests', () => { expect.assertions(2) http.default({ + endpoint: 'app', url: '/session' }).then(result => { expect(result).toEqual({status: 'success'}) @@ -757,6 +736,7 @@ describe('perform api requests', () => { expect.assertions(4) http.default({ + endpoint: 'app', url: '/anything', params: { bla: 'truc' @@ -788,6 +768,7 @@ describe('perform api requests', () => { expect.assertions(2) http.default({ + endpoint: 'gdpr', url: '/gdpr_forget_device' }).then(result => { expect(result).toEqual({ @@ -811,6 +792,7 @@ describe('perform api requests', () => { expect.assertions(2) http.default({ + endpoint: 'app', url: '/disable_third_party_sharing' }).then(result => { expect(result).toEqual({ diff --git a/src/sdk/__tests__/main/main-disabled.gdpr.spec.js b/src/sdk/__tests__/main/main-disabled.gdpr.spec.js index 9d823003..a22a18af 100644 --- a/src/sdk/__tests__/main/main-disabled.gdpr.spec.js +++ b/src/sdk/__tests__/main/main-disabled.gdpr.spec.js @@ -14,6 +14,7 @@ import * as GdprForgetDevice from '../../gdpr-forget-device' import * as Listeners from '../../listeners' import * as http from '../../http' import * as Scheduler from '../../scheduler' +import * as ActivityState from '../../activity-state' import AdjustInstance from '../../main.js' import Suite from './main.suite' @@ -58,6 +59,8 @@ describe('main entry point - test GDPR-Forget-Me when in initially disabled stat jest.spyOn(Listeners, 'register') jest.spyOn(Scheduler, 'delay') jest.spyOn(Scheduler, 'flush') + jest.spyOn(ActivityState.default, 'getWebUUID') + jest.spyOn(ActivityState.default, 'getAttribution') Preferences.setDisabled({reason: 'general'}) }) @@ -80,7 +83,7 @@ describe('main entry point - test GDPR-Forget-Me when in initially disabled stat it('initiates and prevents running all static methods and track event', () => { AdjustInstance.initSdk(suite.config) - expect.assertions(28) + expect.assertions(32) return Utils.flushPromises() .then(() => { @@ -181,7 +184,7 @@ describe('main entry point - test GDPR-Forget-Me when in initially disabled stat AdjustInstance.initSdk(suite.config) - expect.assertions(30) + expect.assertions(34) return Utils.flushPromises() .then(() => { @@ -230,7 +233,7 @@ describe('main entry point - test GDPR-Forget-Me when in initially disabled stat AdjustInstance.initSdk(suite.config) - expect.assertions(30) + expect.assertions(34) return Utils.flushPromises() .then(() => { diff --git a/src/sdk/__tests__/main/main-disabled.general.spec.js b/src/sdk/__tests__/main/main-disabled.general.spec.js index 691dd0b6..bd1b439d 100644 --- a/src/sdk/__tests__/main/main-disabled.general.spec.js +++ b/src/sdk/__tests__/main/main-disabled.general.spec.js @@ -13,6 +13,7 @@ import * as Preferences from '../../preferences' import * as GdprForgetDevice from '../../gdpr-forget-device' import * as Listeners from '../../listeners' import * as Scheduler from '../../scheduler' +import * as ActivityState from '../../activity-state' import AdjustInstance from '../../main.js' import Suite from './main.suite' @@ -54,6 +55,8 @@ describe('main entry point - test disable/enable when in initially disabled stat jest.spyOn(Listeners, 'destroy') jest.spyOn(Scheduler, 'delay') jest.spyOn(Scheduler, 'flush') + jest.spyOn(ActivityState.default, 'getWebUUID') + jest.spyOn(ActivityState.default, 'getAttribution') Preferences.setDisabled({ reason: 'general' }) }) diff --git a/src/sdk/__tests__/main/main-enabled.gdpr.spec.js b/src/sdk/__tests__/main/main-enabled.gdpr.spec.js index 13f02e90..0e137db2 100644 --- a/src/sdk/__tests__/main/main-enabled.gdpr.spec.js +++ b/src/sdk/__tests__/main/main-enabled.gdpr.spec.js @@ -13,6 +13,7 @@ import * as GdprForgetDevice from '../../gdpr-forget-device' import * as Listeners from '../../listeners' import * as http from '../../http' import * as Scheduler from '../../scheduler' +import * as ActivityState from '../../activity-state' import AdjustInstance from '../../main.js' import Suite from './main.suite' @@ -59,6 +60,8 @@ describe('main entry point - test GDPR-Forget-Me when in initially enabled state jest.spyOn(Listeners, 'destroy') jest.spyOn(Scheduler, 'delay') jest.spyOn(Scheduler, 'flush') + jest.spyOn(ActivityState.default, 'getWebUUID') + jest.spyOn(ActivityState.default, 'getAttribution') Preferences.setDisabled(null) }) diff --git a/src/sdk/__tests__/main/main-enabled.general.spec.js b/src/sdk/__tests__/main/main-enabled.general.spec.js index 29f64688..4320337c 100644 --- a/src/sdk/__tests__/main/main-enabled.general.spec.js +++ b/src/sdk/__tests__/main/main-enabled.general.spec.js @@ -13,6 +13,7 @@ import * as Preferences from '../../preferences' import * as GdprForgetDevice from '../../gdpr-forget-device' import * as Listeners from '../../listeners' import * as Scheduler from '../../scheduler' +import * as ActivityState from '../../activity-state' import AdjustInstance from '../../main.js' import Suite from './main.suite' @@ -54,6 +55,8 @@ describe('main entry point - test enable/disable when in initially enabled state jest.spyOn(Listeners, 'destroy') jest.spyOn(Scheduler, 'delay') jest.spyOn(Scheduler, 'flush') + jest.spyOn(ActivityState.default, 'getWebUUID') + jest.spyOn(ActivityState.default, 'getAttribution') }) afterEach(() => { @@ -234,7 +237,7 @@ describe('main entry point - test enable/disable when in initially enabled state AdjustInstance.initSdk(suite.config) - expect.assertions(28) + expect.assertions(32) return Utils.flushPromises() .then(() => { @@ -435,7 +438,7 @@ describe('main entry point - test enable/disable when in initially enabled state AdjustInstance.initSdk(suite.config) - expect.assertions(28) + expect.assertions(32) return Utils.flushPromises() .then(() => { diff --git a/src/sdk/__tests__/main/main-gdpr-disabled.gdpr.spec.js b/src/sdk/__tests__/main/main-gdpr-disabled.gdpr.spec.js index b6608b12..2ae0ca1c 100644 --- a/src/sdk/__tests__/main/main-gdpr-disabled.gdpr.spec.js +++ b/src/sdk/__tests__/main/main-gdpr-disabled.gdpr.spec.js @@ -13,6 +13,7 @@ import * as GdprForgetDevice from '../../gdpr-forget-device' import * as Listeners from '../../listeners' import * as http from '../../http' import * as Scheduler from '../../scheduler' +import * as ActivityState from '../../activity-state' import AdjustInstance from '../../main.js' import Suite from './main.suite' @@ -56,6 +57,8 @@ describe('main entry point - test GDPR-Forget-Me when in initially GDPR disabled jest.spyOn(Listeners, 'register') jest.spyOn(Scheduler, 'delay') jest.spyOn(Scheduler, 'flush') + jest.spyOn(ActivityState.default, 'getWebUUID') + jest.spyOn(ActivityState.default, 'getAttribution') Preferences.setDisabled({reason: 'gdpr'}) }) @@ -79,7 +82,7 @@ describe('main entry point - test GDPR-Forget-Me when in initially GDPR disabled AdjustInstance.initSdk(suite.config) - expect.assertions(28) + expect.assertions(32) return Utils.flushPromises() .then(() => { @@ -173,7 +176,7 @@ describe('main entry point - test GDPR-Forget-Me when in initially GDPR disabled AdjustInstance.initSdk(suite.config) - expect.assertions(30) + expect.assertions(34) return Utils.flushPromises() .then(() => { @@ -222,7 +225,7 @@ describe('main entry point - test GDPR-Forget-Me when in initially GDPR disabled AdjustInstance.initSdk(suite.config) - expect.assertions(30) + expect.assertions(34) return Utils.flushPromises() .then(() => { diff --git a/src/sdk/__tests__/main/main.storage-available.spec.js b/src/sdk/__tests__/main/main.storage-available.spec.js index 490de711..197651e8 100644 --- a/src/sdk/__tests__/main/main.storage-available.spec.js +++ b/src/sdk/__tests__/main/main.storage-available.spec.js @@ -12,6 +12,7 @@ import * as Attribution from '../../attribution' import * as Storage from '../../storage/storage' import * as Listeners from '../../listeners' import * as Scheduler from '../../scheduler' +import * as ActivityState from '../../activity-state' import AdjustInstance from '../../main' import OtherInstance from '../../main' import Suite from './main.suite' @@ -49,6 +50,8 @@ describe('main entry point - test instance initiation when storage is available' jest.spyOn(Listeners, 'register') jest.spyOn(Listeners, 'destroy') jest.spyOn(Scheduler, 'flush') + jest.spyOn(ActivityState.default, 'getWebUUID') + jest.spyOn(ActivityState.default, 'getAttribution') sessionWatchSpy = jest.spyOn(Session, 'watch') }) diff --git a/src/sdk/__tests__/main/main.suite.js b/src/sdk/__tests__/main/main.suite.js index 825f6834..9e45b4be 100644 --- a/src/sdk/__tests__/main/main.suite.js +++ b/src/sdk/__tests__/main/main.suite.js @@ -106,7 +106,7 @@ function expectDelayedTrackEvent_Async () { .then(() => { PubSub.publish('sdk:installed') jest.runOnlyPendingTimers() - + expect(Logger.default.log).toHaveBeenLastCalledWith('Delayed track event task is running now') expect(event.default).toHaveBeenCalledWith({eventToken: 'bla123'}, expect.any(Number)) @@ -164,6 +164,12 @@ function expectNotRunningTrackEventWhenNoStorage () { function expectRunningStatic () { + _instance.getWebUUID() + expect(ActivityState.default.getWebUUID).toHaveBeenCalled() + + _instance.getAttribution() + expect(ActivityState.default.getAttribution).toHaveBeenCalled() + const params = [ {key: 'key1', value: 'value1'}, {key: 'key2', value: 'value2'} @@ -193,11 +199,19 @@ function expectRunningStatic () { _instance.switchToOfflineMode() expect(Queue.setOffline).toHaveBeenCalledWith(true) - return {assertions: 8} + return {assertions: 10} } function expectNotRunningStatic () { + _instance.getWebUUID() + expect(Logger.default.log).toHaveBeenLastCalledWith('Adjust SDK is disabled, can not get web_uuid') + expect(ActivityState.default.getWebUUID).not.toHaveBeenCalled() + + _instance.getAttribution() + expect(Logger.default.log).toHaveBeenLastCalledWith('Adjust SDK is disabled, can not get attribution') + expect(ActivityState.default.getAttribution).not.toHaveBeenCalled() + _instance.addGlobalCallbackParameters([{key: 'key', value: 'value'}]) expect(Logger.default.log).toHaveBeenLastCalledWith('Adjust SDK is disabled, can not add global callback parameters') @@ -233,7 +247,7 @@ function expectNotRunningStatic () { expect(Logger.default.log).toHaveBeenLastCalledWith('Adjust SDK is disabled, can not set offline mode') expect(Queue.setOffline).not.toHaveBeenCalled() - return {assertions: 14} + return {assertions: 18} } function expectNotRunningStaticWhenNoStorage () { diff --git a/src/sdk/__tests__/request.spec.js b/src/sdk/__tests__/request.spec.js index 09abc905..6ba4995a 100644 --- a/src/sdk/__tests__/request.spec.js +++ b/src/sdk/__tests__/request.spec.js @@ -3,9 +3,11 @@ import * as http from '../http' import * as Time from '../time' import * as Logger from '../logger' import * as Listeners from '../listeners' +import * as UrlStartegy from '../url-strategy' jest.mock('../http') jest.mock('../logger') +jest.mock('../url-strategy') jest.useFakeTimers() describe('test request functionality', () => { @@ -61,6 +63,7 @@ describe('test request functionality', () => { jest.runOnlyPendingTimers() expect(http.default).toHaveBeenCalledWith({ + endpoint: 'app', url: '/global-request', method: 'GET', params: { @@ -98,6 +101,7 @@ describe('test request functionality', () => { jest.runOnlyPendingTimers() expect(http.default).toHaveBeenCalledWith({ + endpoint: 'app', url: '/global-request', method: 'GET', params: { @@ -218,6 +222,7 @@ describe('test request functionality', () => { expect(http.default).toHaveBeenCalledTimes(1) expect(http.default).toHaveBeenLastCalledWith({ + endpoint: 'app', url: '/other-request', method: 'POST', params: { @@ -238,6 +243,7 @@ describe('test request functionality', () => { expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 1300) expect(http.default).toHaveBeenCalledTimes(2) expect(http.default).toHaveBeenLastCalledWith({ + endpoint: 'app', url: '/other-request', method: 'POST', params: { @@ -261,6 +267,7 @@ describe('test request functionality', () => { expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 1300) expect(http.default).toHaveBeenCalledTimes(1) expect(http.default).toHaveBeenLastCalledWith({ + endpoint: 'app', url: '/other-request', method: 'POST', params: { @@ -292,6 +299,7 @@ describe('test request functionality', () => { jest.runOnlyPendingTimers() expect(http.default).toHaveBeenCalledWith({ + endpoint: 'app', url: '/global-request', method: 'GET', params: { @@ -336,6 +344,7 @@ describe('test request functionality', () => { expect(http.default).toHaveBeenCalledTimes(1) expect(http.default).toHaveBeenLastCalledWith({ + endpoint: 'app', url: '/some-request', method: 'POST', params: { @@ -357,6 +366,7 @@ describe('test request functionality', () => { expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 666) expect(http.default).toHaveBeenCalledTimes(2) expect(http.default).toHaveBeenLastCalledWith({ + endpoint: 'app', url: '/some-request', method: 'POST', params: { @@ -379,6 +389,7 @@ describe('test request functionality', () => { expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 777) expect(http.default).toHaveBeenCalledTimes(1) expect(http.default).toHaveBeenLastCalledWith({ + endpoint: 'app', url: '/some-request', method: 'POST', params: { @@ -407,6 +418,7 @@ describe('test request functionality', () => { jest.runOnlyPendingTimers() expect(http.default).toHaveBeenCalledWith({ + endpoint: 'app', url: '/global-request', method: 'GET', params: { @@ -580,7 +592,6 @@ describe('test request functionality', () => { }) it('retires unsuccessful request because of no connection without back-off', () => { - const newNow = Date.now() const matchLocalCreatedAt = (attempts) => ({ params: { @@ -855,6 +866,7 @@ describe('test request functionality', () => { jest.runOnlyPendingTimers() expect(http.default).toHaveBeenCalledWith({ + endpoint: 'app', url: '/global-request', method: 'GET', params: { @@ -1031,6 +1043,7 @@ describe('test request functionality', () => { jest.runOnlyPendingTimers() expect(http.default).toHaveBeenCalledWith({ + endpoint: 'app', url: '/global-request', method: 'GET', params: { @@ -1092,6 +1105,7 @@ describe('test request functionality', () => { jest.runOnlyPendingTimers() expect(http.default).toHaveBeenCalledWith({ + endpoint: 'app', url: '/another-failed-request', method: 'GET', params: { @@ -1202,6 +1216,7 @@ describe('test request functionality', () => { jest.runOnlyPendingTimers() expect(http.default).toHaveBeenCalledWith({ + endpoint: 'app', url: '/another-global-request', method: 'GET', params: { @@ -1230,6 +1245,7 @@ describe('test request functionality', () => { jest.runOnlyPendingTimers() expect(http.default).toHaveBeenCalledWith({ + endpoint: 'app', url: '/new-url', method: 'POST', params: { @@ -1283,6 +1299,7 @@ describe('test request functionality', () => { jest.runOnlyPendingTimers() expect(http.default).toHaveBeenCalledWith({ + endpoint: 'app', url: '/another-global-request', method: 'GET', params: { @@ -1318,6 +1335,7 @@ describe('test request functionality', () => { jest.runOnlyPendingTimers() expect(http.default).toHaveBeenCalledWith({ + endpoint: 'app', url: '/another-global-request', method: 'GET', params: { @@ -1342,6 +1360,7 @@ describe('test request functionality', () => { jest.runOnlyPendingTimers() expect(http.default).toHaveBeenCalledWith({ + endpoint: 'app', url: '/another-global-request', method: 'GET', params: { @@ -1383,4 +1402,258 @@ describe('test request functionality', () => { }) + describe('url startegy retries functionality', () => { + const testEndpoints = jest.requireMock('../url-strategy').mockEndpoints.endpoints + + // let getBaseUrlsIterator to return pre-created iterator so it's possible to spy iterator methods + const iterator = jest.requireActual(('../url-strategy')).getBaseUrlsIterator(testEndpoints) + + const expectHttpCall = (times, endpoint, url) => { + expect(http.default).toHaveBeenCalledTimes(times) + expect(http.default).toHaveBeenCalledWith({ + endpoint: endpoint, + url: url, + method: 'GET', + params: { + attempts: times, + createdAt: now + } + }) + } + + const clearIteratorMock = (iterator) => { + jest.spyOn(iterator, 'next').mockClear() + jest.spyOn(iterator, 'reset').mockClear() + } + + beforeAll(() => { + jest.spyOn(UrlStartegy, 'getBaseUrlsIterator').mockImplementation(() => iterator) + jest.spyOn(iterator, 'next') + jest.spyOn(iterator, 'reset') + + createdAtSpy.mockReturnValue(now) + }) + + afterEach(() => { + jest.clearAllMocks() + iterator.reset() + }) + + afterAll(() => { + jest.clearAllTimers() + jest.restoreAllMocks() + }) + + it('does not retries if request succesfully sent', () => { + Request + .default({ + url: '/global-request', + params: { + some: 'param' + } + }) + .send() + + expect.assertions(9) + + expect(UrlStartegy.getBaseUrlsIterator).toHaveBeenCalled() + expect(iterator.next).toHaveBeenCalledTimes(1) + expect(iterator.next).toHaveReturnedWith({ value: testEndpoints.default, done: false }) + + expect(Logger.default.log).toHaveBeenLastCalledWith('Trying request /global-request in 150ms') + + jest.runOnlyPendingTimers() + + expect(http.default).toHaveBeenCalledWith({ + endpoint: 'app.default', + url: '/global-request', + method: 'GET', + params: { + attempts: 1, + createdAt: now, + some: 'param' + } + }) + + return Utils.flushPromises() + .then(() => { + expect(Logger.default.log).toHaveBeenCalledWith('Request /global-request has been finished') + + // iterator was reset and next called in request successful callback + expect(iterator.next).toHaveBeenCalledTimes(2) + expect(iterator.next).toHaveReturnedTimes(2) + expect(iterator.next).toHaveReturnedWith({ value: testEndpoints.default, done: false }) + }) + }) + + it('retries to send request to endpoints iteratively and stops to iterate when connected succesfully', () => { + http.default.mockRejectedValue(Utils.errorResponse('NO_CONNECTION')) + + Request + .default({ url: '/global-request' }) + .send() + + expect.assertions(38) + + expect(UrlStartegy.getBaseUrlsIterator).toHaveBeenCalled() + expect(iterator.next).toHaveReturnedWith({ value: testEndpoints.default, done: false }) + clearIteratorMock(iterator) + + expect(Logger.default.log).toHaveBeenLastCalledWith('Trying request /global-request in 150ms') + + jest.runOnlyPendingTimers() + + expectHttpCall(1, 'app.default', '/global-request') + + return Utils.flushPromises() + .then(() => { + expect(iterator.next).toHaveReturnedWith({ value: testEndpoints.india, done: false }) + clearIteratorMock(iterator) + + expect(Logger.default.log).toHaveBeenLastCalledWith('Re-trying request /global-request in 150ms') + + jest.runOnlyPendingTimers() + + expectHttpCall(2, 'app.india', '/global-request') + + return Utils.flushPromises() + }) + .then(() => { + expect(iterator.next).toHaveReturnedWith({ value: testEndpoints.china, done: false }) + clearIteratorMock(iterator) + + expect(Logger.default.log).toHaveBeenLastCalledWith('Re-trying request /global-request in 150ms') + + jest.runOnlyPendingTimers() + + expectHttpCall(3, 'app.china', '/global-request') + + return Utils.flushPromises() + }).then(() => { + expect(iterator.next).toHaveReturnedWith({ value: undefined, done: true }) + expect(iterator.reset).toHaveBeenCalled() + expect(iterator.next).toHaveReturnedWith({ value: testEndpoints.default, done: false }) + clearIteratorMock(iterator) + + expect(Logger.default.log).toHaveBeenLastCalledWith('Re-trying request /global-request in 60000ms') + + jest.runOnlyPendingTimers() + + expectHttpCall(4, 'app.default', '/global-request') + + return Utils.flushPromises() + }).then(() => { + expect(iterator.next).toHaveReturnedWith({ value: testEndpoints.india, done: false }) + clearIteratorMock(iterator) + + expect(Logger.default.log).toHaveBeenLastCalledWith('Re-trying request /global-request in 150ms') + + jest.runOnlyPendingTimers() + + expectHttpCall(5, 'app.india', '/global-request') + + return Utils.flushPromises() + }) + .then(() => { + expect(iterator.next).toHaveReturnedWith({ value: testEndpoints.china, done: false }) + clearIteratorMock(iterator) + + expect(Logger.default.log).toHaveBeenLastCalledWith('Re-trying request /global-request in 150ms') + + jest.runOnlyPendingTimers() + + expectHttpCall(6, 'app.china', '/global-request') + + return Utils.flushPromises() + }).then(() => { + expect(iterator.next).toHaveReturnedWith({ value: undefined, done: true }) + expect(iterator.reset).toHaveBeenCalled() + expect(iterator.next).toHaveReturnedWith({ value: testEndpoints.default, done: false }) + clearIteratorMock(iterator) + + expect(Logger.default.log).toHaveBeenLastCalledWith('Re-trying request /global-request in 60000ms') + + jest.runOnlyPendingTimers() + + expectHttpCall(7, 'app.default', '/global-request') + + http.default.mockResolvedValue({}) // let http successfully resolve next time + + return Utils.flushPromises() + }) + .then(() => { + expect(iterator.next).toHaveReturnedWith({ value: testEndpoints.india, done: false }) + clearIteratorMock(iterator) + + expect(Logger.default.log).toHaveBeenLastCalledWith('Re-trying request /global-request in 150ms') + + jest.runOnlyPendingTimers() + + expectHttpCall(8, 'app.india', '/global-request') + + return Utils.flushPromises() + }) + .then(() => { + + jest.runOnlyPendingTimers() + + expect(Logger.default.log).toHaveBeenCalledWith('Request /global-request has been finished') + }) + }) + + it('does not iterate endpoints if another error happened', () => { + http.default.mockRejectedValue(Utils.errorResponse('UNKNOWN')) + + Request + .default({ url: '/global-request' }) + .send() + + expect.assertions(14) + + expect(UrlStartegy.getBaseUrlsIterator).toHaveBeenCalled() + expect(iterator.next).toHaveReturnedWith({ value: testEndpoints.default, done: false }) + clearIteratorMock(iterator) + + expect(Logger.default.log).toHaveBeenLastCalledWith('Trying request /global-request in 150ms') + + jest.runOnlyPendingTimers() + + expectHttpCall(1, 'app.default', '/global-request') + + return Utils.flushPromises() + .then(() => { + expect(iterator.next).not.toHaveBeenCalled() + clearIteratorMock(iterator) + + expect(Logger.default.log).toHaveBeenLastCalledWith('Re-trying request /global-request in 100ms') // 100ms is because of back-off + + jest.runOnlyPendingTimers() + + expectHttpCall(2, 'app.default', '/global-request') + + http.default.mockResolvedValue({}) // let http successfully resolve next time + + return Utils.flushPromises() + }) + .then(() => { + expect(iterator.next).not.toHaveBeenCalled() + clearIteratorMock(iterator) + + expect(Logger.default.log).toHaveBeenLastCalledWith('Re-trying request /global-request in 200ms') + + jest.runOnlyPendingTimers() + + expectHttpCall(3, 'app.default', '/global-request') + + return Utils.flushPromises() + }) + .then(() => { + jest.runOnlyPendingTimers() + + expect(Logger.default.log).toHaveBeenCalledWith('Request /global-request has been finished') + }) + }) + + }) + }) diff --git a/src/sdk/__tests__/sdk-click.spec.js b/src/sdk/__tests__/sdk-click.spec.js index 1ec508fc..7a01626b 100644 --- a/src/sdk/__tests__/sdk-click.spec.js +++ b/src/sdk/__tests__/sdk-click.spec.js @@ -6,6 +6,7 @@ import * as ActivityState from '../activity-state' jest.mock('../http') jest.mock('../logger') +jest.mock('../url-strategy') jest.useFakeTimers() describe('test sdk-click functionality', () => { @@ -63,6 +64,7 @@ describe('test sdk-click functionality', () => { } const fullConfig = { + endpoint: 'app', ...requestConfig, params: { attempts: 1, diff --git a/src/sdk/__tests__/session.spec.js b/src/sdk/__tests__/session.spec.js index 34a7befd..a004961c 100644 --- a/src/sdk/__tests__/session.spec.js +++ b/src/sdk/__tests__/session.spec.js @@ -14,6 +14,7 @@ import {MINUTE, SECOND} from '../constants' jest.mock('../logger') jest.mock('../http') +jest.mock('../url-strategy') jest.useFakeTimers() function goToForeground () { @@ -372,6 +373,7 @@ describe('test session functionality', () => { jest.runOnlyPendingTimers() expect(http.default).toHaveBeenCalledWith({ + endpoint: 'app', url: '/session', method: 'POST', params: { @@ -442,6 +444,7 @@ describe('test session functionality', () => { jest.advanceTimersByTime(150) expect(http.default).toHaveBeenCalledWith({ + endpoint: 'app', url: '/session', method: 'POST', params: { @@ -776,6 +779,7 @@ describe('test session functionality', () => { jest.runOnlyPendingTimers() expect(http.default).toHaveBeenCalledWith({ + endpoint: 'app', url: '/session', method: 'POST', params: { @@ -847,6 +851,7 @@ describe('test session functionality', () => { jest.runOnlyPendingTimers() expect(http.default).toHaveBeenCalledWith({ + endpoint: 'app', url: '/session', method: 'POST', params: { @@ -950,6 +955,7 @@ describe('test session functionality', () => { jest.runOnlyPendingTimers() expect(http.default).toHaveBeenCalledWith({ + endpoint: 'app', url: '/session', method: 'POST', params: { diff --git a/src/sdk/__tests__/smart-banner/network/network.spec.ts b/src/sdk/__tests__/smart-banner/network/network.spec.ts index 1a57c8ea..c8cd538a 100644 --- a/src/sdk/__tests__/smart-banner/network/network.spec.ts +++ b/src/sdk/__tests__/smart-banner/network/network.spec.ts @@ -1,25 +1,17 @@ import { NetworkError, NoConnectionError } from '../../../smart-banner/network/errors' -import * as UrlStrategy from '../../../url-strategy' jest.mock('../../../logger') +jest.mock('../../../url-strategy') + +const UrlStartegyMock = jest.requireMock('../../../url-strategy') +const testEndpoints = UrlStartegyMock.mockEndpoints.endpoints describe('Network tests', () => { const defaultEndpoint = 'https://app.adjust.com' let Network let xhrMock: jest.SpyInstance - const testEndpoints = { - default: { app: 'app.default', gdpr: '' }, - india: { app: 'app.india', gdpr: '' }, - china: { app: 'app.china', gdpr: '' } - } - const urlStrategyRetriesActual = UrlStrategy.urlStrategyRetries - const urlStrategyRetriesMock = (sendRequestCb: (urls: UrlStrategy.BaseUrlsMap) => Promise) => urlStrategyRetriesActual(sendRequestCb, testEndpoints) - beforeEach(() => { - const UrlStrategyModule = require('../../../url-strategy') - jest.spyOn(UrlStrategyModule, 'urlStrategyRetries').mockImplementation(urlStrategyRetriesMock) - Network = require('../../../smart-banner/network/network').Network xhrMock = jest.spyOn(Network, 'xhr') }) diff --git a/src/sdk/__tests__/third-party-sharing.spec.js b/src/sdk/__tests__/third-party-sharing.spec.js index 0ab906c6..2c6aace8 100644 --- a/src/sdk/__tests__/third-party-sharing.spec.js +++ b/src/sdk/__tests__/third-party-sharing.spec.js @@ -9,6 +9,7 @@ import * as Preferences from '../preferences' jest.mock('../http') jest.mock('../logger') +jest.mock('../url-strategy') jest.useFakeTimers() const appOptions = { @@ -23,6 +24,7 @@ function expectRequest () { } const fullConfig = { + endpoint: 'app', ...requestConfig, params: { attempts: 1, diff --git a/src/sdk/__tests__/url-strategy.spec.ts b/src/sdk/__tests__/url-strategy.spec.ts index 21a395b8..191fa544 100644 --- a/src/sdk/__tests__/url-strategy.spec.ts +++ b/src/sdk/__tests__/url-strategy.spec.ts @@ -1,65 +1,69 @@ -import { UrlStrategy, urlStrategyRetries } from '../url-strategy' +import { UrlStrategy, urlStrategyRetries, getBaseUrlsIterator, BaseUrlsMap, BaseUrlsIterator } from '../url-strategy' import * as Globals from '../globals' jest.mock('../logger') describe('test url strategy', () => { + const testEndpoints = { + default: { + app: 'app.default', + gdpr: 'gdpr.default' + }, + india: { + app: 'app.india', + gdpr: 'gdpr.india' + }, + china: { + app: 'app.china', + gdpr: 'gdpr.china' + } + } - describe('development environment', () => { - let Config + let Config - const options = { - appToken: '123abc', - environment: 'sandbox' - } + const options = { + appToken: '123abc', + environment: 'sandbox' + } - const sendRequestMock = jest.fn(() => Promise.reject({ code: 'NO_CONNECTION' })) - - const testEndpoints = { - default: { - app: 'app.default', - gdpr: 'gdpr.default' - }, - india: { - app: 'app.india', - gdpr: 'gdpr.india' - }, - china: { - app: 'app.china', - gdpr: 'gdpr.china' - } - } + const sendRequestMock = jest.fn(() => Promise.reject({ code: 'NO_CONNECTION' })) - const env = Globals.default.env + const env = Globals.default.env - beforeAll(() => { - Globals.default.env = 'development' - }) + beforeAll(() => { + Globals.default.env = 'development' + }) - beforeEach(() => { - Config = require('../config').default - }) + beforeEach(() => { + Config = require('../config').default + }) - afterEach(() => { - Config.destroy() - jest.clearAllMocks() - }) + afterEach(() => { + Config.destroy() + jest.clearAllMocks() + }) - afterAll(() => { - Globals.default.env = env - jest.restoreAllMocks() - }) + afterAll(() => { + Globals.default.env = env + jest.restoreAllMocks() + }) + + describe('Promise-based urlStrategyRetries tests', () => { it('does not override custom url', () => { const customUrl = 'custom-url' Config.set({ ...options, customUrl }) + expect.assertions(2) + return urlStrategyRetries(sendRequestMock, testEndpoints) .catch(reason => expect(reason).toEqual({ code: 'NO_CONNECTION' })) .then(() => expect(sendRequestMock).toHaveBeenCalledWith({ app: customUrl, gdpr: customUrl })) }) - it('retries send requesrt to endpoints iteratively', () => { + it('retries to send request to endpoints iteratively', () => { + expect.assertions(5) + return urlStrategyRetries(sendRequestMock, testEndpoints) .catch(reason => expect(reason).toEqual({ code: 'NO_CONNECTION' })) .then(() => { @@ -73,6 +77,8 @@ describe('test url strategy', () => { it('prefers Indian enpoint and does not try reach Chinese one when india url strategy set', () => { Config.set({ ...options, urlStrategy: UrlStrategy.India }) + expect.assertions(4) + return urlStrategyRetries(sendRequestMock, testEndpoints) .catch(reason => expect(reason).toEqual({ code: 'NO_CONNECTION' })) .then(() => { @@ -85,6 +91,8 @@ describe('test url strategy', () => { it('prefers Chinese enpoint and does not try reach Indian one when china url strategy set', () => { Config.set({ ...options, urlStrategy: UrlStrategy.China }) + expect.assertions(4) + return urlStrategyRetries(sendRequestMock, testEndpoints) .catch(reason => expect(reason).toEqual({ code: 'NO_CONNECTION' })) .then(() => { @@ -99,6 +107,8 @@ describe('test url strategy', () => { .mockImplementationOnce(() => Promise.reject({ code: 'NO_CONNECTION' })) .mockImplementationOnce(() => Promise.resolve()) + expect.assertions(1) + return urlStrategyRetries(sendRequestMock, testEndpoints) .then(() => expect(sendRequestMock).toHaveBeenCalledTimes(2)) }) @@ -106,8 +116,111 @@ describe('test url strategy', () => { it('does not iterate endpoints if another error happened', () => { const sendRequestMock = jest.fn(() => Promise.reject({ code: 'UNKNOWN' })) + expect.assertions(1) + return urlStrategyRetries(sendRequestMock, testEndpoints) .catch(() => expect(sendRequestMock).toHaveBeenCalledTimes(1)) }) + + }) + + describe('BaseUrlsIterator tests', () => { + + const numberOfIterations = Object.keys(testEndpoints).length + + const iterateThrough = (iterator: BaseUrlsIterator, iterationsNumber?: number) => { + const results: BaseUrlsMap[] = [] + let current + let steps = iterationsNumber === undefined ? -1 : iterationsNumber + + do { + current = iterator.next() + if (current.value) { + results.push(current.value) + } + } while (!current.done && --steps !== 0) + + return results + } + + it('returns all values through iteration when default url startegy used', () => { + const iterator = getBaseUrlsIterator(testEndpoints) + + expect(iterator.next()).toEqual({value: testEndpoints.default, done: false}) + expect(iterator.next()).toEqual({value: testEndpoints.india, done: false}) + expect(iterator.next()).toEqual({value: testEndpoints.china, done: false}) + expect(iterator.next()).toEqual({value: undefined, done: true}) + }) + + it('prefers Indian enpoint and does not try reach Chinese one when india url strategy set', () => { + Config.set({ ...options, urlStrategy: UrlStrategy.India }) + + const values = iterateThrough(getBaseUrlsIterator(testEndpoints)) + + expect(values.length).toEqual(2) + expect(values[0]).toEqual(testEndpoints.india) + expect(values[1]).toEqual(testEndpoints.default) + }) + + it('prefers Chinese enpoint and does not try reach Indian one when china url strategy set', () => { + Config.set({ ...options, urlStrategy: UrlStrategy.China }) + + const values = iterateThrough(getBaseUrlsIterator(testEndpoints)) + + expect(values.length).toEqual(2) + expect(values[0]).toEqual(testEndpoints.china) + expect(values[1]).toEqual(testEndpoints.default) + }) + + it('does not override custom url', () => { + const customUrl = 'custom-url' + Config.set({ ...options, customUrl }) + + const values = iterateThrough(getBaseUrlsIterator(testEndpoints)) + + expect(values.length).toEqual(1) + expect(values[0]).toEqual({ app: 'custom-url', gdpr: 'custom-url' }) + }) + + describe('reset allows to restart iteration', () => { + + it('iterate through all endpoints twice', () => { + const iterator = getBaseUrlsIterator(testEndpoints) + + const first = iterateThrough(iterator) + + iterator.reset() + + const second = iterateThrough(iterator) + + expect(first.length).toEqual(numberOfIterations) + expect(second.length).toEqual(numberOfIterations) + expect(second).toEqual(first) + }) + + it('iterate partially then reset', () => { + const iterator = getBaseUrlsIterator(testEndpoints) + + const firstIteration = iterateThrough(iterator, 1) + iterator.reset() + const secondIteration = iterateThrough(iterator, 2) + iterator.reset() + const thirdIteration = iterateThrough(iterator, 3) + iterator.reset() + + expect(firstIteration.length).toEqual(1) + expect(secondIteration.length).toEqual(2) + expect(thirdIteration.length).toEqual(3) + + expect(firstIteration[0]).toEqual(testEndpoints.default) + expect(secondIteration[0]).toEqual(testEndpoints.default) + expect(thirdIteration[0]).toEqual(testEndpoints.default) + + expect(secondIteration[1]).toEqual(testEndpoints.india) + expect(thirdIteration[1]).toEqual(testEndpoints.india) + + expect(thirdIteration[2]).toEqual(testEndpoints.china) + }) + }) }) }) diff --git a/src/sdk/activity-state.js b/src/sdk/activity-state.js index feedfe44..7e35d2ee 100644 --- a/src/sdk/activity-state.js +++ b/src/sdk/activity-state.js @@ -2,12 +2,14 @@ import { type UrlT, type ActivityStateMapT, + type AttributionMapT, type CommonRequestParams } from './types' import {SECOND} from './constants' import {timePassed} from './time' import {isRequest} from './utilities' import Config from './config' +import Logger from './logger' /** * Reference to the activity state @@ -308,6 +310,27 @@ function destroy (): void { _active = false } +function getAttribution (): AttributionMapT | null { + if (!_started) { + return null + } + + if (!_activityState.attribution) { + Logger.log('No attribution data yet') + return null + } + + return _activityState.attribution +} + +function getWebUUID (): string { + if (!_started) { + return null + } + + return _activityState.uuid +} + const ActivityState = { get current () { return currentGetter() }, set current (value) { currentSetter(value) }, @@ -323,7 +346,9 @@ const ActivityState = { updateSessionLength, resetSessionOffset, updateLastActive, - destroy + destroy, + getAttribution, + getWebUUID } export default ActivityState diff --git a/src/sdk/http.js b/src/sdk/http.js index 8dd51ac8..7f32e5d4 100644 --- a/src/sdk/http.js +++ b/src/sdk/http.js @@ -14,7 +14,6 @@ import Logger from './logger' import {isObject, isValidJson, isRequest, entries, isEmptyEntry, reducer} from './utilities' import {publish} from './pub-sub' import defaultParams from './default-params' -import {urlStrategyRetries, BaseUrlsMap} from './url-strategy' type ParamsWithAttemptsT = $PropertyType @@ -175,13 +174,11 @@ function _handleReadyStateChange (reject, resolve, {xhr, url}: {xhr: XMLHttpRequ * @returns {{encodedParams: string, fullUrl: string}} * @private */ -function _prepareUrlAndParams ({url, method, params}: HttpRequestParamsT, defaultParams: DefaultParamsT, baseUrlsMap: BaseUrlsMap): {fullUrl: string, encodedParams: string} { +function _prepareUrlAndParams ({endpoint, url, method, params}: HttpRequestParamsT, defaultParams: DefaultParamsT): {fullUrl: string, encodedParams: string} { const encodedParams = _encodeParams(params, defaultParams) - const base = url === '/gdpr_forget_device' ? 'gdpr' : 'app' - const baseUrl = baseUrlsMap[base] return { - fullUrl: baseUrl + url + (method === 'GET' ? `?${encodedParams}` : ''), + fullUrl: endpoint + url + (method === 'GET' ? `?${encodedParams}` : ''), encodedParams } } @@ -217,8 +214,8 @@ function _prepareHeaders (xhr: XMLHttpRequest, method: $PropertyType { - const {fullUrl, encodedParams} = _prepareUrlAndParams({url, method, params}, defaultParams, baseUrlsMap) +function _buildXhr ({endpoint, url, method = 'GET', params = {}}: HttpRequestParamsT, defaultParams: DefaultParamsT): Promise { + const {fullUrl, encodedParams} = _prepareUrlAndParams({endpoint, url, method, params}, defaultParams) return new Promise((resolve, reject) => { let xhr = new XMLHttpRequest() @@ -232,10 +229,6 @@ function _buildXhr ({url, method = 'GET', params = {}}: HttpRequestParamsT, defa }) } -function _sendRequestWithUrlStrategyRetries (options: HttpRequestParamsT, defaultParams: DefaultParamsT) { - return urlStrategyRetries(baseUrlsMap => _buildXhr(options, defaultParams, baseUrlsMap)) -} - /** * Intercept response from backend * @@ -302,6 +295,6 @@ function _interceptSuccess (result: HttpSuccessResponseT, url): HttpSuccessRespo */ export default function http (options: HttpRequestParamsT): Promise { return defaultParams() - .then(defaultParams => _sendRequestWithUrlStrategyRetries(options, defaultParams)) + .then(defaultParams => _buildXhr(options, defaultParams)) .then(result => _interceptResponse(result, options.url)) } diff --git a/src/sdk/main.js b/src/sdk/main.js index d8f97185..4c2d44b6 100644 --- a/src/sdk/main.js +++ b/src/sdk/main.js @@ -6,7 +6,8 @@ import { type GlobalParamsT, type CustomErrorT, type ActivityStateMapT, - type SmartBannerOptionsT + type SmartBannerOptionsT, + type AttributionMapT } from './types' import Config from './config' import Storage from './storage/storage' @@ -99,6 +100,24 @@ function initSdk ({logLevel, logOutput, ...options}: InitConfigT = {}): void { }) } +/** + * Get user's current attribution information + * + * @returns {AttributionMapT|undefined} current attribution information if available or `undefined` otherwise + */ +function getAttribution (): ?AttributionMapT { + return _preCheck('get attribution', () => ActivityState.getAttribution()) +} + +/** + * Get `web_uuid` - a unique ID of user generated per subdomain and per browser + * + * @returns {string|undefined} `web_uuid` if available or `undefined` otherwise + */ +function getWebUUID (): ?string { + return _preCheck('get web_uuid', () => ActivityState.getWebUUID()) +} + /** * Track event with already initiated instance * @@ -459,7 +478,7 @@ function _start (options: InitOptionsT): void { * @param {boolean=false} schedule * @private */ -function _preCheck (description: string, callback: () => mixed, {schedule, stopBeforeInit}: {schedule?: boolean, stopBeforeInit?: boolean} = {}) { +function _preCheck (description: string, callback: () => mixed, {schedule, stopBeforeInit}: {schedule?: boolean, stopBeforeInit?: boolean} = {}): mixed { if (Storage.getType() === STORAGE_TYPES.NO_STORAGE) { Logger.log(`Adjust SDK can not ${description}, no storage available`) return @@ -480,7 +499,7 @@ function _preCheck (description: string, callback: () => mixed, {schedule, stopB delay(callback, description) Logger.log(`Running ${description} is delayed until Adjust SDK is up`) } else { - callback() + return callback() } } } @@ -491,6 +510,8 @@ function _clearDatabase () { const Adjust = { initSdk, + getAttribution, + getWebUUID, trackEvent, addGlobalCallbackParameters, addGlobalPartnerParameters, diff --git a/src/sdk/request.js b/src/sdk/request.js index 70efa0f1..f07de4e9 100644 --- a/src/sdk/request.js +++ b/src/sdk/request.js @@ -17,6 +17,7 @@ import Logger from './logger' import backOff from './backoff' import {isConnected} from './listeners' import {SECOND, HTTP_ERRORS} from './constants' +import {getBaseUrlsIterator, BaseUrlsIterator, BaseUrlsMap} from './url-strategy' type RequestConfigT = {| url?: UrlT, @@ -91,6 +92,33 @@ const Request = ({url, method = 'GET', params = {}, continueCb, strategy, wait}: */ const _strategy: ?BackOffStrategyT = strategy + /** + * Url Startegy iterator to go through endpoints to retry to send request + */ + const _baseUrlsIterator: BaseUrlsIterator = getBaseUrlsIterator() + + /** + * Current base urls map to send request + */ + let _baseUrlsIteratorCurrent: { value: BaseUrlsMap, done: boolean } = _baseUrlsIterator.next() + + + /** + * Reset iterator state and get the first endpoint to use it in the next try + */ + const _resetBaseUrlsIterator = () => { + _baseUrlsIterator.reset() + _baseUrlsIteratorCurrent = _baseUrlsIterator.next() + } + + /** + * Returns base url depending on request path + */ + const _getBaseUrl = (urlsMap: BaseUrlsMap, url: UrlT): string => { + const base = url === '/gdpr_forget_device' ? 'gdpr' : 'app' + return urlsMap[base] + } + /** * Timeout id to be used for clearing * @@ -236,6 +264,7 @@ const Request = ({url, method = 'GET', params = {}, continueCb, strategy, wait}: _startAt = Date.now() return _preRequest({ + endpoint: _getBaseUrl(_baseUrlsIteratorCurrent.value, _url), url: _url, method: _method, params: { @@ -287,6 +316,7 @@ const Request = ({url, method = 'GET', params = {}, continueCb, strategy, wait}: .reduce(reducer, {}) return http({ + endpoint: options.endpoint, url: options.url, method: options.method, params: { @@ -365,6 +395,8 @@ const Request = ({url, method = 'GET', params = {}, continueCb, strategy, wait}: return } + _resetBaseUrlsIterator() + if (typeof _continueCb === 'function') { _continueCb(result, _finish, _retry) } else { @@ -384,7 +416,21 @@ const Request = ({url, method = 'GET', params = {}, continueCb, strategy, wait}: */ function _error (result: HttpErrorResponseT, resolve, reject): void { if (result && result.action === 'RETRY') { - resolve(_retry(result.code === 'NO_CONNECTION' ? NO_CONNECTION_WAIT : undefined)) + + if (result.code === 'NO_CONNECTION') { + + const nextEndpoint = _baseUrlsIterator.next() // get next endpoint + + if (!nextEndpoint.done) { // next endpoint exists + _baseUrlsIteratorCurrent = nextEndpoint // use the endpoint in the next try + resolve(_retry(DEFAULT_WAIT)) + } else { // no more endpoints, seems there is no connection at all + _resetBaseUrlsIterator() + resolve(_retry(NO_CONNECTION_WAIT)) + } + } else { + resolve(_retry()) + } return } diff --git a/src/sdk/types.js b/src/sdk/types.js index 8d8ecc3b..2775f947 100644 --- a/src/sdk/types.js +++ b/src/sdk/types.js @@ -84,6 +84,7 @@ export type RequestParamsT = $Shape<{| |}> export type HttpRequestParamsT = $ReadOnly<{| + endpoint: string, url: UrlT, method?: MethodT, params: $ReadOnly<{| diff --git a/src/sdk/url-strategy.ts b/src/sdk/url-strategy.ts index 87a263ed..2d59419d 100644 --- a/src/sdk/url-strategy.ts +++ b/src/sdk/url-strategy.ts @@ -97,4 +97,42 @@ function urlStrategyRetries( } } -export { urlStrategyRetries, UrlStrategy, BaseUrlsMap } +interface BaseUrlsIterator extends Iterator { + reset: () => void; +} + +function getPreferredUrls(endpoints: Partial>): BaseUrlsMap[] { + const preferredUrls = getEndpointPreference() + + if (!Array.isArray(preferredUrls)) { + return [preferredUrls] + } else { + const res = preferredUrls + .map(strategy => endpoints[strategy] || null) + .filter((i): i is BaseUrlsMap => !!i) + + return res + } +} + +function getBaseUrlsIterator(endpoints: Partial> = endpointMap): BaseUrlsIterator { + const _urls = getPreferredUrls(endpoints) + + let _counter = 0 + + return { + next: () => { + if (_counter < _urls.length) { + return { value: _urls[_counter++], done: false } + } else { + return { value: undefined, done: true } + } + }, + reset: () => { + _counter = 0 + } + } +} + + +export { urlStrategyRetries, getBaseUrlsIterator, BaseUrlsIterator, UrlStrategy, BaseUrlsMap }