import { loadScript } from "@braintree/asset-loader"; import { BtModuleKeys, BtModuleLoadConfig } from "./types"; import { isAmdEnv } from "../amd-utils"; /** * Safely loads BT modules by checking if the module already exists and verifying if versions mismatch * * @param loadConfig Configuration of BT Module to load * @param version version that should be passed from the client getVersion * @returns Promise * @returns Promise when BT module with same version already exists * @returns Promise.reject(err) when BT module already exists but versions mismatch or empty version passed in */ export async function safeLoadBtModule( loadConfig: BtModuleLoadConfig, version: string, minified = true ) { const bt = getBraintree(); if (bt && bt[loadConfig.module]) { if (version && bt[loadConfig.module]?.VERSION !== version) { const existingVersion = bt[loadConfig.module]?.VERSION; throw new Error( `${loadConfig.module} already loaded with version ${existingVersion} cannot load version ${version}` ); } else { return true; } } if (!version) { throw new Error( `Attempted to load ${loadConfig.module} without specifying version` ); } return loadBtModule(loadConfig, version, minified); } /** * Reads the version and to load the correct version of Bt module * * @param loadConfig Configuration of BT Module to load * @param version Bt module version * @returns Promise or */ function loadBtModule( loadConfig: BtModuleLoadConfig, version: string, minified = true ) { if (isAmdEnv()) { const module = minified ? loadConfig.amdModule.minified : loadConfig.amdModule.unminified; return new Promise((resolve, reject) => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore window.require([module], resolve, reject); }); } const script = minified ? loadConfig.script.minified : loadConfig.script.unminified; return loadScript({ id: `${loadConfig.id}-${version}`, src: `https://js.braintreegateway.com/web/${version}/js/${script}`, }); } /** * Looks for the Braintree web sdk on the window object * * @returns Braintree web sdk */ function getBraintree() { return window?.braintree; } declare global { interface Window { braintree: Partial< Record void; VERSION: string }> > & { fastlane?: object; }; } }