@comgate/checkout-js
Version:
Loading wrapper for Comgate Checkout library.
1,002 lines (1,001 loc) • 34.8 kB
JavaScript
/*
* @comgate/checkout-js v3.0.1 (https://www.npmjs.com/package/@comgate/checkout-js)
* Copyright 2026 - Comgate a.s.
* Licensed under EULA (https://www.unpkg.com/@comgate/checkout-js@3.0.1/LICENSE)
* Build datetime - 2026-06-11T05:57:52Z
*/
const VERSION_DEV = "dev";
const VERSION_1 = "1";
const VERSION_2 = "2";
const VERSION_3 = "3";
const ENVIRONMENT_DEV = "dev";
const ENVIRONMENT_TEST = "test";
const ENVIRONMENT_PROD = "prod";
const ENVIRONMENT_PREFERRED = ENVIRONMENT_PROD;
const ENVIRONMENT_DEV_CDN_URL = "https://localhost:8787/sdk/";
const ENVIRONMENT_TEST_CDN_URL = "https://checkout.comgate-test.cz/sdk/";
const ENVIRONMENT_PROD_CDN_URL = "https://checkout.comgate.cz/sdk/";
const ENVIRONMENT_DEV_API_URL = "https://payments-web/";
const ENVIRONMENT_TEST_API_URL = "https://payments.comgate-test.cz/";
const ENVIRONMENT_PROD_API_URL = "https://payments.comgate.cz/";
const TIMEOUT_LOAD_DEFAULT = 1e4;
const TIMEOUT_LOAD_MIN = 500;
const TIMEOUT_LOAD_MAX = 3e4;
const TIMEOUT_FETCH_DEFAULT = 5e3;
const TIMEOUT_FETCH_MIN = 500;
const TIMEOUT_FETCH_MAX = 15e3;
const checkoutEnvironments = [ENVIRONMENT_DEV, ENVIRONMENT_TEST, ENVIRONMENT_PROD];
const VERSION_PREFERRED = VERSION_3;
const checkoutVersions = [VERSION_2, VERSION_3, VERSION_DEV];
const checkoutIdRegex = /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i;
const versionRegex = new RegExp(`^([23]\.[0-9]+\.[0-9]+|${checkoutVersions.join("|")})$`, "i");
const semverRegex = new RegExp(`^([23]\.[0-9]+\.[0-9]+)$`, "i");
const MODULE_LOADER = "loader";
const MODULE_CORE = "core";
const FILE_MODULE_CORE = "checkout-core.min.js";
const moduleCore = {
boundName: "comgateCheckoutCore",
name: MODULE_CORE,
events: {
ready: "ComgateCheckoutCoreLoaded"
},
mountPoint: ["comgate", "checkout", "core"],
file: FILE_MODULE_CORE
};
const MODULE_APPLEPAY = "applepay";
const FILE_MODULE_APPLEPAY = "checkout-apple-pay.min.js";
const moduleApplePay = {
boundName: "comgateCheckoutApplePay",
name: MODULE_APPLEPAY,
events: {
ready: "ComgateCheckoutApplePayLoaded"
},
mountPoint: ["comgate", "checkout", "applepay"],
file: FILE_MODULE_APPLEPAY
};
const MODULE_GOOGLEPAY = "googlepay";
const FILE_MODULE_GOOGLEPAY = "checkout-google-pay.min.js";
const moduleGooglePay = {
boundName: "comgateCheckoutGooglePay",
name: MODULE_GOOGLEPAY,
events: {
ready: "ComgateCheckoutGooglePayLoaded"
},
mountPoint: ["comgate", "checkout", "googlepay"],
file: FILE_MODULE_GOOGLEPAY
};
const MODULE_CARD = "card";
const FILE_MODULE_CARD = "checkout-card.min.js";
const moduleCard = {
boundName: "comgateCheckoutCard",
name: MODULE_CARD,
events: {
ready: "ComgateCheckoutCardLoaded"
},
mountPoint: ["comgate", "checkout", "card"],
file: FILE_MODULE_CARD
};
const EVENT_MODULES_LOADED = "comgate-checkout-js-module-loaded";
const MODULE_LOAD_SUCCESSFULLY = "true";
const MODULE_LOAD_FAILED = "false";
const outerModuleList = [MODULE_CORE, MODULE_APPLEPAY, MODULE_GOOGLEPAY, MODULE_CARD];
const createPrefetchLinkElement = (prefetchId, version2, baseUrl, file) => {
const prefetch2 = document.createElement("link");
prefetch2.id = prefetchId;
prefetch2.rel = "prefetch";
prefetch2.as = "script";
prefetch2.href = resolveFileUrl(baseUrl, version2, file);
return prefetch2;
};
const createPreloadLinkElement = (preloadId, version2, baseUrl, file) => {
const preload2 = document.createElement("link");
preload2.id = preloadId;
preload2.rel = "preload";
preload2.as = "script";
preload2.href = resolveFileUrl(baseUrl, version2, file);
return preload2;
};
const createScriptElement = (loadId, version2, isAsync = true, isDeferred = false, baseUrl, file) => {
const script = document.createElement("script");
script.id = loadId;
script.src = resolveFileUrl(baseUrl, version2, file);
script.async = isAsync;
script.defer = isDeferred;
return script;
};
const setElementData = (element, name, value) => {
try {
if (element && element instanceof HTMLElement && "dataset" in element) {
element.dataset[name] = value;
return true;
}
} catch (error) {
}
return false;
};
const getElementData = (element, name) => {
try {
if (element && element instanceof HTMLElement && "dataset" in element) {
return element.dataset[name];
}
} catch (error) {
}
return void 0;
};
const doesModuleAlreadyExist = (moduleConfig) => {
return moduleConfig.boundName in window;
};
const getModuleMountObject = (moduleConfig) => {
const moduleObject = moduleConfig.mountPoint.reduce((accumulator, currentValue) => accumulator == null ? void 0 : accumulator[currentValue], window);
if (validateModuleObject(moduleObject)) {
return moduleObject;
}
return void 0;
};
const validateModuleObject = (object) => object && typeof object == "object" && "create" in object && typeof object.create == "function" && "version" in object && typeof object.version == "function";
const resolveDebug = (config) => {
return config.debug === true;
};
const resolveEnvironment = (config) => {
return ("environment" in config ? config.environment : ENVIRONMENT_PREFERRED) || ENVIRONMENT_PREFERRED;
};
const resolveFileUrl = (cdnBaseUrl, version2, file) => {
return `${cdnBaseUrl + version2.version}${resolveFileName(version2, file)}`;
};
const resolveFileName = (version2, file) => {
if (file && file.length > 0) {
return "/" + expandFileName(file, version2.hash);
}
return "";
};
const expandFileName = (file, hash) => {
if (hash) {
const lastDot = file.lastIndexOf(".");
if (lastDot >= 0) {
const name = file.slice(0, lastDot);
const ext = file.slice(lastDot);
return `${name}.${hash}${ext}`;
}
}
return file;
};
const resolveUrl = (config, type) => {
const env = resolveEnvironment(config);
if (type === "cdn") {
return {
[ENVIRONMENT_DEV]: ENVIRONMENT_DEV_CDN_URL,
[ENVIRONMENT_TEST]: ENVIRONMENT_TEST_CDN_URL,
[ENVIRONMENT_PROD]: ENVIRONMENT_PROD_CDN_URL
}[env];
}
return {
[ENVIRONMENT_DEV]: ENVIRONMENT_DEV_API_URL,
[ENVIRONMENT_TEST]: ENVIRONMENT_TEST_API_URL,
[ENVIRONMENT_PROD]: ENVIRONMENT_PROD_API_URL
}[env];
};
let serverVersions;
const semverPrefix = "v/";
const majorPrefix = "@";
const resolveVersion = async (config, cdnBaseUrl) => {
if (config.version === VERSION_1 || config.version && /^1\.\d+\.\d+$/.test(config.version)) {
throw new Error("Checkout SDK: Version 1 is no longer supported. Please use version 2 or 3.");
}
try {
if (!serverVersions) {
await safeFetch(cdnBaseUrl + "versions.json").then((res) => {
if (res.ok && res.isJson) {
serverVersions = res.data;
} else if (resolveDebug(config)) {
console.warn("Checkout SDK: Invalid versions.json response, using cdn fallback.", {
url: cdnBaseUrl + "versions.json",
error: res == null ? void 0 : res.error
});
}
}).catch((error) => {
if (resolveDebug(config)) {
console.warn("Checkout SDK: can't fetch versions.json, using cdn fallback.", { url: cdnBaseUrl + "versions.json", error });
}
});
}
return getExpandedVersion(config.version, serverVersions);
} catch (error) {
return {
version: majorPrefix + VERSION_PREFERRED
};
}
};
function getExpandedVersion(custom, server) {
if (!server) {
if (custom && semverRegex.test(custom)) {
return { version: semverPrefix + custom };
}
if (custom && checkoutVersions.includes(custom)) {
return { version: majorPrefix + custom };
}
return { version: majorPrefix + VERSION_PREFERRED };
}
if (custom && semverRegex.test(custom)) {
const major = custom.split(".")[0];
if (server.majors[major]) {
return {
hash: server.majors[major].hash,
version: semverPrefix + custom
};
}
}
if (custom && custom in server.majors) {
return {
hash: server.majors[custom].hash,
version: semverPrefix + server.majors[custom].latest
};
}
if (VERSION_PREFERRED in server.majors) {
return {
hash: server.majors[VERSION_PREFERRED].hash,
version: semverPrefix + server.majors[VERSION_PREFERRED].latest
};
}
return {
version: majorPrefix + VERSION_PREFERRED
};
}
async function safeFetch(url, options = {}, timeout = 1e4) {
const timeoutMs = validateNumber(timeout, TIMEOUT_FETCH_MIN, TIMEOUT_FETCH_MAX, TIMEOUT_FETCH_DEFAULT);
let controller;
let timer;
if (AbortSignal !== void 0 && typeof AbortSignal.timeout === "function") {
options.signal = AbortSignal.timeout(timeoutMs);
} else if (AbortController !== void 0) {
controller = new AbortController();
timer = setTimeout(() => controller.abort(), timeoutMs);
options.signal = controller.signal;
}
try {
const response = await fetch(url, options);
if (timer) {
clearTimeout(timer);
}
const headers = headersToObject(response.headers);
if (!response.ok) {
let rawText2 = null;
try {
rawText2 = await response.text();
} catch {
}
return {
status: response.status,
ok: false,
isJson: false,
headers,
data: null,
raw: () => rawText2,
error: `HTTP error: ${response.status} ${response.statusText}`.trim()
};
}
const rawText = await response.text();
try {
const data = JSON.parse(rawText);
return {
status: response.status,
ok: true,
isJson: true,
headers,
data,
raw: () => rawText
};
} catch {
return {
status: response.status,
ok: true,
isJson: false,
headers,
data: null,
raw: () => rawText,
error: "Response is not valid JSON."
};
}
} catch (error_) {
if (timer) clearTimeout(timer);
return {
status: 0,
ok: false,
isJson: false,
headers: {},
data: null,
raw: () => null,
error: (error_ == null ? void 0 : error_.name) === "AbortError" ? "Request timed out." : `Unexpected error: ${(error_ == null ? void 0 : error_.message) || String(error_)}`
};
}
}
function headersToObject(headers) {
const result = {};
headers.forEach((value, key) => {
result[key] = value;
});
return result;
}
function validateNumber(value, min, max, defaultValue) {
if (value && typeof value === "number") {
if (value < min) {
return min;
}
if (value > max) {
return max;
}
return value;
}
return defaultValue;
}
function buildElementId(elementType, name) {
return `cg-${elementType}-checkout-${name.toLowerCase()}`;
}
function baseConfigValidator(config) {
if (!window) {
return "Window object is not available. Please ensure you are running this in a valid browser environment.";
}
if (typeof window !== "object") {
return "Invalid window type. An object is expected. Please ensure you are running this in a valid browser environment.";
}
if (!config || typeof config !== "object") {
return "Config: Invalid type. An object is expected.";
}
if ("debug" in config && typeof config.debug !== "boolean") {
return "Config: Invalid debug value. Boolean expected.";
}
if (!config.checkoutId || typeof config.checkoutId !== "string" || !checkoutIdRegex.test(config.checkoutId)) {
return "Config: Invalid checkoutId format. UUIDv4 expected.";
}
if ("timeout" in config && !Number.isInteger(config.timeout)) {
return "Config: Invalid timeout value. A number in milliseconds is expected.";
}
if ("version" in config && (!config.version || typeof config.version !== "string" || !versionRegex.test(config.version))) {
return `Config: Invalid version value '${config.version}'. Allowed values: ${versionRegex.toString()}`;
}
if (config.version && config.version === VERSION_1) {
return "Config: Please upgrade to the latest version. Version 1 is no longer supported.";
}
if (!("modules" in config) || !Array.isArray(config.modules)) {
return `Config: The "modules" property must be provided as an array. Allowed values: ${outerModuleList.join(", ")}.`;
}
if (config.modules.length === 0 || config.modules.length === 1 && config.modules.includes(MODULE_CORE)) {
return `Config: No modules have been provided. At least one module is required (excluding core). Allowed values: ${outerModuleList.join(", ")}.`;
}
const invalid = config.modules.find((m) => !outerModuleList.includes(m));
if (invalid !== void 0) {
return `Config: Invalid module value '${invalid}'. Allowed values: ${outerModuleList.join(", ")}.`;
}
return true;
}
function preloadConfigValidator(config) {
const validResponse = baseConfigValidator(config);
if (validResponse !== true) {
return validResponse;
}
return true;
}
async function preloadComgateCheckout(config) {
const validationResponse = preloadConfigValidator(config);
if (validationResponse !== true) {
return Promise.reject({
success: false,
checkoutId: config == null ? void 0 : config.checkoutId,
preloaded: [],
error: {
[MODULE_LOADER]: new TypeError(validationResponse)
}
});
}
const frozenConfig = Object.freeze(JSON.parse(JSON.stringify(config)));
const cdnBaseUrl = resolveUrl(frozenConfig, "cdn");
const resolvedVersion = await resolveVersion(frozenConfig, cdnBaseUrl);
return new Promise((resolve, reject) => {
const preloadResults = [];
if (frozenConfig.excludeCore !== true) {
preloadResults.push(preload({ config: frozenConfig, module: moduleCore, cdnBaseUrl, resolvedVersion }));
}
if (frozenConfig.modules !== void 0) {
if (frozenConfig.modules.includes(MODULE_APPLEPAY)) {
preloadResults.push(preload({ config: frozenConfig, module: moduleApplePay, cdnBaseUrl, resolvedVersion }));
}
if (frozenConfig.modules.includes(MODULE_GOOGLEPAY)) {
preloadResults.push(preload({ config: frozenConfig, module: moduleGooglePay, cdnBaseUrl, resolvedVersion }));
}
if (frozenConfig.modules.includes(MODULE_CARD)) {
preloadResults.push(preload({ config: frozenConfig, module: moduleCard, cdnBaseUrl, resolvedVersion }));
}
}
Promise.all(preloadResults).then((modulesStatus) => {
const preloadResponse = {
checkoutId: frozenConfig.checkoutId,
preloaded: [],
success: true
};
modulesStatus.forEach((module) => {
if (module.success) {
preloadResponse.preloaded.push(module.name);
} else {
preloadResponse.success = false;
preloadResponse.error = preloadResponse.error || {};
preloadResponse.error[module.name] = module.error;
}
});
if (frozenConfig.onPreload !== void 0 && typeof frozenConfig.onPreload === "function") {
frozenConfig.onPreload(preloadResponse);
}
if (preloadResponse.success) {
resolve(preloadResponse);
return;
}
reject(preloadResponse);
});
});
}
const isModuleLoaded$1 = (module) => {
const moduleLoadId = buildElementId("load", module.name);
const element = document.querySelector(`#${moduleLoadId}`);
if (element) {
const success = getElementData(element, "success");
if (success === MODULE_LOAD_SUCCESSFULLY) {
return true;
}
}
return false;
};
const preload = async (preloadConfig) => new Promise((resolve, reject) => {
let element = null;
try {
if (isModuleLoaded$1(preloadConfig.module)) {
resolve({
success: true,
name: preloadConfig.module.name
});
return;
}
const preloadId = buildElementId("preload", preloadConfig.module.name);
element = document.querySelector(`#${preloadId}`);
if (element) {
resolve({
success: true,
name: preloadConfig.module.name
});
} else {
const preload2 = createPreloadLinkElement(preloadId, preloadConfig.resolvedVersion, preloadConfig.cdnBaseUrl, preloadConfig.module.file);
document.head.append(preload2);
resolve({
success: true,
name: preloadConfig.module.name
});
}
} catch (error) {
setElementData(element, "success", MODULE_LOAD_FAILED);
reject({
success: false,
name: preloadConfig.module.name,
error: new Error("Unexpected error.", { cause: error })
});
}
});
function loadConfigValidator(config) {
const validResponse = baseConfigValidator(config);
if (validResponse !== true) {
return validResponse;
}
if ("environment" in config && (!config.environment || !checkoutEnvironments.includes(config.environment))) {
return `Config: Invalid environment value '${config.environment}'. Allowed values: ${checkoutEnvironments.join(", ")}.`;
}
const isAsyncDefined = "async" in config;
const isDeferDefined = "defer" in config;
if (isAsyncDefined && typeof config.async !== "boolean") {
return "Config: Invalid async value. Boolean expected.";
}
if (isDeferDefined && typeof config.defer !== "boolean") {
return "Config: Invalid defer value. Boolean expected.";
}
if (config.async && config.defer) {
return "Config: Only one of async or defer may be set to true.";
}
return true;
}
async function loadComgateCheckout(config) {
var _a, _b;
const validationResponse = loadConfigValidator(config);
if (validationResponse !== true) {
return Promise.reject({
success: false,
checkoutId: config == null ? void 0 : config.checkoutId,
error: {
[MODULE_LOADER]: new TypeError(validationResponse)
}
});
}
const frozenConfig = Object.freeze(JSON.parse(JSON.stringify(config)));
const env = resolveEnvironment(frozenConfig);
const cdnBaseUrl = resolveUrl(frozenConfig, "cdn");
const apiBaseUrl = resolveUrl(frozenConfig, "api");
(_a = window.comgate ?? (window.comgate = {})).checkout ?? (_a.checkout = {});
window.comgate.checkout.checkoutId = frozenConfig.checkoutId;
(_b = window.comgate.checkout).config ?? (_b.config = {});
if (env !== ENVIRONMENT_PROD) {
window.comgate.checkout.config.baseCdnUrl = cdnBaseUrl;
window.comgate.checkout.config.baseApiUrl = apiBaseUrl;
window.comgate.checkout.config.environment = env;
}
const resolvedVersion = await resolveVersion(frozenConfig, cdnBaseUrl);
window.comgate.checkout.config.version = resolvedVersion.version;
return new Promise((resolve, reject) => {
let coreLoading = null;
if (doesModuleAlreadyExist(moduleCore)) {
coreLoading = Promise.resolve({
success: true,
name: moduleCore.name,
mount: getModuleMountObject(moduleCore)
});
handleCoreLoading({ event: null, resolve, reject, coreLoading, frozenConfig, cdnBaseUrl, resolvedVersion });
return;
}
document.addEventListener(moduleCore.events.ready, (event) => {
if (coreLoading) {
handleCoreLoading({ event, resolve, reject, coreLoading, frozenConfig, cdnBaseUrl, resolvedVersion });
} else {
reject({
checkoutId: frozenConfig.checkoutId,
success: false,
error: {
[MODULE_CORE]: new Error("Failed to handle Core module loading.")
}
});
}
});
coreLoading = load(frozenConfig, moduleCore, cdnBaseUrl, resolvedVersion).catch((error) => {
reject({
checkoutId: frozenConfig.checkoutId,
success: false,
error: {
[MODULE_CORE]: new Error("Failed to handle Core module loading.", { cause: JSON.stringify(error) })
}
});
return Promise.resolve({
success: false,
name: MODULE_CORE,
error: new Error("Failed to handle Core module loading.", { cause: error })
});
});
preloadComgateCheckout({
...config,
excludeCore: true
});
});
}
const handleCoreLoading = async (parameters) => {
const loadResults = [parameters.coreLoading];
if (parameters.frozenConfig.modules !== void 0) {
if (parameters.frozenConfig.modules.includes(MODULE_APPLEPAY)) {
loadResults.push(load(parameters.frozenConfig, moduleApplePay, parameters.cdnBaseUrl, parameters.resolvedVersion));
}
if (parameters.frozenConfig.modules.includes(MODULE_GOOGLEPAY)) {
loadResults.push(load(parameters.frozenConfig, moduleGooglePay, parameters.cdnBaseUrl, parameters.resolvedVersion));
}
if (parameters.frozenConfig.modules.includes(MODULE_CARD)) {
loadResults.push(load(parameters.frozenConfig, moduleCard, parameters.cdnBaseUrl, parameters.resolvedVersion));
}
}
const modulesStatus = await Promise.all(loadResults);
const loadResponse = {
checkoutId: parameters.frozenConfig.checkoutId,
success: true
};
modulesStatus.forEach((module) => {
if (module.success) {
loadResponse[module.name] = module.mount;
} else {
loadResponse.success = false;
loadResponse.error = loadResponse.error || {};
loadResponse.error[module.name] = module.error;
}
});
if (parameters.frozenConfig.onLoad !== void 0 && typeof parameters.frozenConfig.onLoad === "function") {
parameters.frozenConfig.onLoad(loadResponse);
}
window.dispatchEvent(new Event(EVENT_MODULES_LOADED));
if (loadResponse.success) {
parameters.resolve(loadResponse);
} else {
parameters.reject(loadResponse);
}
};
const load = async (config, module, cdnBaseUrl, resolvedVersion) => new Promise((resolve, reject) => {
let resolved = false;
let timeoutId;
let isAsync = true;
let isDeferred = false;
let element = null;
const isAsyncDefined = "async" in config;
const isDeferDefined = "defer" in config;
try {
if (isAsyncDefined || isDeferDefined) {
if (config.async === true) {
isAsync = true;
isDeferred = false;
} else if (config.defer === true) {
isAsync = false;
isDeferred = true;
} else {
if (isAsyncDefined) {
isAsync = Boolean(config.async);
}
if (isDeferDefined) {
isDeferred = Boolean(config.defer);
}
}
}
const loadId = buildElementId("load", module.name);
element = document.querySelector(`#${loadId}`);
if (element) {
if (getElementData(element, "success") === MODULE_LOAD_SUCCESSFULLY) {
setElementData(element, "success", resolveModuleLoad(resolve, module) ? MODULE_LOAD_SUCCESSFULLY : MODULE_LOAD_FAILED);
} else {
element.remove();
element = null;
}
}
if (!element) {
const script = createScriptElement(loadId, resolvedVersion, isAsync, isDeferred, cdnBaseUrl, module.file);
script.addEventListener("error", (error) => {
if (!resolved) {
resolved = true;
clearTimeout(timeoutId);
setElementData(script, "success", MODULE_LOAD_FAILED);
reject({
success: false,
name: module.name,
error: `Failed to load script: ${JSON.stringify(error)}`
});
}
});
const timeout = validateNumber(config.timeout, TIMEOUT_LOAD_MIN, TIMEOUT_LOAD_MAX, TIMEOUT_LOAD_DEFAULT);
timeoutId = window.setTimeout(() => {
if (!resolved) {
resolved = true;
clearTimeout(timeoutId);
const mountObject = getModuleMountObject(module);
if (!mountObject) {
setElementData(script, "success", MODULE_LOAD_FAILED);
reject({
success: false,
name: module.name,
error: new Error("Timeout reached.")
});
return;
}
setElementData(script, "success", MODULE_LOAD_SUCCESSFULLY);
resolve({
success: true,
name: module.name,
mount: mountObject
});
}
}, timeout);
document.addEventListener(module.events.ready, () => {
if (!resolved) {
resolved = true;
clearTimeout(timeoutId);
setElementData(script, "success", resolveModuleLoad(resolve, module) ? MODULE_LOAD_SUCCESSFULLY : MODULE_LOAD_FAILED);
}
});
document.head.append(script);
} else if (!resolved) {
resolved = true;
clearTimeout(timeoutId);
setElementData(element, "success", resolveModuleLoad(resolve, module) ? MODULE_LOAD_SUCCESSFULLY : MODULE_LOAD_FAILED);
}
} catch (error) {
if (!resolved) {
resolved = true;
setElementData(element, "success", MODULE_LOAD_FAILED);
reject({
success: false,
name: module.name,
error: new Error("Unexpected error.", { cause: error })
});
}
}
});
const resolveModuleLoad = (onResolve, module) => {
const mountObject = getModuleMountObject(module);
if (!mountObject) {
onResolve({
success: false,
name: module.name,
error: new Error(`The module does not mount correctly. Path window.${module.mountPoint.join(".")} is undefined.`)
});
return false;
}
onResolve({
success: true,
name: module.name,
mount: mountObject
});
return true;
};
function prefetchConfigValidator(config) {
const validResponse = baseConfigValidator(config);
if (validResponse !== true) {
return validResponse;
}
return true;
}
async function prefetchComgateCheckout(config) {
const validationResponse = prefetchConfigValidator(config);
if (validationResponse !== true) {
return Promise.reject({
success: false,
checkoutId: config == null ? void 0 : config.checkoutId,
prefetched: [],
error: {
[MODULE_LOADER]: new TypeError(validationResponse)
}
});
}
const frozenConfig = Object.freeze({
...JSON.parse(JSON.stringify(config)),
onPrefetch: config.onPrefetch
});
const cdnBaseUrl = resolveUrl(frozenConfig, "cdn");
const resolvedVersion = await resolveVersion(frozenConfig, cdnBaseUrl);
return new Promise((resolve, reject) => {
const prefetchResults = [];
if (frozenConfig.excludeCore !== true) {
prefetchResults.push(prefetch({ config: frozenConfig, module: moduleCore, cdnBaseUrl, resolvedVersion }));
}
if (frozenConfig.modules !== void 0) {
if (frozenConfig.modules.includes(MODULE_APPLEPAY)) {
prefetchResults.push(prefetch({ config: frozenConfig, module: moduleApplePay, cdnBaseUrl, resolvedVersion }));
}
if (frozenConfig.modules.includes(MODULE_GOOGLEPAY)) {
prefetchResults.push(prefetch({ config: frozenConfig, module: moduleGooglePay, cdnBaseUrl, resolvedVersion }));
}
if (frozenConfig.modules.includes(MODULE_CARD)) {
prefetchResults.push(prefetch({ config: frozenConfig, module: moduleCard, cdnBaseUrl, resolvedVersion }));
}
}
Promise.all(prefetchResults).then((modulesStatus) => {
const prefetchResponse = {
checkoutId: frozenConfig.checkoutId,
prefetched: [],
success: true
};
modulesStatus.forEach((module) => {
if (module.success) {
prefetchResponse.prefetched.push(module.name);
} else {
prefetchResponse.success = false;
prefetchResponse.error = prefetchResponse.error || {};
prefetchResponse.error[module.name] = module.error;
}
});
if (frozenConfig.onPrefetch !== void 0 && typeof frozenConfig.onPrefetch === "function") {
frozenConfig.onPrefetch(prefetchResponse);
}
if (prefetchResponse.success) {
resolve(prefetchResponse);
return;
}
reject(prefetchResponse);
});
});
}
const isModuleLoaded = (module) => {
const moduleLoadId = buildElementId("load", module.name);
const element = document.querySelector(`#${moduleLoadId}`);
if (element) {
const success = getElementData(element, "success");
if (success === MODULE_LOAD_SUCCESSFULLY) {
return true;
}
}
return false;
};
const prefetch = async (prefetchConfig) => new Promise((resolve, reject) => {
let element = null;
try {
if (isModuleLoaded(prefetchConfig.module)) {
resolve({
success: true,
name: prefetchConfig.module.name
});
return;
}
const prefetchId = buildElementId("prefetch", prefetchConfig.module.name);
element = document.querySelector(`#${prefetchId}`);
if (element) {
resolve({
success: true,
name: prefetchConfig.module.name
});
} else {
const link = createPrefetchLinkElement(prefetchId, prefetchConfig.resolvedVersion, prefetchConfig.cdnBaseUrl, prefetchConfig.module.file);
document.head.append(link);
resolve({
success: true,
name: prefetchConfig.module.name
});
}
} catch (error) {
setElementData(element, "success", MODULE_LOAD_FAILED);
reject({
success: false,
name: prefetchConfig.module.name,
error: new Error("Unexpected error.", { cause: error })
});
}
});
const version = "3.0.1";
const revision = "839976af";
function getLoaderVersion() {
return {
version,
revision
};
}
const MAX_WAIT_FRAMES = 5;
function waitForSelector(selector) {
let frame = 0;
return new Promise((resolve) => {
function check() {
const elements = document.querySelectorAll(selector);
if (elements.length > 0) {
resolve(elements);
return;
}
frame++;
if (frame >= MAX_WAIT_FRAMES) {
resolve(null);
return;
}
requestAnimationFrame(check);
}
requestAnimationFrame(check);
});
}
async function resolveMountPoint(mountPoint, moduleId) {
const tag = `[ComgateCheckout](${moduleId}):`;
if (mountPoint === void 0 || mountPoint === null) {
throw new Error(
`${tag} Mount point is required but was not provided. Pass a CSS selector string (e.g. "#my-container") or a direct HTMLDivElement reference.`
);
}
if (typeof mountPoint === "string") {
let elements = document.querySelectorAll(mountPoint);
if (elements.length === 0) {
const delayed = await waitForSelector(mountPoint);
if (delayed === null) {
throw new Error(`${tag} Mount point selector "${mountPoint}" did not match any element in the DOM.`);
}
elements = delayed;
}
if (elements.length > 1) {
throw new Error(`${tag} Mount point selector "${mountPoint}" matched ${elements.length} elements — must match exactly one.`);
}
const element = elements[0];
if (!(element instanceof HTMLDivElement)) {
throw new TypeError(
`${tag} Mount point selector "${mountPoint}" matched an element that is not a <div> (got <${element.tagName.toLowerCase()}>).`
);
}
if (!element.id) {
throw new Error(`${tag} Mount point element matched by "${mountPoint}" must have a non-empty "id" attribute.`);
}
return { element, id: element.id };
}
if (!mountPoint.isConnected) {
throw new Error(`${tag} Mount point element is not connected to the DOM.`);
}
if (!mountPoint.id) {
throw new Error(`${tag} Mount point element must have a non-empty "id" attribute.`);
}
return { element: mountPoint, id: mountPoint.id };
}
function errorMessage(error) {
if (error instanceof Error) return error.message;
return String(error);
}
async function initModule(moduleName, loaderModule, create, mountPoint) {
if (!loaderModule) {
return { success: false, error: `${moduleName} module was not loaded`, instance: null };
}
let instance;
try {
instance = await create(loaderModule);
} catch (error) {
return { success: false, error: errorMessage(error), instance: null };
}
try {
await instance.canMakePayments();
const { element } = await resolveMountPoint(mountPoint, instance.getModuleId());
try {
await instance.mount(element);
} finally {
element.classList.remove("is-loading");
}
return { success: true, instance, error: void 0 };
} catch (error) {
return { success: false, error: errorMessage(error), instance };
}
}
async function useCheckout(config) {
if (!config.checkoutId || !checkoutIdRegex.test(config.checkoutId)) {
throw new Error(`Invalid checkoutId: "${config.checkoutId}"`);
}
if (!config.core) {
throw new Error('Missing required "core" configuration in useCheckout().');
}
const modules = [MODULE_CORE];
if (config.applepay) modules.push(MODULE_APPLEPAY);
if (config.googlepay) modules.push(MODULE_GOOGLEPAY);
if (config.card) modules.push(MODULE_CARD);
const loadResult = await loadComgateCheckout({
checkoutId: config.checkoutId,
modules,
version: config.version ?? VERSION_3,
environment: config.environment ?? ENVIRONMENT_PROD,
debug: config.debug ?? false
});
if (!loadResult.core) {
throw new Error("Core module is not available after loading");
}
const coreInstance = await loadResult.core.create({
...config.core,
checkoutId: config.checkoutId,
debug: config.debug ?? false,
env: config.environment ?? ENVIRONMENT_PROD
});
const [apResult, gpResult, cardResult] = await Promise.all([
config.applepay ? initModule(
"Apple Pay",
loadResult.applepay,
(m) => m.create(coreInstance, config.applepay),
config.applepay.mountPoint
) : Promise.resolve(void 0),
config.googlepay ? initModule(
"Google Pay",
loadResult.googlepay,
(m) => m.create(coreInstance, config.googlepay),
config.googlepay.mountPoint
) : Promise.resolve(void 0),
config.card ? initModule("Card", loadResult.card, (m) => m.create(coreInstance, config.card), config.card.mountPoint) : Promise.resolve(void 0)
]);
const overallSuccess = [apResult, gpResult, cardResult].filter((r) => r !== void 0).every((r) => r.success);
return {
success: overallSuccess,
core: { success: true, instance: coreInstance, error: void 0 },
applepay: config.applepay ? apResult ?? { success: false, error: "Unknown error", instance: null } : void 0,
googlepay: config.googlepay ? gpResult ?? { success: false, error: "Unknown error", instance: null } : void 0,
card: config.card ? cardResult ?? { success: false, error: "Unknown error", instance: null } : void 0
};
}
export {
ENVIRONMENT_DEV,
ENVIRONMENT_PREFERRED,
ENVIRONMENT_PROD,
ENVIRONMENT_TEST,
MODULE_APPLEPAY,
MODULE_CARD,
MODULE_CORE,
MODULE_GOOGLEPAY,
MODULE_LOADER,
VERSION_1,
VERSION_2,
VERSION_3,
VERSION_DEV,
VERSION_PREFERRED,
checkoutIdRegex,
checkoutVersions,
getLoaderVersion,
loadComgateCheckout,
prefetchComgateCheckout,
preloadComgateCheckout,
useCheckout,
versionRegex
};
//# sourceMappingURL=comgate-checkout-js.es.js.map