@dintero/checkout-web-sdk 0.12.11 → 0.12.13

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.
@@ -19,7 +19,7 @@ export interface DinteroCheckoutInstance {
19
19
  handler: SubscriptionHandler;
20
20
  eventTypes: InternalCheckoutEvents[];
21
21
  } | {
22
- handler: SubscriptionHandler;
22
+ handler: SubscriptionHandler | undefined;
23
23
  eventTypes: CheckoutEvents[];
24
24
  })[];
25
25
  session: Session | undefined;
@@ -10,7 +10,7 @@ interface SubscriptionOptions {
10
10
  handler: SubscriptionHandler;
11
11
  eventTypes: (CheckoutEvents | InternalCheckoutEvents)[];
12
12
  checkout: DinteroCheckoutInstance;
13
- source: Window;
13
+ source: Window | null;
14
14
  }
15
15
  export type Subscription = {
16
16
  /**
@@ -6,7 +6,7 @@ require('native-promise-only');
6
6
 
7
7
  var pkg = {
8
8
  name: "@dintero/checkout-web-sdk",
9
- version: "0.12.11",
9
+ version: "0.12.13",
10
10
  description: "Dintero Checkout SDK for web frontends",
11
11
  main: "dist/dintero-checkout-web-sdk.cjs.js",
12
12
  module: "dist/dintero-checkout-web-sdk.esm.js",
@@ -40,15 +40,15 @@ var pkg = {
40
40
  devDependencies: {
41
41
  "@babel/core": "7.29.0",
42
42
  "@babel/preset-typescript": "7.28.5",
43
- "@biomejs/biome": "2.4.10",
43
+ "@biomejs/biome": "2.4.13",
44
44
  "@preconstruct/cli": "2.8.12",
45
45
  "@semantic-release/exec": "7.1.0",
46
46
  "@semantic-release/git": "10.0.1",
47
- "@vitest/browser": "4.1.2",
47
+ "@vitest/browser": "4.1.5",
48
48
  "@vitest/browser-webdriverio": "^4.0.4",
49
49
  "semantic-release": "25.0.3",
50
- typescript: "5.9.3",
51
- vitest: "4.1.2",
50
+ typescript: "6.0.3",
51
+ vitest: "4.1.5",
52
52
  webdriverio: "9.27.0"
53
53
  },
54
54
  dependencies: {
@@ -88,7 +88,7 @@ let InternalCheckoutEvents = /*#__PURE__*/function (InternalCheckoutEvents) {
88
88
  * Rejects the promise if there is a problem loading the iframe.
89
89
  */
90
90
  const createIframeAsync = (container, url) => {
91
- if (!container || !container.appendChild) {
91
+ if (!container?.appendChild) {
92
92
  throw new Error("Invalid container");
93
93
  }
94
94
  const iframe = document.createElement("iframe");
@@ -240,8 +240,8 @@ const hostnameIsTop = () => {
240
240
  return true;
241
241
  }
242
242
  const hostname = getHostname();
243
- const topHostname = window.top.location.hostname;
244
- return topHostname && hostname && hostname === topHostname;
243
+ const topHostname = window.top?.location.hostname;
244
+ return Boolean(topHostname && hostname && hostname === topHostname);
245
245
  } catch (_) {
246
246
  return false;
247
247
  }
@@ -276,7 +276,7 @@ const createPopOutWindow = (sid, url, width, height) => {
276
276
  };
277
277
  window.addEventListener("message", handleAppLoaded);
278
278
  // Open pop out
279
- popOut = window.open(url, "dintero-checkout", features);
279
+ popOut = window.open(url, "dintero-checkout", features) ?? undefined;
280
280
  // Check that pop out was opened
281
281
  if (!popOut) {
282
282
  console.log("createPopOutWindow no popOut");
@@ -299,7 +299,11 @@ const openPopOut = async options => {
299
299
  let popOutWindow;
300
300
  if (popOutWindow && !popOutWindow.closed) {
301
301
  // Skip if already open.
302
- return;
302
+ return {
303
+ close: () => {},
304
+ focus: () => {},
305
+ popOutWindow: undefined
306
+ };
303
307
  }
304
308
 
305
309
  // Open popup window
@@ -339,7 +343,9 @@ const openPopOut = async options => {
339
343
  intervalId = window.setInterval(checkIfPopupClosed, 200);
340
344
 
341
345
  // Set up pub/sub of messages from pop out to SDK
342
- unsubscribe = options.onOpen(popOutWindow);
346
+ if (popOutWindow) {
347
+ unsubscribe = options.onOpen(popOutWindow);
348
+ }
343
349
  return {
344
350
  close: closePopOut,
345
351
  focus: focusPopOut,
@@ -395,7 +401,7 @@ const getBackdropZIndex = () => {
395
401
  const elements = document.getElementsByTagName("*");
396
402
  const highest = Array.from(elements).reduce((acc, element) => {
397
403
  try {
398
- const zIndexStr = document.defaultView.getComputedStyle(element, null).getPropertyValue("z-index");
404
+ const zIndexStr = document.defaultView?.getComputedStyle(element, null).getPropertyValue("z-index");
399
405
  const zIndex = Number.parseInt(zIndexStr || "0", 10);
400
406
  if (!Number.isNaN(zIndex) && zIndex > acc) {
401
407
  return zIndex;
@@ -614,11 +620,11 @@ const focusTrap = e => {
614
620
  const closeButton = document.getElementById(CLOSE_BACKDROP_BUTTON_ID);
615
621
  if (e.key === "Tab" || e.code === "Tab") {
616
622
  if (document.activeElement === focusButton) {
617
- closeButton.focus();
623
+ closeButton?.focus();
618
624
  e.preventDefault();
619
625
  } else {
620
626
  // Tab
621
- focusButton.focus();
627
+ focusButton?.focus();
622
628
  e.preventDefault();
623
629
  }
624
630
  }
@@ -746,6 +752,8 @@ const configureButton = (button, {
746
752
  ...directStyles
747
753
  } = styles;
748
754
  for (const [key, value] of Object.entries(directStyles)) {
755
+ // TODO: CSSStyleDeclaration lost its string index signature in TS6;
756
+ // styles from checkout are camelCase property names sent at runtime.
749
757
  button.style[key] = value;
750
758
  }
751
759
 
@@ -1068,6 +1076,7 @@ const createPopOutMessageHandler = (source, checkout) => {
1068
1076
  const popOutChangedLanguageHandler = {
1069
1077
  internalPopOutHandler: true,
1070
1078
  eventTypes: [InternalCheckoutEvents.LanguageChanged],
1079
+ // biome-ignore lint/suspicious/noExplicitAny: internal LanguageChanged event, not part of SessionEvent
1071
1080
  handler: (eventData, checkout) => {
1072
1081
  // Tell the embedded checkout to change language.
1073
1082
  postSetLanguage(checkout.iframe, checkout.options.sid, eventData.language);
@@ -1079,6 +1088,7 @@ const createPopOutMessageHandler = (source, checkout) => {
1079
1088
  const popOutCompletedHandler = {
1080
1089
  internalPopOutHandler: true,
1081
1090
  eventTypes: paymentCompletedEvents,
1091
+ // biome-ignore lint/suspicious/noExplicitAny: href is not present on all SessionEvent subtypes
1082
1092
  handler: (eventData, _checkout) => {
1083
1093
  if (eventData.href) {
1084
1094
  // Remove open pop out button rendered by SDK
@@ -1108,8 +1118,11 @@ const createPopOutMessageHandler = (source, checkout) => {
1108
1118
  ...checkout.handlers]) {
1109
1119
  if (handlerObject.eventTypes.includes(event.data.type) && handlerObject.handler) {
1110
1120
  // Invoking the handler function if the event type matches the handler.
1121
+ const {
1122
+ handler
1123
+ } = handlerObject;
1111
1124
  safelyInvoke(() => {
1112
- handlerObject.handler(event.data, checkout);
1125
+ handler(event.data, checkout);
1113
1126
  });
1114
1127
  }
1115
1128
  }
@@ -1128,13 +1141,9 @@ const createPopOutMessageHandler = (source, checkout) => {
1128
1141
  * Configures and shows the pop out with the payment options.
1129
1142
  */
1130
1143
  const showPopOut = async (event, checkout) => {
1131
- const {
1132
- close,
1133
- focus,
1134
- popOutWindow
1135
- } = await popOutModule.openPopOut({
1144
+ const openPopOutResult = await popOutModule.openPopOut({
1136
1145
  sid: checkout.options.sid,
1137
- endpoint: checkout.options.endpoint,
1146
+ endpoint: checkout.options.endpoint ?? "https://checkout.dintero.com",
1138
1147
  shouldCallValidateSession: Boolean(checkout.options.onValidateSession),
1139
1148
  shouldCallAddressCallback: false,
1140
1149
  // handled by embedded checkout not the pop out window
@@ -1147,6 +1156,11 @@ const showPopOut = async (event, checkout) => {
1147
1156
  checkout.popOutWindow = undefined;
1148
1157
  }
1149
1158
  });
1159
+ const {
1160
+ close,
1161
+ focus,
1162
+ popOutWindow
1163
+ } = openPopOutResult;
1150
1164
  if (popOutWindow) {
1151
1165
  postOpenPopOutEvent(checkout.iframe, checkout.options.sid);
1152
1166
  // Add pop out window to checkout instance
@@ -1177,7 +1191,7 @@ const createPopOutValidationCallback = (event, checkout) => {
1177
1191
  // Redirect user to session in pop out window
1178
1192
  checkout.popOutWindow.location.href = url.getPopOutUrl({
1179
1193
  sid: checkout.options.sid,
1180
- endpoint: checkout.options.endpoint,
1194
+ endpoint: checkout.options.endpoint ?? "https://checkout.dintero.com",
1181
1195
  shouldCallValidateSession: false,
1182
1196
  shouldCallAddressCallback: false,
1183
1197
  language: event.language
@@ -1212,6 +1226,8 @@ const handlePopOutButtonClick = async (event, checkout) => {
1212
1226
  try {
1213
1227
  checkout.options.onValidateSession({
1214
1228
  type: CheckoutEvents.ValidateSession,
1229
+ // TODO: session may be undefined before SessionLoaded fires;
1230
+ // ValidateSession.session is typed as Session (non-optional).
1215
1231
  session: checkout.session,
1216
1232
  callback
1217
1233
  }, checkout, callback);
@@ -1229,7 +1245,7 @@ const handlePopOutButtonClick = async (event, checkout) => {
1229
1245
  * Type guard for ShowPopOutButton
1230
1246
  */
1231
1247
  const isShowPopOutButton = event => {
1232
- return event && event.type === InternalCheckoutEvents.ShowPopOutButton;
1248
+ return typeof event === "object" && event !== null && event.type === InternalCheckoutEvents.ShowPopOutButton;
1233
1249
  };
1234
1250
 
1235
1251
  /**
@@ -1291,7 +1307,7 @@ const embed = async options => {
1291
1307
  // Create inner container to offset any styling on the container.
1292
1308
  const innerContainer = document.createElement("div");
1293
1309
  innerContainer.style.position = "relative";
1294
- innerContainer.style["box-sizing"] = "border-box";
1310
+ innerContainer.style.boxSizing = "border-box";
1295
1311
  const internalOptions = {
1296
1312
  endpoint: "https://checkout.dintero.com",
1297
1313
  innerContainer: innerContainer,
@@ -1342,7 +1358,9 @@ const embed = async options => {
1342
1358
  * Function that removes the iframe, pop out and all event listeners.
1343
1359
  */
1344
1360
  const destroy = () => {
1345
- cleanUpPopOut(checkout);
1361
+ if (checkout) {
1362
+ cleanUpPopOut(checkout);
1363
+ }
1346
1364
  if (iframe) {
1347
1365
  if (internalOptions.popOut) {
1348
1366
  // Try to remove backdrop if it exists
@@ -1368,6 +1386,7 @@ const embed = async options => {
1368
1386
  if (!checkout) {
1369
1387
  throw new Error("Unable to create action promise: checkout is undefined");
1370
1388
  }
1389
+ const checkoutInstance = checkout;
1371
1390
  return new Promise((resolve, reject) => {
1372
1391
  const eventSubscriptions = [];
1373
1392
  eventSubscriptions.push(subscribe({
@@ -1380,8 +1399,8 @@ const embed = async options => {
1380
1399
  resolve(sessionEvent);
1381
1400
  },
1382
1401
  eventTypes: [resolveEvent],
1383
- checkout,
1384
- source: checkout.iframe.contentWindow
1402
+ checkout: checkoutInstance,
1403
+ source: checkoutInstance.iframe.contentWindow
1385
1404
  }));
1386
1405
  eventSubscriptions.push(subscribe({
1387
1406
  sid,
@@ -1393,8 +1412,8 @@ const embed = async options => {
1393
1412
  reject(`Received unexpected event: ${rejectEvent}`);
1394
1413
  },
1395
1414
  eventTypes: [rejectEvent],
1396
- checkout,
1397
- source: checkout.iframe.contentWindow
1415
+ checkout: checkoutInstance,
1416
+ source: checkoutInstance.iframe.contentWindow
1398
1417
  }));
1399
1418
  action();
1400
1419
  });
@@ -1434,6 +1453,7 @@ const embed = async options => {
1434
1453
  * If no custom handler is set the followHref handler is used instead.
1435
1454
  */
1436
1455
  const handleWithResult = (_sid, endpoint, handler) => {
1456
+ // biome-ignore lint/suspicious/noExplicitAny: requires dynamic key access on event payload
1437
1457
  return (event, checkout) => {
1438
1458
  if (!has_delivered_final_event) {
1439
1459
  has_delivered_final_event = true;
@@ -1514,15 +1534,17 @@ const embed = async options => {
1514
1534
  eventTypes: [CheckoutEvents.SessionLoaded, CheckoutEvents.SessionUpdated]
1515
1535
  }, {
1516
1536
  eventTypes: [CheckoutEvents.SessionPaymentOnHold],
1517
- handler: handleWithResult(sid, endpoint, onPayment || followHref)
1537
+ // TODO: user callbacks have narrower event param types than SubscriptionHandler;
1538
+ // casts are safe because handleWithResult only invokes them with the matching event type.
1539
+ handler: handleWithResult(sid, endpoint, onPayment ?? followHref)
1518
1540
  }, {
1519
1541
  eventTypes: [CheckoutEvents.SessionPaymentAuthorized],
1520
- handler: handleWithResult(sid, endpoint, onPaymentAuthorized || onPayment || followHref)
1542
+ handler: handleWithResult(sid, endpoint, onPaymentAuthorized ?? onPayment ?? followHref)
1521
1543
  }, {
1522
- handler: handleWithResult(sid, endpoint, onSessionCancel || followHref),
1544
+ handler: handleWithResult(sid, endpoint, onSessionCancel ?? followHref),
1523
1545
  eventTypes: [CheckoutEvents.SessionCancel]
1524
1546
  }, {
1525
- handler: handleWithResult(sid, endpoint, onPaymentError || followHref),
1547
+ handler: handleWithResult(sid, endpoint, onPaymentError ?? followHref),
1526
1548
  eventTypes: [CheckoutEvents.SessionPaymentError]
1527
1549
  }, {
1528
1550
  handler: onSessionNotFound,
@@ -1553,7 +1575,7 @@ const embed = async options => {
1553
1575
  checkout = {
1554
1576
  destroy,
1555
1577
  iframe,
1556
- language,
1578
+ language: language ?? "",
1557
1579
  lockSession,
1558
1580
  refreshSession,
1559
1581
  setActivePaymentProductType,
@@ -1564,6 +1586,7 @@ const embed = async options => {
1564
1586
  session: undefined,
1565
1587
  popOutWindow: undefined
1566
1588
  };
1589
+ const checkoutInstance = checkout;
1567
1590
  for (const {
1568
1591
  handler,
1569
1592
  eventTypes
@@ -1574,8 +1597,8 @@ const embed = async options => {
1574
1597
  endpoint,
1575
1598
  handler,
1576
1599
  eventTypes,
1577
- checkout,
1578
- source: checkout.iframe.contentWindow
1600
+ checkout: checkoutInstance,
1601
+ source: checkoutInstance.iframe.contentWindow
1579
1602
  }));
1580
1603
  }
1581
1604
  }
@@ -1583,7 +1606,7 @@ const embed = async options => {
1583
1606
  // Add iframe to DOM
1584
1607
  await initiate();
1585
1608
  // Return object with function to destroy the checkout.
1586
- return checkout;
1609
+ return checkoutInstance;
1587
1610
  };
1588
1611
 
1589
1612
  /**
@@ -6,7 +6,7 @@ require('native-promise-only');
6
6
 
7
7
  var pkg = {
8
8
  name: "@dintero/checkout-web-sdk",
9
- version: "0.12.11",
9
+ version: "0.12.13",
10
10
  description: "Dintero Checkout SDK for web frontends",
11
11
  main: "dist/dintero-checkout-web-sdk.cjs.js",
12
12
  module: "dist/dintero-checkout-web-sdk.esm.js",
@@ -40,15 +40,15 @@ var pkg = {
40
40
  devDependencies: {
41
41
  "@babel/core": "7.29.0",
42
42
  "@babel/preset-typescript": "7.28.5",
43
- "@biomejs/biome": "2.4.10",
43
+ "@biomejs/biome": "2.4.13",
44
44
  "@preconstruct/cli": "2.8.12",
45
45
  "@semantic-release/exec": "7.1.0",
46
46
  "@semantic-release/git": "10.0.1",
47
- "@vitest/browser": "4.1.2",
47
+ "@vitest/browser": "4.1.5",
48
48
  "@vitest/browser-webdriverio": "^4.0.4",
49
49
  "semantic-release": "25.0.3",
50
- typescript: "5.9.3",
51
- vitest: "4.1.2",
50
+ typescript: "6.0.3",
51
+ vitest: "4.1.5",
52
52
  webdriverio: "9.27.0"
53
53
  },
54
54
  dependencies: {
@@ -88,7 +88,7 @@ let InternalCheckoutEvents = /*#__PURE__*/function (InternalCheckoutEvents) {
88
88
  * Rejects the promise if there is a problem loading the iframe.
89
89
  */
90
90
  const createIframeAsync = (container, url) => {
91
- if (!container || !container.appendChild) {
91
+ if (!container?.appendChild) {
92
92
  throw new Error("Invalid container");
93
93
  }
94
94
  const iframe = document.createElement("iframe");
@@ -240,8 +240,8 @@ const hostnameIsTop = () => {
240
240
  return true;
241
241
  }
242
242
  const hostname = getHostname();
243
- const topHostname = window.top.location.hostname;
244
- return topHostname && hostname && hostname === topHostname;
243
+ const topHostname = window.top?.location.hostname;
244
+ return Boolean(topHostname && hostname && hostname === topHostname);
245
245
  } catch (_) {
246
246
  return false;
247
247
  }
@@ -276,7 +276,7 @@ const createPopOutWindow = (sid, url, width, height) => {
276
276
  };
277
277
  window.addEventListener("message", handleAppLoaded);
278
278
  // Open pop out
279
- popOut = window.open(url, "dintero-checkout", features);
279
+ popOut = window.open(url, "dintero-checkout", features) ?? undefined;
280
280
  // Check that pop out was opened
281
281
  if (!popOut) {
282
282
  console.log("createPopOutWindow no popOut");
@@ -299,7 +299,11 @@ const openPopOut = async options => {
299
299
  let popOutWindow;
300
300
  if (popOutWindow && !popOutWindow.closed) {
301
301
  // Skip if already open.
302
- return;
302
+ return {
303
+ close: () => {},
304
+ focus: () => {},
305
+ popOutWindow: undefined
306
+ };
303
307
  }
304
308
 
305
309
  // Open popup window
@@ -339,7 +343,9 @@ const openPopOut = async options => {
339
343
  intervalId = window.setInterval(checkIfPopupClosed, 200);
340
344
 
341
345
  // Set up pub/sub of messages from pop out to SDK
342
- unsubscribe = options.onOpen(popOutWindow);
346
+ if (popOutWindow) {
347
+ unsubscribe = options.onOpen(popOutWindow);
348
+ }
343
349
  return {
344
350
  close: closePopOut,
345
351
  focus: focusPopOut,
@@ -395,7 +401,7 @@ const getBackdropZIndex = () => {
395
401
  const elements = document.getElementsByTagName("*");
396
402
  const highest = Array.from(elements).reduce((acc, element) => {
397
403
  try {
398
- const zIndexStr = document.defaultView.getComputedStyle(element, null).getPropertyValue("z-index");
404
+ const zIndexStr = document.defaultView?.getComputedStyle(element, null).getPropertyValue("z-index");
399
405
  const zIndex = Number.parseInt(zIndexStr || "0", 10);
400
406
  if (!Number.isNaN(zIndex) && zIndex > acc) {
401
407
  return zIndex;
@@ -614,11 +620,11 @@ const focusTrap = e => {
614
620
  const closeButton = document.getElementById(CLOSE_BACKDROP_BUTTON_ID);
615
621
  if (e.key === "Tab" || e.code === "Tab") {
616
622
  if (document.activeElement === focusButton) {
617
- closeButton.focus();
623
+ closeButton?.focus();
618
624
  e.preventDefault();
619
625
  } else {
620
626
  // Tab
621
- focusButton.focus();
627
+ focusButton?.focus();
622
628
  e.preventDefault();
623
629
  }
624
630
  }
@@ -746,6 +752,8 @@ const configureButton = (button, {
746
752
  ...directStyles
747
753
  } = styles;
748
754
  for (const [key, value] of Object.entries(directStyles)) {
755
+ // TODO: CSSStyleDeclaration lost its string index signature in TS6;
756
+ // styles from checkout are camelCase property names sent at runtime.
749
757
  button.style[key] = value;
750
758
  }
751
759
 
@@ -1068,6 +1076,7 @@ const createPopOutMessageHandler = (source, checkout) => {
1068
1076
  const popOutChangedLanguageHandler = {
1069
1077
  internalPopOutHandler: true,
1070
1078
  eventTypes: [InternalCheckoutEvents.LanguageChanged],
1079
+ // biome-ignore lint/suspicious/noExplicitAny: internal LanguageChanged event, not part of SessionEvent
1071
1080
  handler: (eventData, checkout) => {
1072
1081
  // Tell the embedded checkout to change language.
1073
1082
  postSetLanguage(checkout.iframe, checkout.options.sid, eventData.language);
@@ -1079,6 +1088,7 @@ const createPopOutMessageHandler = (source, checkout) => {
1079
1088
  const popOutCompletedHandler = {
1080
1089
  internalPopOutHandler: true,
1081
1090
  eventTypes: paymentCompletedEvents,
1091
+ // biome-ignore lint/suspicious/noExplicitAny: href is not present on all SessionEvent subtypes
1082
1092
  handler: (eventData, _checkout) => {
1083
1093
  if (eventData.href) {
1084
1094
  // Remove open pop out button rendered by SDK
@@ -1108,8 +1118,11 @@ const createPopOutMessageHandler = (source, checkout) => {
1108
1118
  ...checkout.handlers]) {
1109
1119
  if (handlerObject.eventTypes.includes(event.data.type) && handlerObject.handler) {
1110
1120
  // Invoking the handler function if the event type matches the handler.
1121
+ const {
1122
+ handler
1123
+ } = handlerObject;
1111
1124
  safelyInvoke(() => {
1112
- handlerObject.handler(event.data, checkout);
1125
+ handler(event.data, checkout);
1113
1126
  });
1114
1127
  }
1115
1128
  }
@@ -1128,13 +1141,9 @@ const createPopOutMessageHandler = (source, checkout) => {
1128
1141
  * Configures and shows the pop out with the payment options.
1129
1142
  */
1130
1143
  const showPopOut = async (event, checkout) => {
1131
- const {
1132
- close,
1133
- focus,
1134
- popOutWindow
1135
- } = await popOutModule.openPopOut({
1144
+ const openPopOutResult = await popOutModule.openPopOut({
1136
1145
  sid: checkout.options.sid,
1137
- endpoint: checkout.options.endpoint,
1146
+ endpoint: checkout.options.endpoint ?? "https://checkout.dintero.com",
1138
1147
  shouldCallValidateSession: Boolean(checkout.options.onValidateSession),
1139
1148
  shouldCallAddressCallback: false,
1140
1149
  // handled by embedded checkout not the pop out window
@@ -1147,6 +1156,11 @@ const showPopOut = async (event, checkout) => {
1147
1156
  checkout.popOutWindow = undefined;
1148
1157
  }
1149
1158
  });
1159
+ const {
1160
+ close,
1161
+ focus,
1162
+ popOutWindow
1163
+ } = openPopOutResult;
1150
1164
  if (popOutWindow) {
1151
1165
  postOpenPopOutEvent(checkout.iframe, checkout.options.sid);
1152
1166
  // Add pop out window to checkout instance
@@ -1177,7 +1191,7 @@ const createPopOutValidationCallback = (event, checkout) => {
1177
1191
  // Redirect user to session in pop out window
1178
1192
  checkout.popOutWindow.location.href = url.getPopOutUrl({
1179
1193
  sid: checkout.options.sid,
1180
- endpoint: checkout.options.endpoint,
1194
+ endpoint: checkout.options.endpoint ?? "https://checkout.dintero.com",
1181
1195
  shouldCallValidateSession: false,
1182
1196
  shouldCallAddressCallback: false,
1183
1197
  language: event.language
@@ -1212,6 +1226,8 @@ const handlePopOutButtonClick = async (event, checkout) => {
1212
1226
  try {
1213
1227
  checkout.options.onValidateSession({
1214
1228
  type: CheckoutEvents.ValidateSession,
1229
+ // TODO: session may be undefined before SessionLoaded fires;
1230
+ // ValidateSession.session is typed as Session (non-optional).
1215
1231
  session: checkout.session,
1216
1232
  callback
1217
1233
  }, checkout, callback);
@@ -1229,7 +1245,7 @@ const handlePopOutButtonClick = async (event, checkout) => {
1229
1245
  * Type guard for ShowPopOutButton
1230
1246
  */
1231
1247
  const isShowPopOutButton = event => {
1232
- return event && event.type === InternalCheckoutEvents.ShowPopOutButton;
1248
+ return typeof event === "object" && event !== null && event.type === InternalCheckoutEvents.ShowPopOutButton;
1233
1249
  };
1234
1250
 
1235
1251
  /**
@@ -1291,7 +1307,7 @@ const embed = async options => {
1291
1307
  // Create inner container to offset any styling on the container.
1292
1308
  const innerContainer = document.createElement("div");
1293
1309
  innerContainer.style.position = "relative";
1294
- innerContainer.style["box-sizing"] = "border-box";
1310
+ innerContainer.style.boxSizing = "border-box";
1295
1311
  const internalOptions = {
1296
1312
  endpoint: "https://checkout.dintero.com",
1297
1313
  innerContainer: innerContainer,
@@ -1342,7 +1358,9 @@ const embed = async options => {
1342
1358
  * Function that removes the iframe, pop out and all event listeners.
1343
1359
  */
1344
1360
  const destroy = () => {
1345
- cleanUpPopOut(checkout);
1361
+ if (checkout) {
1362
+ cleanUpPopOut(checkout);
1363
+ }
1346
1364
  if (iframe) {
1347
1365
  if (internalOptions.popOut) {
1348
1366
  // Try to remove backdrop if it exists
@@ -1368,6 +1386,7 @@ const embed = async options => {
1368
1386
  if (!checkout) {
1369
1387
  throw new Error("Unable to create action promise: checkout is undefined");
1370
1388
  }
1389
+ const checkoutInstance = checkout;
1371
1390
  return new Promise((resolve, reject) => {
1372
1391
  const eventSubscriptions = [];
1373
1392
  eventSubscriptions.push(subscribe({
@@ -1380,8 +1399,8 @@ const embed = async options => {
1380
1399
  resolve(sessionEvent);
1381
1400
  },
1382
1401
  eventTypes: [resolveEvent],
1383
- checkout,
1384
- source: checkout.iframe.contentWindow
1402
+ checkout: checkoutInstance,
1403
+ source: checkoutInstance.iframe.contentWindow
1385
1404
  }));
1386
1405
  eventSubscriptions.push(subscribe({
1387
1406
  sid,
@@ -1393,8 +1412,8 @@ const embed = async options => {
1393
1412
  reject(`Received unexpected event: ${rejectEvent}`);
1394
1413
  },
1395
1414
  eventTypes: [rejectEvent],
1396
- checkout,
1397
- source: checkout.iframe.contentWindow
1415
+ checkout: checkoutInstance,
1416
+ source: checkoutInstance.iframe.contentWindow
1398
1417
  }));
1399
1418
  action();
1400
1419
  });
@@ -1434,6 +1453,7 @@ const embed = async options => {
1434
1453
  * If no custom handler is set the followHref handler is used instead.
1435
1454
  */
1436
1455
  const handleWithResult = (_sid, endpoint, handler) => {
1456
+ // biome-ignore lint/suspicious/noExplicitAny: requires dynamic key access on event payload
1437
1457
  return (event, checkout) => {
1438
1458
  if (!has_delivered_final_event) {
1439
1459
  has_delivered_final_event = true;
@@ -1514,15 +1534,17 @@ const embed = async options => {
1514
1534
  eventTypes: [CheckoutEvents.SessionLoaded, CheckoutEvents.SessionUpdated]
1515
1535
  }, {
1516
1536
  eventTypes: [CheckoutEvents.SessionPaymentOnHold],
1517
- handler: handleWithResult(sid, endpoint, onPayment || followHref)
1537
+ // TODO: user callbacks have narrower event param types than SubscriptionHandler;
1538
+ // casts are safe because handleWithResult only invokes them with the matching event type.
1539
+ handler: handleWithResult(sid, endpoint, onPayment ?? followHref)
1518
1540
  }, {
1519
1541
  eventTypes: [CheckoutEvents.SessionPaymentAuthorized],
1520
- handler: handleWithResult(sid, endpoint, onPaymentAuthorized || onPayment || followHref)
1542
+ handler: handleWithResult(sid, endpoint, onPaymentAuthorized ?? onPayment ?? followHref)
1521
1543
  }, {
1522
- handler: handleWithResult(sid, endpoint, onSessionCancel || followHref),
1544
+ handler: handleWithResult(sid, endpoint, onSessionCancel ?? followHref),
1523
1545
  eventTypes: [CheckoutEvents.SessionCancel]
1524
1546
  }, {
1525
- handler: handleWithResult(sid, endpoint, onPaymentError || followHref),
1547
+ handler: handleWithResult(sid, endpoint, onPaymentError ?? followHref),
1526
1548
  eventTypes: [CheckoutEvents.SessionPaymentError]
1527
1549
  }, {
1528
1550
  handler: onSessionNotFound,
@@ -1553,7 +1575,7 @@ const embed = async options => {
1553
1575
  checkout = {
1554
1576
  destroy,
1555
1577
  iframe,
1556
- language,
1578
+ language: language ?? "",
1557
1579
  lockSession,
1558
1580
  refreshSession,
1559
1581
  setActivePaymentProductType,
@@ -1564,6 +1586,7 @@ const embed = async options => {
1564
1586
  session: undefined,
1565
1587
  popOutWindow: undefined
1566
1588
  };
1589
+ const checkoutInstance = checkout;
1567
1590
  for (const {
1568
1591
  handler,
1569
1592
  eventTypes
@@ -1574,8 +1597,8 @@ const embed = async options => {
1574
1597
  endpoint,
1575
1598
  handler,
1576
1599
  eventTypes,
1577
- checkout,
1578
- source: checkout.iframe.contentWindow
1600
+ checkout: checkoutInstance,
1601
+ source: checkoutInstance.iframe.contentWindow
1579
1602
  }));
1580
1603
  }
1581
1604
  }
@@ -1583,7 +1606,7 @@ const embed = async options => {
1583
1606
  // Add iframe to DOM
1584
1607
  await initiate();
1585
1608
  // Return object with function to destroy the checkout.
1586
- return checkout;
1609
+ return checkoutInstance;
1587
1610
  };
1588
1611
 
1589
1612
  /**