@dropins/tools 1.9.0-beta.3 → 2.0.0-alpha-20260608090548
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -19
- package/chunks/Image.js +1 -1
- package/chunks/Image.js.map +1 -1
- package/components.js +1 -1
- package/components.js.map +1 -1
- package/package.json +1 -1
- package/recaptcha.js +3 -3
- package/recaptcha.js.map +1 -1
- package/types/elsie/src/i18n/en_US.json.d.ts +1 -0
- package/types/elsie/src/i18n/index.d.ts +3 -0
package/package.json
CHANGED
package/recaptcha.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*! Copyright 2026 Adobe
|
|
2
2
|
All Rights Reserved. */
|
|
3
|
-
import{FetchGraphQL as C}from"./fetch-graphql.js";const s={failedFetch:"Failed to fetch config from backend with status:",failedSetStorageConfig:"Failed to set storage config",failedGetStorageConfig:"Configuration could not be loaded.",failedExecutionRecaptcha:"Recaptcha execution failed",failedInitializing:"An error occurred while initializing ReCaptcha:",mixedTypesWarning:"Multiple reCAPTCHA types detected across forms (both v3 and Enterprise). This configuration is not supported — all forms must use the same reCAPTCHA type. Please update your configuration in Commerce Admin "},f={PLACE_ORDER:"placeOrder",CONTACT:"contactUs",CUSTOMER_LOGIN:"generateCustomerToken",CUSTOMER_FORGOT_PASSWORD:"requestPasswordResetEmail",CUSTOMER_CREATE:"createCustomerV2",CUSTOMER_EDIT:"updateCustomerV2",NEWSLETTER:"subscribeEmailToNewsletter",PRODUCT_REVIEW:"createProductReview",SENDFRIEND:"SENDFRIEND",BRAINTREE:"BRAINTREE"},_=".grecaptcha-badge iframe",y=(o,e)=>{if(o&&o.forms){const t=o.forms.concat(e).map(i=>typeof i!="string"?{...i,enabledBadgePlace:!1}:{badgeId:f[i],enabledBadgePlace:!1});return{...o,forms:[...new Set(t)]}}},m=async(o,e=1,t=1e3)=>{const i=sessionStorage.getItem(o);return i!==null?JSON.parse(i):e>0?(await new Promise(r=>setTimeout(r,t)),m(o,e-1,t)):null},b=(o,e,t)=>{if(!o||!e.websiteKey)return null;try{sessionStorage.setItem(o,JSON.stringify(e))}catch(i){return t&&console.error(s.failedSetStorageConfig,i),null}},R=o=>new Promise((e,t)=>{try{if(document.querySelector(o)){e();return}const i=new MutationObserver(()=>{document.querySelector(o)&&(e(),i.disconnect())});i.observe(document.body,{childList:!0,subtree:!1})}catch(i){t(i)}}),w=async()=>{try{return await R(_),!0}catch{return!1}},E=o=>{const e=t=>t.replace(/_([a-z])/g,(i,r)=>r.toUpperCase());return Object.keys(o).reduce((t,i)=>{const r=e(i);return t[r]=o[i],t},{})},{failedExecutionRecaptcha:p}=s,
|
|
3
|
+
import{FetchGraphQL as C}from"./fetch-graphql.js";const s={failedFetch:"Failed to fetch config from backend with status:",failedSetStorageConfig:"Failed to set storage config",failedGetStorageConfig:"Configuration could not be loaded.",failedExecutionRecaptcha:"Recaptcha execution failed",failedInitializing:"An error occurred while initializing ReCaptcha:",mixedTypesWarning:"Multiple reCAPTCHA types detected across forms (both v3 and Enterprise). This configuration is not supported — all forms must use the same reCAPTCHA type. Please update your configuration in Commerce Admin "},f={PLACE_ORDER:"placeOrder",CONTACT:"contactUs",CUSTOMER_LOGIN:"generateCustomerToken",CUSTOMER_FORGOT_PASSWORD:"requestPasswordResetEmail",CUSTOMER_CREATE:"createCustomerV2",COMPANY_CREATE:"createCompany",CUSTOMER_EDIT:"updateCustomerV2",NEWSLETTER:"subscribeEmailToNewsletter",PRODUCT_REVIEW:"createProductReview",SENDFRIEND:"SENDFRIEND",BRAINTREE:"BRAINTREE"},_=".grecaptcha-badge iframe",y=(o,e)=>{if(o&&o.forms){const t=o.forms.concat(e).map(i=>typeof i!="string"?{...i,enabledBadgePlace:!1}:{badgeId:f[i],enabledBadgePlace:!1});return{...o,forms:[...new Set(t)]}}},m=async(o,e=1,t=1e3)=>{const i=sessionStorage.getItem(o);return i!==null?JSON.parse(i):e>0?(await new Promise(r=>setTimeout(r,t)),m(o,e-1,t)):null},b=(o,e,t)=>{if(!o||!e.websiteKey)return null;try{sessionStorage.setItem(o,JSON.stringify(e))}catch(i){return t&&console.error(s.failedSetStorageConfig,i),null}},R=o=>new Promise((e,t)=>{try{if(document.querySelector(o)){e();return}const i=new MutationObserver(()=>{document.querySelector(o)&&(e(),i.disconnect())});i.observe(document.body,{childList:!0,subtree:!1})}catch(i){t(i)}}),w=async()=>{try{return await R(_),!0}catch{return!1}},E=o=>{const e=t=>t.replace(/_([a-z])/g,(i,r)=>r.toUpperCase());return Object.keys(o).reduce((t,i)=>{const r=e(i);return t[r]=o[i],t},{})},{failedExecutionRecaptcha:p}=s,T=async(o,e=!1)=>{if(!window.grecaptcha)return Promise.reject(p);try{return e?await window.grecaptcha.enterprise.execute(o,{action:"click"}):await window.grecaptcha.execute(o,{action:"click"})}catch(t){return Promise.reject(`${p} : ${t}`)}},S=()=>new Promise(o=>{const e=new MutationObserver((i,r)=>{window.grecaptcha&&(r.disconnect(),o(!0))}),t={childList:!0,subtree:!0,attributes:!0};e.observe(document.body,t)}),A=async(o,e,t,i=!1)=>{window.grecaptcha||await S();const r=i?grecaptcha.enterprise:grecaptcha;return r.ready(()=>{const n=document.querySelectorAll(`#${o}`);n.length&&(n.forEach(a=>a.id=`${a.id}_${Math.random().toString(36)}`),n.forEach(a=>{if(a.innerHTML==="")try{r.render(a.id,{sitekey:e.websiteKey,badge:e.badgePosition,size:"invisible",theme:e.theme??"light"})}catch(g){t&&console.error(g)}}))})},P=`
|
|
4
4
|
is_enabled
|
|
5
5
|
configurations {
|
|
6
6
|
website_key
|
|
@@ -12,9 +12,9 @@ import{FetchGraphQL as C}from"./fetch-graphql.js";const s={failedFetch:"Failed t
|
|
|
12
12
|
validation_failure_message
|
|
13
13
|
theme
|
|
14
14
|
}`,v=o=>`query {
|
|
15
|
-
${o.map(t=>` ${t}: recaptchaFormConfig(formType: ${t}) {${
|
|
15
|
+
${o.map(t=>` ${t}: recaptchaFormConfig(formType: ${t}) {${P}
|
|
16
16
|
}`).join(`
|
|
17
17
|
`)}
|
|
18
18
|
}`,l=new C().getMethods(),$="https://www.google.com/recaptcha/api.js",k="https://www.google.com/recaptcha/enterprise.js",u="[ReCaptcha]";class I{constructor(){var e;this._enableReCAPTCHA=!1,this._recaptchaBackendEndpoint=((e=l.getConfig())==null?void 0:e.endpoint)||"",this._recaptchaScriptUrl=$,this._configStorageKey="recaptchaConfig",this._logger=!1}_log(...e){this._logger&&console.log(u,...e)}_normalizeFormConfigResponse(e,t){const i=e==null?void 0:e.data;if(!i)return;const r=[];let n=null;const a=new Set;for(const h of t){const c=i[h];if(!(c!=null&&c.is_enabled))continue;const d=Array.isArray(c.configurations)?c.configurations[0]:c.configurations;if(d){if(d.re_captcha_type&&a.add(d.re_captcha_type),!d.website_key){this._log(`Skipping ${h}: enabled but missing website_key`);continue}r.push(h),n||(n=d)}}if(a.size>1){console.warn(u,s.mixedTypesWarning,`
|
|
19
|
-
Detected: ${[...a].join(", ")}`);return}if(!n||r.length===0){this._log("No enabled forms found in recaptchaFormConfig response");return}const g=n.re_captcha_type==="RECAPTCHA_ENTERPRISE";return this._log(`Using reCAPTCHA ${g?"Enterprise":"v3"}`,`| Enabled forms: ${r.join(", ")}`),{data:{recaptchaConfig:{is_enabled:!0,website_key:n.website_key,badge_position:n.badge_position,language_code:n.language_code,minimum_score:n.minimum_score,failure_message:n.validation_failure_message,theme:n.theme,forms:r,recaptcha_type:g?"enterprise":"v3"}}}}async _updateBadgePosition(e,t){if(t)if((t==null?void 0:t.badgePosition)==="inline")this._log(`Rendering inline badge for: ${e}`),await
|
|
19
|
+
Detected: ${[...a].join(", ")}`);return}if(!n||r.length===0){this._log("No enabled forms found in recaptchaFormConfig response");return}const g=n.re_captcha_type==="RECAPTCHA_ENTERPRISE";return this._log(`Using reCAPTCHA ${g?"Enterprise":"v3"}`,`| Enabled forms: ${r.join(", ")}`),{data:{recaptchaConfig:{is_enabled:!0,website_key:n.website_key,badge_position:n.badge_position,language_code:n.language_code,minimum_score:n.minimum_score,failure_message:n.validation_failure_message,theme:n.theme,forms:r,recaptcha_type:g?"enterprise":"v3"}}}}async _updateBadgePosition(e,t){if(t)if((t==null?void 0:t.badgePosition)==="inline")this._log(`Rendering inline badge for: ${e}`),await A(e,t,this._logger,t.recaptchaType==="enterprise");else{if(!await w())return;const r=document.querySelector(_);t.theme&&r&&!r.src.includes("theme=dark")&&!r.src.includes("theme=light")&&r.setAttribute("src",`${r.src}&theme=${t.theme}`)}}async _addRecaptchaScript(){const e=await this._loadConfig();if(!document.getElementById("recaptchaId")&&e){const t=e.websiteKey,i=e.badgePosition==="inline",r=e.languageCode;if(!t){this._log("No website key found, skipping script injection");return}const n=e.recaptchaType==="enterprise"?k:this._recaptchaScriptUrl,a=document.createElement("script");a.setAttribute("id","recaptchaId"),a.defer=!0,a.src=i?`${n}?render=${t}&badge=none&hl=${r}`:`${n}?render=${t}&badge=${e.badgePosition}&hl=${r}`,this._log(`Loading script: ${a.src}`),document.head.appendChild(a)}}async _fetchStoreConfig(){var e;try{const t=Object.keys(f),i=v(t);this._log(`Fetching config for forms: ${t.join(", ")}`);const r=await l.fetchGraphQl(i,{method:"GET",cache:"force-cache"});if((e=r==null?void 0:r.errors)!=null&&e.length){this._logger&&console.error(r.errors[0].message);return}return this._normalizeFormConfigResponse(r,t)}catch(t){this._logger&&console.error(`${s.failedFetch}:`,t)}}async _loadConfig(){const e=await m(this._configStorageKey);return e?(this._enableReCAPTCHA=!!e.isEnabled,e):(this._logger&&console.error(s.failedGetStorageConfig),null)}setEndpoint(e){e&&(this._recaptchaBackendEndpoint=e,l.setEndpoint(e))}async setConfig(e){var t,i;try{const r=await this._fetchStoreConfig();if(!((t=r==null?void 0:r.data)!=null&&t.recaptchaConfig)){this._log("No reCAPTCHA config returned, clearing storage"),sessionStorage.removeItem(this._configStorageKey);return}const n=E((i=r==null?void 0:r.data)==null?void 0:i.recaptchaConfig),a=y(n,e);a&&(this._log("Config stored:",{type:a.recaptchaType??"v3",enabled:a.isEnabled,badge:a.badgePosition,forms:a.forms}),b(this._configStorageKey,a,this._logger))}catch(r){this._logger&&console.error(s.failedSetStorageConfig,r),sessionStorage.removeItem(this._configStorageKey)}}async initReCaptcha(e=3e3){setTimeout(()=>{(async()=>{try{const t=await this._loadConfig();if(!(t!=null&&t.forms)||!t.isEnabled){this._log("reCAPTCHA disabled or no forms configured, skipping init");return}this._log(`Initializing reCAPTCHA (type: ${t.recaptchaType??"v3"}, badge: ${t.badgePosition})`),await this._addRecaptchaScript(),t.badgePosition==="inline"?await Promise.all(t.forms.map(i=>this._updateBadgePosition(i.badgeId,t))):await this._updateBadgePosition("",t)}catch(t){this._logger&&console.error(s.failedInitializing,t)}})()},e)}async verifyReCaptcha(){try{const e=await this._loadConfig();if(!(e!=null&&e.forms)||!e.websiteKey||!e.isEnabled){this._log("verifyReCaptcha skipped: reCAPTCHA not enabled or missing config");return}this._log(`Requesting token (type: ${e.recaptchaType??"v3"})`);const t=await T(e.websiteKey,e.recaptchaType==="enterprise");return this._log("Token obtained successfully"),t}catch(e){this._logger&&console.error(e)}}enableLogger(e){this._logger=e}getMethods(){return{enableLogger:this.enableLogger.bind(this),setEndpoint:this.setEndpoint.bind(this),setConfig:this.setConfig.bind(this),initReCaptcha:this.initReCaptcha.bind(this),verifyReCaptcha:this.verifyReCaptcha.bind(this)}}}const F=new I,{initReCaptcha:L,verifyReCaptcha:N,setEndpoint:B,setConfig:M,enableLogger:U}=F.getMethods();export{I as RecaptchaModule,U as enableLogger,L as initReCaptcha,l as recaptchaFetchApi,M as setConfig,B as setEndpoint,N as verifyReCaptcha};
|
|
20
20
|
//# sourceMappingURL=recaptcha.js.map
|
package/recaptcha.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recaptcha.js","sources":["@dropins/tools/src/recaptcha/configs/message.config.ts","@dropins/tools/src/recaptcha/configs/typeForms.config.ts","@dropins/tools/src/recaptcha/configs/recaptchaBadgeSelector.config.ts","@dropins/tools/src/recaptcha/lib/_extendConfig.ts","@dropins/tools/src/recaptcha/lib/_storageConfig.ts","@dropins/tools/src/recaptcha/lib/_checkRecaptchaBadge.ts","@dropins/tools/src/recaptcha/lib/_convertKeysToCamelCase.ts","@dropins/tools/src/recaptcha/services/recaptcha.service.ts","@dropins/tools/src/recaptcha/graphql/recaptchaConfig.graphql.ts","@dropins/tools/src/recaptcha/index.ts"],"sourcesContent":["/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nexport const recaptchaMessage = {\n failedFetch: 'Failed to fetch config from backend with status:',\n failedSetStorageConfig: 'Failed to set storage config',\n failedGetStorageConfig: 'Configuration could not be loaded.',\n failedExecutionRecaptcha: 'Recaptcha execution failed',\n failedInitializing: 'An error occurred while initializing ReCaptcha:',\n mixedTypesWarning:\n 'Multiple reCAPTCHA types detected across forms (both v3 and Enterprise). ' +\n 'This configuration is not supported — all forms must use the same reCAPTCHA type. ' +\n 'Please update your configuration in Commerce Admin '\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nexport const typeDefaultForm: Record<string, string> = {\n PLACE_ORDER: 'placeOrder',\n CONTACT: 'contactUs',\n CUSTOMER_LOGIN: 'generateCustomerToken',\n CUSTOMER_FORGOT_PASSWORD: 'requestPasswordResetEmail',\n CUSTOMER_CREATE: 'createCustomerV2',\n CUSTOMER_EDIT: 'updateCustomerV2',\n NEWSLETTER: 'subscribeEmailToNewsletter',\n PRODUCT_REVIEW: 'createProductReview',\n SENDFRIEND: 'SENDFRIEND',\n BRAINTREE: 'BRAINTREE',\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nexport const recaptchaBadgeSelector = '.grecaptcha-badge iframe';","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nimport { ReCaptchaModel } from '../types/recaptcha.types';\nimport { typeDefaultForm } from '../configs/typeForms.config';\n\nexport const extendConfig = (\n config: ReCaptchaModel,\n modifyParams: any[]\n): ReCaptchaModel | undefined => {\n if (config && config.forms) {\n const modifyForm = config.forms.concat(modifyParams).map((el) => {\n if (typeof el !== 'string') return { ...el, enabledBadgePlace: false };\n\n return {\n badgeId: typeDefaultForm[el],\n enabledBadgePlace: false,\n };\n });\n\n return { ...config, forms: [...new Set(modifyForm)] };\n }\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nimport { recaptchaMessage } from '../configs';\nimport { ReCaptchaModel } from '../types/recaptcha.types';\n\nconst getConfigStorage = async (\n storageKey: string,\n retries = 1,\n delay = 1000\n): Promise<ReCaptchaModel | null> => {\n const storedConfig = sessionStorage.getItem(storageKey);\n\n if (storedConfig !== null) {\n return JSON.parse(storedConfig);\n } else if (retries > 0) {\n await new Promise((resolve) => setTimeout(resolve, delay));\n\n return getConfigStorage(storageKey, retries - 1, delay);\n }\n\n return null;\n};\n\nconst setConfigStorage = (\n storageKey: string,\n config: ReCaptchaModel,\n logger: boolean\n) => {\n if (!storageKey || !config.websiteKey) return null;\n\n try {\n sessionStorage.setItem(storageKey, JSON.stringify(config));\n } catch (error) {\n logger && console.error(recaptchaMessage.failedSetStorageConfig, error);\n return null;\n }\n};\n\nexport { getConfigStorage, setConfigStorage };\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nimport { recaptchaBadgeSelector } from '../configs';\n\nconst waitForElement = (selector: string): Promise<void> => {\n return new Promise((resolve, reject) => {\n try {\n // Check if the element is already in the DOM\n if (document.querySelector(selector)) {\n resolve();\n return;\n }\n\n // Create an observer to watch for changes\n const observer = new MutationObserver(() => {\n if (document.querySelector(selector)) {\n resolve();\n observer.disconnect();\n }\n });\n\n // Start observing the body for child changes only\n observer.observe(document.body, {\n childList: true,\n subtree: false,\n });\n } catch (error) {\n reject(error);\n }\n });\n};\n\nexport const checkRecaptchaBadge = async (): Promise<boolean> => {\n try {\n await waitForElement(recaptchaBadgeSelector);\n return true;\n } catch (error) {\n return false;\n }\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nexport const convertKeysToCamelCase = (obj: {\n [key: string]: any;\n}): { [key: string]: string | number | boolean } => {\n const camelCaseKey = (key: string): string => {\n return key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());\n };\n\n return Object.keys(obj).reduce((result, key) => {\n const newKey = camelCaseKey(key);\n result[newKey] = obj[key];\n return result;\n }, {} as { [key: string]: any });\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nimport { recaptchaMessage } from '../configs';\nimport {\n MutationObserverInit,\n ReCaptchaModel,\n} from '../types/recaptcha.types';\nconst { failedExecutionRecaptcha } = recaptchaMessage;\n\nexport const getRecaptchaToken = async (\n websiteKey: string,\n isEnterprise = false\n): Promise<string> => {\n if (!(window as any).grecaptcha) {\n return Promise.reject(failedExecutionRecaptcha);\n }\n\n try {\n const token = isEnterprise\n ? await window.grecaptcha.enterprise.execute(websiteKey, {\n action: 'click',\n })\n : await window.grecaptcha.execute(websiteKey, {\n action: 'click',\n });\n\n return token;\n } catch (error) {\n return Promise.reject(`${failedExecutionRecaptcha} : ${error}`);\n }\n};\n\nexport const waitForReCaptcha = () => {\n return new Promise((resolve) => {\n const observer = new MutationObserver((_, obs) => {\n if (window.grecaptcha) {\n obs.disconnect();\n resolve(true);\n }\n });\n\n const observerOptions: MutationObserverInit = {\n childList: true,\n subtree: true,\n attributes: true,\n };\n\n observer.observe(document.body, observerOptions);\n });\n};\n\nexport const verifyReCaptchaLoad = async (\n badgeId: string,\n config: ReCaptchaModel,\n logger: boolean,\n isEnterprise = false\n): Promise<void> => {\n if (!window.grecaptcha) {\n await waitForReCaptcha();\n }\n\n const api = isEnterprise ? grecaptcha.enterprise : grecaptcha;\n\n return api.ready(() => {\n const badgeContainers = document.querySelectorAll(`#${badgeId}`);\n\n if (!badgeContainers.length) return;\n\n // Handle the case when multiple instances of the drop-in container rendered on the same page\n\n badgeContainers.forEach(\n (element) => (element.id = `${element.id}_${Math.random().toString(36)}`) // NOSONAR\n );\n\n badgeContainers.forEach((element) => {\n if (element.innerHTML === '') {\n try {\n api.render(element.id, {\n sitekey: config.websiteKey as string,\n badge: config.badgePosition,\n size: 'invisible',\n theme: config.theme ?? 'light',\n });\n } catch (error) {\n logger && console.error(error);\n }\n }\n });\n });\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\nconst RECAPTCHA_FORM_CONFIG_FIELDS = `\n is_enabled\n configurations {\n website_key\n badge_position\n language_code\n minimum_score\n re_captcha_type\n technical_failure_message\n validation_failure_message\n theme\n }`;\n\nexport const buildRecaptchaFormConfigQuery = (\n formTypes: string[]\n): string => {\n const queries = formTypes\n .map(\n (formType) =>\n ` ${formType}: recaptchaFormConfig(formType: ${formType}) {${RECAPTCHA_FORM_CONFIG_FIELDS}\n }`\n )\n .join('\\n');\n\n return `query {\\n${queries}\\n}`;\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nimport {\n ReCaptchaResponse,\n PropsFormTypes,\n ReCaptchaModel,\n ReCaptchaFormConfigResult,\n} from './types/recaptcha.types';\nimport {\n recaptchaMessage,\n recaptchaBadgeSelector,\n typeDefaultForm,\n} from './configs';\nimport {\n extendConfig,\n setConfigStorage,\n getConfigStorage,\n checkRecaptchaBadge,\n convertKeysToCamelCase,\n} from './lib';\nimport {\n getRecaptchaToken,\n verifyReCaptchaLoad,\n} from './services/recaptcha.service';\nimport { buildRecaptchaFormConfigQuery } from './graphql/recaptchaConfig.graphql';\n\nimport { FetchGraphQL } from '@adobe-commerce/fetch-graphql';\n\nexport const recaptchaFetchApi = new FetchGraphQL().getMethods();\n\nconst RECAPTCHA_V3_SCRIPT_URL = 'https://www.google.com/recaptcha/api.js';\nconst RECAPTCHA_ENTERPRISE_SCRIPT_URL = 'https://www.google.com/recaptcha/enterprise.js';\n\nconst LOG_PREFIX = '[ReCaptcha]';\n\nexport class RecaptchaModule {\n _enableReCAPTCHA: boolean = false;\n _recaptchaBackendEndpoint: string = recaptchaFetchApi.getConfig()?.endpoint || '';\n _recaptchaScriptUrl: string = RECAPTCHA_V3_SCRIPT_URL;\n _configStorageKey: string = 'recaptchaConfig';\n _logger: boolean = false;\n\n _log(...args: any[]) {\n this._logger && console.log(LOG_PREFIX, ...args);\n }\n\n _normalizeFormConfigResponse(\n response: any,\n formTypes: string[]\n ): ReCaptchaResponse | undefined {\n const data = response?.data;\n if (!data) return undefined;\n\n const enabledForms: string[] = [];\n let globalConfig: ReCaptchaFormConfigResult | null = null;\n const detectedTypes = new Set<string>();\n\n for (const formType of formTypes) {\n const formData = data[formType];\n\n if (!formData?.is_enabled) continue;\n\n // configurations may be an array or a single object\n const config = Array.isArray(formData.configurations)\n ? formData.configurations[0]\n : formData.configurations;\n\n if (!config) continue;\n\n // Track all reCAPTCHA types across enabled forms, regardless of website_key\n if (config.re_captcha_type) {\n detectedTypes.add(config.re_captcha_type);\n }\n\n // Skip forms with empty website_key — enabled but not usable\n if (!config.website_key) {\n this._log(\n `Skipping ${formType}: enabled but missing website_key`\n );\n continue;\n }\n\n enabledForms.push(formType);\n\n if (!globalConfig) {\n globalConfig = config;\n }\n }\n\n // Abort if mixed reCAPTCHA types detected across enabled forms\n if (detectedTypes.size > 1) {\n console.warn(\n LOG_PREFIX,\n recaptchaMessage.mixedTypesWarning,\n `\\nDetected: ${[...detectedTypes].join(', ')}`\n );\n return undefined;\n }\n\n if (!globalConfig || enabledForms.length === 0) {\n this._log('No enabled forms found in recaptchaFormConfig response');\n return undefined;\n }\n\n // Map ReCaptchaConfiguration fields to the existing recaptchaConfig shape\n const isEnterprise =\n globalConfig.re_captcha_type === 'RECAPTCHA_ENTERPRISE';\n\n this._log(\n `Using reCAPTCHA ${isEnterprise ? 'Enterprise' : 'v3'}`,\n `| Enabled forms: ${enabledForms.join(', ')}`\n );\n\n return {\n data: {\n recaptchaConfig: {\n is_enabled: true,\n website_key: globalConfig.website_key,\n badge_position: globalConfig.badge_position,\n language_code: globalConfig.language_code,\n minimum_score: globalConfig.minimum_score,\n failure_message: globalConfig.validation_failure_message,\n theme: globalConfig.theme,\n forms: enabledForms,\n recaptcha_type: isEnterprise ? 'enterprise' : 'v3',\n },\n },\n };\n }\n\n async _updateBadgePosition(\n badgeId: string,\n config: ReCaptchaModel\n ): Promise<void | null> {\n if (!config) return;\n\n if (config?.badgePosition === 'inline') {\n this._log(`Rendering inline badge for: ${badgeId}`);\n await verifyReCaptchaLoad(\n badgeId,\n config,\n this._logger,\n config.recaptchaType === 'enterprise'\n );\n } else {\n const isBadgeLoaded = await checkRecaptchaBadge();\n\n if (!isBadgeLoaded) return;\n\n const recaptchaBadge = document.querySelector(\n recaptchaBadgeSelector\n ) as HTMLIFrameElement;\n\n const shouldUpdateSrc =\n config.theme &&\n recaptchaBadge &&\n !recaptchaBadge.src.includes('theme=dark') &&\n !recaptchaBadge.src.includes('theme=light');\n\n if (shouldUpdateSrc) {\n recaptchaBadge.setAttribute(\n 'src',\n `${recaptchaBadge.src}&theme=${config.theme}`\n );\n }\n }\n }\n\n async _addRecaptchaScript(): Promise<void> {\n const config = await this._loadConfig();\n\n if (!document.getElementById('recaptchaId') && config) {\n const webApiKey = config.websiteKey;\n const isBadgeGlobal = config.badgePosition === 'inline';\n const languageCode = config.languageCode;\n\n if (!webApiKey) {\n this._log('No website key found, skipping script injection');\n return;\n }\n\n const scriptUrl =\n config.recaptchaType === 'enterprise'\n ? RECAPTCHA_ENTERPRISE_SCRIPT_URL\n : this._recaptchaScriptUrl;\n\n const script = document.createElement('script');\n script.setAttribute('id', 'recaptchaId');\n script.defer = true;\n script.src = isBadgeGlobal\n ? `${scriptUrl}?render=${webApiKey}&badge=none&hl=${languageCode}`\n : `${scriptUrl}?render=${webApiKey}&badge=${config.badgePosition}&hl=${languageCode}`;\n\n this._log(`Loading script: ${script.src}`);\n document.head.appendChild(script);\n }\n }\n\n async _fetchStoreConfig(): Promise<ReCaptchaResponse | undefined> {\n try {\n const formTypes = Object.keys(typeDefaultForm);\n const query = buildRecaptchaFormConfigQuery(formTypes);\n\n this._log(`Fetching config for forms: ${formTypes.join(', ')}`);\n\n const response = await recaptchaFetchApi.fetchGraphQl(query, {\n method: 'GET',\n cache: 'force-cache',\n });\n\n if (response?.errors?.length) {\n this._logger && console.error(response.errors[0].message);\n\n return;\n }\n\n return this._normalizeFormConfigResponse(response, formTypes);\n } catch (error) {\n this._logger && console.error(`${recaptchaMessage.failedFetch}:`, error);\n }\n }\n\n async _loadConfig(): Promise<ReCaptchaModel | null> {\n const config = await getConfigStorage(this._configStorageKey);\n\n if (!config) {\n this._logger && console.error(recaptchaMessage.failedGetStorageConfig);\n\n return null;\n }\n\n this._enableReCAPTCHA = !!config.isEnabled;\n\n return config;\n }\n\n setEndpoint(url: string) {\n if (!url) return;\n\n this._recaptchaBackendEndpoint = url;\n recaptchaFetchApi.setEndpoint(url);\n }\n\n async setConfig(configList: PropsFormTypes[]) {\n try {\n const config = await this._fetchStoreConfig();\n\n if (!config?.data?.recaptchaConfig) {\n this._log('No reCAPTCHA config returned, clearing storage');\n sessionStorage.removeItem(this._configStorageKey);\n return;\n }\n\n const transformConfig: ReCaptchaModel = convertKeysToCamelCase(\n config?.data?.recaptchaConfig\n );\n\n const extendedRecaptchaConfig = extendConfig(transformConfig, configList);\n\n if (extendedRecaptchaConfig) {\n this._log('Config stored:', {\n type: extendedRecaptchaConfig.recaptchaType ?? 'v3',\n enabled: extendedRecaptchaConfig.isEnabled,\n badge: extendedRecaptchaConfig.badgePosition,\n forms: extendedRecaptchaConfig.forms,\n });\n setConfigStorage(\n this._configStorageKey,\n extendedRecaptchaConfig,\n this._logger\n );\n }\n } catch (error) {\n this._logger &&\n console.error(recaptchaMessage.failedSetStorageConfig, error);\n\n sessionStorage.removeItem(this._configStorageKey);\n }\n }\n\n async initReCaptcha(lazyLoadTimeout = 3000) {\n // IIFE added to fix SonarQube error \"Promise returned in function argument where a void return was expected\"\n setTimeout(() => {\n (async () => {\n try {\n const config = await this._loadConfig();\n\n if (!config?.forms || !config.isEnabled) {\n this._log('reCAPTCHA disabled or no forms configured, skipping init');\n return;\n }\n\n this._log(\n `Initializing reCAPTCHA (type: ${config.recaptchaType ?? 'v3'}, badge: ${config.badgePosition})`\n );\n\n await this._addRecaptchaScript();\n\n if (config.badgePosition === 'inline') {\n await Promise.all(\n (config.forms as PropsFormTypes[]).map((element) =>\n this._updateBadgePosition(element.badgeId, config)\n )\n );\n } else {\n await this._updateBadgePosition('', config);\n }\n } catch (error) {\n this._logger &&\n console.error(recaptchaMessage.failedInitializing, error);\n }\n })();\n }, lazyLoadTimeout);\n }\n\n async verifyReCaptcha(): Promise<string | undefined> {\n try {\n const config = await this._loadConfig();\n\n if (!config?.forms || !config.websiteKey || !config.isEnabled) {\n this._log('verifyReCaptcha skipped: reCAPTCHA not enabled or missing config');\n return undefined;\n }\n\n this._log(\n `Requesting token (type: ${config.recaptchaType ?? 'v3'})`\n );\n\n const token = await getRecaptchaToken(\n config.websiteKey,\n config.recaptchaType === 'enterprise'\n );\n\n this._log('Token obtained successfully');\n\n return token;\n } catch (error) {\n this._logger && console.error(error);\n }\n }\n\n enableLogger(logger: boolean) {\n this._logger = logger;\n }\n\n getMethods() {\n return {\n enableLogger: this.enableLogger.bind(this),\n setEndpoint: this.setEndpoint.bind(this),\n setConfig: this.setConfig.bind(this),\n initReCaptcha: this.initReCaptcha.bind(this),\n verifyReCaptcha: this.verifyReCaptcha.bind(this),\n };\n }\n}\n\nconst recaptcha = new RecaptchaModule();\n\nconst { initReCaptcha, verifyReCaptcha, setEndpoint, setConfig, enableLogger } =\n recaptcha.getMethods();\n\nexport { setEndpoint, setConfig, initReCaptcha, verifyReCaptcha, enableLogger };\n"],"names":["recaptchaMessage","typeDefaultForm","recaptchaBadgeSelector","extendConfig","config","modifyParams","modifyForm","el","getConfigStorage","storageKey","retries","delay","storedConfig","resolve","setConfigStorage","logger","error","waitForElement","selector","reject","observer","checkRecaptchaBadge","convertKeysToCamelCase","obj","camelCaseKey","key","_","letter","result","newKey","failedExecutionRecaptcha","getRecaptchaToken","websiteKey","isEnterprise","waitForReCaptcha","obs","observerOptions","verifyReCaptchaLoad","badgeId","api","badgeContainers","element","RECAPTCHA_FORM_CONFIG_FIELDS","buildRecaptchaFormConfigQuery","formTypes","formType","recaptchaFetchApi","FetchGraphQL","RECAPTCHA_V3_SCRIPT_URL","RECAPTCHA_ENTERPRISE_SCRIPT_URL","LOG_PREFIX","RecaptchaModule","_a","args","response","data","enabledForms","globalConfig","detectedTypes","formData","recaptchaBadge","webApiKey","isBadgeGlobal","languageCode","scriptUrl","script","query","url","configList","transformConfig","_b","extendedRecaptchaConfig","lazyLoadTimeout","token","recaptcha","initReCaptcha","verifyReCaptcha","setEndpoint","setConfig","enableLogger"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"recaptcha.js","sources":["@dropins/tools/src/recaptcha/configs/message.config.ts","@dropins/tools/src/recaptcha/configs/typeForms.config.ts","@dropins/tools/src/recaptcha/configs/recaptchaBadgeSelector.config.ts","@dropins/tools/src/recaptcha/lib/_extendConfig.ts","@dropins/tools/src/recaptcha/lib/_storageConfig.ts","@dropins/tools/src/recaptcha/lib/_checkRecaptchaBadge.ts","@dropins/tools/src/recaptcha/lib/_convertKeysToCamelCase.ts","@dropins/tools/src/recaptcha/services/recaptcha.service.ts","@dropins/tools/src/recaptcha/graphql/recaptchaConfig.graphql.ts","@dropins/tools/src/recaptcha/index.ts"],"sourcesContent":["/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nexport const recaptchaMessage = {\n failedFetch: 'Failed to fetch config from backend with status:',\n failedSetStorageConfig: 'Failed to set storage config',\n failedGetStorageConfig: 'Configuration could not be loaded.',\n failedExecutionRecaptcha: 'Recaptcha execution failed',\n failedInitializing: 'An error occurred while initializing ReCaptcha:',\n mixedTypesWarning:\n 'Multiple reCAPTCHA types detected across forms (both v3 and Enterprise). ' +\n 'This configuration is not supported — all forms must use the same reCAPTCHA type. ' +\n 'Please update your configuration in Commerce Admin '\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nexport const typeDefaultForm: Record<string, string> = {\n PLACE_ORDER: 'placeOrder',\n CONTACT: 'contactUs',\n CUSTOMER_LOGIN: 'generateCustomerToken',\n CUSTOMER_FORGOT_PASSWORD: 'requestPasswordResetEmail',\n CUSTOMER_CREATE: 'createCustomerV2',\n COMPANY_CREATE: 'createCompany',\n CUSTOMER_EDIT: 'updateCustomerV2',\n NEWSLETTER: 'subscribeEmailToNewsletter',\n PRODUCT_REVIEW: 'createProductReview',\n SENDFRIEND: 'SENDFRIEND',\n BRAINTREE: 'BRAINTREE',\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nexport const recaptchaBadgeSelector = '.grecaptcha-badge iframe';","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nimport { ReCaptchaModel } from '../types/recaptcha.types';\nimport { typeDefaultForm } from '../configs/typeForms.config';\n\nexport const extendConfig = (\n config: ReCaptchaModel,\n modifyParams: any[]\n): ReCaptchaModel | undefined => {\n if (config && config.forms) {\n const modifyForm = config.forms.concat(modifyParams).map((el) => {\n if (typeof el !== 'string') return { ...el, enabledBadgePlace: false };\n\n return {\n badgeId: typeDefaultForm[el],\n enabledBadgePlace: false,\n };\n });\n\n return { ...config, forms: [...new Set(modifyForm)] };\n }\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nimport { recaptchaMessage } from '../configs';\nimport { ReCaptchaModel } from '../types/recaptcha.types';\n\nconst getConfigStorage = async (\n storageKey: string,\n retries = 1,\n delay = 1000\n): Promise<ReCaptchaModel | null> => {\n const storedConfig = sessionStorage.getItem(storageKey);\n\n if (storedConfig !== null) {\n return JSON.parse(storedConfig);\n } else if (retries > 0) {\n await new Promise((resolve) => setTimeout(resolve, delay));\n\n return getConfigStorage(storageKey, retries - 1, delay);\n }\n\n return null;\n};\n\nconst setConfigStorage = (\n storageKey: string,\n config: ReCaptchaModel,\n logger: boolean\n) => {\n if (!storageKey || !config.websiteKey) return null;\n\n try {\n sessionStorage.setItem(storageKey, JSON.stringify(config));\n } catch (error) {\n logger && console.error(recaptchaMessage.failedSetStorageConfig, error);\n return null;\n }\n};\n\nexport { getConfigStorage, setConfigStorage };\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nimport { recaptchaBadgeSelector } from '../configs';\n\nconst waitForElement = (selector: string): Promise<void> => {\n return new Promise((resolve, reject) => {\n try {\n // Check if the element is already in the DOM\n if (document.querySelector(selector)) {\n resolve();\n return;\n }\n\n // Create an observer to watch for changes\n const observer = new MutationObserver(() => {\n if (document.querySelector(selector)) {\n resolve();\n observer.disconnect();\n }\n });\n\n // Start observing the body for child changes only\n observer.observe(document.body, {\n childList: true,\n subtree: false,\n });\n } catch (error) {\n reject(error);\n }\n });\n};\n\nexport const checkRecaptchaBadge = async (): Promise<boolean> => {\n try {\n await waitForElement(recaptchaBadgeSelector);\n return true;\n } catch (error) {\n return false;\n }\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nexport const convertKeysToCamelCase = (obj: {\n [key: string]: any;\n}): { [key: string]: string | number | boolean } => {\n const camelCaseKey = (key: string): string => {\n return key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());\n };\n\n return Object.keys(obj).reduce((result, key) => {\n const newKey = camelCaseKey(key);\n result[newKey] = obj[key];\n return result;\n }, {} as { [key: string]: any });\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nimport { recaptchaMessage } from '../configs';\nimport {\n MutationObserverInit,\n ReCaptchaModel,\n} from '../types/recaptcha.types';\nconst { failedExecutionRecaptcha } = recaptchaMessage;\n\nexport const getRecaptchaToken = async (\n websiteKey: string,\n isEnterprise = false\n): Promise<string> => {\n if (!(window as any).grecaptcha) {\n return Promise.reject(failedExecutionRecaptcha);\n }\n\n try {\n const token = isEnterprise\n ? await window.grecaptcha.enterprise.execute(websiteKey, {\n action: 'click',\n })\n : await window.grecaptcha.execute(websiteKey, {\n action: 'click',\n });\n\n return token;\n } catch (error) {\n return Promise.reject(`${failedExecutionRecaptcha} : ${error}`);\n }\n};\n\nexport const waitForReCaptcha = () => {\n return new Promise((resolve) => {\n const observer = new MutationObserver((_, obs) => {\n if (window.grecaptcha) {\n obs.disconnect();\n resolve(true);\n }\n });\n\n const observerOptions: MutationObserverInit = {\n childList: true,\n subtree: true,\n attributes: true,\n };\n\n observer.observe(document.body, observerOptions);\n });\n};\n\nexport const verifyReCaptchaLoad = async (\n badgeId: string,\n config: ReCaptchaModel,\n logger: boolean,\n isEnterprise = false\n): Promise<void> => {\n if (!window.grecaptcha) {\n await waitForReCaptcha();\n }\n\n const api = isEnterprise ? grecaptcha.enterprise : grecaptcha;\n\n return api.ready(() => {\n const badgeContainers = document.querySelectorAll(`#${badgeId}`);\n\n if (!badgeContainers.length) return;\n\n // Handle the case when multiple instances of the drop-in container rendered on the same page\n\n badgeContainers.forEach(\n (element) => (element.id = `${element.id}_${Math.random().toString(36)}`) // NOSONAR\n );\n\n badgeContainers.forEach((element) => {\n if (element.innerHTML === '') {\n try {\n api.render(element.id, {\n sitekey: config.websiteKey as string,\n badge: config.badgePosition,\n size: 'invisible',\n theme: config.theme ?? 'light',\n });\n } catch (error) {\n logger && console.error(error);\n }\n }\n });\n });\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\nconst RECAPTCHA_FORM_CONFIG_FIELDS = `\n is_enabled\n configurations {\n website_key\n badge_position\n language_code\n minimum_score\n re_captcha_type\n technical_failure_message\n validation_failure_message\n theme\n }`;\n\nexport const buildRecaptchaFormConfigQuery = (\n formTypes: string[]\n): string => {\n const queries = formTypes\n .map(\n (formType) =>\n ` ${formType}: recaptchaFormConfig(formType: ${formType}) {${RECAPTCHA_FORM_CONFIG_FIELDS}\n }`\n )\n .join('\\n');\n\n return `query {\\n${queries}\\n}`;\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nimport {\n ReCaptchaResponse,\n PropsFormTypes,\n ReCaptchaModel,\n ReCaptchaFormConfigResult,\n} from './types/recaptcha.types';\nimport {\n recaptchaMessage,\n recaptchaBadgeSelector,\n typeDefaultForm,\n} from './configs';\nimport {\n extendConfig,\n setConfigStorage,\n getConfigStorage,\n checkRecaptchaBadge,\n convertKeysToCamelCase,\n} from './lib';\nimport {\n getRecaptchaToken,\n verifyReCaptchaLoad,\n} from './services/recaptcha.service';\nimport { buildRecaptchaFormConfigQuery } from './graphql/recaptchaConfig.graphql';\n\nimport { FetchGraphQL } from '@adobe-commerce/fetch-graphql';\n\nexport const recaptchaFetchApi = new FetchGraphQL().getMethods();\n\nconst RECAPTCHA_V3_SCRIPT_URL = 'https://www.google.com/recaptcha/api.js';\nconst RECAPTCHA_ENTERPRISE_SCRIPT_URL = 'https://www.google.com/recaptcha/enterprise.js';\n\nconst LOG_PREFIX = '[ReCaptcha]';\n\nexport class RecaptchaModule {\n _enableReCAPTCHA: boolean = false;\n _recaptchaBackendEndpoint: string = recaptchaFetchApi.getConfig()?.endpoint || '';\n _recaptchaScriptUrl: string = RECAPTCHA_V3_SCRIPT_URL;\n _configStorageKey: string = 'recaptchaConfig';\n _logger: boolean = false;\n\n _log(...args: any[]) {\n this._logger && console.log(LOG_PREFIX, ...args);\n }\n\n _normalizeFormConfigResponse(\n response: any,\n formTypes: string[]\n ): ReCaptchaResponse | undefined {\n const data = response?.data;\n if (!data) return undefined;\n\n const enabledForms: string[] = [];\n let globalConfig: ReCaptchaFormConfigResult | null = null;\n const detectedTypes = new Set<string>();\n\n for (const formType of formTypes) {\n const formData = data[formType];\n\n if (!formData?.is_enabled) continue;\n\n // configurations may be an array or a single object\n const config = Array.isArray(formData.configurations)\n ? formData.configurations[0]\n : formData.configurations;\n\n if (!config) continue;\n\n // Track all reCAPTCHA types across enabled forms, regardless of website_key\n if (config.re_captcha_type) {\n detectedTypes.add(config.re_captcha_type);\n }\n\n // Skip forms with empty website_key — enabled but not usable\n if (!config.website_key) {\n this._log(\n `Skipping ${formType}: enabled but missing website_key`\n );\n continue;\n }\n\n enabledForms.push(formType);\n\n if (!globalConfig) {\n globalConfig = config;\n }\n }\n\n // Abort if mixed reCAPTCHA types detected across enabled forms\n if (detectedTypes.size > 1) {\n console.warn(\n LOG_PREFIX,\n recaptchaMessage.mixedTypesWarning,\n `\\nDetected: ${[...detectedTypes].join(', ')}`\n );\n return undefined;\n }\n\n if (!globalConfig || enabledForms.length === 0) {\n this._log('No enabled forms found in recaptchaFormConfig response');\n return undefined;\n }\n\n // Map ReCaptchaConfiguration fields to the existing recaptchaConfig shape\n const isEnterprise =\n globalConfig.re_captcha_type === 'RECAPTCHA_ENTERPRISE';\n\n this._log(\n `Using reCAPTCHA ${isEnterprise ? 'Enterprise' : 'v3'}`,\n `| Enabled forms: ${enabledForms.join(', ')}`\n );\n\n return {\n data: {\n recaptchaConfig: {\n is_enabled: true,\n website_key: globalConfig.website_key,\n badge_position: globalConfig.badge_position,\n language_code: globalConfig.language_code,\n minimum_score: globalConfig.minimum_score,\n failure_message: globalConfig.validation_failure_message,\n theme: globalConfig.theme,\n forms: enabledForms,\n recaptcha_type: isEnterprise ? 'enterprise' : 'v3',\n },\n },\n };\n }\n\n async _updateBadgePosition(\n badgeId: string,\n config: ReCaptchaModel\n ): Promise<void | null> {\n if (!config) return;\n\n if (config?.badgePosition === 'inline') {\n this._log(`Rendering inline badge for: ${badgeId}`);\n await verifyReCaptchaLoad(\n badgeId,\n config,\n this._logger,\n config.recaptchaType === 'enterprise'\n );\n } else {\n const isBadgeLoaded = await checkRecaptchaBadge();\n\n if (!isBadgeLoaded) return;\n\n const recaptchaBadge = document.querySelector(\n recaptchaBadgeSelector\n ) as HTMLIFrameElement;\n\n const shouldUpdateSrc =\n config.theme &&\n recaptchaBadge &&\n !recaptchaBadge.src.includes('theme=dark') &&\n !recaptchaBadge.src.includes('theme=light');\n\n if (shouldUpdateSrc) {\n recaptchaBadge.setAttribute(\n 'src',\n `${recaptchaBadge.src}&theme=${config.theme}`\n );\n }\n }\n }\n\n async _addRecaptchaScript(): Promise<void> {\n const config = await this._loadConfig();\n\n if (!document.getElementById('recaptchaId') && config) {\n const webApiKey = config.websiteKey;\n const isBadgeGlobal = config.badgePosition === 'inline';\n const languageCode = config.languageCode;\n\n if (!webApiKey) {\n this._log('No website key found, skipping script injection');\n return;\n }\n\n const scriptUrl =\n config.recaptchaType === 'enterprise'\n ? RECAPTCHA_ENTERPRISE_SCRIPT_URL\n : this._recaptchaScriptUrl;\n\n const script = document.createElement('script');\n script.setAttribute('id', 'recaptchaId');\n script.defer = true;\n script.src = isBadgeGlobal\n ? `${scriptUrl}?render=${webApiKey}&badge=none&hl=${languageCode}`\n : `${scriptUrl}?render=${webApiKey}&badge=${config.badgePosition}&hl=${languageCode}`;\n\n this._log(`Loading script: ${script.src}`);\n document.head.appendChild(script);\n }\n }\n\n async _fetchStoreConfig(): Promise<ReCaptchaResponse | undefined> {\n try {\n const formTypes = Object.keys(typeDefaultForm);\n const query = buildRecaptchaFormConfigQuery(formTypes);\n\n this._log(`Fetching config for forms: ${formTypes.join(', ')}`);\n\n const response = await recaptchaFetchApi.fetchGraphQl(query, {\n method: 'GET',\n cache: 'force-cache',\n });\n\n if (response?.errors?.length) {\n this._logger && console.error(response.errors[0].message);\n\n return;\n }\n\n return this._normalizeFormConfigResponse(response, formTypes);\n } catch (error) {\n this._logger && console.error(`${recaptchaMessage.failedFetch}:`, error);\n }\n }\n\n async _loadConfig(): Promise<ReCaptchaModel | null> {\n const config = await getConfigStorage(this._configStorageKey);\n\n if (!config) {\n this._logger && console.error(recaptchaMessage.failedGetStorageConfig);\n\n return null;\n }\n\n this._enableReCAPTCHA = !!config.isEnabled;\n\n return config;\n }\n\n setEndpoint(url: string) {\n if (!url) return;\n\n this._recaptchaBackendEndpoint = url;\n recaptchaFetchApi.setEndpoint(url);\n }\n\n async setConfig(configList: PropsFormTypes[]) {\n try {\n const config = await this._fetchStoreConfig();\n\n if (!config?.data?.recaptchaConfig) {\n this._log('No reCAPTCHA config returned, clearing storage');\n sessionStorage.removeItem(this._configStorageKey);\n return;\n }\n\n const transformConfig: ReCaptchaModel = convertKeysToCamelCase(\n config?.data?.recaptchaConfig\n );\n\n const extendedRecaptchaConfig = extendConfig(transformConfig, configList);\n\n if (extendedRecaptchaConfig) {\n this._log('Config stored:', {\n type: extendedRecaptchaConfig.recaptchaType ?? 'v3',\n enabled: extendedRecaptchaConfig.isEnabled,\n badge: extendedRecaptchaConfig.badgePosition,\n forms: extendedRecaptchaConfig.forms,\n });\n setConfigStorage(\n this._configStorageKey,\n extendedRecaptchaConfig,\n this._logger\n );\n }\n } catch (error) {\n this._logger &&\n console.error(recaptchaMessage.failedSetStorageConfig, error);\n\n sessionStorage.removeItem(this._configStorageKey);\n }\n }\n\n async initReCaptcha(lazyLoadTimeout = 3000) {\n // IIFE added to fix SonarQube error \"Promise returned in function argument where a void return was expected\"\n setTimeout(() => {\n (async () => {\n try {\n const config = await this._loadConfig();\n\n if (!config?.forms || !config.isEnabled) {\n this._log('reCAPTCHA disabled or no forms configured, skipping init');\n return;\n }\n\n this._log(\n `Initializing reCAPTCHA (type: ${config.recaptchaType ?? 'v3'}, badge: ${config.badgePosition})`\n );\n\n await this._addRecaptchaScript();\n\n if (config.badgePosition === 'inline') {\n await Promise.all(\n (config.forms as PropsFormTypes[]).map((element) =>\n this._updateBadgePosition(element.badgeId, config)\n )\n );\n } else {\n await this._updateBadgePosition('', config);\n }\n } catch (error) {\n this._logger &&\n console.error(recaptchaMessage.failedInitializing, error);\n }\n })();\n }, lazyLoadTimeout);\n }\n\n async verifyReCaptcha(): Promise<string | undefined> {\n try {\n const config = await this._loadConfig();\n\n if (!config?.forms || !config.websiteKey || !config.isEnabled) {\n this._log('verifyReCaptcha skipped: reCAPTCHA not enabled or missing config');\n return undefined;\n }\n\n this._log(\n `Requesting token (type: ${config.recaptchaType ?? 'v3'})`\n );\n\n const token = await getRecaptchaToken(\n config.websiteKey,\n config.recaptchaType === 'enterprise'\n );\n\n this._log('Token obtained successfully');\n\n return token;\n } catch (error) {\n this._logger && console.error(error);\n }\n }\n\n enableLogger(logger: boolean) {\n this._logger = logger;\n }\n\n getMethods() {\n return {\n enableLogger: this.enableLogger.bind(this),\n setEndpoint: this.setEndpoint.bind(this),\n setConfig: this.setConfig.bind(this),\n initReCaptcha: this.initReCaptcha.bind(this),\n verifyReCaptcha: this.verifyReCaptcha.bind(this),\n };\n }\n}\n\nconst recaptcha = new RecaptchaModule();\n\nconst { initReCaptcha, verifyReCaptcha, setEndpoint, setConfig, enableLogger } =\n recaptcha.getMethods();\n\nexport { setEndpoint, setConfig, initReCaptcha, verifyReCaptcha, enableLogger };\n"],"names":["recaptchaMessage","typeDefaultForm","recaptchaBadgeSelector","extendConfig","config","modifyParams","modifyForm","el","getConfigStorage","storageKey","retries","delay","storedConfig","resolve","setConfigStorage","logger","error","waitForElement","selector","reject","observer","checkRecaptchaBadge","convertKeysToCamelCase","obj","camelCaseKey","key","_","letter","result","newKey","failedExecutionRecaptcha","getRecaptchaToken","websiteKey","isEnterprise","waitForReCaptcha","obs","observerOptions","verifyReCaptchaLoad","badgeId","api","badgeContainers","element","RECAPTCHA_FORM_CONFIG_FIELDS","buildRecaptchaFormConfigQuery","formTypes","formType","recaptchaFetchApi","FetchGraphQL","RECAPTCHA_V3_SCRIPT_URL","RECAPTCHA_ENTERPRISE_SCRIPT_URL","LOG_PREFIX","RecaptchaModule","_a","args","response","data","enabledForms","globalConfig","detectedTypes","formData","recaptchaBadge","webApiKey","isBadgeGlobal","languageCode","scriptUrl","script","query","url","configList","transformConfig","_b","extendedRecaptchaConfig","lazyLoadTimeout","token","recaptcha","initReCaptcha","verifyReCaptcha","setEndpoint","setConfig","enableLogger"],"mappings":"kDASO,MAAMA,EAAmB,CAC9B,YAAa,mDACb,uBAAwB,+BACxB,uBAAwB,qCACxB,yBAA0B,6BAC1B,mBAAoB,kDACpB,kBACE,gNAGJ,ECVaC,EAA0C,CACrD,YAAa,aACb,QAAS,YACT,eAAgB,wBAChB,yBAA0B,4BAC1B,gBAAiB,mBACjB,eAAgB,gBAChB,cAAe,mBACf,WAAY,6BACZ,eAAgB,sBAChB,WAAY,aACZ,UAAW,WACb,ECZaC,EAAyB,2BCGzBC,EAAe,CAC1BC,EACAC,IAC+B,CAC/B,GAAID,GAAUA,EAAO,MAAO,CAC1B,MAAME,EAAaF,EAAO,MAAM,OAAOC,CAAY,EAAE,IAAKE,GACpD,OAAOA,GAAO,SAAiB,CAAE,GAAGA,EAAI,kBAAmB,EAAA,EAExD,CACL,QAASN,EAAgBM,CAAE,EAC3B,kBAAmB,EAAA,CAEtB,EAED,MAAO,CAAE,GAAGH,EAAQ,MAAO,CAAC,GAAG,IAAI,IAAIE,CAAU,CAAC,CAAA,CACpD,CACF,EChBME,EAAmB,MACvBC,EACAC,EAAU,EACVC,EAAQ,MAC2B,CACnC,MAAMC,EAAe,eAAe,QAAQH,CAAU,EAEtD,OAAIG,IAAiB,KACZ,KAAK,MAAMA,CAAY,EACrBF,EAAU,GACnB,MAAM,IAAI,QAASG,GAAY,WAAWA,EAASF,CAAK,CAAC,EAElDH,EAAiBC,EAAYC,EAAU,EAAGC,CAAK,GAGjD,IACT,EAEMG,EAAmB,CACvBL,EACAL,EACAW,IACG,CACH,GAAI,CAACN,GAAc,CAACL,EAAO,WAAY,OAAO,KAE9C,GAAI,CACF,eAAe,QAAQK,EAAY,KAAK,UAAUL,CAAM,CAAC,CAC3D,OAASY,EAAO,CACd,OAAAD,GAAU,QAAQ,MAAMf,EAAiB,uBAAwBgB,CAAK,EAC/D,IACT,CACF,EChCMC,EAAkBC,GACf,IAAI,QAAQ,CAACL,EAASM,IAAW,CACtC,GAAI,CAEF,GAAI,SAAS,cAAcD,CAAQ,EAAG,CACpCL,EAAA,EACA,MACF,CAGA,MAAMO,EAAW,IAAI,iBAAiB,IAAM,CACtC,SAAS,cAAcF,CAAQ,IACjCL,EAAA,EACAO,EAAS,WAAA,EAEb,CAAC,EAGDA,EAAS,QAAQ,SAAS,KAAM,CAC9B,UAAW,GACX,QAAS,EAAA,CACV,CACH,OAASJ,EAAO,CACdG,EAAOH,CAAK,CACd,CACF,CAAC,EAGUK,EAAsB,SAA8B,CAC/D,GAAI,CACF,aAAMJ,EAAef,CAAsB,EACpC,EACT,MAAgB,CACd,MAAO,EACT,CACF,ECrCaoB,EAA0BC,GAEa,CAClD,MAAMC,EAAgBC,GACbA,EAAI,QAAQ,YAAa,CAACC,EAAGC,IAAWA,EAAO,aAAa,EAGrE,OAAO,OAAO,KAAKJ,CAAG,EAAE,OAAO,CAACK,EAAQH,IAAQ,CAC9C,MAAMI,EAASL,EAAaC,CAAG,EAC/B,OAAAG,EAAOC,CAAM,EAAIN,EAAIE,CAAG,EACjBG,CACT,EAAG,CAAA,CAA4B,CACjC,ECPM,CAAE,yBAAAE,GAA6B9B,EAExB+B,EAAoB,MAC/BC,EACAC,EAAe,KACK,CACpB,GAAI,CAAE,OAAe,WACnB,OAAO,QAAQ,OAAOH,CAAwB,EAGhD,GAAI,CASF,OARcG,EACV,MAAM,OAAO,WAAW,WAAW,QAAQD,EAAY,CACrD,OAAQ,OAAA,CACT,EACD,MAAM,OAAO,WAAW,QAAQA,EAAY,CAC1C,OAAQ,OAAA,CACT,CAGP,OAAShB,EAAO,CACd,OAAO,QAAQ,OAAO,GAAGc,CAAwB,MAAMd,CAAK,EAAE,CAChE,CACF,EAEakB,EAAmB,IACvB,IAAI,QAASrB,GAAY,CAC9B,MAAMO,EAAW,IAAI,iBAAiB,CAACM,EAAGS,IAAQ,CAC5C,OAAO,aACTA,EAAI,WAAA,EACJtB,EAAQ,EAAI,EAEhB,CAAC,EAEKuB,EAAwC,CAC5C,UAAW,GACX,QAAS,GACT,WAAY,EAAA,EAGdhB,EAAS,QAAQ,SAAS,KAAMgB,CAAe,CACjD,CAAC,EAGUC,EAAsB,MACjCC,EACAlC,EACAW,EACAkB,EAAe,KACG,CACb,OAAO,YACV,MAAMC,EAAA,EAGR,MAAMK,EAAMN,EAAe,WAAW,WAAa,WAEnD,OAAOM,EAAI,MAAM,IAAM,CACrB,MAAMC,EAAkB,SAAS,iBAAiB,IAAIF,CAAO,EAAE,EAE1DE,EAAgB,SAIrBA,EAAgB,QACbC,GAAaA,EAAQ,GAAK,GAAGA,EAAQ,EAAE,IAAI,KAAK,OAAA,EAAS,SAAS,EAAE,CAAC,EAAA,EAGxED,EAAgB,QAASC,GAAY,CACnC,GAAIA,EAAQ,YAAc,GACxB,GAAI,CACFF,EAAI,OAAOE,EAAQ,GAAI,CACrB,QAASrC,EAAO,WAChB,MAAOA,EAAO,cACd,KAAM,YACN,MAAOA,EAAO,OAAS,OAAA,CACxB,CACH,OAASY,EAAO,CACdD,GAAU,QAAQ,MAAMC,CAAK,CAC/B,CAEJ,CAAC,EACH,CAAC,CACH,ECxFM0B,EAA+B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAaxBC,EACXC,GAUO;AAAA,EARSA,EACb,IACEC,GACC,KAAKA,CAAQ,mCAAmCA,CAAQ,MAAMH,CAA4B;AAAA,IAAA,EAG7F,KAAK;AAAA,CAAI,CAEc;AAAA,GCGfI,EAAoB,IAAIC,EAAA,EAAe,WAAA,EAE9CC,EAA0B,0CAC1BC,EAAkC,iDAElCC,EAAa,cAEZ,MAAMC,CAAgB,CAAtB,aAAA,OACL,KAAA,iBAA4B,GAC5B,KAAA,4BAAoCC,EAAAN,EAAkB,UAAA,IAAlB,YAAAM,EAA+B,WAAY,GAC/E,KAAA,oBAA8BJ,EAC9B,KAAA,kBAA4B,kBAC5B,KAAA,QAAmB,EAAA,CAEnB,QAAQK,EAAa,CACnB,KAAK,SAAW,QAAQ,IAAIH,EAAY,GAAGG,CAAI,CACjD,CAEA,6BACEC,EACAV,EAC+B,CAC/B,MAAMW,EAAOD,GAAA,YAAAA,EAAU,KACvB,GAAI,CAACC,EAAM,OAEX,MAAMC,EAAyB,CAAA,EAC/B,IAAIC,EAAiD,KACrD,MAAMC,MAAoB,IAE1B,UAAWb,KAAYD,EAAW,CAChC,MAAMe,EAAWJ,EAAKV,CAAQ,EAE9B,GAAI,EAACc,GAAA,MAAAA,EAAU,YAAY,SAG3B,MAAMvD,EAAS,MAAM,QAAQuD,EAAS,cAAc,EAChDA,EAAS,eAAe,CAAC,EACzBA,EAAS,eAEb,GAAKvD,EAQL,IALIA,EAAO,iBACTsD,EAAc,IAAItD,EAAO,eAAe,EAItC,CAACA,EAAO,YAAa,CACvB,KAAK,KACH,YAAYyC,CAAQ,mCAAA,EAEtB,QACF,CAEAW,EAAa,KAAKX,CAAQ,EAErBY,IACHA,EAAerD,GAEnB,CAGA,GAAIsD,EAAc,KAAO,EAAG,CAC1B,QAAQ,KACNR,EACAlD,EAAiB,kBACjB;AAAA,YAAe,CAAC,GAAG0D,CAAa,EAAE,KAAK,IAAI,CAAC,EAAA,EAE9C,MACF,CAEA,GAAI,CAACD,GAAgBD,EAAa,SAAW,EAAG,CAC9C,KAAK,KAAK,wDAAwD,EAClE,MACF,CAGA,MAAMvB,EACJwB,EAAa,kBAAoB,uBAEnC,YAAK,KACH,mBAAmBxB,EAAe,aAAe,IAAI,GACrD,oBAAoBuB,EAAa,KAAK,IAAI,CAAC,EAAA,EAGtC,CACL,KAAM,CACJ,gBAAiB,CACf,WAAY,GACZ,YAAaC,EAAa,YAC1B,eAAgBA,EAAa,eAC7B,cAAeA,EAAa,cAC5B,cAAeA,EAAa,cAC5B,gBAAiBA,EAAa,2BAC9B,MAAOA,EAAa,MACpB,MAAOD,EACP,eAAgBvB,EAAe,aAAe,IAAA,CAChD,CACF,CAEJ,CAEA,MAAM,qBACJK,EACAlC,EACsB,CACtB,GAAKA,EAEL,IAAIA,GAAA,YAAAA,EAAQ,iBAAkB,SAC5B,KAAK,KAAK,+BAA+BkC,CAAO,EAAE,EAClD,MAAMD,EACJC,EACAlC,EACA,KAAK,QACLA,EAAO,gBAAkB,YAAA,MAEtB,CAGL,GAAI,CAFkB,MAAMiB,EAAA,EAER,OAEpB,MAAMuC,EAAiB,SAAS,cAC9B1D,CAAA,EAIAE,EAAO,OACPwD,GACA,CAACA,EAAe,IAAI,SAAS,YAAY,GACzC,CAACA,EAAe,IAAI,SAAS,aAAa,GAG1CA,EAAe,aACb,MACA,GAAGA,EAAe,GAAG,UAAUxD,EAAO,KAAK,EAAA,CAGjD,CACF,CAEA,MAAM,qBAAqC,CACzC,MAAMA,EAAS,MAAM,KAAK,YAAA,EAE1B,GAAI,CAAC,SAAS,eAAe,aAAa,GAAKA,EAAQ,CACrD,MAAMyD,EAAYzD,EAAO,WACnB0D,EAAgB1D,EAAO,gBAAkB,SACzC2D,EAAe3D,EAAO,aAE5B,GAAI,CAACyD,EAAW,CACd,KAAK,KAAK,iDAAiD,EAC3D,MACF,CAEA,MAAMG,EACJ5D,EAAO,gBAAkB,aACrB6C,EACA,KAAK,oBAELgB,EAAS,SAAS,cAAc,QAAQ,EAC9CA,EAAO,aAAa,KAAM,aAAa,EACvCA,EAAO,MAAQ,GACfA,EAAO,IAAMH,EACT,GAAGE,CAAS,WAAWH,CAAS,kBAAkBE,CAAY,GAC9D,GAAGC,CAAS,WAAWH,CAAS,UAAUzD,EAAO,aAAa,OAAO2D,CAAY,GAErF,KAAK,KAAK,mBAAmBE,EAAO,GAAG,EAAE,EACzC,SAAS,KAAK,YAAYA,CAAM,CAClC,CACF,CAEA,MAAM,mBAA4D,OAChE,GAAI,CACF,MAAMrB,EAAY,OAAO,KAAK3C,CAAe,EACvCiE,EAAQvB,EAA8BC,CAAS,EAErD,KAAK,KAAK,8BAA8BA,EAAU,KAAK,IAAI,CAAC,EAAE,EAE9D,MAAMU,EAAW,MAAMR,EAAkB,aAAaoB,EAAO,CAC3D,OAAQ,MACR,MAAO,aAAA,CACR,EAED,IAAId,EAAAE,GAAA,YAAAA,EAAU,SAAV,MAAAF,EAAkB,OAAQ,CAC5B,KAAK,SAAW,QAAQ,MAAME,EAAS,OAAO,CAAC,EAAE,OAAO,EAExD,MACF,CAEA,OAAO,KAAK,6BAA6BA,EAAUV,CAAS,CAC9D,OAAS5B,EAAO,CACd,KAAK,SAAW,QAAQ,MAAM,GAAGhB,EAAiB,WAAW,IAAKgB,CAAK,CACzE,CACF,CAEA,MAAM,aAA8C,CAClD,MAAMZ,EAAS,MAAMI,EAAiB,KAAK,iBAAiB,EAE5D,OAAKJ,GAML,KAAK,iBAAmB,CAAC,CAACA,EAAO,UAE1BA,IAPL,KAAK,SAAW,QAAQ,MAAMJ,EAAiB,sBAAsB,EAE9D,KAMX,CAEA,YAAYmE,EAAa,CAClBA,IAEL,KAAK,0BAA4BA,EACjCrB,EAAkB,YAAYqB,CAAG,EACnC,CAEA,MAAM,UAAUC,EAA8B,SAC5C,GAAI,CACF,MAAMhE,EAAS,MAAM,KAAK,kBAAA,EAE1B,GAAI,GAACgD,EAAAhD,GAAA,YAAAA,EAAQ,OAAR,MAAAgD,EAAc,iBAAiB,CAClC,KAAK,KAAK,gDAAgD,EAC1D,eAAe,WAAW,KAAK,iBAAiB,EAChD,MACF,CAEA,MAAMiB,EAAkC/C,GACtCgD,EAAAlE,GAAA,YAAAA,EAAQ,OAAR,YAAAkE,EAAc,eAAA,EAGVC,EAA0BpE,EAAakE,EAAiBD,CAAU,EAEpEG,IACF,KAAK,KAAK,iBAAkB,CAC1B,KAAMA,EAAwB,eAAiB,KAC/C,QAASA,EAAwB,UACjC,MAAOA,EAAwB,cAC/B,MAAOA,EAAwB,KAAA,CAChC,EACDzD,EACE,KAAK,kBACLyD,EACA,KAAK,OAAA,EAGX,OAASvD,EAAO,CACd,KAAK,SACH,QAAQ,MAAMhB,EAAiB,uBAAwBgB,CAAK,EAE9D,eAAe,WAAW,KAAK,iBAAiB,CAClD,CACF,CAEA,MAAM,cAAcwD,EAAkB,IAAM,CAE1C,WAAW,IAAM,EACd,SAAY,CACX,GAAI,CACF,MAAMpE,EAAS,MAAM,KAAK,YAAA,EAE1B,GAAI,EAACA,GAAA,MAAAA,EAAQ,QAAS,CAACA,EAAO,UAAW,CACvC,KAAK,KAAK,0DAA0D,EACpE,MACF,CAEA,KAAK,KACH,iCAAiCA,EAAO,eAAiB,IAAI,YAAYA,EAAO,aAAa,GAAA,EAG/F,MAAM,KAAK,oBAAA,EAEPA,EAAO,gBAAkB,SAC3B,MAAM,QAAQ,IACXA,EAAO,MAA2B,IAAKqC,GACtC,KAAK,qBAAqBA,EAAQ,QAASrC,CAAM,CAAA,CACnD,EAGF,MAAM,KAAK,qBAAqB,GAAIA,CAAM,CAE9C,OAASY,EAAO,CACd,KAAK,SACH,QAAQ,MAAMhB,EAAiB,mBAAoBgB,CAAK,CAC5D,CACF,GAAA,CACF,EAAGwD,CAAe,CACpB,CAEA,MAAM,iBAA+C,CACnD,GAAI,CACF,MAAMpE,EAAS,MAAM,KAAK,YAAA,EAE1B,GAAI,EAACA,GAAA,MAAAA,EAAQ,QAAS,CAACA,EAAO,YAAc,CAACA,EAAO,UAAW,CAC7D,KAAK,KAAK,kEAAkE,EAC5E,MACF,CAEA,KAAK,KACH,2BAA2BA,EAAO,eAAiB,IAAI,GAAA,EAGzD,MAAMqE,EAAQ,MAAM1C,EAClB3B,EAAO,WACPA,EAAO,gBAAkB,YAAA,EAG3B,YAAK,KAAK,6BAA6B,EAEhCqE,CACT,OAASzD,EAAO,CACd,KAAK,SAAW,QAAQ,MAAMA,CAAK,CACrC,CACF,CAEA,aAAaD,EAAiB,CAC5B,KAAK,QAAUA,CACjB,CAEA,YAAa,CACX,MAAO,CACL,aAAc,KAAK,aAAa,KAAK,IAAI,EACzC,YAAa,KAAK,YAAY,KAAK,IAAI,EACvC,UAAW,KAAK,UAAU,KAAK,IAAI,EACnC,cAAe,KAAK,cAAc,KAAK,IAAI,EAC3C,gBAAiB,KAAK,gBAAgB,KAAK,IAAI,CAAA,CAEnD,CACF,CAEA,MAAM2D,EAAY,IAAIvB,EAEhB,CAAE,cAAAwB,EAAe,gBAAAC,EAAiB,YAAAC,EAAa,UAAAC,EAAW,aAAAC,CAAA,EAC9DL,EAAU,WAAA"}
|
|
@@ -18,6 +18,7 @@ declare const _default: {
|
|
|
18
18
|
"increaseLabel": "Increase Quantity",
|
|
19
19
|
"label": "Quantity",
|
|
20
20
|
"errorMessage": "Enter a valid quantity",
|
|
21
|
+
"requiredMessage": "Quantity is required",
|
|
21
22
|
"minQuantityMessage": "Enter at least {{minQuantity}}",
|
|
22
23
|
"maxQuantityMessage": "Maximum quantity is {{maxQuantity}}"
|
|
23
24
|
},
|
|
@@ -28,6 +28,7 @@ export declare const definition: {
|
|
|
28
28
|
increaseLabel: string;
|
|
29
29
|
label: string;
|
|
30
30
|
errorMessage: string;
|
|
31
|
+
requiredMessage: string;
|
|
31
32
|
minQuantityMessage: string;
|
|
32
33
|
maxQuantityMessage: string;
|
|
33
34
|
};
|
|
@@ -212,6 +213,7 @@ export declare const definition: {
|
|
|
212
213
|
increaseLabel: string;
|
|
213
214
|
label: string;
|
|
214
215
|
errorMessage: string;
|
|
216
|
+
requiredMessage: string;
|
|
215
217
|
minQuantityMessage: string;
|
|
216
218
|
maxQuantityMessage: string;
|
|
217
219
|
};
|
|
@@ -398,6 +400,7 @@ export declare const getDefinitionByLanguage: (lang: Lang) => {
|
|
|
398
400
|
increaseLabel: string;
|
|
399
401
|
label: string;
|
|
400
402
|
errorMessage: string;
|
|
403
|
+
requiredMessage: string;
|
|
401
404
|
minQuantityMessage: string;
|
|
402
405
|
maxQuantityMessage: string;
|
|
403
406
|
};
|