@global-savings-group/caa-engine
Advanced tools
Comparing version 4.1.1 to 4.1.2
@@ -7,3 +7,4 @@ export declare enum AmountType { | ||
Real = "R$", | ||
Zloty = "z\u0142" | ||
Zloty = "z\u0142", | ||
Krona = "kr" | ||
} | ||
@@ -10,0 +11,0 @@ export interface ParsedAmount { |
@@ -1,1 +0,1 @@ | ||
(()=>{"use strict";var e={d:(t,n)=>{for(var o in n)e.o(n,o)&&!e.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:n[o]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{AmountType:()=>a,BackgroundToClientMessageType:()=>ee,ClientToBackgroundMessageType:()=>Y,TestedCodeType:()=>X,getElements:()=>h,getGeneratedSelector:()=>v,getMainDomain:()=>x,setupBackgroundListeners:()=>pe,setupContentListeners:()=>Q});let n=()=>{};function o(e){n=e}const r={error:(e,t)=>n({level:"ERROR",message:e,stack:t instanceof Error&&t.stack||(new Error).stack||""}),info:e=>n({details:JSON.stringify(e),level:"INFO"}),perf:(e,t)=>n({label:e,level:"PERF",meta:t})};var a;!function(e){e.Dollar="$",e.Euro="€",e.Percent="%",e.Pound="£",e.Real="R$",e.Zloty="zł"}(a||(a={}));const i="data-caa-text";function l(e){try{const[,t=""]=e.split('"');return Object(JSON.parse(decodeURI(t)))}catch{return{}}}function c(e){return l(e)}const s=/[0-9.,]+/g;function u(e){return e?e.normalize("NFC").replaceAll(s,""):null}function d({innerText:e,tagName:t}){return function(e){try{return encodeURI(JSON.stringify(e))}catch(e){return r.error("Cannot encode a custom cssSelector: ",e),""}}({innerText:e,tagName:t})}function f(e){const{tagName:t,innerText:n}=l(e);return e.includes(i)&&"string"==typeof t&&"string"==typeof n}function p(e){return f(e)}function m(e){const t=Array.from(document.querySelectorAll(e));return f(e)?t.length>0?t.filter((n=e,function(e){const{tagName:t,innerText:o}=c(n);return e.tagName===t&&u(e.innerText)===u(o)})):function(e){const{tagName:t,innerText:n}=c(e);return Array.from(document.getElementsByTagName(t)).filter((e=>e instanceof HTMLElement)).filter((e=>u(e.innerText)===u(n))).map((e=>(e.setAttribute(i,d(e)),e)))}(e):[];var n}function y(e){try{if(p(e)){const[t=null]=m(e);return t}return document.querySelector(e)}catch(t){return r.error(`Cannot find the element in the DOM with the selector="${e}":`,t),null}}function h(e){try{return p(e)?m(e):Array.from(document.querySelectorAll(e))}catch(t){return r.error(`Cannot find elements in the DOM with the selector="${e}":`,t),[]}}function v(e){const t=function(e){return`[${i}="${d(e)}"]`}(e);return 1===h(t).length?t:null}const g=function(){try{return"object"==typeof browser&&null!==browser&&"runtime"in browser?browser:chrome}catch{return console.warn("[CAA-ENGINE]: not running in a DOM environment, the browser object is not defined."),{}}}();var b,w;async function E(e=500){return new Promise((t=>setTimeout(t,e)))}function S(e,t){return"object"==typeof e&&null!==e&&t in e}function C(e){return!S(e,"disabled")||!e.disabled}function P(e){return!!C(e)&&"none"!==window.getComputedStyle(e).getPropertyValue("pointer-events")}function T(e){if(e.hidden)return!1;const t=window.getComputedStyle(e);return"hidden"!==t.getPropertyValue("visibility")&&"0"!==t.getPropertyValue("opacity")&&"none"!==t.getPropertyValue("display")&&0!==e.offsetWidth&&0!==e.offsetHeight}function B(e){return C(e)&&P(e)&&T(e)}function A(e){return"INPUT"!==e.tagName&&!e.innerHTML.length}!function(e){e.GetPageState="caa-get-page-state",e.ApplyCode="caa-apply-code",e.RemoveCode="caa-remove-code"}(b||(b={})),function(e){e.Reloading="Reloading",e.Done="Done",e.UnhandledError="UnhandledError",e.Timeout="Timeout",e.NoRequiredSelectorsProvided="NoRequiredSelectorsProvided",e.ApplyAndRemoveButtonsHaveSameSelector="ApplyAndRemoveButtonsHaveSameSelector"}(w||(w={}));const M=1e3;function I(e=.5){return new Promise((t=>setTimeout(t,e*M)))}function $(e){e.dispatchEvent(new PointerEvent("pointerdown",{bubbles:!0,pointerType:"mouse"})),e.dispatchEvent(new MouseEvent("mousedown",{bubbles:!0})),e.dispatchEvent(new PointerEvent("pointerup",{bubbles:!0,pointerType:"mouse"})),e.dispatchEvent(new MouseEvent("mouseup",{bubbles:!0})),e.dispatchEvent(new PointerEvent("click",{bubbles:!0,cancelable:!0,pointerType:"mouse"}))}async function N(e,t=0,n=0){if(!e.closeModal)return;if(t>=4)throw w.Timeout;const o=y(e.closeModal);if(!o||!B(o)){if(t>0||n>=4)return;return await E(),N(e,t,n+1)}return r.info("Trying to close modal"),$(o),await E(),N(e,t+1)}function R(e){const t=e&&y(e);return!!t&&T(t)}const k=4;function F(e){return e.loading?function(e){const t={bodyObserver:null,isLoading:R(e)};return[new Promise((n=>{t.bodyObserver=new MutationObserver((()=>{R(e)?t.isLoading=!0:t.isLoading&&n()})),t.bodyObserver.observe(document.body,{attributes:!0,childList:!0,subtree:!0})})),()=>t.bodyObserver?.disconnect()]}(e.loading):[void 0,()=>{}]}function L(e){const[t,n]=function(e){const t={pending:!0};return[(async()=>{for(let n=0;n<k;n++){const n=[e.error,e.removeButton,e.appliedCode];if(!t.pending||n.some(R))break;r.info("Waiting for feedback"),await I()}})(),()=>{t.pending=!1}]}(e),[o,a]=F(e),i=[t,o].filter(Boolean),l=[n,a];return Promise.race(i).finally((()=>{l.forEach((e=>e()))}))}function V(e,t){const n=y(e);return!!(n&&(o=n,S(o,"value")&&B(o)))&&(r.info("Trying to fill in the code"),function(e,t){const{value:n}=e;if(e.value=t,S(e,"_valueTracker")&&e._valueTracker){const t=e._valueTracker;S(t,"setValue")&&"function"==typeof t.setValue&&t.setValue(n)}e.dispatchEvent(new KeyboardEvent("keydown",{bubbles:!0})),e.dispatchEvent(new KeyboardEvent("keypress",{bubbles:!0})),e.dispatchEvent(new KeyboardEvent("input",{bubbles:!0})),e.dispatchEvent(new KeyboardEvent("keyup",{bubbles:!0})),e.dispatchEvent(new Event("change",{bubbles:!0}))}(n,t),!0);var o}function U(e){const t=y(e);return!(!t||!B(t)||(r.info("Trying to submit the code"),$(t),0))}async function D(e,t){for(let n=0;n<10&&!(e.couponInput&&V(e.couponInput,t)&&(await E(),e.applyButton&&U(e.applyButton)));n++);}function O(e){switch(e){case w.Reloading:return w.Reloading;case w.Timeout:return w.Timeout;case w.NoRequiredSelectorsProvided:return w.NoRequiredSelectorsProvided;default:return w.UnhandledError}}function x(e){const t=e.toLowerCase().replace(/^https?:\/\//,"").replace(/:\d+.*/,"").replace(/(:|\/|\?|#).*/,"");if(!/[a-z0-9-.]+/.test(t))throw new Error(`Cannot get main domain from ${e}`);const[n,o,r]=t.split(".").reverse();if("localhost"===n)return n;if(!n||n.length<2)throw new Error(`Wrong root domain "${n}" in ${e}`);if(!o)throw new Error(`Unknown main domain "${o}" in ${e}`);if(!["co.uk","co.za","com.au","com.de","org.uk","uk.com","com.br","com.pl","com.nl","com.mx","com.at","co.at"].includes(`${o}.${n}`))return`${o}.${n}`;if(!r)throw new Error(`Unknown main domain "${r}" in ${e}`);return`${r}.${o}.${n}`}var H;function q(e){try{if(!e)return{html:"",isClickable:!1,isEmpty:!0,isEnabled:!1,isVisible:!1,multipleMatches:!1,result:H.NoSelectorProvided};const t=h(e),[n]=t;return n?{html:n.outerHTML,isClickable:Boolean(t.filter(P).length),isEmpty:A(n),isEnabled:Boolean(t.filter(C).length),isVisible:Boolean(t.filter(T).length),multipleMatches:t.length>1,result:H.ElementFound}:{html:"",isClickable:!1,isEmpty:!0,isEnabled:!1,isVisible:!1,multipleMatches:!1,result:H.NoElementsFound}}catch(e){return e instanceof Error&&"SyntaxError"===e.name?(r.error(H.InvalidCSSSelector,e),{html:"",isClickable:!1,isEmpty:!0,isEnabled:!1,isVisible:!1,multipleMatches:!1,result:H.InvalidCSSSelector}):(r.error(H.Unhandled,e),{html:"",isClickable:!1,isEmpty:!0,isEnabled:!1,isVisible:!1,multipleMatches:!1,result:H.Unhandled})}}function j(e){if(!e)return!1;const t=e.totalAmount?h(e.totalAmount):[],n=e.couponInput?h(e.couponInput).filter(B):[],o=e.applyButton?h(e.applyButton).filter(T):[],r=e.showFormButton?h(e.showFormButton).filter(B):[];return Boolean(n.length)&&Boolean(o.length)&&Boolean(t.length)||Boolean(t.length)&&Boolean(r.length)}function G(e){if(!e||!e.removeButton)return!1;const t=h(e.removeButton).filter(B);return Boolean(t.length)}function z(e){try{if(!e)return{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:H.NoSelectorProvided};const t=h(e),[n]=t;return n?{amount:function(e){if(!e)throw new Error("Cannot parse amount from empty value");if("string"!=typeof e)throw new Error(`Cannot parse amount from "${typeof e}"`);if(!e.match(/\d/))throw new Error(`Amount not found in "${e}"`);let t,n=e.replace(/[^0-9,.]/g,""),o=0;function i(e){t&&t!==e?r.error(`Amount has conflicting types: ${t} and ${e}`):t=e}return n.match(/^\d{1,3}(?:\.\d{3})*(?:,\d{2})?$/)&&(n=n.replaceAll(".","").replace(",",".")),n.match(/^\d{1,3}(?:,\d{3})*(?:.\d{2})?$/)&&(n=n.replaceAll(",","")),(n.match(/^\d*(?:,\d{2})?$/)||n.match(/^\d*(?:,\d{1})?$/))&&(n=n.replaceAll(",",".")),o=parseFloat(n.replace(/([^0-9.])/g,"")),(e.includes("€")||e.includes("EUR"))&&i(a.Euro),e.includes("$")&&(e.includes("R$")?i(a.Real):i(a.Dollar)),e.includes("£")&&i(a.Pound),e.includes("%")&&i(a.Percent),(e.includes("zł")||e.includes("PLN"))&&i(a.Zloty),t?{type:t,value:o}:{value:o}}(n.innerText),html:n.outerHTML,isEmpty:A(n),isVisible:Boolean(t.filter(T).length),multipleMatches:t.length>1,result:H.ElementFound}:{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:H.NoElementsFound}}catch(e){return e instanceof Error&&"SyntaxError"===e.name?(r.error(H.InvalidCSSSelector,e),{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:H.InvalidCSSSelector}):(r.error(H.Unhandled,e),{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:H.Unhandled})}}function W(e){try{if(!e)return{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:H.NoSelectorProvided,value:""};const t=h(e),[n]=t;return n?{html:n.outerHTML,isEmpty:A(n),isVisible:Boolean(t.filter(T).length),multipleMatches:t.length>1,result:H.ElementFound,value:n.innerHTML}:{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:H.NoElementsFound,value:""}}catch(e){return e instanceof Error&&"SyntaxError"===e.name?(r.error(H.InvalidCSSSelector,e),{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:H.InvalidCSSSelector,value:""}):(r.error(H.Unhandled,e),{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:H.Unhandled,value:""})}}function _(){return window.location.href}!function(e){e.ElementFound="ElementFound",e.NoSelectorProvided="NoSelectorProvided",e.Unhandled="Unhandled",e.NoElementsFound="NoElementsFound",e.InvalidCSSSelector="InvalidCSSSelector",e.NoConfigProvided="NoConfigProvided"}(H||(H={}));const K={applyCode:async function(e,t){return new Promise((n=>{const o=()=>{r.info("Page is about to reload."),n({type:w.Reloading})};(async()=>{try{if(!e.couponInput||!e.applyButton)throw w.NoRequiredSelectorsProvided;r.info(`Preparing to apply code: ${t}`),window.addEventListener("beforeunload",o),await async function(e){if(e.showFormButton){for(let t=0;t<4;t++){const t=e.couponInput&&y(e.couponInput);if(t&&B(t))return;const n=y(e.showFormButton);n&&B(n)&&(r.info("Trying to show the coupon form"),$(n)),await E()}throw w.Timeout}}(e),await D(e,t),await L(e),await N(e),r.info(`Code: ${t} applied.`),n({type:w.Done})}catch(e){const o=O(e);r.error(`Failed to apply code: ${t} -- ${o}`,e),n({type:o})}finally{window.removeEventListener("beforeunload",o),r.info("beforeunload listener removed.")}})()}))},getPageState:async function(e){return{amounts:{discount:z(e.discountAmount),subtotal:z(e.subtotalAmount),total:z(e.totalAmount)},coupon:{appliedCode:W(e.appliedCode),canApply:j(e),canRemove:G(e)},currentUrl:_(),elements:{applyButton:q(e.applyButton),closeModal:q(e.closeModal),couponInput:q(e.couponInput),error:q(e.error),loading:q(e.loading),removeButton:q(e.removeButton),showFormButton:q(e.showFormButton)},mainDomain:x(_())}},removeCode:async function(e){let t=!1;try{if(!e.removeButton)throw w.NoRequiredSelectorsProvided;if(e.removeButton===e.applyButton)throw w.ApplyAndRemoveButtonsHaveSameSelector;return r.info("Trying to remove applied code."),window.addEventListener("beforeunload",n),await async function n(o=0){if(o>=4)throw w.Timeout;if(t)throw w.Reloading;if(!e.removeButton)return;const a=y(e.removeButton);return a&&B(a)?($(a),r.info("Waiting for coupon is removed"),await E(),n(o+1)):void 0}(),r.info("Code removed."),{type:w.Done}}catch(e){let t;switch(r.error("Failed to remove the code",e),e){case w.Reloading:t=w.Reloading;break;case w.ApplyAndRemoveButtonsHaveSameSelector:t=w.ApplyAndRemoveButtonsHaveSameSelector;break;default:t=w.UnhandledError}return{type:t}}finally{window.removeEventListener("beforeunload",n),r.info("beforeunload listener removed.")}function n(){r.info("Page is about to reload."),t=!0}}};const J={applyCode:async function(e,t){return new Promise((n=>{const o=()=>{r.info("Page is about to reload."),n({type:w.Reloading})};(async()=>{try{if(!e.couponInput||!e.applyButton)throw w.NoRequiredSelectorsProvided;r.info(`Preparing to apply code: ${t}`),window.addEventListener("beforeunload",o),await function(e,t){return"/br/checkout/"===e.urlPattern?async function(e,t){await D(e,t),await L(e)}(e,t):function(e,t){const[n,o]=F(e);for(let r=0;r<10;r++)if(e.couponInput&&V(e.couponInput,t)){const t=[n,E(2e3)].filter(Boolean);return Promise.race(t).then((()=>{e.applyButton&&U(e.applyButton)})).finally((()=>{o()}))}return Promise.resolve()}(e,t)}(e,t),r.info(`Code: ${t} applied.`),n({type:w.Done})}catch(e){const o=O(e);r.error(`Failed to apply code: ${t} -- ${o}`,e),n({type:o})}finally{window.removeEventListener("beforeunload",o),r.info("beforeunload listener removed.")}})()}))},getPageState:K.getPageState,removeCode:K.removeCode};function Z(e){return"samsung.com"===e.domain?J:K}function Q({logger:e=(()=>{})}={}){g.runtime.onMessage.addListener(((t,n,r)=>{switch(o(e),t.type){case b.GetPageState:{const{getPageState:e}=Z(t.config);return e(t.config).then(r),!0}case b.ApplyCode:{const{applyCode:e}=Z(t.config);return e(t.config,t.code).then(r),!0}case b.RemoveCode:{const{removeCode:e}=Z(t.config);return e(t.config).then(r),!0}}}))}var X,Y,ee,te;!function(e){e.Discount="Discount",e.Invalid="Invalid"}(X||(X={})),function(e){e.TryCodes="caa-try-codes",e.Stop="caa-stop",e.GetPageState="caa-get-page-state"}(Y||(Y={})),function(e){e.CodeTested="caa-code-tested"}(ee||(ee={})),function(e){e.PageLoaded="caa-page-loaded"}(te||(te={}));const ne=1e4,oe=200;async function re(e,t,n){return new Promise((async o=>{let a=!1;const i=setTimeout((()=>{a=!0,o(null)}),ne);for(;!a;){try{const r=await g.tabs.sendMessage(e,{config:t,type:b.GetPageState});if(r&&(!n||n(r)))return clearTimeout(i),void o(r)}catch(e){r.error("get caa page state",e)}await E(oe)}}))}async function ae(e,t,n){const o=await re(e,n,(e=>!!e?.amounts.total.amount));if(!o)return{...t,type:X.Invalid};let a=o.amounts.total.amount;if(o.elements.removeButton.isClickable){try{await async function(e,t){let n=10;try{await g.tabs.sendMessage(e,{config:t,type:b.RemoveCode})}catch(e){r.error("remove caa-engine error",e)}for(;n>0;){n--;const o=await re(e,t);if(o){if(!o.elements.removeButton.isVisible)return;await E(200)}}if(!n)throw new Error("remove code is not removed")}(e,n)}catch(e){return r.error("remove code caa-background",e),{...t,type:X.Invalid}}const o=await re(e,n);if(!o)return{...t,type:X.Invalid};!o.elements.removeButton.isVisible&&o.amounts.total.amount&&(a=o.amounts.total.amount)}try{const o=await g.tabs.sendMessage(e,{code:t.code,config:n,type:b.ApplyCode});r.info({codeApplicationResult:o})}catch(e){r.error("apply code caa-from-content",e)}let i=10;for(;i>0;){i--;const o=await re(e,n,(e=>!!e?.amounts.total.amount));if(!o){await E(oe);continue}const r=o.amounts.total.amount;if(a&&r&&r.value<a.value)return{...t,initialTotal:a,totalWithDiscount:r,type:X.Discount};await E(oe)}return r.info("timeout handleApplyProcess"),{...t,type:X.Invalid}}const ie=new Map;async function le(e,t){const n=x(e),o=new URL(e).pathname,r=await t(n),a=await async function(e,t){const n=ie.get(e);if(n?.length)return n;const o=await fetch(t).then((e=>e.json())).then(ce).catch((()=>[]));return ie.set(e,o),o}(n,r).then(se);let i=null,l=null;for(const e of a)e.urlPattern?new RegExp(e.urlPattern).test(o)&&(l=e):i=e;if(l)return l;if(i)return i;throw new Error(`No config found for ${n}`)}function ce(e){const t=e,n=[];for(const e of t.configs){const t=e;t.data&&(t.disabled||n.push({appliedCode:t.data.appliedCode||void 0,applyButton:t.data.applyButton||void 0,applyType:t.data.applyType||void 0,closeModal:t.data.closeModal||void 0,couponInput:t.data.couponInput||void 0,discountAmount:t.data.discountAmount||void 0,domain:t.data.domain||"",error:t.data.error||void 0,loading:t.data.loading||void 0,removeButton:t.data.removeButton||void 0,showFormButton:t.data.showFormButton||void 0,subtotalAmount:t.data.subtotalAmount||void 0,totalAmount:t.data.totalAmount||void 0,urlPattern:t.data.urlPattern||void 0}))}return n}function se(e){return e.sort(((e,t)=>e.urlPattern?t.urlPattern?e.urlPattern.length-t.urlPattern.length:1:-1))}class ue{active;testedCodes=new Map;constructor(){this.active=!0}get isActive(){return this.active}stop(){this.active=!1}addTestedCode(e,t){this.testedCodes.set(e,t)}getTestedCode(e){return this.testedCodes.get(e)}}function de(e){return e.code.trim().length&&!/\s/.test(e.code.trim())}const fe=new Map;function pe({getUnifiedConfigUrl:e,logger:t=(()=>()=>{})}){g.runtime.onMessage.addListener(((n,a,i)=>{const l=a.tab?.id,c=a.tab?.url;if(void 0!==l)if(o(t(l)),void 0!==c)switch(n.type){case te.PageLoaded:return void r.info({message:n,tabId:l});case Y.Stop:return r.info({message:n,tabId:l}),fe.get(l)?.stop(),void r.info("stopping CAA for tab"+l);case Y.TryCodes:return r.info({message:n,tabId:l}),void async function(e,t,n,{codes:o,cacheDuplicates:a=!1,validateCodes:i=!1,minDelay:l=1e3,config:c}){let s;try{s=c||await le(t,n)}catch(e){return void r.error("Cannot get config for "+t,e)}r.info("starting CAA for tab "+e);const u=new ue;fe.set(e,u);for(const t of o){if(!u.isActive)break;const n=u.getTestedCode(t.code);if(a&&n){await E(l),await me(e,{...n,...t});continue}if(i&&!de(t)){await E(l),await me(e,{...t,type:X.Invalid});continue}const o=(new Date).getTime(),c=await ae(e,t,s);r.perf(t.code+" tested in: ",{code:t.code,timeSpent:(new Date).getTime()-o}),u.addTestedCode(t.code,c),await me(e,c)}fe.delete(e)}(l,c,e,n);case Y.GetPageState:return r.info({message:n,tabId:l}),async function(e,t,n,o){let a;if(o)a=o;else try{a=await le(t,n)}catch(e){return void r.error("No config exists for: "+t,e)}const i=await re(e,a);return r.info({pageState:i,tabId:e}),i}(l,c,e,n.config).then(i),!0}else r.error("No tabUrl provided for "+l);else console.error("No tabId provided")}))}async function me(e,t){r.info({code:t,info:"sending tried code",tabId:e});const n={code:t,type:ee.CodeTested};let o=!1;for(let a=0;a<10;a++){try{await ye(e),o=await g.tabs.sendMessage(e,n)}catch(n){r.info({code:t,info:"Tried code not received by the tab.",tabId:e})}if(o)break;await E(200)}if(!o)throw new Error(`Cannot send tried code to the browser tab. code: ${t.code} , tabId: ${e}`)}async function ye(e){let t=10;for(;t--;){if("complete"===(await g.tabs.get(e)).status)return;await E(100)}}module.exports=t})(); | ||
(()=>{"use strict";var e={d:(t,n)=>{for(var o in n)e.o(n,o)&&!e.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:n[o]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{AmountType:()=>a,BackgroundToClientMessageType:()=>te,ClientToBackgroundMessageType:()=>ee,TestedCodeType:()=>Y,getElements:()=>v,getGeneratedSelector:()=>g,getMainDomain:()=>H,setupBackgroundListeners:()=>me,setupContentListeners:()=>X});let n=()=>{};function o(e){n=e}const r={error:(e,t)=>n({level:"ERROR",message:e,stack:t instanceof Error&&t.stack||(new Error).stack||""}),info:e=>n({details:JSON.stringify(e),level:"INFO"}),perf:(e,t)=>n({label:e,level:"PERF",meta:t})};var a;function i(e){if(!e)throw new Error("Cannot parse amount from empty value");if("string"!=typeof e)throw new Error(`Cannot parse amount from "${typeof e}"`);if(!e.match(/\d/))throw new Error(`Amount not found in "${e}"`);let t=e.replace(/[^0-9,.]/g,"");t.match(/^\d{1,3}(?:\.\d{3})*(?:,\d{2})?$/)&&(t=t.replaceAll(".","").replace(",",".")),t.match(/^\d{1,3}(?:,\d{3})*(?:.\d{2})?$/)&&(t=t.replaceAll(",","")),(t.match(/^\d*(?:,\d{2})?$/)||t.match(/^\d*(?:,\d{1})?$/))&&(t=t.replaceAll(",","."));const n=parseFloat(t.replace(/([^0-9.])/g,"")),o=function(e){let t=null;function n(e){null!==t&&t!==e?r.error(`Amount has conflicting types: ${t} and ${e}`):t=e}return(e.includes("€")||e.includes("EUR"))&&n(a.Euro),e.includes("$")&&(e.includes("R$")?n(a.Real):n(a.Dollar)),e.includes("£")&&n(a.Pound),e.includes("%")&&n(a.Percent),(e.includes("zł")||e.includes("PLN"))&&n(a.Zloty),(e.match(/\b\d*(kr)\d*\b/)||e.includes("SEK"))&&n(a.Krona),t}(e);return null!==o?{type:o,value:n}:{value:n}}!function(e){e.Dollar="$",e.Euro="€",e.Percent="%",e.Pound="£",e.Real="R$",e.Zloty="zł",e.Krona="kr"}(a||(a={}));const l="data-caa-text";function c(e){try{const[,t=""]=e.split('"');return Object(JSON.parse(decodeURI(t)))}catch{return{}}}function s(e){return c(e)}const u=/[0-9.,]+/g;function d(e){return e?e.normalize("NFC").replaceAll(u,""):null}function f({innerText:e,tagName:t}){return function(e){try{return encodeURI(JSON.stringify(e))}catch(e){return r.error("Cannot encode a custom cssSelector: ",e),""}}({innerText:e,tagName:t})}function p(e){const{tagName:t,innerText:n}=c(e);return e.includes(l)&&"string"==typeof t&&"string"==typeof n}function m(e){return p(e)}function y(e){const t=Array.from(document.querySelectorAll(e));return p(e)?t.length>0?t.filter((n=e,function(e){const{tagName:t,innerText:o}=s(n);return e.tagName===t&&d(e.innerText)===d(o)})):function(e){const{tagName:t,innerText:n}=s(e);return Array.from(document.getElementsByTagName(t)).filter((e=>e instanceof HTMLElement)).filter((e=>d(e.innerText)===d(n))).map((e=>(e.setAttribute(l,f(e)),e)))}(e):[];var n}function h(e){try{if(m(e)){const[t=null]=y(e);return t}return document.querySelector(e)}catch(t){return r.error(`Cannot find the element in the DOM with the selector="${e}":`,t),null}}function v(e){try{return m(e)?y(e):Array.from(document.querySelectorAll(e))}catch(t){return r.error(`Cannot find elements in the DOM with the selector="${e}":`,t),[]}}function g(e){const t=function(e){return`[${l}="${f(e)}"]`}(e);return 1===v(t).length?t:null}const b=function(){try{return"object"==typeof browser&&null!==browser&&"runtime"in browser?browser:chrome}catch{return console.warn("[CAA-ENGINE]: not running in a DOM environment, the browser object is not defined."),{}}}();var w,E;async function S(e=500){return new Promise((t=>setTimeout(t,e)))}function C(e,t){return"object"==typeof e&&null!==e&&t in e}function P(e){return!C(e,"disabled")||!e.disabled}function T(e){return!!P(e)&&"none"!==window.getComputedStyle(e).getPropertyValue("pointer-events")}function B(e){if(e.hidden)return!1;const t=window.getComputedStyle(e);return"hidden"!==t.getPropertyValue("visibility")&&"0"!==t.getPropertyValue("opacity")&&"none"!==t.getPropertyValue("display")&&0!==e.offsetWidth&&0!==e.offsetHeight}function A(e){return P(e)&&T(e)&&B(e)}function M(e){return"INPUT"!==e.tagName&&!e.innerHTML.length}!function(e){e.GetPageState="caa-get-page-state",e.ApplyCode="caa-apply-code",e.RemoveCode="caa-remove-code"}(w||(w={})),function(e){e.Reloading="Reloading",e.Done="Done",e.UnhandledError="UnhandledError",e.Timeout="Timeout",e.NoRequiredSelectorsProvided="NoRequiredSelectorsProvided",e.ApplyAndRemoveButtonsHaveSameSelector="ApplyAndRemoveButtonsHaveSameSelector"}(E||(E={}));const I=1e3;function $(e=.5){return new Promise((t=>setTimeout(t,e*I)))}function N(e){e.dispatchEvent(new PointerEvent("pointerdown",{bubbles:!0,pointerType:"mouse"})),e.dispatchEvent(new MouseEvent("mousedown",{bubbles:!0})),e.dispatchEvent(new PointerEvent("pointerup",{bubbles:!0,pointerType:"mouse"})),e.dispatchEvent(new MouseEvent("mouseup",{bubbles:!0})),e.dispatchEvent(new MouseEvent("click",{bubbles:!0,cancelable:!0}))}async function R(e,t=0,n=0){if(!e.closeModal)return;if(t>=4)throw E.Timeout;const o=h(e.closeModal);if(!o||!A(o)){if(t>0||n>=4)return;return await S(),R(e,t,n+1)}return r.info("Trying to close modal"),N(o),await S(),R(e,t+1)}function k(e){const t=e&&h(e);return!!t&&B(t)}const F=4;function L(e){return e.loading?function(e){const t={bodyObserver:null,isLoading:k(e)};return[new Promise((n=>{t.bodyObserver=new MutationObserver((()=>{k(e)?t.isLoading=!0:t.isLoading&&n()})),t.bodyObserver.observe(document.body,{attributes:!0,childList:!0,subtree:!0})})),()=>t.bodyObserver?.disconnect()]}(e.loading):[void 0,()=>{}]}function V(e){const[t,n]=function(e){const t={pending:!0};return[(async()=>{for(let n=0;n<F;n++){const n=[e.error,e.removeButton,e.appliedCode];if(!t.pending||n.some(k))break;r.info("Waiting for feedback"),await $()}})(),()=>{t.pending=!1}]}(e),[o,a]=L(e),i=[t,o].filter(Boolean),l=[n,a];return Promise.race(i).finally((()=>{l.forEach((e=>e()))}))}function U(e,t){const n=h(e);return!!(n&&(o=n,C(o,"value")&&A(o)))&&(r.info("Trying to fill in the code"),function(e,t){const{value:n}=e;if(e.value=t,C(e,"_valueTracker")&&e._valueTracker){const t=e._valueTracker;C(t,"setValue")&&"function"==typeof t.setValue&&t.setValue(n)}e.dispatchEvent(new KeyboardEvent("keydown",{bubbles:!0})),e.dispatchEvent(new KeyboardEvent("keypress",{bubbles:!0})),e.dispatchEvent(new KeyboardEvent("input",{bubbles:!0})),e.dispatchEvent(new KeyboardEvent("keyup",{bubbles:!0})),e.dispatchEvent(new Event("change",{bubbles:!0}))}(n,t),!0);var o}function D(e){const t=h(e);return!(!t||!A(t)||(r.info("Trying to submit the code"),N(t),0))}async function O(e,t){for(let n=0;n<10&&!(e.couponInput&&U(e.couponInput,t)&&(await S(),e.applyButton&&D(e.applyButton)));n++);}function x(e){switch(e){case E.Reloading:return E.Reloading;case E.Timeout:return E.Timeout;case E.NoRequiredSelectorsProvided:return E.NoRequiredSelectorsProvided;default:return E.UnhandledError}}function H(e){const t=e.toLowerCase().replace(/^https?:\/\//,"").replace(/:\d+.*/,"").replace(/(:|\/|\?|#).*/,"");if(!/[a-z0-9-.]+/.test(t))throw new Error(`Cannot get main domain from ${e}`);const[n,o,r]=t.split(".").reverse();if("localhost"===n)return n;if(!n||n.length<2)throw new Error(`Wrong root domain "${n}" in ${e}`);if(!o)throw new Error(`Unknown main domain "${o}" in ${e}`);if(!["co.uk","co.za","com.au","com.de","org.uk","uk.com","com.br","com.pl","com.nl","com.mx","com.at","co.at","com.se"].includes(`${o}.${n}`))return`${o}.${n}`;if(!r)throw new Error(`Unknown main domain "${r}" in ${e}`);return`${r}.${o}.${n}`}var q;function j(e){try{if(!e)return{html:"",isClickable:!1,isEmpty:!0,isEnabled:!1,isVisible:!1,multipleMatches:!1,result:q.NoSelectorProvided};const t=v(e),[n]=t;return n?{html:n.outerHTML,isClickable:Boolean(t.filter(T).length),isEmpty:M(n),isEnabled:Boolean(t.filter(P).length),isVisible:Boolean(t.filter(B).length),multipleMatches:t.length>1,result:q.ElementFound}:{html:"",isClickable:!1,isEmpty:!0,isEnabled:!1,isVisible:!1,multipleMatches:!1,result:q.NoElementsFound}}catch(e){return e instanceof Error&&"SyntaxError"===e.name?(r.error(q.InvalidCSSSelector,e),{html:"",isClickable:!1,isEmpty:!0,isEnabled:!1,isVisible:!1,multipleMatches:!1,result:q.InvalidCSSSelector}):(r.error(q.Unhandled,e),{html:"",isClickable:!1,isEmpty:!0,isEnabled:!1,isVisible:!1,multipleMatches:!1,result:q.Unhandled})}}function G(e){if(!e)return!1;const t=e.totalAmount?v(e.totalAmount):[],n=e.couponInput?v(e.couponInput).filter(A):[],o=e.applyButton?v(e.applyButton).filter(B):[],r=e.showFormButton?v(e.showFormButton).filter(A):[];return Boolean(n.length)&&Boolean(o.length)&&Boolean(t.length)||Boolean(t.length)&&Boolean(r.length)}function K(e){if(!e||!e.removeButton)return!1;const t=v(e.removeButton).filter(A);return Boolean(t.length)}function z(e){try{if(!e)return{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:q.NoSelectorProvided};const t=v(e),[n]=t;return n?{amount:i(n.innerText),html:n.outerHTML,isEmpty:M(n),isVisible:Boolean(t.filter(B).length),multipleMatches:t.length>1,result:q.ElementFound}:{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:q.NoElementsFound}}catch(e){return e instanceof Error&&"SyntaxError"===e.name?(r.error(q.InvalidCSSSelector,e),{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:q.InvalidCSSSelector}):(r.error(q.Unhandled,e),{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:q.Unhandled})}}function W(e){try{if(!e)return{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:q.NoSelectorProvided,value:""};const t=v(e),[n]=t;return n?{html:n.outerHTML,isEmpty:M(n),isVisible:Boolean(t.filter(B).length),multipleMatches:t.length>1,result:q.ElementFound,value:n.innerHTML}:{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:q.NoElementsFound,value:""}}catch(e){return e instanceof Error&&"SyntaxError"===e.name?(r.error(q.InvalidCSSSelector,e),{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:q.InvalidCSSSelector,value:""}):(r.error(q.Unhandled,e),{html:"",isEmpty:!0,isVisible:!1,multipleMatches:!1,result:q.Unhandled,value:""})}}function _(){return window.location.href}!function(e){e.ElementFound="ElementFound",e.NoSelectorProvided="NoSelectorProvided",e.Unhandled="Unhandled",e.NoElementsFound="NoElementsFound",e.InvalidCSSSelector="InvalidCSSSelector",e.NoConfigProvided="NoConfigProvided"}(q||(q={}));const J={applyCode:async function(e,t){return new Promise((n=>{const o=()=>{r.info("Page is about to reload."),n({type:E.Reloading})};(async()=>{try{if(!e.couponInput||!e.applyButton)throw E.NoRequiredSelectorsProvided;r.info(`Preparing to apply code: ${t}`),window.addEventListener("beforeunload",o),await async function(e){if(e.showFormButton){for(let t=0;t<4;t++){const t=e.couponInput&&h(e.couponInput);if(t&&A(t))return;const n=h(e.showFormButton);n&&A(n)&&(r.info("Trying to show the coupon form"),N(n)),await S()}throw E.Timeout}}(e),await O(e,t),await V(e),await R(e),r.info(`Code: ${t} applied.`),n({type:E.Done})}catch(e){const o=x(e);r.error(`Failed to apply code: ${t} -- ${o}`,e),n({type:o})}finally{window.removeEventListener("beforeunload",o),r.info("beforeunload listener removed.")}})()}))},getPageState:async function(e){return{amounts:{discount:z(e.discountAmount),subtotal:z(e.subtotalAmount),total:z(e.totalAmount)},coupon:{appliedCode:W(e.appliedCode),canApply:G(e),canRemove:K(e)},currentUrl:_(),elements:{applyButton:j(e.applyButton),closeModal:j(e.closeModal),couponInput:j(e.couponInput),error:j(e.error),loading:j(e.loading),removeButton:j(e.removeButton),showFormButton:j(e.showFormButton)},mainDomain:H(_())}},removeCode:async function(e){let t=!1;try{if(!e.removeButton)throw E.NoRequiredSelectorsProvided;if(e.removeButton===e.applyButton)throw E.ApplyAndRemoveButtonsHaveSameSelector;return r.info("Trying to remove applied code."),window.addEventListener("beforeunload",n),await async function n(o=0){if(o>=4)throw E.Timeout;if(t)throw E.Reloading;if(!e.removeButton)return;const a=h(e.removeButton);return a&&A(a)?(N(a),r.info("Waiting for coupon is removed"),await S(),n(o+1)):void 0}(),r.info("Code removed."),{type:E.Done}}catch(e){let t;switch(r.error("Failed to remove the code",e),e){case E.Reloading:t=E.Reloading;break;case E.ApplyAndRemoveButtonsHaveSameSelector:t=E.ApplyAndRemoveButtonsHaveSameSelector;break;default:t=E.UnhandledError}return{type:t}}finally{window.removeEventListener("beforeunload",n),r.info("beforeunload listener removed.")}function n(){r.info("Page is about to reload."),t=!0}}};const Z={applyCode:async function(e,t){return new Promise((n=>{const o=()=>{r.info("Page is about to reload."),n({type:E.Reloading})};(async()=>{try{if(!e.couponInput||!e.applyButton)throw E.NoRequiredSelectorsProvided;r.info(`Preparing to apply code: ${t}`),window.addEventListener("beforeunload",o),await function(e,t){return"/br/checkout/"===e.urlPattern?async function(e,t){await O(e,t),await V(e)}(e,t):function(e,t){const[n,o]=L(e);for(let r=0;r<10;r++)if(e.couponInput&&U(e.couponInput,t)){const t=[n,S(2e3)].filter(Boolean);return Promise.race(t).then((()=>{e.applyButton&&D(e.applyButton)})).finally((()=>{o()}))}return Promise.resolve()}(e,t)}(e,t),r.info(`Code: ${t} applied.`),n({type:E.Done})}catch(e){const o=x(e);r.error(`Failed to apply code: ${t} -- ${o}`,e),n({type:o})}finally{window.removeEventListener("beforeunload",o),r.info("beforeunload listener removed.")}})()}))},getPageState:J.getPageState,removeCode:J.removeCode};function Q(e){return"samsung.com"===e.domain?Z:J}function X({logger:e=(()=>{})}={}){b.runtime.onMessage.addListener(((t,n,r)=>{switch(o(e),t.type){case w.GetPageState:{const{getPageState:e}=Q(t.config);return e(t.config).then(r),!0}case w.ApplyCode:{const{applyCode:e}=Q(t.config);return e(t.config,t.code).then(r),!0}case w.RemoveCode:{const{removeCode:e}=Q(t.config);return e(t.config).then(r),!0}}}))}var Y,ee,te,ne;!function(e){e.Discount="Discount",e.Invalid="Invalid"}(Y||(Y={})),function(e){e.TryCodes="caa-try-codes",e.Stop="caa-stop",e.GetPageState="caa-get-page-state"}(ee||(ee={})),function(e){e.CodeTested="caa-code-tested"}(te||(te={})),function(e){e.PageLoaded="caa-page-loaded"}(ne||(ne={}));const oe=1e4,re=200;async function ae(e,t,n){return new Promise((async o=>{let a=!1;const i=setTimeout((()=>{a=!0,o(null)}),oe);for(;!a;){try{const r=await b.tabs.sendMessage(e,{config:t,type:w.GetPageState});if(r&&(!n||n(r)))return clearTimeout(i),void o(r)}catch(e){r.error("get caa page state",e)}await S(re)}}))}async function ie(e,t,n){const o=await ae(e,n,(e=>!!e?.amounts.total.amount));if(!o)return{...t,type:Y.Invalid};let a=o.amounts.total.amount;if(o.elements.removeButton.isClickable){try{await async function(e,t){let n=10;try{await b.tabs.sendMessage(e,{config:t,type:w.RemoveCode})}catch(e){r.error("remove caa-engine error",e)}for(;n>0;){n--;const o=await ae(e,t);if(o){if(!o.elements.removeButton.isVisible)return;await S(200)}}if(!n)throw new Error("remove code is not removed")}(e,n)}catch(e){return r.error("remove code caa-background",e),{...t,type:Y.Invalid}}const o=await ae(e,n);if(!o)return{...t,type:Y.Invalid};!o.elements.removeButton.isVisible&&o.amounts.total.amount&&(a=o.amounts.total.amount)}try{const o=await b.tabs.sendMessage(e,{code:t.code,config:n,type:w.ApplyCode});r.info({codeApplicationResult:o})}catch(e){r.error("apply code caa-from-content",e)}let i=10;for(;i>0;){i--;const o=await ae(e,n,(e=>!!e?.amounts.total.amount));if(!o){await S(re);continue}const r=o.amounts.total.amount;if(a&&r&&r.value<a.value)return{...t,initialTotal:a,totalWithDiscount:r,type:Y.Discount};await S(re)}return r.info("timeout handleApplyProcess"),{...t,type:Y.Invalid}}const le=new Map;async function ce(e,t){const n=H(e),o=new URL(e).pathname,r=await t(n),a=await async function(e,t){const n=le.get(e);if(n?.length)return n;const o=await fetch(t).then((e=>e.json())).then(se).catch((()=>[]));return le.set(e,o),o}(n,r).then(ue);let i=null,l=null;for(const e of a)e.urlPattern?new RegExp(e.urlPattern).test(o)&&(l=e):i=e;if(l)return l;if(i)return i;throw new Error(`No config found for ${n}`)}function se(e){const t=e,n=[];for(const e of t.configs){const t=e;t.data&&(t.disabled||n.push({appliedCode:t.data.appliedCode||void 0,applyButton:t.data.applyButton||void 0,applyType:t.data.applyType||void 0,closeModal:t.data.closeModal||void 0,couponInput:t.data.couponInput||void 0,discountAmount:t.data.discountAmount||void 0,domain:t.data.domain||"",error:t.data.error||void 0,loading:t.data.loading||void 0,removeButton:t.data.removeButton||void 0,showFormButton:t.data.showFormButton||void 0,subtotalAmount:t.data.subtotalAmount||void 0,totalAmount:t.data.totalAmount||void 0,urlPattern:t.data.urlPattern||void 0}))}return n}function ue(e){return e.sort(((e,t)=>e.urlPattern?t.urlPattern?e.urlPattern.length-t.urlPattern.length:1:-1))}class de{active;testedCodes=new Map;constructor(){this.active=!0}get isActive(){return this.active}stop(){this.active=!1}addTestedCode(e,t){this.testedCodes.set(e,t)}getTestedCode(e){return this.testedCodes.get(e)}}function fe(e){return e.code.trim().length&&!/\s/.test(e.code.trim())}const pe=new Map;function me({getUnifiedConfigUrl:e,logger:t=(()=>()=>{})}){b.runtime.onMessage.addListener(((n,a,i)=>{const l=a.tab?.id,c=a.tab?.url;if(void 0!==l)if(o(t(l)),void 0!==c)switch(n.type){case ne.PageLoaded:return void r.info({message:n,tabId:l});case ee.Stop:return r.info({message:n,tabId:l}),pe.get(l)?.stop(),void r.info("stopping CAA for tab"+l);case ee.TryCodes:return r.info({message:n,tabId:l}),void async function(e,t,n,{codes:o,cacheDuplicates:a=!1,validateCodes:i=!1,minDelay:l=1e3,config:c}){let s;try{s=c||await ce(t,n)}catch(e){return void r.error("Cannot get config for "+t,e)}r.info("starting CAA for tab "+e);const u=new de;pe.set(e,u);for(const t of o){if(!u.isActive)break;const n=u.getTestedCode(t.code);if(a&&n){await S(l),await ye(e,{...n,...t});continue}if(i&&!fe(t)){await S(l),await ye(e,{...t,type:Y.Invalid});continue}const o=(new Date).getTime(),c=await ie(e,t,s);r.perf(t.code+" tested in: ",{code:t.code,timeSpent:(new Date).getTime()-o}),u.addTestedCode(t.code,c),await ye(e,c)}pe.delete(e)}(l,c,e,n);case ee.GetPageState:return r.info({message:n,tabId:l}),async function(e,t,n,o){let a;if(o)a=o;else try{a=await ce(t,n)}catch(e){return void r.error("No config exists for: "+t,e)}const i=await ae(e,a);return r.info({pageState:i,tabId:e}),i}(l,c,e,n.config).then(i),!0}else r.error("No tabUrl provided for "+l);else console.warn("No tabId provided")}))}async function ye(e,t){r.info({code:t,info:"sending tried code",tabId:e});const n={code:t,type:te.CodeTested};let o=!1;for(let a=0;a<10;a++){try{await he(e),o=await b.tabs.sendMessage(e,n)}catch(n){r.info({code:t,info:"Tried code not received by the tab.",tabId:e})}if(o)break;await S(200)}if(!o)throw new Error(`Cannot send tried code to the browser tab. code: ${t.code} , tabId: ${e}`)}async function he(e){let t=10;for(;t--;){if("complete"===(await b.tabs.get(e)).status)return;await S(100)}}module.exports=t})(); |
@@ -15,3 +15,3 @@ { | ||
"name": "@global-savings-group/caa-engine", | ||
"version": "4.1.1" | ||
"version": "4.1.2" | ||
} |
Sorry, the diff of this file is not supported yet
57782
393